[PATCH 3/3] drm/i915/display: Implement seamless mode switch
As described in previous commit "drm: Add infrastructure to allow seamless mode switches" here doing the i915 implementation. The main steps are: - drm_atomic_helper_check_modeset() will call atomic_seamless_mode_switch_check()/intel_drrs_seamless_mode_switch_check() if conditions match - intel_drrs_seamless_mode_switch_check() will check if seamless DRRS is enabled and if the requested mode matches with fixed or downclock mode - now at the atomic commit phase during the execution of intel_pre_plane_update(), intel_drrs_deactivate() will return without change the DRRS state if seamless_mode_switch_enabled or seamless_mode_changed is set and there is no modeset happening in this pipe(something after drm_atomic_helper_check_modeset() could still require a modeset and set mode_changed) - then in intel_post_plane_update(), intel_drrs_activate() is called and DRRS mode is switched if seamless_mode_changed is set or the function is skipped if seamless_mode_switch_enabled is set and pipe don't need a modeset After a modeset, seamless_mode_switch_enabled is set to 0 and DRRS is back to automatic mode until the next commit that intel_drrs_seamless_mode_switch_check() is executed and it supports the mode. Cc: Vidya Srinivas Cc: Sean Paul Cc: Ville Syrjälä Signed-off-by: José Roberto de Souza --- drivers/gpu/drm/i915/display/intel_crtc.c | 10 +++ drivers/gpu/drm/i915/display/intel_display.c | 5 +- .../drm/i915/display/intel_display_debugfs.c | 5 +- .../drm/i915/display/intel_display_types.h| 3 +- drivers/gpu/drm/i915/display/intel_dp.c | 2 + drivers/gpu/drm/i915/display/intel_drrs.c | 73 ++- drivers/gpu/drm/i915/display/intel_drrs.h | 5 +- 7 files changed, 96 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_crtc.c b/drivers/gpu/drm/i915/display/intel_crtc.c index 4442aa355f868..d411daa0b2bab 100644 --- a/drivers/gpu/drm/i915/display/intel_crtc.c +++ b/drivers/gpu/drm/i915/display/intel_crtc.c @@ -215,6 +215,15 @@ static int intel_crtc_late_register(struct drm_crtc *crtc) return 0; } +static int intel_crtc_seamless_mode_switch_check(struct drm_atomic_state *_state, +struct drm_crtc *_crtc) +{ + struct intel_atomic_state *state = to_intel_atomic_state(_state); + struct intel_crtc *crtc = to_intel_crtc(_crtc); + + return intel_drrs_seamless_mode_switch_check(state, crtc); +} + #define INTEL_CRTC_FUNCS \ .set_config = drm_atomic_helper_set_config, \ .destroy = intel_crtc_destroy, \ @@ -233,6 +242,7 @@ static const struct drm_crtc_funcs bdw_crtc_funcs = { .enable_vblank = bdw_enable_vblank, .disable_vblank = bdw_disable_vblank, .get_vblank_timestamp = intel_crtc_get_vblank_timestamp, + .atomic_seamless_mode_switch_check = intel_crtc_seamless_mode_switch_check, }; static const struct drm_crtc_funcs ilk_crtc_funcs = { diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index a5f5caeced9a0..ebfa7d68e35fe 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -1329,7 +1329,7 @@ static void intel_pre_plane_update(struct intel_atomic_state *state, intel_atomic_get_new_crtc_state(state, crtc); enum pipe pipe = crtc->pipe; - intel_drrs_deactivate(old_crtc_state); + intel_drrs_deactivate(old_crtc_state, new_crtc_state); intel_psr_pre_plane_update(state, crtc); @@ -7089,6 +7089,7 @@ static void intel_crtc_copy_fastset(const struct intel_crtc_state *old_crtc_stat new_crtc_state->dp_m_n = old_crtc_state->dp_m_n; new_crtc_state->dp_m2_n2 = old_crtc_state->dp_m2_n2; new_crtc_state->drrs_downclock_mode = old_crtc_state->drrs_downclock_mode; + new_crtc_state->drrs_fixed_mode = old_crtc_state->drrs_fixed_mode; } static int intel_crtc_add_planes_to_state(struct intel_atomic_state *state, @@ -7716,6 +7717,8 @@ static int intel_atomic_check(struct drm_device *dev, if (!intel_crtc_needs_modeset(new_crtc_state)) { if (intel_crtc_is_bigjoiner_slave(new_crtc_state)) copy_bigjoiner_crtc_state_nomodeset(state, crtc); + else if (new_crtc_state->uapi.seamless_mode_changed) + intel_crtc_copy_uapi_to_hw_state_modeset(state, crtc); else intel_crtc_copy_uapi_to_hw_state_nomodeset(state, crtc); continue; diff --git a/drivers/gpu/drm/i915/display/intel_display_debugfs.c b/drivers/gpu/drm/i915/display/intel_display_debugfs.c index f9720562336da..1d27ed2b68210 100644 --- a/drivers/gpu/drm/i915/display/intel_display_debugfs.c +++ b/drivers/gpu/drm/i915/display/intel_display_debugfs.c @@ -1108,6 +1108
[PATCH 1/3] drm: Add infrastructure to allow seamless mode switches
Intel hardware supports change between modes with different refresh rates without any glitches or visual artifacts, that feature is called seamless DRRS. So far i915 driver was automatically changing between preferred panel mode and lower refresh rate mode based on idleness but ChromeOS compositor team is requesting to be in control of the mode switch. So for a certain types of content it can switch to mode with a lower refresh rate without user noticing a thing and saving power. This seamless mode switch will be triggered when user-space dispatch a atomic commit with the new mode and clears the DRM_MODE_ATOMIC_ALLOW_MODESET flag. A driver that don't implement atomic_seamless_mode_switch_check function will continue to fail in the atomic check phase with "[CRTC:%d:%s] requires full modeset" debug message. While a driver that implements it and support the seamless change between old and new mode will return 0 otherwise it should return the appropried errno. So here adding basic drm infrastructure to that be supported by i915 and other drivers. Cc: Vidya Srinivas Cc: Sean Paul Cc: Ville Syrjälä Signed-off-by: José Roberto de Souza --- drivers/gpu/drm/drm_atomic.c | 1 + drivers/gpu/drm/drm_atomic_helper.c | 16 +++ drivers/gpu/drm/drm_atomic_state_helper.c | 1 + include/drm/drm_crtc.h| 25 +++ 4 files changed, 43 insertions(+) diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c index 58c0283fb6b0c..21525f9f4b4c1 100644 --- a/drivers/gpu/drm/drm_atomic.c +++ b/drivers/gpu/drm/drm_atomic.c @@ -437,6 +437,7 @@ static void drm_atomic_crtc_print_state(struct drm_printer *p, drm_printf(p, "\tself_refresh_active=%d\n", state->self_refresh_active); drm_printf(p, "\tplanes_changed=%d\n", state->planes_changed); drm_printf(p, "\tmode_changed=%d\n", state->mode_changed); + drm_printf(p, "\tseamless_mode_changed=%d\n", state->seamless_mode_changed); drm_printf(p, "\tactive_changed=%d\n", state->active_changed); drm_printf(p, "\tconnectors_changed=%d\n", state->connectors_changed); drm_printf(p, "\tcolor_mgmt_changed=%d\n", state->color_mgmt_changed); diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index 9603193d2fa13..e6f3a966f7b86 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -631,6 +631,22 @@ drm_atomic_helper_check_modeset(struct drm_device *dev, drm_dbg_atomic(dev, "[CRTC:%d:%s] mode changed\n", crtc->base.id, crtc->name); new_crtc_state->mode_changed = true; + + if (!state->allow_modeset && + crtc->funcs->atomic_seamless_mode_switch_check) { + ret = crtc->funcs->atomic_seamless_mode_switch_check(state, crtc); + if (ret == -EOPNOTSUPP) { + drm_dbg_atomic(dev, "[CRTC:%d:%s] Seamless mode switch not supported\n", + crtc->base.id, crtc->name); + return ret; + } + + if (ret < 0) + return ret; + + new_crtc_state->seamless_mode_changed = true; + new_crtc_state->mode_changed = false; + } } if (old_crtc_state->enable != new_crtc_state->enable) { diff --git a/drivers/gpu/drm/drm_atomic_state_helper.c b/drivers/gpu/drm/drm_atomic_state_helper.c index 3b6d3bdbd0996..c093073ea6e11 100644 --- a/drivers/gpu/drm/drm_atomic_state_helper.c +++ b/drivers/gpu/drm/drm_atomic_state_helper.c @@ -142,6 +142,7 @@ void __drm_atomic_helper_crtc_duplicate_state(struct drm_crtc *crtc, if (state->gamma_lut) drm_property_blob_get(state->gamma_lut); state->mode_changed = false; + state->seamless_mode_changed = false; state->active_changed = false; state->planes_changed = false; state->connectors_changed = false; diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index a70baea0636ca..b7ce378d679d3 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h @@ -140,6 +140,16 @@ struct drm_crtc_state { */ bool mode_changed : 1; + /** +* @seamless_mode_changed: @mode has been changed but user-space +* is requesting to change to the new mode with a fastset and driver +* supports this request. +* To be used by drivers to steer the atomic com
[PATCH 2/3] drm/i915/display: Replace crtc_state's has_drrs by drrs_downclock_mode
Will be adding some additional control options to DRRS that will require to have the DRRS downclock mode stored in the crtc_state. So to optimize memory usage a bit here using it to replace has_drrs as we can check if the drrs_downclock_mode pointer is different than null to have the same behavior has has_drrs. Cc: Vidya Srinivas Cc: Sean Paul Cc: Ville Syrjälä Signed-off-by: José Roberto de Souza --- drivers/gpu/drm/i915/display/intel_display.c | 4 ++-- drivers/gpu/drm/i915/display/intel_display_debugfs.c | 4 ++-- drivers/gpu/drm/i915/display/intel_display_types.h | 4 +++- drivers/gpu/drm/i915/display/intel_dp.c | 2 +- drivers/gpu/drm/i915/display/intel_drrs.c| 4 ++-- 5 files changed, 10 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 0ddfce21a828d..a5f5caeced9a0 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -5360,7 +5360,7 @@ static void intel_dump_pipe_config(const struct intel_crtc_state *pipe_config, drm_dbg_kms(_priv->drm, "ips: %i, double wide: %i, drrs: %i\n", pipe_config->ips_enabled, pipe_config->double_wide, - pipe_config->has_drrs); + CRTC_STATE_HAS_DRRS(pipe_config)); intel_dpll_dump_hw_state(dev_priv, _config->dpll_hw_state); @@ -7088,7 +7088,7 @@ static void intel_crtc_copy_fastset(const struct intel_crtc_state *old_crtc_stat new_crtc_state->fdi_m_n = old_crtc_state->fdi_m_n; new_crtc_state->dp_m_n = old_crtc_state->dp_m_n; new_crtc_state->dp_m2_n2 = old_crtc_state->dp_m2_n2; - new_crtc_state->has_drrs = old_crtc_state->has_drrs; + new_crtc_state->drrs_downclock_mode = old_crtc_state->drrs_downclock_mode; } static int intel_crtc_add_planes_to_state(struct intel_atomic_state *state, diff --git a/drivers/gpu/drm/i915/display/intel_display_debugfs.c b/drivers/gpu/drm/i915/display/intel_display_debugfs.c index 452d773fd4e34..f9720562336da 100644 --- a/drivers/gpu/drm/i915/display/intel_display_debugfs.c +++ b/drivers/gpu/drm/i915/display/intel_display_debugfs.c @@ -1096,7 +1096,7 @@ static int i915_drrs_status(struct seq_file *m, void *unused) /* DRRS Supported */ seq_printf(m, "\tDRRS Enabled: %s\n", - str_yes_no(crtc_state->has_drrs)); + str_yes_no(CRTC_STATE_HAS_DRRS(crtc_state))); seq_printf(m, "\tDRRS Active: %s\n", str_yes_no(intel_drrs_is_active(crtc))); @@ -1786,7 +1786,7 @@ static int i915_drrs_ctl_set(void *data, u64 val) crtc_state = to_intel_crtc_state(crtc->base.state); if (!crtc_state->hw.active || - !crtc_state->has_drrs) + !CRTC_STATE_HAS_DRRS(crtc_state)) goto out; commit = crtc_state->uapi.commit; diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h index cfd042117b109..f0b3cfd3138ce 100644 --- a/drivers/gpu/drm/i915/display/intel_display_types.h +++ b/drivers/gpu/drm/i915/display/intel_display_types.h @@ -1056,7 +1056,7 @@ struct intel_crtc_state { /* m2_n2 for eDP downclock */ struct intel_link_m_n dp_m2_n2; - bool has_drrs; + const struct drm_display_mode *drrs_downclock_mode; /* PSR is supported but might not be enabled due the lack of enabled planes */ bool has_psr; @@ -1264,6 +1264,8 @@ enum drrs_refresh_rate { DRRS_REFRESH_RATE_LOW, }; +#define CRTC_STATE_HAS_DRRS(crtc_state) (!!((crtc_state)->drrs_downclock_mode)) + #define INTEL_PIPE_CRC_ENTRIES_NR 128 struct intel_pipe_crc { spinlock_t lock; diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index d55acc4a028a8..feea172dd2753 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -1881,7 +1881,7 @@ intel_dp_drrs_compute_config(struct intel_connector *connector, if (IS_IRONLAKE(i915) || IS_SANDYBRIDGE(i915) || IS_IVYBRIDGE(i915)) pipe_config->msa_timing_delay = i915->vbt.edp.drrs_msa_timing_delay; - pipe_config->has_drrs = true; + pipe_config->drrs_downclock_mode = downclock_mode; pixel_clock = downclock_mode->clock; if (pipe_config->splitter.enable) diff --git a/drivers/gpu/drm/i915/display/intel_drrs.c b/drivers/gpu/drm/i915/display/intel_drrs.c index 166caf293f7bc..dd527dfc2d1d5 100644 --- a/drivers/gpu/drm/i915/display/intel_drrs.c +++ b/drivers/gpu/drm/i915/display/intel_drrs.c @@ -144,7 +144,7 @@ void intel_drrs_activate(const struct intel_crtc_state *c
[PATCH] drm/damage_helper: Fix handling of cursor dirty buffers
Cursors don't have a framebuffer so the fb comparisson was always failing and atomic state was being committed without any plane state. So here checking if objects match when checking cursors. Fixes: b9fc5e01d1ce ("drm: Add helper to implement legacy dirtyfb") Cc: Daniel Vetter Cc: Rob Clark Cc: Deepak Rawat Cc: Gwan-gyeong Mun Signed-off-by: José Roberto de Souza --- drivers/gpu/drm/drm_damage_helper.c | 8 +++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/drm_damage_helper.c b/drivers/gpu/drm/drm_damage_helper.c index 8eeff0c7bdd47..595187d97c131 100644 --- a/drivers/gpu/drm/drm_damage_helper.c +++ b/drivers/gpu/drm/drm_damage_helper.c @@ -157,12 +157,18 @@ int drm_atomic_helper_dirtyfb(struct drm_framebuffer *fb, retry: drm_for_each_plane(plane, fb->dev) { struct drm_plane_state *plane_state; + bool match; ret = drm_modeset_lock(>mutex, state->acquire_ctx); if (ret) goto out; - if (plane->state->fb != fb) { + match = plane->state->fb == fb; + /* Check if objs match to handle dirty buffers of cursors */ + if (plane->type == DRM_PLANE_TYPE_CURSOR && plane->state->fb) + match |= fb->obj[0] == plane->state->fb->obj[0]; + + if (!match) { drm_modeset_unlock(>mutex); continue; } -- 2.32.0
[PATCH] drm/dp_mst: Add missing drm parameters to recently added call to drm_dbg_kms()
Commit 3769e4c0af5b ("drm/dp_mst: Avoid to mess up payload table by ports in stale topology") added to calls to drm_dbg_kms() but it missed the first parameter, the drm device breaking the build. Fixes: 3769e4c0af5b ("drm/dp_mst: Avoid to mess up payload table by ports in stale topology") Cc: Wayne Lin Cc: Lyude Paul Cc: dri-devel@lists.freedesktop.org Signed-off-by: José Roberto de Souza --- drivers/gpu/drm/drm_dp_mst_topology.c | 7 +-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/drm_dp_mst_topology.c b/drivers/gpu/drm/drm_dp_mst_topology.c index 9ac148efd9e43..ad0795afc21cf 100644 --- a/drivers/gpu/drm/drm_dp_mst_topology.c +++ b/drivers/gpu/drm/drm_dp_mst_topology.c @@ -3389,7 +3389,9 @@ int drm_dp_update_payload_part1(struct drm_dp_mst_topology_mgr *mgr) mutex_unlock(>lock); if (skip) { - drm_dbg_kms("Virtual channel %d is not in current topology\n", i); + drm_dbg_kms(mgr->dev, + "Virtual channel %d is not in current topology\n", + i); continue; } /* Validated ports don't matter if we're releasing @@ -3404,7 +3406,8 @@ int drm_dp_update_payload_part1(struct drm_dp_mst_topology_mgr *mgr) payload->start_slot = req_payload.start_slot; continue; } else { - drm_dbg_kms("Fail:set payload to invalid sink"); + drm_dbg_kms(mgr->dev, + "Fail:set payload to invalid sink"); mutex_unlock(>payload_lock); return -EINVAL; } -- 2.32.0
[PATCH 1/2] drm: Rename DP_PSR_SELECTIVE_UPDATE to better mach eDP spec
DP_PSR_EN_CFG bit 5 aka "Selective Update Region Scan Line Capture Indication" in eDP spec has a ambiguous name, so renaming to better match specification. While at it, replacing bit shit by BIT() macro and adding the version some registers were added to eDP specification. Cc: Cc: Rodrigo Vivi Cc: Jani Nikula Cc: Gwan-gyeong Mun Signed-off-by: José Roberto de Souza --- include/drm/drm_dp_helper.h | 16 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h index 1e85c2021f2f..d6f6a084a190 100644 --- a/include/drm/drm_dp_helper.h +++ b/include/drm/drm_dp_helper.h @@ -687,14 +687,14 @@ struct drm_device; #define DP_DSC_ENABLE 0x160 /* DP 1.4 */ # define DP_DECOMPRESSION_EN(1 << 0) -#define DP_PSR_EN_CFG 0x170 /* XXX 1.2? */ -# define DP_PSR_ENABLE (1 << 0) -# define DP_PSR_MAIN_LINK_ACTIVE (1 << 1) -# define DP_PSR_CRC_VERIFICATION (1 << 2) -# define DP_PSR_FRAME_CAPTURE (1 << 3) -# define DP_PSR_SELECTIVE_UPDATE (1 << 4) -# define DP_PSR_IRQ_HPD_WITH_CRC_ERRORS (1 << 5) -# define DP_PSR_ENABLE_PSR2(1 << 6) /* eDP 1.4a */ +#define DP_PSR_EN_CFG 0x170 /* XXX 1.2? */ +# define DP_PSR_ENABLE BIT(0) +# define DP_PSR_MAIN_LINK_ACTIVE BIT(1) +# define DP_PSR_CRC_VERIFICATION BIT(2) +# define DP_PSR_FRAME_CAPTURE BIT(3) +# define DP_PSR_SU_REGION_SCANLINE_CAPTURE BIT(4) /* eDP 1.4a */ +# define DP_PSR_IRQ_HPD_WITH_CRC_ERRORSBIT(5) /* eDP 1.4a */ +# define DP_PSR_ENABLE_PSR2BIT(6) /* eDP 1.4a */ #define DP_ADAPTER_CTRL0x1a0 # define DP_ADAPTER_CTRL_FORCE_LOAD_SENSE (1 << 0) -- 2.31.1 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH CI 1/4] drm: Add function to convert rect in 16.16 fixed format to regular format
Much more clear to read one function call than four lines doing this conversion. v7: - function renamed - calculating width and height before truncate - inlined v10: - renamed parameters from source and destination to src and dst to match sister functions Cc: Ville Syrjälä Cc: dri-devel@lists.freedesktop.org Cc: Gwan-gyeong Mun Reviewed-by: Gwan-gyeong Mun Signed-off-by: José Roberto de Souza --- include/drm/drm_rect.h | 13 + 1 file changed, 13 insertions(+) diff --git a/include/drm/drm_rect.h b/include/drm/drm_rect.h index e7f4d24cdd00..39f2deee709c 100644 --- a/include/drm/drm_rect.h +++ b/include/drm/drm_rect.h @@ -206,6 +206,19 @@ static inline bool drm_rect_equals(const struct drm_rect *r1, r1->y1 == r2->y1 && r1->y2 == r2->y2; } +/** + * drm_rect_fp_to_int - Convert a rect in 16.16 fixed point form to int form. + * @dst: rect to be stored the converted value + * @src: rect in 16.16 fixed point form + */ +static inline void drm_rect_fp_to_int(struct drm_rect *dst, + const struct drm_rect *src) +{ + drm_rect_init(dst, src->x1 >> 16, src->y1 >> 16, + drm_rect_width(src) >> 16, + drm_rect_height(src) >> 16); +} + bool drm_rect_intersect(struct drm_rect *r, const struct drm_rect *clip); bool drm_rect_clip_scaled(struct drm_rect *src, struct drm_rect *dst, const struct drm_rect *clip); -- 2.30.0 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH v9 1/5] drm: Add function to convert rect in 16.16 fixed format to regular format
Much more clear to read one function call than four lines doing this conversion. v7: - function renamed - calculating width and height before truncate - inlined Cc: Ville Syrjälä Cc: dri-devel@lists.freedesktop.org Cc: Gwan-gyeong Mun Signed-off-by: José Roberto de Souza --- include/drm/drm_rect.h | 13 + 1 file changed, 13 insertions(+) diff --git a/include/drm/drm_rect.h b/include/drm/drm_rect.h index e7f4d24cdd00..7eb84af4a818 100644 --- a/include/drm/drm_rect.h +++ b/include/drm/drm_rect.h @@ -206,6 +206,19 @@ static inline bool drm_rect_equals(const struct drm_rect *r1, r1->y1 == r2->y1 && r1->y2 == r2->y2; } +/** + * drm_rect_fp_to_int - Convert a rect in 16.16 fixed point form to int form. + * @destination: rect to be stored the converted value + * @source: rect in 16.16 fixed point form + */ +static inline void drm_rect_fp_to_int(struct drm_rect *destination, + const struct drm_rect *source) +{ + drm_rect_init(destination, source->x1 >> 16, source->y1 >> 16, + drm_rect_width(source) >> 16, + drm_rect_height(source) >> 16); +} + bool drm_rect_intersect(struct drm_rect *r, const struct drm_rect *clip); bool drm_rect_clip_scaled(struct drm_rect *src, struct drm_rect *dst, const struct drm_rect *clip); -- 2.29.2 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH v7 1/5] drm: Add function to convert rect in 16.16 fixed format to regular format
Much more clear to read one function call than four lines doing this conversion. v7: - function renamed - calculating width and height before truncate - inlined Cc: Ville Syrjälä Cc: dri-devel@lists.freedesktop.org Cc: Gwan-gyeong Mun Signed-off-by: José Roberto de Souza --- include/drm/drm_rect.h | 13 + 1 file changed, 13 insertions(+) diff --git a/include/drm/drm_rect.h b/include/drm/drm_rect.h index e7f4d24cdd00..7eb84af4a818 100644 --- a/include/drm/drm_rect.h +++ b/include/drm/drm_rect.h @@ -206,6 +206,19 @@ static inline bool drm_rect_equals(const struct drm_rect *r1, r1->y1 == r2->y1 && r1->y2 == r2->y2; } +/** + * drm_rect_fp_to_int - Convert a rect in 16.16 fixed point form to int form. + * @destination: rect to be stored the converted value + * @source: rect in 16.16 fixed point form + */ +static inline void drm_rect_fp_to_int(struct drm_rect *destination, + const struct drm_rect *source) +{ + drm_rect_init(destination, source->x1 >> 16, source->y1 >> 16, + drm_rect_width(source) >> 16, + drm_rect_height(source) >> 16); +} + bool drm_rect_intersect(struct drm_rect *r, const struct drm_rect *clip); bool drm_rect_clip_scaled(struct drm_rect *src, struct drm_rect *dst, const struct drm_rect *clip); -- 2.29.2 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH v7 1/5] drm: Add function to convert rect in 16.16 fixed format to regular format
Much more clear to read one function call than four lines doing this conversion. v7: - function renamed - calculating width and height before truncate - inlined Cc: Ville Syrjälä Cc: dri-devel@lists.freedesktop.org Cc: Gwan-gyeong Mun Signed-off-by: José Roberto de Souza --- include/drm/drm_rect.h | 13 + 1 file changed, 13 insertions(+) diff --git a/include/drm/drm_rect.h b/include/drm/drm_rect.h index e7f4d24cdd00..7eb84af4a818 100644 --- a/include/drm/drm_rect.h +++ b/include/drm/drm_rect.h @@ -206,6 +206,19 @@ static inline bool drm_rect_equals(const struct drm_rect *r1, r1->y1 == r2->y1 && r1->y2 == r2->y2; } +/** + * drm_rect_fp_to_int - Convert a rect in 16.16 fixed point form to int form. + * @destination: rect to be stored the converted value + * @source: rect in 16.16 fixed point form + */ +static inline void drm_rect_fp_to_int(struct drm_rect *destination, + const struct drm_rect *source) +{ + drm_rect_init(destination, source->x1 >> 16, source->y1 >> 16, + drm_rect_width(source) >> 16, + drm_rect_height(source) >> 16); +} + bool drm_rect_intersect(struct drm_rect *r, const struct drm_rect *clip); bool drm_rect_clip_scaled(struct drm_rect *src, struct drm_rect *dst, const struct drm_rect *clip); -- 2.29.2 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH v6 1/5] drm: Add function to convert rect in 16.16 fixed format to regular format
Much more clear to read one function call than four lines doing this conversion. Cc: dri-devel@lists.freedesktop.org Cc: Gwan-gyeong Mun Signed-off-by: José Roberto de Souza --- drivers/gpu/drm/drm_rect.c | 15 +++ include/drm/drm_rect.h | 2 ++ 2 files changed, 17 insertions(+) diff --git a/drivers/gpu/drm/drm_rect.c b/drivers/gpu/drm/drm_rect.c index 0460e874896e..24345704b353 100644 --- a/drivers/gpu/drm/drm_rect.c +++ b/drivers/gpu/drm/drm_rect.c @@ -373,3 +373,18 @@ void drm_rect_rotate_inv(struct drm_rect *r, } } EXPORT_SYMBOL(drm_rect_rotate_inv); + +/** + * drm_rect_convert_16_16_to_regular - Convert a rect in 16.16 fixed point form + * to regular form. + * @in: rect in 16.16 fixed point form + * @out: rect to be stored the converted value + */ +void drm_rect_convert_16_16_to_regular(struct drm_rect *in, struct drm_rect *out) +{ + out->x1 = in->x1 >> 16; + out->y1 = in->y1 >> 16; + out->x2 = in->x2 >> 16; + out->y2 = in->y2 >> 16; +} +EXPORT_SYMBOL(drm_rect_convert_16_16_to_regular); diff --git a/include/drm/drm_rect.h b/include/drm/drm_rect.h index e7f4d24cdd00..2ef8180416cd 100644 --- a/include/drm/drm_rect.h +++ b/include/drm/drm_rect.h @@ -223,5 +223,7 @@ void drm_rect_rotate(struct drm_rect *r, void drm_rect_rotate_inv(struct drm_rect *r, int width, int height, unsigned int rotation); +void drm_rect_convert_16_16_to_regular(struct drm_rect *in, + struct drm_rect *out); #endif -- 2.29.2 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH v5 1/6] drm/damage_helper: Check if damage clips has valid values
Userspace can set a damage clip with a negative coordinate, negative width or height or larger than the plane. This invalid values could cause issues in some HW or even worst enable security flaws. v2: - add debug messages to let userspace know why atomic commit failed due invalid damage clips Cc: Simon Ser Cc: Gwan-gyeong Mun Cc: Sean Paul Cc: Fabio Estevam Cc: Deepak Rawat Cc: dri-devel@lists.freedesktop.org Signed-off-by: José Roberto de Souza --- drivers/gpu/drm/drm_atomic_helper.c | 4 +- drivers/gpu/drm/drm_damage_helper.c | 59 - include/drm/drm_damage_helper.h | 4 +- 3 files changed, 55 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index ba1507036f26..c6b341ecae2c 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -897,7 +897,9 @@ drm_atomic_helper_check_planes(struct drm_device *dev, drm_atomic_helper_plane_changed(state, old_plane_state, new_plane_state, plane); - drm_atomic_helper_check_plane_damage(state, new_plane_state); + ret = drm_atomic_helper_check_plane_damage(state, new_plane_state); + if (ret) + return ret; if (!funcs || !funcs->atomic_check) continue; diff --git a/drivers/gpu/drm/drm_damage_helper.c b/drivers/gpu/drm/drm_damage_helper.c index 3a4126dc2520..69a557aaa8cf 100644 --- a/drivers/gpu/drm/drm_damage_helper.c +++ b/drivers/gpu/drm/drm_damage_helper.c @@ -33,6 +33,7 @@ #include #include #include +#include /** * DOC: overview @@ -104,36 +105,76 @@ void drm_plane_enable_fb_damage_clips(struct drm_plane *plane) EXPORT_SYMBOL(drm_plane_enable_fb_damage_clips); /** - * drm_atomic_helper_check_plane_damage - Verify plane damage on atomic_check. + * drm_atomic_helper_check_plane_damage - Verify plane damage clips on + * atomic_check. * @state: The driver state object. - * @plane_state: Plane state for which to verify damage. + * @plane_state: Plane state for which to verify damage clips. * - * This helper function makes sure that damage from plane state is discarded - * for full modeset. If there are more reasons a driver would want to do a full - * plane update rather than processing individual damage regions, then those - * cases should be taken care of here. + * This helper checks if all damage clips has valid values and makes sure that + * damage clips from plane state is discarded for full modeset. If there are + * more reasons a driver would want to do a full plane update rather than + * processing individual damage regions, then those cases should be taken care + * of here. * * Note that _plane_state.fb_damage_clips == NULL in plane state means that * full plane update should happen. It also ensure helper iterator will return * _plane_state.src as damage. + * + * Return: Zero on success, negative errno on failure. */ -void drm_atomic_helper_check_plane_damage(struct drm_atomic_state *state, - struct drm_plane_state *plane_state) +int drm_atomic_helper_check_plane_damage(struct drm_atomic_state *state, +struct drm_plane_state *plane_state) { + struct drm_mode_rect *damage_clips; struct drm_crtc_state *crtc_state; + unsigned int num_clips, w, h; + + num_clips = drm_plane_get_damage_clips_count(plane_state); + if (!num_clips) + return 0; if (plane_state->crtc) { crtc_state = drm_atomic_get_new_crtc_state(state, plane_state->crtc); if (WARN_ON(!crtc_state)) - return; + return 0; if (drm_atomic_crtc_needs_modeset(crtc_state)) { drm_property_blob_put(plane_state->fb_damage_clips); plane_state->fb_damage_clips = NULL; + return 0; + } + } + + w = drm_rect_width(_state->src) >> 16; + h = drm_rect_height(_state->src) >> 16; + damage_clips = drm_plane_get_damage_clips(plane_state); + + for (; num_clips; num_clips--, damage_clips++) { + if (damage_clips->x1 < 0 || damage_clips->x2 < 0 || + damage_clips->y1 < 0 || damage_clips->y2 < 0) { + drm_dbg_atomic(state->dev, + "Invalid damage clip, negative coordinate\n"); + return -EINVAL; + } + + if (damage_clips->x2 < damage_clips->x1 || + damage_clips->y2 < damage_clips->y1) { + drm_dbg_atomic(state->dev, +
[PATCH] drm/damage_helper: Check if damage clips has valid values
Userspace can set a damage clip with a negative coordinate, negative width or height or larger than the plane. This invalid values could cause issues in some HW or even worst enable security flaws. Cc: Gwan-gyeong Mun Cc: Sean Paul Cc: Fabio Estevam Cc: Deepak Rawat Cc: dri-devel@lists.freedesktop.org Signed-off-by: José Roberto de Souza --- drivers/gpu/drm/drm_atomic_helper.c | 4 ++- drivers/gpu/drm/drm_damage_helper.c | 49 +++-- include/drm/drm_damage_helper.h | 4 +-- 3 files changed, 45 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index ba1507036f26..c6b341ecae2c 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -897,7 +897,9 @@ drm_atomic_helper_check_planes(struct drm_device *dev, drm_atomic_helper_plane_changed(state, old_plane_state, new_plane_state, plane); - drm_atomic_helper_check_plane_damage(state, new_plane_state); + ret = drm_atomic_helper_check_plane_damage(state, new_plane_state); + if (ret) + return ret; if (!funcs || !funcs->atomic_check) continue; diff --git a/drivers/gpu/drm/drm_damage_helper.c b/drivers/gpu/drm/drm_damage_helper.c index 3a4126dc2520..9adb369440ba 100644 --- a/drivers/gpu/drm/drm_damage_helper.c +++ b/drivers/gpu/drm/drm_damage_helper.c @@ -104,36 +104,67 @@ void drm_plane_enable_fb_damage_clips(struct drm_plane *plane) EXPORT_SYMBOL(drm_plane_enable_fb_damage_clips); /** - * drm_atomic_helper_check_plane_damage - Verify plane damage on atomic_check. + * drm_atomic_helper_check_plane_damage - Verify plane damage clips on + * atomic_check. * @state: The driver state object. - * @plane_state: Plane state for which to verify damage. + * @plane_state: Plane state for which to verify damage clips. * - * This helper function makes sure that damage from plane state is discarded - * for full modeset. If there are more reasons a driver would want to do a full - * plane update rather than processing individual damage regions, then those - * cases should be taken care of here. + * This helper checks if all damage clips has valid values and makes sure that + * damage clips from plane state is discarded for full modeset. If there are + * more reasons a driver would want to do a full plane update rather than + * processing individual damage regions, then those cases should be taken care + * of here. * * Note that _plane_state.fb_damage_clips == NULL in plane state means that * full plane update should happen. It also ensure helper iterator will return * _plane_state.src as damage. + * + * Return: Zero on success, negative errno on failure. */ -void drm_atomic_helper_check_plane_damage(struct drm_atomic_state *state, - struct drm_plane_state *plane_state) +int drm_atomic_helper_check_plane_damage(struct drm_atomic_state *state, +struct drm_plane_state *plane_state) { + struct drm_mode_rect *damaged_clips; struct drm_crtc_state *crtc_state; + unsigned int num_clips, w, h; + + num_clips = drm_plane_get_damage_clips_count(plane_state); + if (!num_clips) + return 0; if (plane_state->crtc) { crtc_state = drm_atomic_get_new_crtc_state(state, plane_state->crtc); if (WARN_ON(!crtc_state)) - return; + return 0; if (drm_atomic_crtc_needs_modeset(crtc_state)) { drm_property_blob_put(plane_state->fb_damage_clips); plane_state->fb_damage_clips = NULL; + return 0; } } + + w = drm_rect_width(_state->src) >> 16; + h = drm_rect_height(_state->src) >> 16; + damaged_clips = drm_plane_get_damage_clips(plane_state); + + for (; num_clips; num_clips--, damaged_clips++) { + if (damaged_clips->x1 < 0 || damaged_clips->x2 < 0 || + damaged_clips->y1 < 0 || damaged_clips->y2 < 0) + return -EINVAL; + + if (damaged_clips->x2 < damaged_clips->x1 || + damaged_clips->y2 < damaged_clips->y1) + return -EINVAL; + + if ((damaged_clips->x2 - damaged_clips->x1) > w || + (damaged_clips->y2 - damaged_clips->y1) > h) + return -EINVAL; + } + + return 0; } EXPORT_SYMBOL(drm_atomic_helper_check_plane_damage); diff --git a/include/drm/drm_damage_helper.h b/include/drm/drm_damage_helper.h index 40c34a5bf149..5e344d1a2b22 100644 --- a/i
[PATCH] intel: sync i915_pciids.h with kernel
Two new patches landed in kernel adding new PCI ids: 123f62de419f ("drm/i915/rkl: Add RKL platform info and PCI ids") 52797a8e8529 ("drm/i915/ehl: Add new PCI ids") Cc: Matt Roper Signed-off-by: José Roberto de Souza --- intel/i915_pciids.h | 13 + 1 file changed, 13 insertions(+) diff --git a/intel/i915_pciids.h b/intel/i915_pciids.h index 662d8351..d6cb2899 100644 --- a/intel/i915_pciids.h +++ b/intel/i915_pciids.h @@ -588,7 +588,11 @@ INTEL_VGA_DEVICE(0x4551, info), \ INTEL_VGA_DEVICE(0x4541, info), \ INTEL_VGA_DEVICE(0x4E71, info), \ + INTEL_VGA_DEVICE(0x4557, info), \ + INTEL_VGA_DEVICE(0x4555, info), \ INTEL_VGA_DEVICE(0x4E61, info), \ + INTEL_VGA_DEVICE(0x4E57, info), \ + INTEL_VGA_DEVICE(0x4E55, info), \ INTEL_VGA_DEVICE(0x4E51, info) /* TGL */ @@ -605,4 +609,13 @@ INTEL_VGA_DEVICE(0x9AD9, info), \ INTEL_VGA_DEVICE(0x9AF8, info) +/* RKL */ +#define INTEL_RKL_IDS(info) \ + INTEL_VGA_DEVICE(0x4C80, info), \ + INTEL_VGA_DEVICE(0x4C8A, info), \ + INTEL_VGA_DEVICE(0x4C8B, info), \ + INTEL_VGA_DEVICE(0x4C8C, info), \ + INTEL_VGA_DEVICE(0x4C90, info), \ + INTEL_VGA_DEVICE(0x4C9A, info) + #endif /* _I915_PCIIDS_H */ -- 2.27.0 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH] drm/mst: Fix possible NULL pointer dereference in drm_dp_mst_process_up_req()
According to DP specification, DP_SINK_EVENT_NOTIFY is also a broadcast message but as this function only handles DP_CONNECTION_STATUS_NOTIFY I will only make the static analyzer that caught this issue happy by not calling drm_dp_get_mst_branch_device_by_guid() with a NULL guid, causing drm_dp_mst_process_up_req() to return in the "if (!mstb)" right bellow. Fixes: 9408cc94eb04 ("drm/dp_mst: Handle UP requests asynchronously") Cc: Lyude Paul Cc: Sean Paul Signed-off-by: José Roberto de Souza --- drivers/gpu/drm/drm_dp_mst_topology.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/drm_dp_mst_topology.c b/drivers/gpu/drm/drm_dp_mst_topology.c index 23cf46bfef74..a811247cecfe 100644 --- a/drivers/gpu/drm/drm_dp_mst_topology.c +++ b/drivers/gpu/drm/drm_dp_mst_topology.c @@ -3829,7 +3829,8 @@ drm_dp_mst_process_up_req(struct drm_dp_mst_topology_mgr *mgr, else if (msg->req_type == DP_RESOURCE_STATUS_NOTIFY) guid = msg->u.resource_stat.guid; - mstb = drm_dp_get_mst_branch_device_by_guid(mgr, guid); + if (guid) + mstb = drm_dp_get_mst_branch_device_by_guid(mgr, guid); } else { mstb = drm_dp_get_mst_branch_device(mgr, hdr->lct, hdr->rad); } -- 2.25.0 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH v2 1/2] drm/i915/dc3co: Do the full calculation of DC3CO exit only once
This will calculaet the DC3CO exit delay only once per full modeset. Cc: Imre Deak Cc: Anshuman Gupta Reviewed-by: Anshuman Gupta Signed-off-by: José Roberto de Souza --- drivers/gpu/drm/i915/display/intel_psr.c | 10 -- 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_psr.c b/drivers/gpu/drm/i915/display/intel_psr.c index 7f4056057f0c..fdd7f93953b1 100644 --- a/drivers/gpu/drm/i915/display/intel_psr.c +++ b/drivers/gpu/drm/i915/display/intel_psr.c @@ -802,7 +802,9 @@ static void intel_psr_enable_locked(struct drm_i915_private *dev_priv, dev_priv->psr.busy_frontbuffer_bits = 0; dev_priv->psr.pipe = to_intel_crtc(crtc_state->uapi.crtc)->pipe; dev_priv->psr.dc3co_enabled = !!crtc_state->dc3co_exitline; - dev_priv->psr.dc3co_exit_delay = intel_get_frame_time_us(crtc_state); + /* DC5/DC6 required idle frames = 6 */ + val = usecs_to_jiffies(intel_get_frame_time_us(crtc_state) * 6); + dev_priv->psr.dc3co_exit_delay = val; dev_priv->psr.transcoder = crtc_state->cpu_transcoder; /* @@ -1277,8 +1279,6 @@ static void tgl_dc3co_flush(struct drm_i915_private *dev_priv, unsigned int frontbuffer_bits, enum fb_op_origin origin) { - u32 delay; - mutex_lock(_priv->psr.lock); if (!dev_priv->psr.dc3co_enabled) @@ -1296,10 +1296,8 @@ tgl_dc3co_flush(struct drm_i915_private *dev_priv, goto unlock; tgl_psr2_enable_dc3co(dev_priv); - /* DC5/DC6 required idle frames = 6 */ - delay = 6 * dev_priv->psr.dc3co_exit_delay; mod_delayed_work(system_wq, _priv->psr.idle_work, -usecs_to_jiffies(delay)); +dev_priv->psr.dc3co_exit_delay); unlock: mutex_unlock(_priv->psr.lock); -- 2.25.0 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH v2 2/2] drm/i915/dc3co: Avoid full modeset when EXITLINE needs to be changed
A recent change in BSpec allow us to change EXTLINE while transcoder is enabled so this allow us to change it even when doing the first fastset after taking over previous hardware state set by BIOS. BIOS don't enable PSR, so if sink supports PSR it will be enabled on the first fastset, so moving the EXTLINE compute and set to PSR flows allow us to simplfy a bunch of code. This will save a lot of time in all the IGT tests that uses CRC, as when PSR2 is enabled CRCs are not generated, so we switch to PSR1, so the previous code would compute dc3co_exitline=0 causing a full modeset that would shutdown pipe, enable and train link. v2: only programming EXTLINE when DC3CO is enabled BSpec: 49196 Cc: Imre Deak Cc: Anshuman Gupta Signed-off-by: José Roberto de Souza --- drivers/gpu/drm/i915/display/intel_ddi.c | 86 drivers/gpu/drm/i915/display/intel_display.c | 1 - drivers/gpu/drm/i915/display/intel_psr.c | 46 +++ 3 files changed, 46 insertions(+), 87 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c index bbf1c0a243a2..e52c3cae2965 100644 --- a/drivers/gpu/drm/i915/display/intel_ddi.c +++ b/drivers/gpu/drm/i915/display/intel_ddi.c @@ -3344,86 +3344,6 @@ static void intel_ddi_disable_fec_state(struct intel_encoder *encoder, POSTING_READ(intel_dp->regs.dp_tp_ctl); } -static void -tgl_clear_psr2_transcoder_exitline(const struct intel_crtc_state *cstate) -{ - struct drm_i915_private *dev_priv = to_i915(cstate->uapi.crtc->dev); - u32 val; - - if (!cstate->dc3co_exitline) - return; - - val = I915_READ(EXITLINE(cstate->cpu_transcoder)); - val &= ~(EXITLINE_MASK | EXITLINE_ENABLE); - I915_WRITE(EXITLINE(cstate->cpu_transcoder), val); -} - -static void -tgl_set_psr2_transcoder_exitline(const struct intel_crtc_state *cstate) -{ - u32 val, exit_scanlines; - struct drm_i915_private *dev_priv = to_i915(cstate->uapi.crtc->dev); - - if (!cstate->dc3co_exitline) - return; - - exit_scanlines = cstate->dc3co_exitline; - exit_scanlines <<= EXITLINE_SHIFT; - val = I915_READ(EXITLINE(cstate->cpu_transcoder)); - val &= ~(EXITLINE_MASK | EXITLINE_ENABLE); - val |= exit_scanlines; - val |= EXITLINE_ENABLE; - I915_WRITE(EXITLINE(cstate->cpu_transcoder), val); -} - -static void tgl_dc3co_exitline_compute_config(struct intel_encoder *encoder, - struct intel_crtc_state *cstate) -{ - u32 exit_scanlines; - struct drm_i915_private *dev_priv = to_i915(cstate->uapi.crtc->dev); - u32 crtc_vdisplay = cstate->hw.adjusted_mode.crtc_vdisplay; - - cstate->dc3co_exitline = 0; - - if (!(dev_priv->csr.allowed_dc_mask & DC_STATE_EN_DC3CO)) - return; - - /* B.Specs:49196 DC3CO only works with pipeA and DDIA.*/ - if (to_intel_crtc(cstate->uapi.crtc)->pipe != PIPE_A || - encoder->port != PORT_A) - return; - - if (!cstate->has_psr2 || !cstate->hw.active) - return; - - /* -* DC3CO Exit time 200us B.Spec 49196 -* PSR2 transcoder Early Exit scanlines = ROUNDUP(200 / line time) + 1 -*/ - exit_scanlines = - intel_usecs_to_scanlines(>hw.adjusted_mode, 200) + 1; - - if (WARN_ON(exit_scanlines > crtc_vdisplay)) - return; - - cstate->dc3co_exitline = crtc_vdisplay - exit_scanlines; - DRM_DEBUG_KMS("DC3CO exit scanlines %d\n", cstate->dc3co_exitline); -} - -static void tgl_dc3co_exitline_get_config(struct intel_crtc_state *crtc_state) -{ - u32 val; - struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev); - - if (INTEL_GEN(dev_priv) < 12) - return; - - val = I915_READ(EXITLINE(crtc_state->cpu_transcoder)); - - if (val & EXITLINE_ENABLE) - crtc_state->dc3co_exitline = val & EXITLINE_MASK; -} - static void tgl_ddi_pre_enable_dp(struct intel_encoder *encoder, const struct intel_crtc_state *crtc_state, const struct drm_connector_state *conn_state) @@ -3436,7 +3356,6 @@ static void tgl_ddi_pre_enable_dp(struct intel_encoder *encoder, int level = intel_ddi_dp_level(intel_dp); enum transcoder transcoder = crtc_state->cpu_transcoder; - tgl_set_psr2_transcoder_exitline(crtc_state); intel_dp_set_link_params(intel_dp, crtc_state->port_clock, crtc_state->lane_count, is_mst); @@ -3822,7 +3741,6 @@ static void intel_ddi_post_disable_dp(struct intel_encoder *encoder, dig_port->ddi_io_power_domain); int
[PATCH 2/4] drm/mst: Some style improvements in drm_dp_mst_topology_mgr_set_mst()
Removing this lose code block and removing unnecessary bracket. Cc: Lyude Paul Signed-off-by: José Roberto de Souza --- drivers/gpu/drm/drm_dp_mst_topology.c | 14 ++ 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/drm_dp_mst_topology.c b/drivers/gpu/drm/drm_dp_mst_topology.c index 38bf111e5f9b..e3a22362aaf2 100644 --- a/drivers/gpu/drm/drm_dp_mst_topology.c +++ b/drivers/gpu/drm/drm_dp_mst_topology.c @@ -3491,6 +3491,8 @@ int drm_dp_mst_topology_mgr_set_mst(struct drm_dp_mst_topology_mgr *mgr, bool ms mgr->mst_state = mst_state; /* set the device into MST mode */ if (mst_state) { + struct drm_dp_payload reset_pay; + WARN_ON(mgr->mst_primary); /* get dpcd info */ @@ -3521,16 +3523,12 @@ int drm_dp_mst_topology_mgr_set_mst(struct drm_dp_mst_topology_mgr *mgr, bool ms ret = drm_dp_dpcd_writeb(mgr->aux, DP_MSTM_CTRL, DP_MST_EN | DP_UP_REQ_EN | DP_UPSTREAM_IS_SRC); - if (ret < 0) { + if (ret < 0) goto out_unlock; - } - { - struct drm_dp_payload reset_pay; - reset_pay.start_slot = 0; - reset_pay.num_slots = 0x3f; - drm_dp_dpcd_write_payload(mgr, 0, _pay); - } + reset_pay.start_slot = 0; + reset_pay.num_slots = 0x3f; + drm_dp_dpcd_write_payload(mgr, 0, _pay); queue_work(system_long_wq, >work); -- 2.25.0 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH 1/4] drm/mst: Don't do atomic checks over disabled managers
5 [ 306.054647] hardirqs last enabled at (77505): [] _raw_spin_unlock_irqrestore+0x47/0x60 [ 306.064270] hardirqs last disabled at (77504): [] _raw_spin_lock_irqsave+0xf/0x50 [ 306.073404] softirqs last enabled at (77402): [] __do_softirq+0x389/0x47f [ 306.081885] softirqs last disabled at (77395): [] irq_exit+0xa9/0xc0 [ 306.089859] CPU: 3 PID: 183 Comm: kworker/3:2 Tainted: G D 5.5.0-rc6+ #1404 [ 306.098167] Hardware name: Intel Corporation Ice Lake Client Platform/IceLake U DDR4 SODIMM PD RVP TLC, BIOS ICLSFWR1.R00.3201.A00.1905140358 05/14/2019 [ 306.111882] Workqueue: events drm_dp_delayed_destroy_work [ 306.117314] Call Trace: [ 306.119780] dump_stack+0x71/0xa0 [ 306.123135] ___might_sleep.cold+0xf7/0x10b [ 306.127399] exit_signals+0x2b/0x360 [ 306.131014] do_exit+0xa7/0xc70 [ 306.134189] ? kthread+0x100/0x140 [ 306.137615] rewind_stack_do_exit+0x17/0x20 Fixes: cd82d82cbc04 ("drm/dp_mst: Add branch bandwidth validation to MST atomic check") Cc: Mikita Lipski Cc: Alex Deucher Cc: Lyude Paul Signed-off-by: José Roberto de Souza --- drivers/gpu/drm/drm_dp_mst_topology.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/gpu/drm/drm_dp_mst_topology.c b/drivers/gpu/drm/drm_dp_mst_topology.c index 4b74193b89ce..38bf111e5f9b 100644 --- a/drivers/gpu/drm/drm_dp_mst_topology.c +++ b/drivers/gpu/drm/drm_dp_mst_topology.c @@ -5034,6 +5034,9 @@ int drm_dp_mst_atomic_check(struct drm_atomic_state *state) int i, ret = 0; for_each_new_mst_mgr_in_state(state, mgr, mst_state, i) { + if (!mgr->mst_state) + continue; + ret = drm_dp_mst_atomic_check_vcpi_alloc_limit(mgr, mst_state); if (ret) break; -- 2.25.0 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH 4/4] drm/i915/display: Set TRANS_DDI_MODE_SELECT to default value when disabling TRANS_DDI
TGL timeouts when disabling MST transcoder and fifo underruns over MST transcoders are fixed when setting TRANS_DDI_MODE_SELECT to 0(HDMI mode) during the disable sequence. Although BSpec disable sequence don't require this step it is a harmless change and it is also done by Windows driver. Anyhow HW team was notified about that but it can take some time to documentation to be updated. A case that always lead to those issues is: - do a modeset enabling pipe A and pipe B in the same MST stream leaving A as master - disable pipe A, promote B as master doing a full modeset in A - enable pipe A, changing the master transcoder back to A(doing a full modeset in B) - Pow: underruns and timeouts The transcoders involved will only work again when complete disabled and their power wells turned off causing a reset in their registers. Cc: Ville Syrjälä Cc: Matt Roper Signed-off-by: José Roberto de Souza --- drivers/gpu/drm/i915/display/intel_ddi.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c index 32ea3c7e8b62..82e90f271974 100644 --- a/drivers/gpu/drm/i915/display/intel_ddi.c +++ b/drivers/gpu/drm/i915/display/intel_ddi.c @@ -1997,6 +1997,7 @@ void intel_ddi_disable_transcoder_func(const struct intel_crtc_state *crtc_state val = I915_READ(TRANS_DDI_FUNC_CTL(cpu_transcoder)); val &= ~TRANS_DDI_FUNC_ENABLE; + val &= ~TRANS_DDI_MODE_SELECT_MASK; if (INTEL_GEN(dev_priv) >= 12) { if (!intel_dp_mst_is_master_trans(crtc_state)) -- 2.25.0 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH 3/4] drm/i915/display: Remove useless call intel_dp_mst_encoder_cleanup()
This is a eDP function and it will always returns true for non-eDP ports. Signed-off-by: José Roberto de Souza --- drivers/gpu/drm/i915/display/intel_dp.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index 4074d83b1a5f..a50b5b6dd009 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -7537,7 +7537,6 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port, if (!intel_edp_init_connector(intel_dp, intel_connector)) { intel_dp_aux_fini(intel_dp); - intel_dp_mst_encoder_cleanup(intel_dig_port); goto fail; } -- 2.25.0 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH v2 libdrm] intel: sync i915_pciids.h with kernel
Changes: 651cc835d5f6 ("drm/i915: Add new EHL/JSL PCI ids") b6a8781a447c ("drm/i915/cml: Remove unsupport PCI ID") 8717c6b7414f ("drm/i915/cml: Separate U series pci id from origianl list.") v2: added the latest CML changes Cc: James Ausmus Cc: Matt Roper Cc: Lucas De Marchi Reviewed-by: Matt Roper (v1 EHL/JSL changes) Signed-off-by: José Roberto de Souza --- intel/i915_pciids.h | 31 ++- 1 file changed, 18 insertions(+), 13 deletions(-) diff --git a/intel/i915_pciids.h b/intel/i915_pciids.h index b1f66b11..1d2c1221 100644 --- a/intel/i915_pciids.h +++ b/intel/i915_pciids.h @@ -446,23 +446,18 @@ /* CML GT1 */ #define INTEL_CML_GT1_IDS(info)\ - INTEL_VGA_DEVICE(0x9B21, info), \ - INTEL_VGA_DEVICE(0x9BAA, info), \ - INTEL_VGA_DEVICE(0x9BAB, info), \ - INTEL_VGA_DEVICE(0x9BAC, info), \ - INTEL_VGA_DEVICE(0x9BA0, info), \ INTEL_VGA_DEVICE(0x9BA5, info), \ INTEL_VGA_DEVICE(0x9BA8, info), \ INTEL_VGA_DEVICE(0x9BA4, info), \ INTEL_VGA_DEVICE(0x9BA2, info) +#define INTEL_CML_U_GT1_IDS(info) \ + INTEL_VGA_DEVICE(0x9B21, info), \ + INTEL_VGA_DEVICE(0x9BAA, info), \ + INTEL_VGA_DEVICE(0x9BAC, info) + /* CML GT2 */ #define INTEL_CML_GT2_IDS(info)\ - INTEL_VGA_DEVICE(0x9B41, info), \ - INTEL_VGA_DEVICE(0x9BCA, info), \ - INTEL_VGA_DEVICE(0x9BCB, info), \ - INTEL_VGA_DEVICE(0x9BCC, info), \ - INTEL_VGA_DEVICE(0x9BC0, info), \ INTEL_VGA_DEVICE(0x9BC5, info), \ INTEL_VGA_DEVICE(0x9BC8, info), \ INTEL_VGA_DEVICE(0x9BC4, info), \ @@ -471,6 +466,11 @@ INTEL_VGA_DEVICE(0x9BE6, info), \ INTEL_VGA_DEVICE(0x9BF6, info) +#define INTEL_CML_U_GT2_IDS(info) \ + INTEL_VGA_DEVICE(0x9B41, info), \ + INTEL_VGA_DEVICE(0x9BCA, info), \ + INTEL_VGA_DEVICE(0x9BCC, info) + #define INTEL_KBL_IDS(info) \ INTEL_KBL_GT1_IDS(info), \ INTEL_KBL_GT2_IDS(info), \ @@ -536,7 +536,9 @@ INTEL_WHL_U_GT3_IDS(info), \ INTEL_AML_CFL_GT2_IDS(info), \ INTEL_CML_GT1_IDS(info), \ - INTEL_CML_GT2_IDS(info) + INTEL_CML_GT2_IDS(info), \ + INTEL_CML_U_GT1_IDS(info), \ + INTEL_CML_U_GT2_IDS(info) /* CNL */ #define INTEL_CNL_PORT_F_IDS(info) \ @@ -579,12 +581,15 @@ INTEL_VGA_DEVICE(0x8A51, info), \ INTEL_VGA_DEVICE(0x8A5D, info) -/* EHL */ +/* EHL/JSL */ #define INTEL_EHL_IDS(info) \ INTEL_VGA_DEVICE(0x4500, info), \ INTEL_VGA_DEVICE(0x4571, info), \ INTEL_VGA_DEVICE(0x4551, info), \ - INTEL_VGA_DEVICE(0x4541, info) + INTEL_VGA_DEVICE(0x4541, info), \ + INTEL_VGA_DEVICE(0x4E71, info), \ + INTEL_VGA_DEVICE(0x4E61, info), \ + INTEL_VGA_DEVICE(0x4E51, info) /* TGL */ #define INTEL_TGL_12_IDS(info) \ -- 2.24.1 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH libdrm] intel: sync i915_pciids.h with kernel
It is missing the new EHL/JSL PCI ids added in commit 651cc835d5f6 ("drm/i915: Add new EHL/JSL PCI ids") Cc: James Ausmus Cc: Matt Roper Signed-off-by: José Roberto de Souza --- intel/i915_pciids.h | 7 +-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/intel/i915_pciids.h b/intel/i915_pciids.h index b1f66b11..3e26a917 100644 --- a/intel/i915_pciids.h +++ b/intel/i915_pciids.h @@ -579,12 +579,15 @@ INTEL_VGA_DEVICE(0x8A51, info), \ INTEL_VGA_DEVICE(0x8A5D, info) -/* EHL */ +/* EHL/JSL */ #define INTEL_EHL_IDS(info) \ INTEL_VGA_DEVICE(0x4500, info), \ INTEL_VGA_DEVICE(0x4571, info), \ INTEL_VGA_DEVICE(0x4551, info), \ - INTEL_VGA_DEVICE(0x4541, info) + INTEL_VGA_DEVICE(0x4541, info), \ + INTEL_VGA_DEVICE(0x4E71, info), \ + INTEL_VGA_DEVICE(0x4E61, info), \ + INTEL_VGA_DEVICE(0x4E51, info) /* TGL */ #define INTEL_TGL_12_IDS(info) \ -- 2.24.0 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH CI 1/2] drm/connector: Share with non-atomic drivers the function to get the single encoder
This 3 non-atomic drivers all have the same function getting the only encoder available in the connector, also atomic drivers have this fallback. So moving it a common place and sharing between atomic and non-atomic drivers. While at it I also removed the mention of drm_atomic_helper_best_encoder() that was renamed in commit 297e30b5d9b6 ("drm/atomic-helper: Unexport drm_atomic_helper_best_encoder"). v3: moving drm_connector_get_single_encoder to drm_kms_helper module Reviewed-by: Laurent Pinchart Reviewed-by: Ville Syrjälä Suggested-by: Ville Syrjälä Cc: Ville Syrjälä Cc: Daniel Vetter Cc: Laurent Pinchart Cc: dri-devel@lists.freedesktop.org Cc: intel-...@lists.freedesktop.org Signed-off-by: José Roberto de Souza --- drivers/gpu/drm/ast/ast_mode.c | 12 drivers/gpu/drm/drm_atomic_helper.c| 15 ++- drivers/gpu/drm/drm_crtc_helper.c | 17 - drivers/gpu/drm/drm_crtc_helper_internal.h | 3 +++ drivers/gpu/drm/mgag200/mgag200_mode.c | 11 --- drivers/gpu/drm/udl/udl_connector.c| 8 include/drm/drm_modeset_helper_vtables.h | 7 +++ 7 files changed, 24 insertions(+), 49 deletions(-) diff --git a/drivers/gpu/drm/ast/ast_mode.c b/drivers/gpu/drm/ast/ast_mode.c index d349c721501c..eef95e1af06b 100644 --- a/drivers/gpu/drm/ast/ast_mode.c +++ b/drivers/gpu/drm/ast/ast_mode.c @@ -687,17 +687,6 @@ static void ast_encoder_destroy(struct drm_encoder *encoder) kfree(encoder); } - -static struct drm_encoder *ast_best_single_encoder(struct drm_connector *connector) -{ - int enc_id = connector->encoder_ids[0]; - /* pick the encoder ids */ - if (enc_id) - return drm_encoder_find(connector->dev, NULL, enc_id); - return NULL; -} - - static const struct drm_encoder_funcs ast_enc_funcs = { .destroy = ast_encoder_destroy, }; @@ -847,7 +836,6 @@ static void ast_connector_destroy(struct drm_connector *connector) static const struct drm_connector_helper_funcs ast_connector_helper_funcs = { .mode_valid = ast_mode_valid, .get_modes = ast_get_modes, - .best_encoder = ast_best_single_encoder, }; static const struct drm_connector_funcs ast_connector_funcs = { diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index 4706439fb490..9d7e4da6c292 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -97,17 +97,6 @@ drm_atomic_helper_plane_changed(struct drm_atomic_state *state, } } -/* - * For connectors that support multiple encoders, either the - * .atomic_best_encoder() or .best_encoder() operation must be implemented. - */ -static struct drm_encoder * -pick_single_encoder_for_connector(struct drm_connector *connector) -{ - WARN_ON(connector->encoder_ids[1]); - return drm_encoder_find(connector->dev, NULL, connector->encoder_ids[0]); -} - static int handle_conflicting_encoders(struct drm_atomic_state *state, bool disable_conflicting_encoders) { @@ -135,7 +124,7 @@ static int handle_conflicting_encoders(struct drm_atomic_state *state, else if (funcs->best_encoder) new_encoder = funcs->best_encoder(connector); else - new_encoder = pick_single_encoder_for_connector(connector); + new_encoder = drm_connector_get_single_encoder(connector); if (new_encoder) { if (encoder_mask & drm_encoder_mask(new_encoder)) { @@ -359,7 +348,7 @@ update_connector_routing(struct drm_atomic_state *state, else if (funcs->best_encoder) new_encoder = funcs->best_encoder(connector); else - new_encoder = pick_single_encoder_for_connector(connector); + new_encoder = drm_connector_get_single_encoder(connector); if (!new_encoder) { DRM_DEBUG_ATOMIC("No suitable encoder found for [CONNECTOR:%d:%s]\n", diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c index a51824a7e7c1..4a7447a53cea 100644 --- a/drivers/gpu/drm/drm_crtc_helper.c +++ b/drivers/gpu/drm/drm_crtc_helper.c @@ -460,6 +460,17 @@ drm_crtc_helper_disable(struct drm_crtc *crtc) __drm_helper_disable_unused_functions(dev); } +/* + * For connectors that support multiple encoders, either the + * .atomic_best_encoder() or .best_encoder() operation must be implemented. + */ +struct drm_encoder * +drm_connector_get_single_encoder(struct drm_connector *connector) +{ + WARN_ON(connector->encoder_ids[1]); + return drm_encoder_find(connector->dev, NULL, connector->encoder_ids[0]); +} + /** * drm_crtc_helper_set_config - set a new config from userspace * @set: mode set configuration @@ -625,7 +636,11 @@ int drm_crtc_helper_set_
[PATCH CI 2/2] 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). To more effiently do that lets switch from an array of encoder ids to bitmask. v2: Fixing missed return on amdgpu_dm_connector_to_encoder() Suggested-by: Ville Syrjälä Cc: Ville Syrjälä Cc: Alex Deucher Cc: dri-devel@lists.freedesktop.org Cc: intel-...@lists.freedesktop.org Cc: nouv...@lists.freedesktop.org Cc: amd-...@lists.freedesktop.org Reviewed-by: Ville Syrjälä Signed-off-by: Dhinakaran Pandiyan Signed-off-by: José Roberto de Souza --- .../gpu/drm/amd/amdgpu/amdgpu_connectors.c| 23 +- drivers/gpu/drm/amd/amdgpu/dce_virtual.c | 5 ++- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 8 - drivers/gpu/drm/drm_client_modeset.c | 3 +- drivers/gpu/drm/drm_connector.c | 31 +-- drivers/gpu/drm/drm_crtc_helper.c | 9 -- drivers/gpu/drm/drm_probe_helper.c| 3 +- drivers/gpu/drm/nouveau/dispnv04/disp.c | 2 +- drivers/gpu/drm/nouveau/dispnv50/disp.c | 2 +- drivers/gpu/drm/nouveau/nouveau_connector.c | 7 ++--- drivers/gpu/drm/radeon/radeon_connectors.c| 27 ++-- include/drm/drm_connector.h | 18 +-- 12 files changed, 55 insertions(+), 83 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c index ece55c8fa673..d8729285f731 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c @@ -217,11 +217,10 @@ amdgpu_connector_update_scratch_regs(struct drm_connector *connector, struct drm_encoder *encoder; const struct drm_connector_helper_funcs *connector_funcs = connector->helper_private; bool connected; - int i; best_encoder = connector_funcs->best_encoder(connector); - drm_connector_for_each_possible_encoder(connector, encoder, i) { + drm_connector_for_each_possible_encoder(connector, encoder) { if ((encoder == best_encoder) && (status == connector_status_connected)) connected = true; else @@ -236,9 +235,8 @@ amdgpu_connector_find_encoder(struct drm_connector *connector, int encoder_type) { struct drm_encoder *encoder; - int i; - drm_connector_for_each_possible_encoder(connector, encoder, i) { + drm_connector_for_each_possible_encoder(connector, encoder) { if (encoder->encoder_type == encoder_type) return encoder; } @@ -347,10 +345,9 @@ static struct drm_encoder * amdgpu_connector_best_single_encoder(struct drm_connector *connector) { struct drm_encoder *encoder; - int i; /* pick the first one */ - drm_connector_for_each_possible_encoder(connector, encoder, i) + drm_connector_for_each_possible_encoder(connector, encoder) return encoder; return NULL; @@ -1065,9 +1062,8 @@ amdgpu_connector_dvi_detect(struct drm_connector *connector, bool force) /* find analog encoder */ if (amdgpu_connector->dac_load_detect) { struct drm_encoder *encoder; - int i; - drm_connector_for_each_possible_encoder(connector, encoder, i) { + drm_connector_for_each_possible_encoder(connector, encoder) { if (encoder->encoder_type != DRM_MODE_ENCODER_DAC && encoder->encoder_type != DRM_MODE_ENCODER_TVDAC) continue; @@ -1117,9 +1113,8 @@ amdgpu_connector_dvi_encoder(struct drm_connector *connector) { struct amdgpu_connector *amdgpu_connector = to_amdgpu_connector(connector); struct drm_encoder *encoder; - int i; - drm_connector_for_each_possible_encoder(connector, encoder, i) { + drm_connector_for_each_possible_encoder(connector, encoder) { if (amdgpu_connector->use_digital == true) { if (encoder->encoder_type == DRM_MODE_ENCODER_TMDS) return encoder; @@ -1134,7 +1129,7 @@ amdgpu_connector_dvi_encoder(struct drm_connector *connector) /* then check use digitial */ /* pick the first one */ - drm_connector_for_each_possible_encoder(connector, encoder, i) + drm_connector_for_each_possible_encoder(connector, encoder) return encoder; return NULL; @@ -1271,9 +1266,8 @@ u16 amdgpu_connector_encoder_get_dp_bridge_encoder_id(struct drm_connector *conn { struct drm_encoder *encoder; struct amdgpu_encoder *amdgpu_encoder; - int i; - drm_connector_for_each_possible_encoder(connector, encoder, i) { + drm_connector_for_
[PATCH 1/2] drm/connector: Share with non-atomic drivers the function to get the single encoder
This 3 non-atomic drivers all have the same function getting the only encoder available in the connector, also atomic drivers have this fallback. So moving it a common place and sharing between atomic and non-atomic drivers. While at it I also removed the mention of drm_atomic_helper_best_encoder() that was renamed in commit 297e30b5d9b6 ("drm/atomic-helper: Unexport drm_atomic_helper_best_encoder"). v3: moving drm_connector_get_single_encoder to drm_kms_helper module Suggested-by: Ville Syrjälä Cc: Ville Syrjälä Cc: Daniel Vetter Cc: Laurent Pinchart Cc: dri-devel@lists.freedesktop.org Cc: intel-...@lists.freedesktop.org Signed-off-by: José Roberto de Souza --- drivers/gpu/drm/ast/ast_mode.c | 12 drivers/gpu/drm/drm_atomic_helper.c| 15 ++- drivers/gpu/drm/drm_crtc_helper.c | 17 - drivers/gpu/drm/drm_crtc_helper_internal.h | 3 +++ drivers/gpu/drm/mgag200/mgag200_mode.c | 11 --- drivers/gpu/drm/udl/udl_connector.c| 8 include/drm/drm_modeset_helper_vtables.h | 6 +++--- 7 files changed, 24 insertions(+), 48 deletions(-) diff --git a/drivers/gpu/drm/ast/ast_mode.c b/drivers/gpu/drm/ast/ast_mode.c index d349c721501c..eef95e1af06b 100644 --- a/drivers/gpu/drm/ast/ast_mode.c +++ b/drivers/gpu/drm/ast/ast_mode.c @@ -687,17 +687,6 @@ static void ast_encoder_destroy(struct drm_encoder *encoder) kfree(encoder); } - -static struct drm_encoder *ast_best_single_encoder(struct drm_connector *connector) -{ - int enc_id = connector->encoder_ids[0]; - /* pick the encoder ids */ - if (enc_id) - return drm_encoder_find(connector->dev, NULL, enc_id); - return NULL; -} - - static const struct drm_encoder_funcs ast_enc_funcs = { .destroy = ast_encoder_destroy, }; @@ -847,7 +836,6 @@ static void ast_connector_destroy(struct drm_connector *connector) static const struct drm_connector_helper_funcs ast_connector_helper_funcs = { .mode_valid = ast_mode_valid, .get_modes = ast_get_modes, - .best_encoder = ast_best_single_encoder, }; static const struct drm_connector_funcs ast_connector_funcs = { diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index 4706439fb490..9d7e4da6c292 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -97,17 +97,6 @@ drm_atomic_helper_plane_changed(struct drm_atomic_state *state, } } -/* - * For connectors that support multiple encoders, either the - * .atomic_best_encoder() or .best_encoder() operation must be implemented. - */ -static struct drm_encoder * -pick_single_encoder_for_connector(struct drm_connector *connector) -{ - WARN_ON(connector->encoder_ids[1]); - return drm_encoder_find(connector->dev, NULL, connector->encoder_ids[0]); -} - static int handle_conflicting_encoders(struct drm_atomic_state *state, bool disable_conflicting_encoders) { @@ -135,7 +124,7 @@ static int handle_conflicting_encoders(struct drm_atomic_state *state, else if (funcs->best_encoder) new_encoder = funcs->best_encoder(connector); else - new_encoder = pick_single_encoder_for_connector(connector); + new_encoder = drm_connector_get_single_encoder(connector); if (new_encoder) { if (encoder_mask & drm_encoder_mask(new_encoder)) { @@ -359,7 +348,7 @@ update_connector_routing(struct drm_atomic_state *state, else if (funcs->best_encoder) new_encoder = funcs->best_encoder(connector); else - new_encoder = pick_single_encoder_for_connector(connector); + new_encoder = drm_connector_get_single_encoder(connector); if (!new_encoder) { DRM_DEBUG_ATOMIC("No suitable encoder found for [CONNECTOR:%d:%s]\n", diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c index a51824a7e7c1..4a7447a53cea 100644 --- a/drivers/gpu/drm/drm_crtc_helper.c +++ b/drivers/gpu/drm/drm_crtc_helper.c @@ -460,6 +460,17 @@ drm_crtc_helper_disable(struct drm_crtc *crtc) __drm_helper_disable_unused_functions(dev); } +/* + * For connectors that support multiple encoders, either the + * .atomic_best_encoder() or .best_encoder() operation must be implemented. + */ +struct drm_encoder * +drm_connector_get_single_encoder(struct drm_connector *connector) +{ + WARN_ON(connector->encoder_ids[1]); + return drm_encoder_find(connector->dev, NULL, connector->encoder_ids[0]); +} + /** * drm_crtc_helper_set_config - set a new config from userspace * @set: mode set configuration @@ -625,7 +636,11 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set, new_encoder
[PATCH 2/2] 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). To more effiently do that lets switch from an array of encoder ids to bitmask. v2: Fixing missed return on amdgpu_dm_connector_to_encoder() Suggested-by: Ville Syrjälä Cc: Ville Syrjälä Cc: Alex Deucher Cc: dri-devel@lists.freedesktop.org Cc: intel-...@lists.freedesktop.org Cc: nouv...@lists.freedesktop.org Cc: amd-...@lists.freedesktop.org Reviewed-by: Ville Syrjälä Signed-off-by: Dhinakaran Pandiyan Signed-off-by: José Roberto de Souza --- .../gpu/drm/amd/amdgpu/amdgpu_connectors.c| 23 +- drivers/gpu/drm/amd/amdgpu/dce_virtual.c | 5 ++- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 8 - drivers/gpu/drm/drm_client_modeset.c | 3 +- drivers/gpu/drm/drm_connector.c | 31 +-- drivers/gpu/drm/drm_crtc_helper.c | 9 -- drivers/gpu/drm/drm_probe_helper.c| 3 +- drivers/gpu/drm/nouveau/dispnv04/disp.c | 2 +- drivers/gpu/drm/nouveau/dispnv50/disp.c | 2 +- drivers/gpu/drm/nouveau/nouveau_connector.c | 7 ++--- drivers/gpu/drm/radeon/radeon_connectors.c| 27 ++-- include/drm/drm_connector.h | 18 +-- 12 files changed, 55 insertions(+), 83 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c index ece55c8fa673..d8729285f731 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c @@ -217,11 +217,10 @@ amdgpu_connector_update_scratch_regs(struct drm_connector *connector, struct drm_encoder *encoder; const struct drm_connector_helper_funcs *connector_funcs = connector->helper_private; bool connected; - int i; best_encoder = connector_funcs->best_encoder(connector); - drm_connector_for_each_possible_encoder(connector, encoder, i) { + drm_connector_for_each_possible_encoder(connector, encoder) { if ((encoder == best_encoder) && (status == connector_status_connected)) connected = true; else @@ -236,9 +235,8 @@ amdgpu_connector_find_encoder(struct drm_connector *connector, int encoder_type) { struct drm_encoder *encoder; - int i; - drm_connector_for_each_possible_encoder(connector, encoder, i) { + drm_connector_for_each_possible_encoder(connector, encoder) { if (encoder->encoder_type == encoder_type) return encoder; } @@ -347,10 +345,9 @@ static struct drm_encoder * amdgpu_connector_best_single_encoder(struct drm_connector *connector) { struct drm_encoder *encoder; - int i; /* pick the first one */ - drm_connector_for_each_possible_encoder(connector, encoder, i) + drm_connector_for_each_possible_encoder(connector, encoder) return encoder; return NULL; @@ -1065,9 +1062,8 @@ amdgpu_connector_dvi_detect(struct drm_connector *connector, bool force) /* find analog encoder */ if (amdgpu_connector->dac_load_detect) { struct drm_encoder *encoder; - int i; - drm_connector_for_each_possible_encoder(connector, encoder, i) { + drm_connector_for_each_possible_encoder(connector, encoder) { if (encoder->encoder_type != DRM_MODE_ENCODER_DAC && encoder->encoder_type != DRM_MODE_ENCODER_TVDAC) continue; @@ -1117,9 +1113,8 @@ amdgpu_connector_dvi_encoder(struct drm_connector *connector) { struct amdgpu_connector *amdgpu_connector = to_amdgpu_connector(connector); struct drm_encoder *encoder; - int i; - drm_connector_for_each_possible_encoder(connector, encoder, i) { + drm_connector_for_each_possible_encoder(connector, encoder) { if (amdgpu_connector->use_digital == true) { if (encoder->encoder_type == DRM_MODE_ENCODER_TMDS) return encoder; @@ -1134,7 +1129,7 @@ amdgpu_connector_dvi_encoder(struct drm_connector *connector) /* then check use digitial */ /* pick the first one */ - drm_connector_for_each_possible_encoder(connector, encoder, i) + drm_connector_for_each_possible_encoder(connector, encoder) return encoder; return NULL; @@ -1271,9 +1266,8 @@ u16 amdgpu_connector_encoder_get_dp_bridge_encoder_id(struct drm_connector *conn { struct drm_encoder *encoder; struct amdgpu_encoder *amdgpu_encoder; - int i; - drm_connector_for_each_possible_encoder(connector, encoder, i) { + drm_connector_for_
[PATCH 1/2] drm/connector: Share with non-atomic drivers the function to get the single encoder
This 3 non-atomic drivers all have the same function getting the only encoder available in the connector, also atomic drivers have this fallback. So moving it a common place and sharing between atomic and non-atomic drivers. While at it I also removed the mention of drm_atomic_helper_best_encoder() that was renamed in commit 297e30b5d9b6 ("drm/atomic-helper: Unexport drm_atomic_helper_best_encoder"). Suggested-by: Ville Syrjälä Cc: Ville Syrjälä Cc: Daniel Vetter Cc: Laurent Pinchart Cc: dri-devel@lists.freedesktop.org Cc: intel-...@lists.freedesktop.org Signed-off-by: José Roberto de Souza --- drivers/gpu/drm/ast/ast_mode.c | 12 drivers/gpu/drm/drm_atomic_helper.c | 15 ++- drivers/gpu/drm/drm_connector.c | 11 +++ drivers/gpu/drm/drm_crtc_helper.c| 8 +++- drivers/gpu/drm/drm_crtc_internal.h | 2 ++ drivers/gpu/drm/mgag200/mgag200_mode.c | 11 --- drivers/gpu/drm/udl/udl_connector.c | 8 include/drm/drm_modeset_helper_vtables.h | 6 +++--- 8 files changed, 25 insertions(+), 48 deletions(-) diff --git a/drivers/gpu/drm/ast/ast_mode.c b/drivers/gpu/drm/ast/ast_mode.c index d349c721501c..eef95e1af06b 100644 --- a/drivers/gpu/drm/ast/ast_mode.c +++ b/drivers/gpu/drm/ast/ast_mode.c @@ -687,17 +687,6 @@ static void ast_encoder_destroy(struct drm_encoder *encoder) kfree(encoder); } - -static struct drm_encoder *ast_best_single_encoder(struct drm_connector *connector) -{ - int enc_id = connector->encoder_ids[0]; - /* pick the encoder ids */ - if (enc_id) - return drm_encoder_find(connector->dev, NULL, enc_id); - return NULL; -} - - static const struct drm_encoder_funcs ast_enc_funcs = { .destroy = ast_encoder_destroy, }; @@ -847,7 +836,6 @@ static void ast_connector_destroy(struct drm_connector *connector) static const struct drm_connector_helper_funcs ast_connector_helper_funcs = { .mode_valid = ast_mode_valid, .get_modes = ast_get_modes, - .best_encoder = ast_best_single_encoder, }; static const struct drm_connector_funcs ast_connector_funcs = { diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index 4706439fb490..9d7e4da6c292 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -97,17 +97,6 @@ drm_atomic_helper_plane_changed(struct drm_atomic_state *state, } } -/* - * For connectors that support multiple encoders, either the - * .atomic_best_encoder() or .best_encoder() operation must be implemented. - */ -static struct drm_encoder * -pick_single_encoder_for_connector(struct drm_connector *connector) -{ - WARN_ON(connector->encoder_ids[1]); - return drm_encoder_find(connector->dev, NULL, connector->encoder_ids[0]); -} - static int handle_conflicting_encoders(struct drm_atomic_state *state, bool disable_conflicting_encoders) { @@ -135,7 +124,7 @@ static int handle_conflicting_encoders(struct drm_atomic_state *state, else if (funcs->best_encoder) new_encoder = funcs->best_encoder(connector); else - new_encoder = pick_single_encoder_for_connector(connector); + new_encoder = drm_connector_get_single_encoder(connector); if (new_encoder) { if (encoder_mask & drm_encoder_mask(new_encoder)) { @@ -359,7 +348,7 @@ update_connector_routing(struct drm_atomic_state *state, else if (funcs->best_encoder) new_encoder = funcs->best_encoder(connector); else - new_encoder = pick_single_encoder_for_connector(connector); + new_encoder = drm_connector_get_single_encoder(connector); if (!new_encoder) { DRM_DEBUG_ATOMIC("No suitable encoder found for [CONNECTOR:%d:%s]\n", diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c index 4c766624b20d..3e2a632cf861 100644 --- a/drivers/gpu/drm/drm_connector.c +++ b/drivers/gpu/drm/drm_connector.c @@ -2334,3 +2334,14 @@ struct drm_tile_group *drm_mode_create_tile_group(struct drm_device *dev, return tg; } EXPORT_SYMBOL(drm_mode_create_tile_group); + +/* + * For connectors that support multiple encoders, either the + * .atomic_best_encoder() or .best_encoder() operation must be implemented. + */ +struct drm_encoder * +drm_connector_get_single_encoder(struct drm_connector *connector) +{ + WARN_ON(connector->encoder_ids[1]); + return drm_encoder_find(connector->dev, NULL, connector->encoder_ids[0]); +} diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c index a51824a7e7c1..a1f3c388e398 100644 --- a/drivers/gpu/drm/drm_crtc_helper.c +++ b/drivers/gpu/drm/drm_crtc_helper.c @@ -48,6 +48
[PATCH 2/2] drm/connector: Allow max possible encoders to attach to a connector
From: Dhinakaran Pandiyan 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). To more effiently do that lets switch from an array of encoder ids to bitmask. v2: Fixing missed return on amdgpu_dm_connector_to_encoder() Suggested-by: Ville Syrjälä Cc: Ville Syrjälä Cc: Alex Deucher Cc: dri-devel@lists.freedesktop.org Cc: intel-...@lists.freedesktop.org Cc: nouv...@lists.freedesktop.org Cc: amd-...@lists.freedesktop.org Reviewed-by: Ville Syrjälä Signed-off-by: Dhinakaran Pandiyan Signed-off-by: José Roberto de Souza --- .../gpu/drm/amd/amdgpu/amdgpu_connectors.c| 23 --- drivers/gpu/drm/amd/amdgpu/dce_virtual.c | 5 +-- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 8 +++- drivers/gpu/drm/drm_client_modeset.c | 3 +- drivers/gpu/drm/drm_connector.c | 40 +++ drivers/gpu/drm/drm_probe_helper.c| 3 +- drivers/gpu/drm/nouveau/dispnv04/disp.c | 2 +- drivers/gpu/drm/nouveau/dispnv50/disp.c | 2 +- drivers/gpu/drm/nouveau/nouveau_connector.c | 7 ++-- drivers/gpu/drm/radeon/radeon_connectors.c| 27 + include/drm/drm_connector.h | 18 - 11 files changed, 55 insertions(+), 83 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c index ece55c8fa673..d8729285f731 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c @@ -217,11 +217,10 @@ amdgpu_connector_update_scratch_regs(struct drm_connector *connector, struct drm_encoder *encoder; const struct drm_connector_helper_funcs *connector_funcs = connector->helper_private; bool connected; - int i; best_encoder = connector_funcs->best_encoder(connector); - drm_connector_for_each_possible_encoder(connector, encoder, i) { + drm_connector_for_each_possible_encoder(connector, encoder) { if ((encoder == best_encoder) && (status == connector_status_connected)) connected = true; else @@ -236,9 +235,8 @@ amdgpu_connector_find_encoder(struct drm_connector *connector, int encoder_type) { struct drm_encoder *encoder; - int i; - drm_connector_for_each_possible_encoder(connector, encoder, i) { + drm_connector_for_each_possible_encoder(connector, encoder) { if (encoder->encoder_type == encoder_type) return encoder; } @@ -347,10 +345,9 @@ static struct drm_encoder * amdgpu_connector_best_single_encoder(struct drm_connector *connector) { struct drm_encoder *encoder; - int i; /* pick the first one */ - drm_connector_for_each_possible_encoder(connector, encoder, i) + drm_connector_for_each_possible_encoder(connector, encoder) return encoder; return NULL; @@ -1065,9 +1062,8 @@ amdgpu_connector_dvi_detect(struct drm_connector *connector, bool force) /* find analog encoder */ if (amdgpu_connector->dac_load_detect) { struct drm_encoder *encoder; - int i; - drm_connector_for_each_possible_encoder(connector, encoder, i) { + drm_connector_for_each_possible_encoder(connector, encoder) { if (encoder->encoder_type != DRM_MODE_ENCODER_DAC && encoder->encoder_type != DRM_MODE_ENCODER_TVDAC) continue; @@ -1117,9 +1113,8 @@ amdgpu_connector_dvi_encoder(struct drm_connector *connector) { struct amdgpu_connector *amdgpu_connector = to_amdgpu_connector(connector); struct drm_encoder *encoder; - int i; - drm_connector_for_each_possible_encoder(connector, encoder, i) { + drm_connector_for_each_possible_encoder(connector, encoder) { if (amdgpu_connector->use_digital == true) { if (encoder->encoder_type == DRM_MODE_ENCODER_TMDS) return encoder; @@ -1134,7 +1129,7 @@ amdgpu_connector_dvi_encoder(struct drm_connector *connector) /* then check use digitial */ /* pick the first one */ - drm_connector_for_each_possible_encoder(connector, encoder, i) + drm_connector_for_each_possible_encoder(connector, encoder) return encoder; return NULL; @@ -1271,9 +1266,8 @@ u16 amdgpu_connector_encoder_get_dp_bridge_encoder_id(struct drm_connector *conn { struct drm_encoder *encoder; struct amdgpu_encoder *amdgpu_encoder; - int i; - drm_connector_for_each_possible_encoder(connector, encoder, i) { + drm_connector_for_each_possible_encoder(connector, e
[PATCH v2.1] drm/connector: Allow max possible encoders to attach to a connector
From: Dhinakaran Pandiyan 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). To more effiently do that lets switch from an array of encoder ids to bitmask. Also removing the best_encoder hook from the drivers that only have one encoder per connector(this ones have one encoder in the whole driver), pick_single_encoder_for_connector() will do the same job with no functional change. v2: Fixing missed return on amdgpu_dm_connector_to_encoder() Suggested-by: Ville Syrjälä Cc: Ville Syrjälä Cc: Alex Deucher Cc: dri-devel@lists.freedesktop.org Cc: intel-...@lists.freedesktop.org Cc: nouv...@lists.freedesktop.org Cc: amd-...@lists.freedesktop.org Signed-off-by: Dhinakaran Pandiyan Signed-off-by: José Roberto de Souza --- .../gpu/drm/amd/amdgpu/amdgpu_connectors.c| 23 +- drivers/gpu/drm/amd/amdgpu/dce_virtual.c | 5 ++- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 8 - drivers/gpu/drm/ast/ast_mode.c| 12 --- drivers/gpu/drm/drm_atomic_helper.c | 9 -- drivers/gpu/drm/drm_client_modeset.c | 3 +- drivers/gpu/drm/drm_connector.c | 31 +-- drivers/gpu/drm/drm_probe_helper.c| 3 +- drivers/gpu/drm/mgag200/mgag200_mode.c| 11 --- drivers/gpu/drm/nouveau/dispnv04/disp.c | 2 +- drivers/gpu/drm/nouveau/dispnv50/disp.c | 2 +- drivers/gpu/drm/nouveau/nouveau_connector.c | 7 ++--- drivers/gpu/drm/radeon/radeon_connectors.c| 27 ++-- drivers/gpu/drm/udl/udl_connector.c | 8 - include/drm/drm_connector.h | 18 +-- 15 files changed, 55 insertions(+), 114 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c index ece55c8fa673..d8729285f731 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c @@ -217,11 +217,10 @@ amdgpu_connector_update_scratch_regs(struct drm_connector *connector, struct drm_encoder *encoder; const struct drm_connector_helper_funcs *connector_funcs = connector->helper_private; bool connected; - int i; best_encoder = connector_funcs->best_encoder(connector); - drm_connector_for_each_possible_encoder(connector, encoder, i) { + drm_connector_for_each_possible_encoder(connector, encoder) { if ((encoder == best_encoder) && (status == connector_status_connected)) connected = true; else @@ -236,9 +235,8 @@ amdgpu_connector_find_encoder(struct drm_connector *connector, int encoder_type) { struct drm_encoder *encoder; - int i; - drm_connector_for_each_possible_encoder(connector, encoder, i) { + drm_connector_for_each_possible_encoder(connector, encoder) { if (encoder->encoder_type == encoder_type) return encoder; } @@ -347,10 +345,9 @@ static struct drm_encoder * amdgpu_connector_best_single_encoder(struct drm_connector *connector) { struct drm_encoder *encoder; - int i; /* pick the first one */ - drm_connector_for_each_possible_encoder(connector, encoder, i) + drm_connector_for_each_possible_encoder(connector, encoder) return encoder; return NULL; @@ -1065,9 +1062,8 @@ amdgpu_connector_dvi_detect(struct drm_connector *connector, bool force) /* find analog encoder */ if (amdgpu_connector->dac_load_detect) { struct drm_encoder *encoder; - int i; - drm_connector_for_each_possible_encoder(connector, encoder, i) { + drm_connector_for_each_possible_encoder(connector, encoder) { if (encoder->encoder_type != DRM_MODE_ENCODER_DAC && encoder->encoder_type != DRM_MODE_ENCODER_TVDAC) continue; @@ -1117,9 +1113,8 @@ amdgpu_connector_dvi_encoder(struct drm_connector *connector) { struct amdgpu_connector *amdgpu_connector = to_amdgpu_connector(connector); struct drm_encoder *encoder; - int i; - drm_connector_for_each_possible_encoder(connector, encoder, i) { + drm_connector_for_each_possible_encoder(connector, encoder) { if (amdgpu_connector->use_digital == true) { if (encoder->encoder_type == DRM_MODE_ENCODER_TMDS) return encoder; @@ -1134,7 +1129,7 @@ amdgpu_connector_dvi_encoder(struct drm_connector *connector) /* then check use digitial */ /* pick the first one */ - drm_connector_for_each_possible_encoder(connector, encoder, i) + drm_connector_for_
[PATCH v2] drm/connector: Allow max possible encoders to attach to a connector
From: Dhinakaran Pandiyan 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). To more effiently do that lets switch from an array of encoder ids to bitmask. Also removing the best_encoder hook from the drivers that only have one encoder per connector(this ones have one encoder in the whole driver), pick_single_encoder_for_connector() will do the same job with no functional change. v2: Fixing missed return on amdgpu_dm_connector_to_encoder() Suggested-by: Ville Syrjälä Cc: Ville Syrjälä Cc: Alex Deucher Cc: dri-devel@lists.freedesktop.org Cc: intel-...@lists.freedesktop.org Cc: nouv...@lists.freedesktop.org Cc: amd-...@lists.freedesktop.org Signed-off-by: Dhinakaran Pandiyan Signed-off-by: José Roberto de Souza --- .../gpu/drm/amd/amdgpu/amdgpu_connectors.c| 23 +- drivers/gpu/drm/amd/amdgpu/dce_virtual.c | 5 ++- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 6 +++- drivers/gpu/drm/ast/ast_mode.c| 12 --- drivers/gpu/drm/drm_atomic_helper.c | 9 -- drivers/gpu/drm/drm_client_modeset.c | 3 +- drivers/gpu/drm/drm_connector.c | 31 +-- drivers/gpu/drm/drm_probe_helper.c| 3 +- drivers/gpu/drm/mgag200/mgag200_mode.c| 11 --- drivers/gpu/drm/nouveau/dispnv04/disp.c | 2 +- drivers/gpu/drm/nouveau/dispnv50/disp.c | 2 +- drivers/gpu/drm/nouveau/nouveau_connector.c | 7 ++--- drivers/gpu/drm/radeon/radeon_connectors.c| 27 ++-- drivers/gpu/drm/udl/udl_connector.c | 8 - include/drm/drm_connector.h | 18 +-- 15 files changed, 53 insertions(+), 114 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c index ece55c8fa673..d8729285f731 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c @@ -217,11 +217,10 @@ amdgpu_connector_update_scratch_regs(struct drm_connector *connector, struct drm_encoder *encoder; const struct drm_connector_helper_funcs *connector_funcs = connector->helper_private; bool connected; - int i; best_encoder = connector_funcs->best_encoder(connector); - drm_connector_for_each_possible_encoder(connector, encoder, i) { + drm_connector_for_each_possible_encoder(connector, encoder) { if ((encoder == best_encoder) && (status == connector_status_connected)) connected = true; else @@ -236,9 +235,8 @@ amdgpu_connector_find_encoder(struct drm_connector *connector, int encoder_type) { struct drm_encoder *encoder; - int i; - drm_connector_for_each_possible_encoder(connector, encoder, i) { + drm_connector_for_each_possible_encoder(connector, encoder) { if (encoder->encoder_type == encoder_type) return encoder; } @@ -347,10 +345,9 @@ static struct drm_encoder * amdgpu_connector_best_single_encoder(struct drm_connector *connector) { struct drm_encoder *encoder; - int i; /* pick the first one */ - drm_connector_for_each_possible_encoder(connector, encoder, i) + drm_connector_for_each_possible_encoder(connector, encoder) return encoder; return NULL; @@ -1065,9 +1062,8 @@ amdgpu_connector_dvi_detect(struct drm_connector *connector, bool force) /* find analog encoder */ if (amdgpu_connector->dac_load_detect) { struct drm_encoder *encoder; - int i; - drm_connector_for_each_possible_encoder(connector, encoder, i) { + drm_connector_for_each_possible_encoder(connector, encoder) { if (encoder->encoder_type != DRM_MODE_ENCODER_DAC && encoder->encoder_type != DRM_MODE_ENCODER_TVDAC) continue; @@ -1117,9 +1113,8 @@ amdgpu_connector_dvi_encoder(struct drm_connector *connector) { struct amdgpu_connector *amdgpu_connector = to_amdgpu_connector(connector); struct drm_encoder *encoder; - int i; - drm_connector_for_each_possible_encoder(connector, encoder, i) { + drm_connector_for_each_possible_encoder(connector, encoder) { if (amdgpu_connector->use_digital == true) { if (encoder->encoder_type == DRM_MODE_ENCODER_TMDS) return encoder; @@ -1134,7 +1129,7 @@ amdgpu_connector_dvi_encoder(struct drm_connector *connector) /* then check use digitial */ /* pick the first one */ - drm_connector_for_each_possible_encoder(connector, encoder, i) + drm_connector_for_
[PATCH] drm/connector: Allow max possible encoders to attach to a connector
From: Dhinakaran Pandiyan 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). To more effiently do that lets switch from an array of encoder ids to bitmask. Also removing the best_encoder hook from the drivers that only have one encoder per connector(this ones have one encoder in the whole driver), pick_single_encoder_for_connector() will do the same job with no functional change. Suggested-by: Ville Syrjälä Cc: Ville Syrjälä Cc: Alex Deucher Cc: dri-devel@lists.freedesktop.org Cc: intel-...@lists.freedesktop.org Cc: nouv...@lists.freedesktop.org Cc: amd-...@lists.freedesktop.org Signed-off-by: Dhinakaran Pandiyan Signed-off-by: José Roberto de Souza --- .../gpu/drm/amd/amdgpu/amdgpu_connectors.c| 23 +- drivers/gpu/drm/amd/amdgpu/dce_virtual.c | 5 ++- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 6 +++- drivers/gpu/drm/ast/ast_mode.c| 12 --- drivers/gpu/drm/drm_atomic_helper.c | 9 -- drivers/gpu/drm/drm_client_modeset.c | 3 +- drivers/gpu/drm/drm_connector.c | 31 +-- drivers/gpu/drm/drm_probe_helper.c| 3 +- drivers/gpu/drm/mgag200/mgag200_mode.c| 11 --- drivers/gpu/drm/nouveau/dispnv04/disp.c | 2 +- drivers/gpu/drm/nouveau/dispnv50/disp.c | 2 +- drivers/gpu/drm/nouveau/nouveau_connector.c | 7 ++--- drivers/gpu/drm/radeon/radeon_connectors.c| 27 ++-- drivers/gpu/drm/udl/udl_connector.c | 8 - include/drm/drm_connector.h | 18 +-- 15 files changed, 53 insertions(+), 114 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c index ece55c8fa673..d8729285f731 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c @@ -217,11 +217,10 @@ amdgpu_connector_update_scratch_regs(struct drm_connector *connector, struct drm_encoder *encoder; const struct drm_connector_helper_funcs *connector_funcs = connector->helper_private; bool connected; - int i; best_encoder = connector_funcs->best_encoder(connector); - drm_connector_for_each_possible_encoder(connector, encoder, i) { + drm_connector_for_each_possible_encoder(connector, encoder) { if ((encoder == best_encoder) && (status == connector_status_connected)) connected = true; else @@ -236,9 +235,8 @@ amdgpu_connector_find_encoder(struct drm_connector *connector, int encoder_type) { struct drm_encoder *encoder; - int i; - drm_connector_for_each_possible_encoder(connector, encoder, i) { + drm_connector_for_each_possible_encoder(connector, encoder) { if (encoder->encoder_type == encoder_type) return encoder; } @@ -347,10 +345,9 @@ static struct drm_encoder * amdgpu_connector_best_single_encoder(struct drm_connector *connector) { struct drm_encoder *encoder; - int i; /* pick the first one */ - drm_connector_for_each_possible_encoder(connector, encoder, i) + drm_connector_for_each_possible_encoder(connector, encoder) return encoder; return NULL; @@ -1065,9 +1062,8 @@ amdgpu_connector_dvi_detect(struct drm_connector *connector, bool force) /* find analog encoder */ if (amdgpu_connector->dac_load_detect) { struct drm_encoder *encoder; - int i; - drm_connector_for_each_possible_encoder(connector, encoder, i) { + drm_connector_for_each_possible_encoder(connector, encoder) { if (encoder->encoder_type != DRM_MODE_ENCODER_DAC && encoder->encoder_type != DRM_MODE_ENCODER_TVDAC) continue; @@ -1117,9 +1113,8 @@ amdgpu_connector_dvi_encoder(struct drm_connector *connector) { struct amdgpu_connector *amdgpu_connector = to_amdgpu_connector(connector); struct drm_encoder *encoder; - int i; - drm_connector_for_each_possible_encoder(connector, encoder, i) { + drm_connector_for_each_possible_encoder(connector, encoder) { if (amdgpu_connector->use_digital == true) { if (encoder->encoder_type == DRM_MODE_ENCODER_TMDS) return encoder; @@ -1134,7 +1129,7 @@ amdgpu_connector_dvi_encoder(struct drm_connector *connector) /* then check use digitial */ /* pick the first one */ - drm_connector_for_each_possible_encoder(connector, encoder, i) + drm_connector_for_each_possible_encoder(connector, encoder) return en
[PATCH v2 03/11] drm/i915/psr: Set PSR CRC verification bit in sink inside PSR1 block
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); -- 2.19.2 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH v2 01/11] drm/i915: Disable PSR in Apple panels
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, + DP_DPCD_QUIRK_NO_PSR, }; /** -- 2.19.2 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH v2 02/11] drm/i915/psr: Don't tell sink that main link will be active while is active PSR2
For PSR2 there is no register to tell HW to keep main link enabled 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); -- 2.19.2 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH v2 09/11] drm/i915: Remove old PSR2 FIXME about frontbuffer tracking
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. Acked-by: Dhinakaran Pandiyan Reviewed-by: Rodrigo Vivi Signed-off-by: José Roberto de Souza --- 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 f9eccaac850a..0257dbcf9384 100644 --- a/drivers/gpu/drm/i915/intel_psr.c +++ b/drivers/gpu/drm/i915/intel_psr.c @@ -495,9 +495,6 @@ static void hsw_activate_psr2(struct intel_dp *intel_dp) idle_frames = max(idle_frames, dev_priv->psr.sink_sync_latency + 1); val = idle_frames << EDP_PSR2_IDLE_FRAME_SHIFT; - /* 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
[PATCH v2 07/11] drm/i915/psr: Check if resolution is supported by default SU granularity
Selective updates have a default granularity requirements as stated by eDP spec, so check if HW can match those requirements before enable PSR2. 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 +* 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. +*/ + if (crtc_hdisplay % 4) { + DRM_DEBUG_KMS("PSR2 not enabled, default SU granularity not match\n"); + return false; + } + return true; } -- 2.19.2 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH v2 11/11] drm/i915/psr: Set the right frames values
EDP_PSR2_FRAME_BEFORE_SU() is the number of frames that PSR2 HW will wait before enter in PSR2 activation state, important to note here is that it will wait for X frames not X idle frames. So lets reuse the previous approch to get the maximum number of frames between 6 and sink_sync_latency to enter in PSR2 activation state and just remove the VBT idle_frames. And EDP_PSR2_FRAME_BEFORE_SU() is the number of idle frames that PSR2 HW will wait before enter in PSR2 deep sleep when PSR2 is active. Important note here is that HW will need to go to PSR2 idle state every time it exits PSR2 deep sleep, so avoid as much as possible deep sleep will provide in overal more power savings as PSR2 sleep will save some power as memory will not be read in the idle frames and screen will be partialy updated without exit PSR2. Cc: Rodrigo Vivi Cc: Dhinakaran Pandiyan Signed-off-by: José Roberto de Souza --- drivers/gpu/drm/i915/intel_psr.c | 12 +++- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_psr.c b/drivers/gpu/drm/i915/intel_psr.c index 0257dbcf9384..36c2eb27ed8d 100644 --- a/drivers/gpu/drm/i915/intel_psr.c +++ b/drivers/gpu/drm/i915/intel_psr.c @@ -489,18 +489,20 @@ static void hsw_activate_psr2(struct intel_dp *intel_dp) /* Let's use 6 as the minimum to cover all known cases including the * off-by-one issue that HW has in some cases. +* sink_sync_latency of 8 means source has to wait for more than 8 +* frames, so sink_sync_latency + 1. */ - int idle_frames = max(6, dev_priv->vbt.psr.idle_frames); + val = max(6, dev_priv->psr.sink_sync_latency + 1); + val = min_t(u32, val, EDP_PSR2_FRAME_BEFORE_SU_MAX); + val = EDP_PSR2_FRAME_BEFORE_SU(val); - idle_frames = max(idle_frames, dev_priv->psr.sink_sync_latency + 1); - val = idle_frames << EDP_PSR2_IDLE_FRAME_SHIFT; + /* Avoid deep sleep as much as possible to avoid PSR2 idle state */ + val |= EDP_PSR2_IDLE_FRAME(EDP_PSR2_IDLE_FRAME_MAX); val |= EDP_PSR2_ENABLE | EDP_SU_TRACK_ENABLE; if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv)) val |= EDP_Y_COORDINATE_ENABLE; - val |= EDP_PSR2_FRAME_BEFORE_SU(dev_priv->psr.sink_sync_latency + 1); - if (dev_priv->vbt.psr.tp2_tp3_wakeup_time_us >= 0 && dev_priv->vbt.psr.tp2_tp3_wakeup_time_us <= 50) val |= EDP_PSR2_TP2_TIME_50us; -- 2.19.2 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH v2 06/11] drm: Add the PSR SU granularity registers offsets
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 */ + /* * 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, -- 2.19.2 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH v2 04/11] drm/i915/psr: Enable sink to trigger a interruption on PSR2 CRC mismatch
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 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; -- 2.19.2 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH v2 08/11] drm/i915/psr: Check if source supports sink specific SU granularity
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; + } + + 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"); + + return val; +} + 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_dp); + 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; } -- 2.19.2 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH v2 05/11] drm/i915/icl: Do not change reserved registers related to PSR2
For ICL the bit 12 of CHICKEN_TRANS is reserved so we should not touch it and as by default VSC_DATA_SEL_SOFTWARE_CONTROL is already unset in gen10 + GLK we can just drop it and fix for both gens. Cc: Dhinakaran Pandiyan Reviewed-by: Rodrigo Vivi Signed-off-by: José Roberto de Souza --- drivers/gpu/drm/i915/intel_psr.c | 11 --- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_psr.c b/drivers/gpu/drm/i915/intel_psr.c index 77162c469079..c4a8f476eea9 100644 --- a/drivers/gpu/drm/i915/intel_psr.c +++ b/drivers/gpu/drm/i915/intel_psr.c @@ -649,17 +649,14 @@ static void intel_psr_enable_source(struct intel_dp *intel_dp, if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) hsw_psr_setup_aux(intel_dp); - if (dev_priv->psr.psr2_enabled) { + if (dev_priv->psr.psr2_enabled && (IS_GEN9(dev_priv) && + !IS_GEMINILAKE(dev_priv))) { i915_reg_t reg = gen9_chicken_trans_reg(dev_priv, cpu_transcoder); u32 chicken = I915_READ(reg); - if (IS_GEN9(dev_priv) && !IS_GEMINILAKE(dev_priv)) - chicken |= (PSR2_VSC_ENABLE_PROG_HEADER - | PSR2_ADD_VERTICAL_LINE_COUNT); - - else - chicken &= ~VSC_DATA_SEL_SOFTWARE_CONTROL; + chicken |= PSR2_VSC_ENABLE_PROG_HEADER | + PSR2_ADD_VERTICAL_LINE_COUNT; I915_WRITE(reg, chicken); } -- 2.19.2 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH v2 10/11] drm/i915: Improve PSR2 CTL macros
- 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) -#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_SHIFT0 +#define EDP_PSR2_IDLE_FRAME_MAX 0xf +#define EDP_PSR2_IDLE_FRAME(a) ((a) << EDP_PSR2_IDLE_FRAME_SHIFT) #define _PSR_EVENT_TRANS_A 0x60848 #define _PSR_EVENT_TRANS_B 0x61848 -- 2.19.2 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH 9/9] drm/i915: Remove old PSR2 FIXME about frontbuffer tracking
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 --- 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
[PATCH 3/9] drm/i915/psr: Enable sink to trigger a interruption on PSR2 CRC mismatch
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; } 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
[PATCH 5/9] drm: Add offset of PSR2 SU X granularity value
Source is required to comply to sink SU granularity when DP_PSR2_SU_GRANULARITY_REQUIRED is set in DP_PSR_CAPS, so adding the register here. Cc: Dhinakaran Pandiyan Cc: Rodrigo Vivi Signed-off-by: José Roberto de Souza --- include/drm/drm_dp_helper.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h index db516c48cda3..acc7ccfd2044 100644 --- a/include/drm/drm_dp_helper.h +++ b/include/drm/drm_dp_helper.h @@ -314,6 +314,9 @@ # 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 */ + /* * 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, -- 2.19.2 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH 7/9] drm/i915/psr: Rename PSR2 macros to better match meaning
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 being set so better rename to make it clear. 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(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_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/drivers/gpu/drm/i915/intel_psr.c b/drivers/gpu/drm/i915/intel_psr.c index 9215c9052381..ba7bbe3f8df2 100644 --- a/drivers/gpu/drm/i915/intel_psr.c +++ b/drivers/gpu/drm/i915/intel_psr.c @@ -479,6 +479,7 @@ static void hsw_activate_psr1(struct intel_dp *intel_dp) static void hsw_activate_psr2(struct intel_dp *intel_dp) { struct drm_i915_private *dev_priv = dp_to_i915(intel_dp); + struct i915_psr *psr = _priv->psr; u32 val; /* Let's use 6 as the minimum to cover all known cases including the @@ -486,8 +487,8 @@ static void hsw_activate_psr2(struct intel_dp *intel_dp) */ int idle_frames = max(6, dev_priv->vbt.psr.idle_frames); - idle_frames = max(idle_frames, dev_priv->psr.sink_sync_latency + 1); - val = idle_frames << EDP_PSR2_IDLE_FRAME_SHIFT; + idle_frames = max(idle_frames, psr->sink_sync_latency + 1); + val = EDP_PSR2_IDLE_FRAMES_TO_DEEP_SLEEP(idle_frames); /* FIXME: selective update is probably totally broken because it doesn't * mesh at all with our frontbuffer tracking. And the hw alone isn't @@ -496,7 +497,7 @@ static void hsw_activate_psr2(struct intel_dp *intel_dp) if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv)
[PATCH 6/9] drm/i915/psr: Check if source supports sink specific SU granularity
According to eDP spec, sink can required specific selective update granularity that source must comply. Here caching the value if required and checking 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 | 32 2 files changed, 33 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index f763b30f98d9..cbcd85af95bf 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -506,6 +506,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 7607a58a6ec0..9215c9052381 100644 --- a/drivers/gpu/drm/i915/intel_psr.c +++ b/drivers/gpu/drm/i915/intel_psr.c @@ -257,6 +257,21 @@ 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 = 0; + ssize_t r; + + if (!(intel_dp->psr_dpcd[1] & DP_PSR2_SU_GRANULARITY_REQUIRED)) + return val; + + 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"); + + return val; +} + void intel_psr_init_dpcd(struct intel_dp *intel_dp) { struct drm_i915_private *dev_priv = @@ -311,6 +326,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_dp); + dev_priv->psr.su_x_granularity = + intel_dp_get_su_x_granulartiy(intel_dp); } } } @@ -525,6 +542,21 @@ static bool intel_psr2_config_valid(struct intel_dp *intel_dp, return false; } + if (dev_priv->psr.su_x_granularity) { + /* +* HW will always send full lines in SU blocks, so X will +* 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. +*/ + if (crtc_hdisplay % dev_priv->psr.su_x_granularity) { + DRM_DEBUG_KMS("PSR2 not enabled, HW can not match sink SU granularity requirement\n"); + return false; + } + } + return true; } -- 2.19.2 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH 4/9] drm/i915/icl: Do not change reserved registers related to PSR2
For ICL the bit 12 of CHICKEN_TRANS is reserved so we should not touch it and as by default VSC_DATA_SEL_SOFTWARE_CONTROL is already unset in gen10 + GLK we can just drop it and fix for both gens. Cc: Dhinakaran Pandiyan Cc: Rodrigo Vivi Signed-off-by: José Roberto de Souza --- drivers/gpu/drm/i915/intel_psr.c | 11 --- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_psr.c b/drivers/gpu/drm/i915/intel_psr.c index 607c3ec41679..7607a58a6ec0 100644 --- a/drivers/gpu/drm/i915/intel_psr.c +++ b/drivers/gpu/drm/i915/intel_psr.c @@ -635,17 +635,14 @@ static void intel_psr_enable_source(struct intel_dp *intel_dp, if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) hsw_psr_setup_aux(intel_dp); - if (dev_priv->psr.psr2_enabled) { + if (dev_priv->psr.psr2_enabled && (IS_GEN9(dev_priv) && + !IS_GEMINILAKE(dev_priv))) { i915_reg_t reg = gen9_chicken_trans_reg(dev_priv, cpu_transcoder); u32 chicken = I915_READ(reg); - if (IS_GEN9(dev_priv) && !IS_GEMINILAKE(dev_priv)) - chicken |= (PSR2_VSC_ENABLE_PROG_HEADER - | PSR2_ADD_VERTICAL_LINE_COUNT); - - else - chicken &= ~VSC_DATA_SEL_SOFTWARE_CONTROL; + chicken |= PSR2_VSC_ENABLE_PROG_HEADER | + PSR2_ADD_VERTICAL_LINE_COUNT; I915_WRITE(reg, chicken); } -- 2.19.2 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH 2/9] drm/i915/psr: Don't tell sink that main link will be active while is active PSR2
For PSR2 there is no register to tell HW to keep main link enabled while PSR2 is active, so don't configure sink DPCD with a misleading value. Cc: Dhinakaran Pandiyan Cc: Rodrigo Vivi Signed-off-by: José Roberto de Souza --- drivers/gpu/drm/i915/intel_psr.c | 10 ++ 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_psr.c b/drivers/gpu/drm/i915/intel_psr.c index f5d27a02eb28..888e348cc1b4 100644 --- a/drivers/gpu/drm/i915/intel_psr.c +++ b/drivers/gpu/drm/i915/intel_psr.c @@ -391,12 +391,14 @@ 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 (INTEL_GEN(dev_priv) >= 8) + dpcd_val |= DP_PSR_CRC_VERIFICATION; } - 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); drm_dp_dpcd_writeb(_dp->aux, DP_SET_POWER, DP_SET_POWER_D0); -- 2.19.2 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH 1/9] drm/i915: Disable PSR in Apple panels
i915 yet don't support PSR in Apple panels, so lets keep it disabled while we work on that. Fixes: 598c6cfe0690 (drm/i915/psr: Enable PSR1 on gen-9+ HW) 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, }; /** -- 2.19.2 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH 8/9] drm/i915/psr: Set the right frames values
EDP_PSR2_IDLE_FRAMES_TO_DEEP_SLEEP() was being set with the number of frames that it should wait to enter PSR, what is wrong. Here it is setting this field with the highest value to avoid PSR2 exits frequently, as when HW exit deep sleep it needs to go to idle state causing a PSR exit for then waiting a few frames before activate PSR2 again. This will result in more power saving as the sleep state also provide some power savings by doing selective updates instead of full screen updates. About EDP_PSR2_FRAMES_BEFORE_ACTIVATE() it is the number of frames (not idle frames) that PSR2 hardware will wait to activate PSR2, so lets keep using the sink sync latency. Cc: Rodrigo Vivi Cc: Dhinakaran Pandiyan Signed-off-by: José Roberto de Souza --- drivers/gpu/drm/i915/intel_psr.c | 12 +--- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_psr.c b/drivers/gpu/drm/i915/intel_psr.c index ba7bbe3f8df2..6fd793fec5e9 100644 --- a/drivers/gpu/drm/i915/intel_psr.c +++ b/drivers/gpu/drm/i915/intel_psr.c @@ -482,13 +482,13 @@ static void hsw_activate_psr2(struct intel_dp *intel_dp) struct i915_psr *psr = _priv->psr; u32 val; - /* Let's use 6 as the minimum to cover all known cases including the -* off-by-one issue that HW has in some cases. + /* sink_sync_latency of 8 means source has to wait for more than 8 +* frames, we'll go with 9 frames for now */ - int idle_frames = max(6, dev_priv->vbt.psr.idle_frames); + val = EDP_PSR2_FRAMES_BEFORE_ACTIVATE(psr->sink_sync_latency + 1); - idle_frames = max(idle_frames, psr->sink_sync_latency + 1); - val = EDP_PSR2_IDLE_FRAMES_TO_DEEP_SLEEP(idle_frames); + /* 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 @@ -497,8 +497,6 @@ static void hsw_activate_psr2(struct intel_dp *intel_dp) if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv)) val |= EDP_Y_COORDINATE_ENABLE; - val |= EDP_PSR2_FRAMES_BEFORE_ACTIVATE(psr->sink_sync_latency + 1); - if (dev_priv->vbt.psr.tp2_tp3_wakeup_time_us >= 0 && dev_priv->vbt.psr.tp2_tp3_wakeup_time_us <= 50) val |= EDP_PSR2_TP2_TIME_50us; -- 2.19.2 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH 2/2] drm/edid: Parse manufacturer id only once per sink
It was parsing the manufacturer id of the sink for each entry in quirk list. Signed-off-by: José Roberto de Souza --- drivers/gpu/drm/drm_edid.c | 21 - 1 file changed, 4 insertions(+), 17 deletions(-) diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index 1a0ddf3d326b..69209fcc40f0 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -1770,22 +1770,6 @@ void drm_edid_manufacturer_parse(const struct edid *edid, char manufacturer[3]) } EXPORT_SYMBOL(drm_edid_manufacturer_parse); -/** - * edid_vendor - match a string against EDID's obfuscated vendor field - * @edid: EDID to match - * @vendor: vendor string - * - * Returns true if @vendor is in @edid, false otherwise - */ -static bool edid_vendor(const struct edid *edid, const char *vendor) -{ - char edid_vendor[3]; - - drm_edid_manufacturer_parse(edid, edid_vendor); - - return !strncmp(edid_vendor, vendor, 3); -} - /** * edid_get_quirks - return quirk flags for a given EDID * @edid: EDID to process @@ -1795,12 +1779,15 @@ static bool edid_vendor(const struct edid *edid, const char *vendor) static u32 edid_get_quirks(const struct edid *edid) { const struct edid_quirk *quirk; + char edid_vendor[3]; int i; + drm_edid_manufacturer_parse(edid, edid_vendor); + for (i = 0; i < ARRAY_SIZE(edid_quirk_list); i++) { quirk = _quirk_list[i]; - if (edid_vendor(edid, quirk->vendor) && + if (!strncmp(edid_vendor, quirk->vendor, 3) && (EDID_PRODUCT_ID(edid) == quirk->product_id)) return quirk->quirks; } -- 2.19.1 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH 1/2] drm/edid: Add and export function to parse manufacturer id
This function will be helpful to drivers that wants to add its own quirks to sinks. Signed-off-by: José Roberto de Souza --- drivers/gpu/drm/drm_edid.c | 20 include/drm/drm_edid.h | 1 + 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index b506e3622b08..1a0ddf3d326b 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -1755,6 +1755,21 @@ EXPORT_SYMBOL(drm_edid_duplicate); /*** EDID parsing ***/ +/** + * drm_edid_manufacturer_parse - parse the EDID manufacturer id to readable + * characters and set into manufacturer parameter. + * @edid: EDID to get the manufacturer + * @manufacturer: the char buffer to store the id + */ +void drm_edid_manufacturer_parse(const struct edid *edid, char manufacturer[3]) +{ + manufacturer[0] = ((edid->mfg_id[0] & 0x7c) >> 2) + '@'; + manufacturer[1] = (((edid->mfg_id[0] & 0x3) << 3) | + ((edid->mfg_id[1] & 0xe0) >> 5)) + '@'; + manufacturer[2] = (edid->mfg_id[1] & 0x1f) + '@'; +} +EXPORT_SYMBOL(drm_edid_manufacturer_parse); + /** * edid_vendor - match a string against EDID's obfuscated vendor field * @edid: EDID to match @@ -1766,10 +1781,7 @@ static bool edid_vendor(const struct edid *edid, const char *vendor) { char edid_vendor[3]; - edid_vendor[0] = ((edid->mfg_id[0] & 0x7c) >> 2) + '@'; - edid_vendor[1] = (((edid->mfg_id[0] & 0x3) << 3) | - ((edid->mfg_id[1] & 0xe0) >> 5)) + '@'; - edid_vendor[2] = (edid->mfg_id[1] & 0x1f) + '@'; + drm_edid_manufacturer_parse(edid, edid_vendor); return !strncmp(edid_vendor, vendor, 3); } diff --git a/include/drm/drm_edid.h b/include/drm/drm_edid.h index e3c404833115..e4f3f7f34d6a 100644 --- a/include/drm/drm_edid.h +++ b/include/drm/drm_edid.h @@ -466,6 +466,7 @@ struct edid *drm_get_edid_switcheroo(struct drm_connector *connector, struct i2c_adapter *adapter); struct edid *drm_edid_duplicate(const struct edid *edid); int drm_add_edid_modes(struct drm_connector *connector, struct edid *edid); +void drm_edid_manufacturer_parse(const struct edid *edid, char manufacturer[3]); u8 drm_match_cea_mode(const struct drm_display_mode *to_match); enum hdmi_picture_aspect drm_get_cea_aspect_ratio(const u8 video_code); -- 2.19.1 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH] drm: Do not call drm_dp_cec_set_edid() while registering DP connectors
drm_dp_cec_register_connector() is called when registering each DP connector in DRM, while sounds a good idea register CEC adapters as earlier as possible, it causes some driver initialization delay trying to do DPCD transactions in disconnected connectors. This change will cause no regressions as drm_dp_cec_set_edid() will still be called in further detection of connected connectors with a valid edid parameter. This change reduced the module load of i915 by average 0.5sec in a machine with just one DP port disconnected while reducing more than 3sec in a machine with 4 DP ports disconnected. Cc: Hans Verkuil Signed-off-by: José Roberto de Souza --- drivers/gpu/drm/drm_dp_cec.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/gpu/drm/drm_dp_cec.c b/drivers/gpu/drm/drm_dp_cec.c index 8a718f85079a..b15cee85b702 100644 --- a/drivers/gpu/drm/drm_dp_cec.c +++ b/drivers/gpu/drm/drm_dp_cec.c @@ -424,8 +424,6 @@ void drm_dp_cec_register_connector(struct drm_dp_aux *aux, const char *name, aux->cec.parent = parent; INIT_DELAYED_WORK(>cec.unregister_work, drm_dp_cec_unregister_work); - - drm_dp_cec_set_edid(aux, NULL); } EXPORT_SYMBOL(drm_dp_cec_register_connector); -- 2.19.1 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH 1/2] drm: Do not call drm_dp_cec_set_edid() while registering DP connectors
drm_dp_cec_register_connector() is called when registering each DP connector in DRM, while sounds a good idea register CEC adapters as earlier as possible, it causes some driver initialization delay trying to do DPCD transactions in disconnected connectors. This change will cause no regressions as drm_dp_cec_set_edid() will still be called in further detection of connected connectors with a valid edid parameter. This change reduced the module load of i915 by average 0.5sec in a machine with just one DP port disconnected while reducing more than 3sec in a machine with 4 DP ports disconnected. Cc: Hans Verkuil Signed-off-by: José Roberto de Souza --- drivers/gpu/drm/drm_dp_cec.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/gpu/drm/drm_dp_cec.c b/drivers/gpu/drm/drm_dp_cec.c index 8a718f85079a..b15cee85b702 100644 --- a/drivers/gpu/drm/drm_dp_cec.c +++ b/drivers/gpu/drm/drm_dp_cec.c @@ -424,8 +424,6 @@ void drm_dp_cec_register_connector(struct drm_dp_aux *aux, const char *name, aux->cec.parent = parent; INIT_DELAYED_WORK(>cec.unregister_work, drm_dp_cec_unregister_work); - - drm_dp_cec_set_edid(aux, NULL); } EXPORT_SYMBOL(drm_dp_cec_register_connector); -- 2.19.0 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH 2/2] drm/i915: Do not get aux power for disconnected DP ports
For ICL type-c ports there is a aux power restriction, it can only be enabled while there is sink connected. BSpec: 21750 Cc: Maarten Lankhorst Signed-off-by: José Roberto de Souza --- drivers/gpu/drm/i915/intel_dp.c | 19 ++- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 6b4c19123f2a..48fd38cd4ba4 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -5019,19 +5019,27 @@ intel_dp_long_pulse(struct intel_connector *connector, struct intel_dp *intel_dp = intel_attached_dp(>base); enum drm_connector_status status; u8 sink_irq_vector = 0; + bool got_aux_power; WARN_ON(!drm_modeset_is_locked(_priv->drm.mode_config.connection_mutex)); + /* Can't disconnect eDP */ + if (!intel_dp_is_edp(intel_dp) && + !intel_digital_port_connected(_to_dig_port(intel_dp)->base)) { + status = connector_status_disconnected; + got_aux_power = false; + goto port_disconnected; + } + intel_display_power_get(dev_priv, intel_dp->aux_power_domain); + got_aux_power = true; - /* Can't disconnect eDP */ if (intel_dp_is_edp(intel_dp)) status = edp_detect(intel_dp); - else if (intel_digital_port_connected(_to_dig_port(intel_dp)->base)) - status = intel_dp_detect_dpcd(intel_dp); else - status = connector_status_disconnected; + status = intel_dp_detect_dpcd(intel_dp); +port_disconnected: if (status == connector_status_disconnected) { memset(_dp->compliance, 0, sizeof(intel_dp->compliance)); @@ -5122,7 +5130,8 @@ intel_dp_long_pulse(struct intel_connector *connector, if (status != connector_status_connected && !intel_dp->is_mst) intel_dp_unset_edid(intel_dp); - intel_display_power_put(dev_priv, intel_dp->aux_power_domain); + if (got_aux_power) + intel_display_power_put(dev_priv, intel_dp->aux_power_domain); return status; } -- 2.19.0 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH v3] drm: Return -EOPNOTSUPP in drm_setclientcap() when driver do not support KMS
All DRM_CLIENT capabilities are tied to KMS support, so returning -EOPNOTSUPP when KMS is not supported. v2: returning -EOPNOTSUPP(same value as posix ENOTSUP and available in uapi) instead of -ENOTSUPP v3: adding comments about the feature requirement about capabilities Cc: Chris Wilson Signed-off-by: José Roberto de Souza --- drivers/gpu/drm/drm_ioctl.c | 6 ++ 1 file changed, 6 insertions(+) diff --git a/drivers/gpu/drm/drm_ioctl.c b/drivers/gpu/drm/drm_ioctl.c index 60dfbfae6a02..94bd872d56c4 100644 --- a/drivers/gpu/drm/drm_ioctl.c +++ b/drivers/gpu/drm/drm_ioctl.c @@ -306,6 +306,12 @@ drm_setclientcap(struct drm_device *dev, void *data, struct drm_file *file_priv) { struct drm_set_client_cap *req = data; + /* No render-only settable capabilities for now */ + + /* Below caps that only works with KMS drivers */ + if (!drm_core_check_feature(dev, DRIVER_MODESET)) + return -EOPNOTSUPP; + switch (req->capability) { case DRM_CLIENT_CAP_STEREO_3D: if (req->value > 1) -- 2.19.0 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH v2] drm: Return -EOPNOTSUPP in drm_setclientcap() when driver do not support KMS
All DRM_CLIENT capabilities are tied to KMS support, so returning -EOPNOTSUPP when KMS is not supported. v2: returning -EOPNOTSUPP(same value as posix ENOTSUP and available in uapi) instead of -ENOTSUPP Cc: Chris Wilson Signed-off-by: José Roberto de Souza --- drivers/gpu/drm/drm_ioctl.c | 3 +++ drivers/gpu/drm/i915/i915_perf.c | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/drm_ioctl.c b/drivers/gpu/drm/drm_ioctl.c index 60dfbfae6a02..c0de628c194c 100644 --- a/drivers/gpu/drm/drm_ioctl.c +++ b/drivers/gpu/drm/drm_ioctl.c @@ -306,6 +306,9 @@ drm_setclientcap(struct drm_device *dev, void *data, struct drm_file *file_priv) { struct drm_set_client_cap *req = data; + if (!drm_core_check_feature(dev, DRIVER_MODESET)) + return -EOPNOTSUPP; + switch (req->capability) { case DRM_CLIENT_CAP_STEREO_3D: if (req->value > 1) diff --git a/drivers/gpu/drm/i915/i915_perf.c b/drivers/gpu/drm/i915/i915_perf.c index 664b96bb65a3..c1edd1e69a3e 100644 --- a/drivers/gpu/drm/i915/i915_perf.c +++ b/drivers/gpu/drm/i915/i915_perf.c @@ -2817,7 +2817,7 @@ int i915_perf_open_ioctl(struct drm_device *dev, void *data, if (!dev_priv->perf.initialized) { DRM_DEBUG("i915 perf interface not available for this system\n"); - return -ENOTSUPP; + return -EOPNOTSUPP; } known_open_flags = I915_PERF_FLAG_FD_CLOEXEC | -- 2.19.0 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH] drm: Return -ENOTSUPP in drm_setclientcap() when driver do not support KMS
All DRM_CLIENT capabilities are tied to KMS support, so returning -ENOTSUPP when KMS is not supported. Cc: Chris Wilson Signed-off-by: José Roberto de Souza --- drivers/gpu/drm/drm_ioctl.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/gpu/drm/drm_ioctl.c b/drivers/gpu/drm/drm_ioctl.c index 6b4a633b4240..842423fe9762 100644 --- a/drivers/gpu/drm/drm_ioctl.c +++ b/drivers/gpu/drm/drm_ioctl.c @@ -306,6 +306,9 @@ drm_setclientcap(struct drm_device *dev, void *data, struct drm_file *file_priv) { struct drm_set_client_cap *req = data; + if (!drm_core_check_feature(dev, DRIVER_MODESET)) + return -ENOTSUPP; + switch (req->capability) { case DRM_CLIENT_CAP_STEREO_3D: if (req->value > 1) -- 2.19.0 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH 1/6] drm: Let userspace check if driver supports modeset
GPU accelerators usually don't have display block or the display driver part can be disable when building driver(for servers it save some resources) so it is important let userspace check this capability too. Signed-off-by: José Roberto de Souza --- drivers/gpu/drm/drm_ioctl.c | 3 +++ include/uapi/drm/drm.h | 1 + 2 files changed, 4 insertions(+) diff --git a/drivers/gpu/drm/drm_ioctl.c b/drivers/gpu/drm/drm_ioctl.c index ea10e9a26aad..3a8438ae9b51 100644 --- a/drivers/gpu/drm/drm_ioctl.c +++ b/drivers/gpu/drm/drm_ioctl.c @@ -244,6 +244,9 @@ static int drm_getcap(struct drm_device *dev, void *data, struct drm_file *file_ case DRM_CAP_SYNCOBJ: req->value = drm_core_check_feature(dev, DRIVER_SYNCOBJ); return 0; + case DRM_CAP_MODESET: + req->value = drm_core_check_feature(dev, DRIVER_MODESET); + return 0; } /* Other caps only work with KMS drivers */ diff --git a/include/uapi/drm/drm.h b/include/uapi/drm/drm.h index 300f336633f2..85fae6ddbf48 100644 --- a/include/uapi/drm/drm.h +++ b/include/uapi/drm/drm.h @@ -649,6 +649,7 @@ struct drm_gem_open { #define DRM_CAP_PAGE_FLIP_TARGET 0x11 #define DRM_CAP_CRTC_IN_VBLANK_EVENT 0x12 #define DRM_CAP_SYNCOBJ0x13 +#define DRM_CAP_MODESET0x14 /** DRM_IOCTL_GET_CAP ioctl argument type */ struct drm_get_cap { -- 2.18.0 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH 5/6] drm/i915: Do not call modeset related functions when display is disabled
No need to run i915_load_modeset_init() when num_pipes == 0 also kms depends on things initialized in i915_load_modeset_init() so not initializing it too. fbdev and audio have guards against num_pipes == 0 but lets move it to the if block to make it explicit to readers. Also as planes, CRTCs, encoders and connectors are not being added it is necessary to unset the MODESET driver feature otherwise it will crash when registering driver in drm, also disabling ATOMIC as do not make sense have ATOMIC and do not have MODESET. There is more modeset/display calls that still needs to be removed, this is a initial work. Signed-off-by: José Roberto de Souza --- drivers/gpu/drm/i915/i915_drv.c | 69 - 1 file changed, 41 insertions(+), 28 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index aacb467fe3ea..e109815cfa51 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -1248,23 +1248,26 @@ static void i915_driver_register(struct drm_i915_private *dev_priv) if (IS_GEN5(dev_priv)) intel_gpu_ips_init(dev_priv); - intel_audio_init(dev_priv); + if (INTEL_INFO(dev_priv)->num_pipes) { + intel_audio_init(dev_priv); - /* -* Some ports require correctly set-up hpd registers for detection to -* work properly (leading to ghost connected connector status), e.g. VGA -* on gm45. Hence we can only set up the initial fbdev config after hpd -* irqs are fully enabled. We do it last so that the async config -* cannot run before the connectors are registered. -*/ - intel_fbdev_initial_config_async(dev); + /* +* Some ports require correctly set-up hpd registers for +* detection to work properly (leading to ghost connected +* connector status), e.g. VGA on gm45. Hence we can only set +* up the initial fbdev config after hpd irqs are fully enabled. +* We do it last so that the async config cannot run before the +* connectors are registered. +*/ + intel_fbdev_initial_config_async(dev); - /* -* We need to coordinate the hotplugs with the asynchronous fbdev -* configuration, for which we use the fbdev->async_cookie. -*/ - if (INTEL_INFO(dev_priv)->num_pipes) + /* +* We need to coordinate the hotplugs with the asynchronous +* fbdev configuration, for which we use the +* fbdev->async_cookie. +*/ drm_kms_helper_poll_init(dev); + } } /** @@ -1273,15 +1276,17 @@ static void i915_driver_register(struct drm_i915_private *dev_priv) */ static void i915_driver_unregister(struct drm_i915_private *dev_priv) { - intel_fbdev_unregister(dev_priv); - intel_audio_deinit(dev_priv); + if (INTEL_INFO(dev_priv)->num_pipes) { + intel_fbdev_unregister(dev_priv); + intel_audio_deinit(dev_priv); - /* -* After flushing the fbdev (incl. a late async config which will -* have delayed queuing of a hotplug event), then flush the hotplug -* events. -*/ - drm_kms_helper_poll_fini(_priv->drm); + /* +* After flushing the fbdev (incl. a late async config which +* will have delayed queuing of a hotplug event), then flush the +* hotplug events. +*/ + drm_kms_helper_poll_fini(_priv->drm); + } intel_gpu_ips_teardown(); acpi_video_unregister(); @@ -1333,6 +1338,9 @@ int i915_driver_load(struct pci_dev *pdev, const struct pci_device_id *ent) if (!i915_modparams.nuclear_pageflip && match_info->gen < 5) driver.driver_features &= ~DRIVER_ATOMIC; + if (i915_modparams.disable_display) + driver.driver_features &= ~(DRIVER_MODESET | DRIVER_ATOMIC); + ret = -ENOMEM; dev_priv = kzalloc(sizeof(*dev_priv), GFP_KERNEL); if (dev_priv) @@ -1387,9 +1395,11 @@ int i915_driver_load(struct pci_dev *pdev, const struct pci_device_id *ent) if (ret) goto cleanup_irq; - ret = i915_load_modeset_init(_priv->drm); - if (ret < 0) - goto cleanup_gem; + if (INTEL_INFO(dev_priv)->num_pipes) { + ret = i915_load_modeset_init(_priv->drm); + if (ret < 0) + goto cleanup_gem; + } i915_driver_register(dev_priv); @@ -1439,11 +1449,13 @@ void i915_driver_unload(struct drm_device *dev) intel_display_power_get(dev_priv, POWER_DOMAIN_INIT); - drm_atomic_helper_shutdown(dev); + if (INTEL_INFO(dev_priv)->num_pipes) +
[PATCH 4/6] drm/i915: Move drm_vblank_init() to i915_load_modeset_init()
i915_load_modeset_init() is a more suitable place than i915_driver_load() as vblank is part of modeset API. Signed-off-by: José Roberto de Souza --- drivers/gpu/drm/i915/i915_drv.c | 19 +++ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 402ed9b4f29e..aacb467fe3ea 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -643,6 +643,13 @@ static int i915_load_modeset_init(struct drm_device *dev) if (i915_inject_load_failure()) return -ENODEV; + if (INTEL_INFO(dev_priv)->num_pipes == 0) { + ret = drm_vblank_init(_priv->drm, + INTEL_INFO(dev_priv)->num_pipes); + if (ret) + goto out; + } + intel_bios_init(dev_priv); /* If we have > 1 VGA cards, then we need to arbitrate access @@ -1367,18 +1374,6 @@ int i915_driver_load(struct pci_dev *pdev, const struct pci_device_id *ent) if (ret < 0) goto out_cleanup_mmio; - /* -* TODO: move the vblank init and parts of modeset init steps into one -* of the i915_driver_init_/i915_driver_register functions according -* to the role/effect of the given init step. -*/ - if (INTEL_INFO(dev_priv)->num_pipes) { - ret = drm_vblank_init(_priv->drm, - INTEL_INFO(dev_priv)->num_pipes); - if (ret) - goto out_cleanup_hw; - } - ret = intel_irq_install(dev_priv); if (ret) goto out_cleanup_hw; -- 2.18.0 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH 3/6] drm/i915: Move out non-modeset calls from modeset init and cleanup
i915_load_modeset_init() and intel_modeset_cleanup() was initializing and cleaning up things that is not modeset only. This will make easy initialize drive without display part. Signed-off-by: José Roberto de Souza --- drivers/gpu/drm/i915/i915_drv.c | 56 ++-- drivers/gpu/drm/i915/i915_drv.h | 1 + drivers/gpu/drm/i915/intel_display.c | 16 +++- 3 files changed, 42 insertions(+), 31 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 99792039176f..402ed9b4f29e 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -665,25 +665,15 @@ static int i915_load_modeset_init(struct drm_device *dev) /* must happen before intel_power_domains_init_hw() on VLV/CHV */ intel_update_rawclk(dev_priv); - intel_power_domains_init_hw(dev_priv, false); - intel_csr_ucode_init(dev_priv); - ret = intel_irq_install(dev_priv); - if (ret) - goto cleanup_csr; - intel_setup_gmbus(dev_priv); /* Important: The output setup functions called by modeset_init need * working irqs for e.g. gmbus and dp aux transfers. */ ret = intel_modeset_init(dev); if (ret) - goto cleanup_irq; - - ret = i915_gem_init(dev_priv); - if (ret) - goto cleanup_modeset; + goto cleanup_gmbus; intel_setup_overlay(dev_priv); @@ -692,23 +682,17 @@ static int i915_load_modeset_init(struct drm_device *dev) ret = intel_fbdev_init(dev); if (ret) - goto cleanup_gem; + goto cleanup_modeset; /* Only enable hotplug handling once the fbdev is fully set up. */ intel_hpd_init(dev_priv); return 0; -cleanup_gem: - if (i915_gem_suspend(dev_priv)) - DRM_ERROR("failed to idle hardware; continuing to unload!\n"); - i915_gem_fini(dev_priv); cleanup_modeset: intel_modeset_cleanup(dev); -cleanup_irq: - drm_irq_uninstall(dev); +cleanup_gmbus: intel_teardown_gmbus(dev_priv); -cleanup_csr: intel_csr_ucode_fini(dev_priv); intel_power_domains_fini(dev_priv); vga_switcheroo_unregister_client(pdev); @@ -1395,9 +1379,22 @@ int i915_driver_load(struct pci_dev *pdev, const struct pci_device_id *ent) goto out_cleanup_hw; } + ret = intel_irq_install(dev_priv); + if (ret) + goto out_cleanup_hw; + + /* i915_gem_init() call chain will call +* intel_display_power_put(i915, POWER_DOMAIN_GT_IRQ); +*/ + intel_power_domains_init_hw(dev_priv, false); + + ret = i915_gem_init(dev_priv); + if (ret) + goto cleanup_irq; + ret = i915_load_modeset_init(_priv->drm); if (ret < 0) - goto out_cleanup_hw; + goto cleanup_gem; i915_driver_register(dev_priv); @@ -1411,6 +1408,12 @@ int i915_driver_load(struct pci_dev *pdev, const struct pci_device_id *ent) return 0; +cleanup_gem: + if (i915_gem_suspend(dev_priv)) + DRM_ERROR("failed to idle hardware; continuing to unload!\n"); + i915_gem_fini(dev_priv); +cleanup_irq: + drm_irq_uninstall(_priv->drm); out_cleanup_hw: i915_driver_cleanup_hw(dev_priv); out_cleanup_mmio: @@ -1445,8 +1448,21 @@ void i915_driver_unload(struct drm_device *dev) intel_gvt_cleanup(dev_priv); + intel_modeset_cleanup_prepare(dev); + + intel_disable_gt_powersave(dev_priv); + + /* +* Interrupts and polling as the first thing to avoid creating havoc. +* Too much stuff here (turning of connectors, ...) would +* experience fancy races otherwise. +*/ + intel_irq_uninstall(dev_priv); + intel_modeset_cleanup(dev); + intel_cleanup_gt_powersave(dev_priv); + intel_bios_cleanup(dev_priv); vga_switcheroo_unregister_client(pdev); diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 4fb937399440..51eb48f6b57a 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -3419,6 +3419,7 @@ mkwrite_device_info(struct drm_i915_private *dev_priv) /* modesetting */ extern void intel_modeset_init_hw(struct drm_device *dev); extern int intel_modeset_init(struct drm_device *dev); +extern void intel_modeset_cleanup_prepare(struct drm_device *dev); extern void intel_modeset_cleanup(struct drm_device *dev); extern int intel_connector_register(struct drm_connector *); extern void intel_connector_unregister(struct drm_connector *); diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index bbf63741ae80..136fb8d51967 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -15905,7 +15905,7 @@ static void intel_hp
[PATCH 2/6] drm/i915: Set PCH as NOP if display is disabled
num_pipes is set to 0 if disable_display is set inside intel_device_info_runtime_init() but when that happen PCH will already be set in intel_detect_pch(). i915_driver_load() i915_driver_init_early() ... intel_detect_pch() ... ... i915_driver_init_hw() intel_device_info_runtime_init() Cc: Jani Nikula Signed-off-by: José Roberto de Souza --- drivers/gpu/drm/i915/i915_drv.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 3834bd758a2e..99792039176f 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -287,7 +287,8 @@ static void intel_detect_pch(struct drm_i915_private *dev_priv) * Use PCH_NOP (PCH but no South Display) for PCH platforms without * display. */ - if (pch && INTEL_INFO(dev_priv)->num_pipes == 0) { + if (pch && ((INTEL_INFO(dev_priv)->num_pipes == 0) || + i915_modparams.disable_display)) { DRM_DEBUG_KMS("Display disabled, reverting to NOP PCH\n"); dev_priv->pch_type = PCH_NOP; dev_priv->pch_id = 0; -- 2.18.0 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH 6/6] drm/i915: Remove redundante checks for num_pipes == 0
This 'if's will always be false because of previous changes. Signed-off-by: José Roberto de Souza --- drivers/gpu/drm/i915/i915_drv.c | 12 +++- drivers/gpu/drm/i915/intel_audio.c | 3 --- drivers/gpu/drm/i915/intel_display.c | 3 --- drivers/gpu/drm/i915/intel_i2c.c | 3 --- 4 files changed, 3 insertions(+), 18 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index e109815cfa51..bad7ad0bd5ac 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -643,12 +643,9 @@ static int i915_load_modeset_init(struct drm_device *dev) if (i915_inject_load_failure()) return -ENODEV; - if (INTEL_INFO(dev_priv)->num_pipes == 0) { - ret = drm_vblank_init(_priv->drm, - INTEL_INFO(dev_priv)->num_pipes); - if (ret) - goto out; - } + ret = drm_vblank_init(_priv->drm, INTEL_INFO(dev_priv)->num_pipes); + if (ret) + goto out; intel_bios_init(dev_priv); @@ -684,9 +681,6 @@ static int i915_load_modeset_init(struct drm_device *dev) intel_setup_overlay(dev_priv); - if (INTEL_INFO(dev_priv)->num_pipes == 0) - return 0; - ret = intel_fbdev_init(dev); if (ret) goto cleanup_modeset; diff --git a/drivers/gpu/drm/i915/intel_audio.c b/drivers/gpu/drm/i915/intel_audio.c index bb94172ffc07..f02cb211d3e7 100644 --- a/drivers/gpu/drm/i915/intel_audio.c +++ b/drivers/gpu/drm/i915/intel_audio.c @@ -960,9 +960,6 @@ void i915_audio_component_init(struct drm_i915_private *dev_priv) { int ret; - if (INTEL_INFO(dev_priv)->num_pipes == 0) - return; - ret = component_add(dev_priv->drm.dev, _audio_component_bind_ops); if (ret < 0) { DRM_ERROR("failed to add audio component (%d)\n", ret); diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 136fb8d51967..b572151c52fa 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -15137,9 +15137,6 @@ int intel_modeset_init(struct drm_device *dev) intel_init_pm(dev_priv); - if (INTEL_INFO(dev_priv)->num_pipes == 0) - return 0; - /* * There may be no VBT; and if the BIOS enabled SSC we can * just keep using it to avoid unnecessary flicker. Whereas if the diff --git a/drivers/gpu/drm/i915/intel_i2c.c b/drivers/gpu/drm/i915/intel_i2c.c index bef32b7c248e..2f941c5b2e8c 100644 --- a/drivers/gpu/drm/i915/intel_i2c.c +++ b/drivers/gpu/drm/i915/intel_i2c.c @@ -819,9 +819,6 @@ int intel_setup_gmbus(struct drm_i915_private *dev_priv) unsigned int pin; int ret; - if (INTEL_INFO(dev_priv)->num_pipes == 0) - return 0; - if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) dev_priv->gpio_mmio_base = VLV_DISPLAY_BASE; else if (!HAS_GMCH_DISPLAY(dev_priv)) -- 2.18.0 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH libdrm 1/2] intel: Introducing Whiskey Lake platform
Whiskey Lake uses the same gen graphics as Coffe Lake, including some ids that were previously marked as reserved on Coffe Lake, but that now are moved to WHL page. So, let's just move them to WHL macros that will feed into CFL macro just to keep it better organized to make easier future code review but it will be handled as a CFL. This is a copy of merged i915's commit b9be78531d27 ("drm/i915/whl: Introducing Whiskey Lake platform") Cc: Rodrigo Vivi Signed-off-by: José Roberto de Souza --- intel/intel_chipset.h | 33 + 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/intel/intel_chipset.h b/intel/intel_chipset.h index 32b2c48f..44e65f9e 100644 --- a/intel/intel_chipset.h +++ b/intel/intel_chipset.h @@ -231,16 +231,17 @@ #define PCI_CHIP_COFFEELAKE_S_GT2_4 0x3E9A #define PCI_CHIP_COFFEELAKE_H_GT2_1 0x3E9B #define PCI_CHIP_COFFEELAKE_H_GT2_2 0x3E94 -#define PCI_CHIP_COFFEELAKE_U_GT1_1 0x3EA1 -#define PCI_CHIP_COFFEELAKE_U_GT1_2 0x3EA4 -#define PCI_CHIP_COFFEELAKE_U_GT2_1 0x3EA0 -#define PCI_CHIP_COFFEELAKE_U_GT2_2 0x3EA3 -#define PCI_CHIP_COFFEELAKE_U_GT2_3 0x3EA9 -#define PCI_CHIP_COFFEELAKE_U_GT3_1 0x3EA2 -#define PCI_CHIP_COFFEELAKE_U_GT3_2 0x3EA5 -#define PCI_CHIP_COFFEELAKE_U_GT3_3 0x3EA6 -#define PCI_CHIP_COFFEELAKE_U_GT3_4 0x3EA7 -#define PCI_CHIP_COFFEELAKE_U_GT3_5 0x3EA8 +#define PCI_CHIP_COFFEELAKE_U_GT2_1 0x3EA9 +#define PCI_CHIP_COFFEELAKE_U_GT3_1 0x3EA5 +#define PCI_CHIP_COFFEELAKE_U_GT3_2 0x3EA6 +#define PCI_CHIP_COFFEELAKE_U_GT3_3 0x3EA7 +#define PCI_CHIP_COFFEELAKE_U_GT3_4 0x3EA8 + +#define PCI_CHIP_WHISKEYLAKE_U_GT1_1 0x3EA1 +#define PCI_CHIP_WHISKEYLAKE_U_GT2_1 0x3EA0 +#define PCI_CHIP_WHISKEYLAKE_U_GT3_1 0x3EA2 +#define PCI_CHIP_WHISKEYLAKE_U_GT3_2 0x3EA3 +#define PCI_CHIP_WHISKEYLAKE_U_GT3_3 0x3EA4 #define PCI_CHIP_CANNONLAKE_0 0x5A51 #define PCI_CHIP_CANNONLAKE_1 0x5A59 @@ -510,16 +511,16 @@ #define IS_CFL_H(devid) ((devid) == PCI_CHIP_COFFEELAKE_H_GT2_1 || \ (devid) == PCI_CHIP_COFFEELAKE_H_GT2_2) -#define IS_CFL_U(devid) ((devid) == PCI_CHIP_COFFEELAKE_U_GT1_1 || \ - (devid) == PCI_CHIP_COFFEELAKE_U_GT1_2 || \ - (devid) == PCI_CHIP_COFFEELAKE_U_GT2_1 || \ - (devid) == PCI_CHIP_COFFEELAKE_U_GT2_2 || \ - (devid) == PCI_CHIP_COFFEELAKE_U_GT2_3 || \ +#define IS_CFL_U(devid) ((devid) == PCI_CHIP_COFFEELAKE_U_GT2_1 || \ (devid) == PCI_CHIP_COFFEELAKE_U_GT3_1 || \ (devid) == PCI_CHIP_COFFEELAKE_U_GT3_2 || \ (devid) == PCI_CHIP_COFFEELAKE_U_GT3_3 || \ (devid) == PCI_CHIP_COFFEELAKE_U_GT3_4 || \ - (devid) == PCI_CHIP_COFFEELAKE_U_GT3_5) + (devid) == PCI_CHIP_WHISKEYLAKE_U_GT1_1 || \ + (devid) == PCI_CHIP_WHISKEYLAKE_U_GT2_1 || \ + (devid) == PCI_CHIP_WHISKEYLAKE_U_GT3_1 || \ + (devid) == PCI_CHIP_WHISKEYLAKE_U_GT3_2 || \ + (devid) == PCI_CHIP_WHISKEYLAKE_U_GT3_3) #define IS_COFFEELAKE(devid) (IS_CFL_S(devid) || \ IS_CFL_H(devid) || \ -- 2.17.1 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH libdrm 2/2] intel: Introducing Amber Lake platform
Amber Lake uses the same gen graphics as Kaby Lake, including a id that were previously marked as reserved on Kaby Lake, but that now is moved to AML page. So, let's just move it to AML macro that will feed into KBL macro just to keep it better organized to make easier future code review but it will be handled as a KBL. This is a copy of merged i915's commit e364672477a1 ("drm/i915/aml: Introducing Amber Lake platform") Cc: Rodrigo Vivi Signed-off-by: José Roberto de Souza --- intel/intel_chipset.h | 9 ++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/intel/intel_chipset.h b/intel/intel_chipset.h index 44e65f9e..583d6447 100644 --- a/intel/intel_chipset.h +++ b/intel/intel_chipset.h @@ -201,7 +201,6 @@ #define PCI_CHIP_KABYLAKE_ULX_GT1_50x5915 #define PCI_CHIP_KABYLAKE_ULX_GT1 0x590E #define PCI_CHIP_KABYLAKE_ULX_GT2_00x591E -#define PCI_CHIP_KABYLAKE_ULX_GT2_10x591C #define PCI_CHIP_KABYLAKE_DT_GT2 0x5912 #define PCI_CHIP_KABYLAKE_M_GT20x5917 #define PCI_CHIP_KABYLAKE_DT_GT1 0x5902 @@ -213,6 +212,9 @@ #define PCI_CHIP_KABYLAKE_SRV_GT1 0x590A #define PCI_CHIP_KABYLAKE_WKS_GT2 0x591D +#define PCI_CHIP_AMBERLAKE_ULX_GT2_1 0x591C +#define PCI_CHIP_AMBERLAKE_ULX_GT2_2 0x87C0 + #define PCI_CHIP_BROXTON_0 0x0A84 #define PCI_CHIP_BROXTON_1 0x1A84 #define PCI_CHIP_BROXTON_2 0x5A84 @@ -468,12 +470,13 @@ #define IS_KBL_GT2(devid) ((devid) == PCI_CHIP_KABYLAKE_ULT_GT2 || \ (devid) == PCI_CHIP_KABYLAKE_ULT_GT2F || \ (devid) == PCI_CHIP_KABYLAKE_ULX_GT2_0 || \ -(devid) == PCI_CHIP_KABYLAKE_ULX_GT2_1 || \ (devid) == PCI_CHIP_KABYLAKE_DT_GT2|| \ (devid) == PCI_CHIP_KABYLAKE_M_GT2 || \ (devid) == PCI_CHIP_KABYLAKE_HALO_GT2 || \ (devid) == PCI_CHIP_KABYLAKE_SRV_GT2 || \ -(devid) == PCI_CHIP_KABYLAKE_WKS_GT2) +(devid) == PCI_CHIP_KABYLAKE_WKS_GT2 || \ +(devid) == PCI_CHIP_AMBERLAKE_ULX_GT2_1 || \ +(devid) == PCI_CHIP_AMBERLAKE_ULX_GT2_2) #define IS_KBL_GT3(devid) ((devid) == PCI_CHIP_KABYLAKE_ULT_GT3_0 || \ (devid) == PCI_CHIP_KABYLAKE_ULT_GT3_1 || \ -- 2.17.1 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH v3 10/10] drm/i915/debugfs: Print sink PSR status
IGT tests could be improved with sink status, knowing for sure that hardware have activate or exit PSR. Cc: Dhinakaran Pandiyan <dhinakaran.pandi...@intel.com> Cc: Rodrigo Vivi <rodrigo.v...@intel.com> Signed-off-by: José Roberto de Souza <jose.so...@intel.com> --- v3: rebased drivers/gpu/drm/i915/i915_debugfs.c | 29 + 1 file changed, 29 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 1dba2c451255..89dc5b05ec24 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -2603,6 +2603,26 @@ static const char *psr2_live_status(u32 val) return "unknown"; } +static const char *psr_sink_self_refresh_status(u8 val) +{ + static const char * const sink_status[] = { + "inactive", + "transitioning to active", + "active", + "active receiving selective update", + "transitioning to inactive", + "reserved", + "reserved", + "sink internal error" + }; + + val &= DP_PSR_SINK_STATE_MASK; + if (val < ARRAY_SIZE(sink_status)) + return sink_status[val]; + + return "unknown"; +} + static int i915_edp_psr_status(struct seq_file *m, void *data) { struct drm_i915_private *dev_priv = node_to_i915(m->private); @@ -2684,6 +2704,15 @@ static int i915_edp_psr_status(struct seq_file *m, void *data) seq_printf(m, "EDP_PSR2_STATUS: %x [%s]\n", psr2, psr2_live_status(psr2)); } + + if (dev_priv->psr.enabled) { + struct drm_dp_aux *aux = _priv->psr.enabled->aux; + u8 val; + + if (drm_dp_dpcd_readb(aux, DP_PSR_STATUS, ) == 1) + seq_printf(m, "Sink self refresh status: 0x%x [%s]\n", + val, psr_sink_self_refresh_status(val)); + } mutex_unlock(_priv->psr.lock); intel_runtime_pm_put(dev_priv); -- 2.16.3 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH v3 07/10] drm/i915/psr: Use PSR2 macro for PSR2
Cosmetic change. Reviewed-by: Rodrigo Vivi <rodrigo.v...@intel.com> Signed-off-by: José Roberto de Souza <jose.so...@intel.com> --- v3: rebased drivers/gpu/drm/i915/i915_reg.h | 3 ++- drivers/gpu/drm/i915/intel_psr.c | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 9d61ab1288d3..dad0e4b82aab 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -4069,8 +4069,9 @@ enum { #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_IDLE_MASK 0xf #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_STATUS_MMIO(0x6f940) #define EDP_PSR2_STATUS_STATE_MASK (0xf<<28) diff --git a/drivers/gpu/drm/i915/intel_psr.c b/drivers/gpu/drm/i915/intel_psr.c index 5efddd920681..bec455e28943 100644 --- a/drivers/gpu/drm/i915/intel_psr.c +++ b/drivers/gpu/drm/i915/intel_psr.c @@ -382,7 +382,7 @@ static void hsw_activate_psr2(struct intel_dp *intel_dp) uint32_t val; uint8_t sink_latency; - val = idle_frames << EDP_PSR_IDLE_FRAME_SHIFT; + val = idle_frames << EDP_PSR2_IDLE_FRAME_SHIFT; /* FIXME: selective update is probably totally broken because it doesn't * mesh at all with our frontbuffer tracking. And the hw alone isn't -- 2.16.3 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH v3 05/10] drm/i915/psr/cnl: Enable Y-coordinate support in source
For Geminilake and Cannonlake+ the Y-coordinate support must be enabled in PSR2_CTL too. Spec: 7713 and 7720 Cc: Dhinakaran Pandiyan <dhinakaran.pandi...@intel.com> Reviewed-by: Rodrigo Vivi <rodrigo.v...@intel.com> Signed-off-by: José Roberto de Souza <jose.so...@intel.com> --- v3: rebased drivers/gpu/drm/i915/i915_reg.h | 3 +++ drivers/gpu/drm/i915/intel_psr.c | 16 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 33e52cc98d99..9d61ab1288d3 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -4058,6 +4058,8 @@ enum { #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_500(0<<8) @@ -7064,6 +7066,7 @@ enum { #define CHICKEN_TRANS_A 0x420c0 #define CHICKEN_TRANS_B 0x420c4 #define CHICKEN_TRANS(trans) _MMIO_TRANS(trans, CHICKEN_TRANS_A, CHICKEN_TRANS_B) +#define VSC_DATA_SEL_SOFTWARE_CONTROL (1<<25) /* GLK and CNL+ */ #define DDI_TRAINING_OVERRIDE_ENABLE (1<<19) #define DDI_TRAINING_OVERRIDE_VALUE (1<<18) #define DDIE_TRAINING_OVERRIDE_ENABLE (1<<17) /* CHICKEN_TRANS_A only */ diff --git a/drivers/gpu/drm/i915/intel_psr.c b/drivers/gpu/drm/i915/intel_psr.c index fb2d0fe7106b..84e1f8be5c48 100644 --- a/drivers/gpu/drm/i915/intel_psr.c +++ b/drivers/gpu/drm/i915/intel_psr.c @@ -386,8 +386,10 @@ static void hsw_activate_psr2(struct intel_dp *intel_dp) /* 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; + val |= EDP_PSR2_ENABLE | EDP_SU_TRACK_ENABLE; + if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv)) { + val |= EDP_Y_COORDINATE_VALID | EDP_Y_COORDINATE_ENABLE; + } if (drm_dp_dpcd_readb(_dp->aux, DP_SYNCHRONIZATION_LATENCY_IN_SINK, @@ -569,8 +571,14 @@ static void hsw_psr_enable_source(struct intel_dp *intel_dp, hsw_psr_setup_aux(intel_dp); if (dev_priv->psr.psr2_support) { - u32 chicken = PSR2_VSC_ENABLE_PROG_HEADER - | PSR2_ADD_VERTICAL_LINE_COUNT; + u32 chicken = I915_READ(CHICKEN_TRANS(cpu_transcoder)); + + if (INTEL_GEN(dev_priv) == 9 && !IS_GEMINILAKE(dev_priv)) + chicken |= (PSR2_VSC_ENABLE_PROG_HEADER + | PSR2_ADD_VERTICAL_LINE_COUNT); + + else + chicken &= ~VSC_DATA_SEL_SOFTWARE_CONTROL; I915_WRITE(CHICKEN_TRANS(cpu_transcoder), chicken); I915_WRITE(EDP_PSR_DEBUG, -- 2.16.3 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH v3 08/10] drm/i915/psr: Cache sink synchronization latency
This value do not change overtime so better cache it than fetch it every PSR enable. Cc: Dhinakaran Pandiyan <dhinakaran.pandi...@intel.com> Reviewed-by: Rodrigo Vivi <rodrigo.v...@intel.com> Signed-off-by: José Roberto de Souza <jose.so...@intel.com> --- v3: rebased drivers/gpu/drm/i915/i915_drv.h | 1 + drivers/gpu/drm/i915/intel_psr.c | 28 2 files changed, 17 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 46cae097201c..5373b171bb96 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -608,6 +608,7 @@ struct i915_psr { bool alpm; bool has_hw_tracking; bool psr2_enabled; + u8 sink_sync_latency; void (*enable_source)(struct intel_dp *, const struct intel_crtc_state *); diff --git a/drivers/gpu/drm/i915/intel_psr.c b/drivers/gpu/drm/i915/intel_psr.c index bec455e28943..d079cf0b034c 100644 --- a/drivers/gpu/drm/i915/intel_psr.c +++ b/drivers/gpu/drm/i915/intel_psr.c @@ -122,6 +122,18 @@ static bool intel_dp_get_alpm_status(struct intel_dp *intel_dp) return alpm_caps & DP_ALPM_CAP; } +static u8 intel_dp_get_sink_sync_latency(struct intel_dp *intel_dp) +{ + u8 val = 0; + + if (drm_dp_dpcd_readb(_dp->aux, + DP_SYNCHRONIZATION_LATENCY_IN_SINK, ) == 1) + val &= DP_MAX_RESYNC_FRAME_COUNT_MASK; + else + DRM_ERROR("Unable to get sink synchronization latency\n"); + return val; +} + void intel_psr_init_dpcd(struct intel_dp *intel_dp) { struct drm_i915_private *dev_priv = @@ -158,6 +170,8 @@ void intel_psr_init_dpcd(struct intel_dp *intel_dp) intel_dp_get_colorimetry_status(intel_dp); dev_priv->psr.alpm = intel_dp_get_alpm_status(intel_dp); + dev_priv->psr.sink_sync_latency = + intel_dp_get_sink_sync_latency(intel_dp); } } } @@ -379,10 +393,7 @@ static void hsw_activate_psr2(struct intel_dp *intel_dp) * with the 5 or 6 idle patterns. */ uint32_t idle_frames = max(6, dev_priv->vbt.psr.idle_frames); - uint32_t val; - uint8_t sink_latency; - - val = idle_frames << EDP_PSR2_IDLE_FRAME_SHIFT; + u32 val = idle_frames << EDP_PSR2_IDLE_FRAME_SHIFT; /* FIXME: selective update is probably totally broken because it doesn't * mesh at all with our frontbuffer tracking. And the hw alone isn't @@ -392,14 +403,7 @@ static void hsw_activate_psr2(struct intel_dp *intel_dp) val |= EDP_Y_COORDINATE_VALID | EDP_Y_COORDINATE_ENABLE; } - if (drm_dp_dpcd_readb(_dp->aux, - DP_SYNCHRONIZATION_LATENCY_IN_SINK, - _latency) == 1) { - sink_latency &= DP_MAX_RESYNC_FRAME_COUNT_MASK; - } else { - sink_latency = 0; - } - val |= EDP_PSR2_FRAME_BEFORE_SU(sink_latency + 1); + val |= EDP_PSR2_FRAME_BEFORE_SU(dev_priv->psr.sink_sync_latency + 1); if (dev_priv->vbt.psr.tp2_tp3_wakeup_time > 5) val |= EDP_PSR2_TP2_TIME_2500; -- 2.16.3 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH v3 06/10] drm/i915/psr: Do not override PSR2 sink support
Sink can support our PSR2 requirements but userspace can request a resolution that PSR2 hardware do not support, in this case it was overwritten the PSR2 sink support. Adding another flag here, this way if requested resolution changed to a value that PSR2 hardware can handle, PSR2 can be enabled. Cc: Dhinakaran Pandiyan <dhinakaran.pandi...@intel.com> Reviewed-by: Rodrigo Vivi <rodrigo.v...@intel.com> Signed-off-by: José Roberto de Souza <jose.so...@intel.com> --- v3: rebased drivers/gpu/drm/i915/i915_debugfs.c | 4 ++-- drivers/gpu/drm/i915/i915_drv.h | 3 ++- drivers/gpu/drm/i915/intel_psr.c| 33 + 3 files changed, 21 insertions(+), 19 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index ff90577da450..1dba2c451255 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -2630,7 +2630,7 @@ static int i915_edp_psr_status(struct seq_file *m, void *data) yesno(work_busy(_priv->psr.work.work))); if (HAS_DDI(dev_priv)) { - if (dev_priv->psr.psr2_support) + if (dev_priv->psr.psr2_enabled) enabled = I915_READ(EDP_PSR2_CTL) & EDP_PSR2_ENABLE; else enabled = I915_READ(EDP_PSR_CTL) & EDP_PSR_ENABLE; @@ -2678,7 +2678,7 @@ static int i915_edp_psr_status(struct seq_file *m, void *data) seq_printf(m, "Performance_Counter: %u\n", psrperf); } - if (dev_priv->psr.psr2_support) { + if (dev_priv->psr.psr2_enabled) { u32 psr2 = I915_READ(EDP_PSR2_STATUS); seq_printf(m, "EDP_PSR2_STATUS: %x [%s]\n", diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 92cf6f4e9e00..46cae097201c 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -602,11 +602,12 @@ struct i915_psr { bool active; struct delayed_work work; unsigned busy_frontbuffer_bits; - bool psr2_support; + bool sink_psr2_support; bool link_standby; bool colorimetry_support; bool alpm; bool has_hw_tracking; + bool psr2_enabled; void (*enable_source)(struct intel_dp *, const struct intel_crtc_state *); diff --git a/drivers/gpu/drm/i915/intel_psr.c b/drivers/gpu/drm/i915/intel_psr.c index 84e1f8be5c48..5efddd920681 100644 --- a/drivers/gpu/drm/i915/intel_psr.c +++ b/drivers/gpu/drm/i915/intel_psr.c @@ -148,11 +148,12 @@ void intel_psr_init_dpcd(struct intel_dp *intel_dp) * Y-coordinate requirement panels we would need to enable * GTC first. */ - dev_priv->psr.psr2_support = intel_dp_get_y_coord_required(intel_dp); - DRM_DEBUG_KMS("PSR2 %s on sink", - dev_priv->psr.psr2_support ? "supported" : "not supported"); + dev_priv->psr.sink_psr2_support = + intel_dp_get_y_coord_required(intel_dp); + DRM_DEBUG_KMS("PSR2 %s on sink", dev_priv->psr.sink_psr2_support + ? "supported" : "not supported"); - if (dev_priv->psr.psr2_support) { + if (dev_priv->psr.sink_psr2_support) { dev_priv->psr.colorimetry_support = intel_dp_get_colorimetry_status(intel_dp); dev_priv->psr.alpm = @@ -193,7 +194,7 @@ static void hsw_psr_setup_vsc(struct intel_dp *intel_dp, struct drm_i915_private *dev_priv = to_i915(intel_dig_port->base.base.dev); struct edp_vsc_psr psr_vsc; - if (dev_priv->psr.psr2_support) { + if (dev_priv->psr.psr2_enabled) { /* Prepare VSC Header for SU as per EDP 1.4 spec, Table 6.11 */ memset(_vsc, 0, sizeof(psr_vsc)); psr_vsc.sdp_header.HB0 = 0; @@ -265,7 +266,7 @@ static void hsw_psr_enable_sink(struct intel_dp *intel_dp) struct drm_i915_private *dev_priv = to_i915(dev); /* Enable ALPM at sink for psr2 */ - if (dev_priv->psr.psr2_support && dev_priv->psr.alpm) + if (dev_priv->psr.psr2_enabled && dev_priv->psr.alpm) drm_dp_dpcd_writeb(_dp->aux, DP_RECEIVER_ALPM_CONFIG, DP_ALPM_ENABLE); @@ -424,7 +425,7 @@ static void hsw_psr_activate(struct intel_dp *intel_dp) */ /* psr1 and psr2 are mutually exclusive.*/ - if (dev_priv->psr.psr2_support) + if (dev_priv->psr.psr2_enabled) hsw_activate_psr2(intel_dp); else hsw_activate_psr1(intel_
[PATCH v3 04/10] drm/i915/psr: Tie PSR2 support to Y coordinate requirement
Although i915 don't implement aux sync frame through tests was findout that pannels can do selective update when the y-coordinate is also included in SDP, that is why it is required to run PSR2 in i915. So moving to only one place the sink requirements that the actual driver needs to enable PSR2. Also intel_psr2_config_valid() is called every time the crtc config is computed, wasting some time every time it was checking for Y coordinate requirement. This allow us to nuke y_cord_support and some of VSC setup code that was handling a scenario that would never happen(PSR2 without Y coordinate). Also here renaming intel_dp_get_y_cord_status() to intel_dp_get_y_coord_required() as it more accurate to the name and function of bit according to eDP spec. Cc: Rodrigo Vivi <rodrigo.v...@intel.com> Reviewed-by: Dhinakaran Pandiyan <dhinakaran.pandi...@intel.com> Signed-off-by: José Roberto de Souza <jose.so...@intel.com> --- v3: rebased drivers/gpu/drm/i915/i915_drv.h | 1 - drivers/gpu/drm/i915/intel_psr.c | 46 +--- 2 files changed, 19 insertions(+), 28 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index fade9029b6f5..92cf6f4e9e00 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -604,7 +604,6 @@ struct i915_psr { unsigned busy_frontbuffer_bits; bool psr2_support; bool link_standby; - bool y_cord_support; bool colorimetry_support; bool alpm; bool has_hw_tracking; diff --git a/drivers/gpu/drm/i915/intel_psr.c b/drivers/gpu/drm/i915/intel_psr.c index c0a6f63b586f..fb2d0fe7106b 100644 --- a/drivers/gpu/drm/i915/intel_psr.c +++ b/drivers/gpu/drm/i915/intel_psr.c @@ -93,7 +93,7 @@ static void psr_aux_io_power_put(struct intel_dp *intel_dp) intel_display_power_put(dev_priv, psr_aux_domain(intel_dp)); } -static bool intel_dp_get_y_cord_status(struct intel_dp *intel_dp) +static bool intel_dp_get_y_coord_required(struct intel_dp *intel_dp) { uint8_t psr_caps = 0; @@ -130,22 +130,29 @@ void intel_psr_init_dpcd(struct intel_dp *intel_dp) drm_dp_dpcd_read(_dp->aux, DP_PSR_SUPPORT, intel_dp->psr_dpcd, sizeof(intel_dp->psr_dpcd)); - if (intel_dp->psr_dpcd[0] & DP_PSR_IS_SUPPORTED) { + if (intel_dp->psr_dpcd[0]) { dev_priv->psr.sink_support = true; DRM_DEBUG_KMS("Detected EDP PSR Panel.\n"); } if (INTEL_GEN(dev_priv) >= 9 && - (intel_dp->psr_dpcd[0] & DP_PSR2_IS_SUPPORTED)) { - - dev_priv->psr.sink_support = true; - dev_priv->psr.psr2_support = true; + (intel_dp->psr_dpcd[0] == DP_PSR2_WITH_Y_COORD_IS_SUPPORTED)) { + /* +* All panels that supports PSR version 03h (PSR2 + +* Y-coordinate) can handle Y-coordinates in VSC but we are +* only sure that it is going to be used when required by the +* panel. This way panel is capable to do selective update +* without a aux frame sync. +* +* To support PSR version 02h and PSR version 03h without +* Y-coordinate requirement panels we would need to enable +* GTC first. +*/ + dev_priv->psr.psr2_support = intel_dp_get_y_coord_required(intel_dp); DRM_DEBUG_KMS("PSR2 %s on sink", dev_priv->psr.psr2_support ? "supported" : "not supported"); if (dev_priv->psr.psr2_support) { - dev_priv->psr.y_cord_support = - intel_dp_get_y_cord_status(intel_dp); dev_priv->psr.colorimetry_support = intel_dp_get_colorimetry_status(intel_dp); dev_priv->psr.alpm = @@ -191,16 +198,12 @@ static void hsw_psr_setup_vsc(struct intel_dp *intel_dp, memset(_vsc, 0, sizeof(psr_vsc)); psr_vsc.sdp_header.HB0 = 0; psr_vsc.sdp_header.HB1 = 0x7; - if (dev_priv->psr.colorimetry_support && - dev_priv->psr.y_cord_support) { + if (dev_priv->psr.colorimetry_support) { psr_vsc.sdp_header.HB2 = 0x5; psr_vsc.sdp_header.HB3 = 0x13; - } else if (dev_priv->psr.y_cord_support) { + } else { psr_vsc.sdp_header.HB2 = 0x4; psr_vsc.sdp_header.HB3 = 0xe; - } else { - psr_vsc.sdp_header.HB2 = 0x3; - psr_vsc.sdp_header.HB3 = 0xc; } } else { /* Prepare VSC packet as
[PATCH v3 03/10] drm/i915/psr: Nuke aux frame sync
eDP spec states that aux frame is required to do PSR2 selective update but i915 don't fully implement it. It sends the aux frame sync messages but the value is always zero as the GTC is not enabled in driver. Through tests was findout that pannels can do selective update when the y-coordinate is also included in SDP, that is why it is required to run PSR2 in i915. A dummy value is not useful at all to sink, so removing everything related to aux frame sync, if GTC is enabled we can bring this back. Cc: Vathsala Nagaraju <vathsala.nagar...@intel.com> Acked-by: Rodrigo Vivi <rodrigo.v...@intel.com> Reviewed-by: Dhinakaran Pandiyan <dhinakaran.pandi...@intel.com> Signed-off-by: José Roberto de Souza <jose.so...@intel.com> --- v3: rebased drivers/gpu/drm/i915/i915_drv.h | 1 - drivers/gpu/drm/i915/intel_psr.c | 24 +--- 2 files changed, 1 insertion(+), 24 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 800230ba1c3b..fade9029b6f5 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -603,7 +603,6 @@ struct i915_psr { struct delayed_work work; unsigned busy_frontbuffer_bits; bool psr2_support; - bool aux_frame_sync; bool link_standby; bool y_cord_support; bool colorimetry_support; diff --git a/drivers/gpu/drm/i915/intel_psr.c b/drivers/gpu/drm/i915/intel_psr.c index b8e083e10029..c0a6f63b586f 100644 --- a/drivers/gpu/drm/i915/intel_psr.c +++ b/drivers/gpu/drm/i915/intel_psr.c @@ -137,16 +137,9 @@ void intel_psr_init_dpcd(struct intel_dp *intel_dp) if (INTEL_GEN(dev_priv) >= 9 && (intel_dp->psr_dpcd[0] & DP_PSR2_IS_SUPPORTED)) { - uint8_t frame_sync_cap; dev_priv->psr.sink_support = true; - if (drm_dp_dpcd_readb(_dp->aux, - DP_SINK_DEVICE_AUX_FRAME_SYNC_CAP, - _sync_cap) != 1) - frame_sync_cap = 0; - dev_priv->psr.aux_frame_sync = frame_sync_cap & DP_AUX_FRAME_SYNC_CAP; - /* PSR2 needs frame sync as well */ - dev_priv->psr.psr2_support = dev_priv->psr.aux_frame_sync; + dev_priv->psr.psr2_support = true; DRM_DEBUG_KMS("PSR2 %s on sink", dev_priv->psr.psr2_support ? "supported" : "not supported"); @@ -268,12 +261,6 @@ static void hsw_psr_enable_sink(struct intel_dp *intel_dp) struct drm_device *dev = dig_port->base.base.dev; struct drm_i915_private *dev_priv = to_i915(dev); - - /* Enable AUX frame sync at sink */ - if (dev_priv->psr.aux_frame_sync) - drm_dp_dpcd_writeb(_dp->aux, - DP_SINK_DEVICE_AUX_FRAME_SYNC_CONF, - DP_AUX_FRAME_SYNC_ENABLE); /* Enable ALPM at sink for psr2 */ if (dev_priv->psr.psr2_support && dev_priv->psr.alpm) drm_dp_dpcd_writeb(_dp->aux, @@ -712,11 +699,6 @@ static void hsw_psr_disable(struct intel_dp *intel_dp, i915_reg_t psr_status; u32 psr_status_mask; - if (dev_priv->psr.aux_frame_sync) - drm_dp_dpcd_writeb(_dp->aux, - DP_SINK_DEVICE_AUX_FRAME_SYNC_CONF, - 0); - if (dev_priv->psr.psr2_support) { psr_status = EDP_PSR2_STATUS; psr_status_mask = EDP_PSR2_STATUS_STATE_MASK; @@ -860,10 +842,6 @@ static void intel_psr_exit(struct drm_i915_private *dev_priv) return; if (HAS_DDI(dev_priv)) { - if (dev_priv->psr.aux_frame_sync) - drm_dp_dpcd_writeb(_dp->aux, - DP_SINK_DEVICE_AUX_FRAME_SYNC_CONF, - 0); if (dev_priv->psr.psr2_support) { val = I915_READ(EDP_PSR2_CTL); WARN_ON(!(val & EDP_PSR2_ENABLE)); -- 2.16.3 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH v3 02/10] drm: Add DP last received PSR SDP VSC register and bits
This is a register to help debug what is in the last SDP VSC packet revived by sink. Signed-off-by: José Roberto de Souza <jose.so...@intel.com> Reviewed-by: Rodrigo Vivi <rodrigo.v...@intel.com> --- v3: rebased include/drm/drm_dp_helper.h | 9 + 1 file changed, 9 insertions(+) diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h index 0bac0c7d0dec..91c9bcd4196f 100644 --- a/include/drm/drm_dp_helper.h +++ b/include/drm/drm_dp_helper.h @@ -795,6 +795,15 @@ # define DP_LAST_ACTUAL_SYNCHRONIZATION_LATENCY_MASK (0xf << 4) # define DP_LAST_ACTUAL_SYNCHRONIZATION_LATENCY_SHIFT 4 +#define DP_LAST_RECEIVED_PSR_SDP 0x200a /* eDP 1.2 */ +# define DP_PSR_STATE_BIT (1 << 0) /* eDP 1.2 */ +# define DP_UPDATE_RFB_BIT (1 << 1) /* eDP 1.2 */ +# define DP_CRC_VALID_BIT (1 << 2) /* eDP 1.2 */ +# define DP_SU_VALID (1 << 3) /* eDP 1.4 */ +# define DP_FIRST_SCAN_LINE_SU_REGION (1 << 4) /* eDP 1.4 */ +# define DP_LAST_SCAN_LINE_SU_REGION (1 << 5) /* eDP 1.4 */ +# define DP_Y_COORDINATE_VALID (1 << 6) /* eDP 1.4a */ + #define DP_RECEIVER_ALPM_STATUS0x200b /* eDP 1.4 */ # define DP_ALPM_LOCK_TIMEOUT_ERROR(1 << 0) -- 2.16.3 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH v3 09/10] drm/i915/psr: Set DPCD PSR2 enable bit when needed
In the 2 eDP1.4a pannels tested set or not set bit have no effect but is better set it and comply with specification. Signed-off-by: José Roberto de Souza <jose.so...@intel.com> Cc: Dhinakaran Pandiyan <dhinakaran.pandi...@intel.com> Reviewed-by: Rodrigo Vivi <rodrigo.v...@intel.com> --- v3: rebased drivers/gpu/drm/i915/intel_psr.c | 11 ++- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_psr.c b/drivers/gpu/drm/i915/intel_psr.c index d079cf0b034c..2d53f7398a6d 100644 --- a/drivers/gpu/drm/i915/intel_psr.c +++ b/drivers/gpu/drm/i915/intel_psr.c @@ -278,18 +278,19 @@ static void hsw_psr_enable_sink(struct intel_dp *intel_dp) struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); struct drm_device *dev = dig_port->base.base.dev; struct drm_i915_private *dev_priv = to_i915(dev); + u8 dpcd_val = DP_PSR_ENABLE; /* Enable ALPM at sink for psr2 */ if (dev_priv->psr.psr2_enabled && dev_priv->psr.alpm) drm_dp_dpcd_writeb(_dp->aux, DP_RECEIVER_ALPM_CONFIG, DP_ALPM_ENABLE); + + if (dev_priv->psr.psr2_enabled) + dpcd_val |= DP_PSR_ENABLE_PSR2; if (dev_priv->psr.link_standby) - drm_dp_dpcd_writeb(_dp->aux, DP_PSR_EN_CFG, - DP_PSR_ENABLE | DP_PSR_MAIN_LINK_ACTIVE); - else - drm_dp_dpcd_writeb(_dp->aux, DP_PSR_EN_CFG, - DP_PSR_ENABLE); + dpcd_val |= DP_PSR_MAIN_LINK_ACTIVE; + 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); } -- 2.16.3 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH v3 01/10] drm: Add DP PSR2 sink enable bit
To comply with eDP1.4a this bit should be set when enabling PSR2. Signed-off-by: José Roberto de Souza <jose.so...@intel.com> Reviewed-by: Rodrigo Vivi <rodrigo.v...@intel.com> --- v3: rebased 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 62903bae0221..0bac0c7d0dec 100644 --- a/include/drm/drm_dp_helper.h +++ b/include/drm/drm_dp_helper.h @@ -478,6 +478,7 @@ # define DP_PSR_FRAME_CAPTURE (1 << 3) # define DP_PSR_SELECTIVE_UPDATE (1 << 4) # define DP_PSR_IRQ_HPD_WITH_CRC_ERRORS (1 << 5) +# define DP_PSR_ENABLE_PSR2(1 << 6) /* eDP 1.4a */ #define DP_ADAPTER_CTRL0x1a0 # define DP_ADAPTER_CTRL_FORCE_LOAD_SENSE (1 << 0) -- 2.16.3 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH v2 03/10] drm/i915/psr: Nuke aux frame sync
eDP spec states that aux frame is required to do PSR2 selective update but i915 don't fully implement it. It sends the aux frame sync messages but the value is always zero as the GTC is not enabled in driver. Through tests was findout that pannels can do selective update when the y-coordinate is also included in SDP, that is why it is required to run PSR2 in i915. A dummy value is not useful at all to sink, so removing everything related to aux frame sync, if GTC is enabled we can bring this back. Cc: Vathsala Nagaraju <vathsala.nagar...@intel.com> Acked-by: Rodrigo Vivi <rodrigo.v...@intel.com> Reviewed-by: Dhinakaran Pandiyan <dhinakaran.pandi...@intel.com> Signed-off-by: José Roberto de Souza <jose.so...@intel.com> --- drivers/gpu/drm/i915/i915_drv.h | 1 - drivers/gpu/drm/i915/intel_psr.c | 24 +--- 2 files changed, 1 insertion(+), 24 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 800230ba1c3b..fade9029b6f5 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -603,7 +603,6 @@ struct i915_psr { struct delayed_work work; unsigned busy_frontbuffer_bits; bool psr2_support; - bool aux_frame_sync; bool link_standby; bool y_cord_support; bool colorimetry_support; diff --git a/drivers/gpu/drm/i915/intel_psr.c b/drivers/gpu/drm/i915/intel_psr.c index b8e083e10029..c0a6f63b586f 100644 --- a/drivers/gpu/drm/i915/intel_psr.c +++ b/drivers/gpu/drm/i915/intel_psr.c @@ -137,16 +137,9 @@ void intel_psr_init_dpcd(struct intel_dp *intel_dp) if (INTEL_GEN(dev_priv) >= 9 && (intel_dp->psr_dpcd[0] & DP_PSR2_IS_SUPPORTED)) { - uint8_t frame_sync_cap; dev_priv->psr.sink_support = true; - if (drm_dp_dpcd_readb(_dp->aux, - DP_SINK_DEVICE_AUX_FRAME_SYNC_CAP, - _sync_cap) != 1) - frame_sync_cap = 0; - dev_priv->psr.aux_frame_sync = frame_sync_cap & DP_AUX_FRAME_SYNC_CAP; - /* PSR2 needs frame sync as well */ - dev_priv->psr.psr2_support = dev_priv->psr.aux_frame_sync; + dev_priv->psr.psr2_support = true; DRM_DEBUG_KMS("PSR2 %s on sink", dev_priv->psr.psr2_support ? "supported" : "not supported"); @@ -268,12 +261,6 @@ static void hsw_psr_enable_sink(struct intel_dp *intel_dp) struct drm_device *dev = dig_port->base.base.dev; struct drm_i915_private *dev_priv = to_i915(dev); - - /* Enable AUX frame sync at sink */ - if (dev_priv->psr.aux_frame_sync) - drm_dp_dpcd_writeb(_dp->aux, - DP_SINK_DEVICE_AUX_FRAME_SYNC_CONF, - DP_AUX_FRAME_SYNC_ENABLE); /* Enable ALPM at sink for psr2 */ if (dev_priv->psr.psr2_support && dev_priv->psr.alpm) drm_dp_dpcd_writeb(_dp->aux, @@ -712,11 +699,6 @@ static void hsw_psr_disable(struct intel_dp *intel_dp, i915_reg_t psr_status; u32 psr_status_mask; - if (dev_priv->psr.aux_frame_sync) - drm_dp_dpcd_writeb(_dp->aux, - DP_SINK_DEVICE_AUX_FRAME_SYNC_CONF, - 0); - if (dev_priv->psr.psr2_support) { psr_status = EDP_PSR2_STATUS; psr_status_mask = EDP_PSR2_STATUS_STATE_MASK; @@ -860,10 +842,6 @@ static void intel_psr_exit(struct drm_i915_private *dev_priv) return; if (HAS_DDI(dev_priv)) { - if (dev_priv->psr.aux_frame_sync) - drm_dp_dpcd_writeb(_dp->aux, - DP_SINK_DEVICE_AUX_FRAME_SYNC_CONF, - 0); if (dev_priv->psr.psr2_support) { val = I915_READ(EDP_PSR2_CTL); WARN_ON(!(val & EDP_PSR2_ENABLE)); -- 2.16.2 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH v2 04/10] drm/i915/psr: Tie PSR2 support to Y coordinate requirement
Although i915 don't implement aux sync frame through tests was findout that pannels can do selective update when the y-coordinate is also included in SDP, that is why it is required to run PSR2 in i915. So moving to only one place the sink requirements that the actual driver needs to enable PSR2. Also intel_psr2_config_valid() is called every time the crtc config is computed, wasting some time every time it was checking for Y coordinate requirement. This allow us to nuke y_cord_support and some of VSC setup code that was handling a scenario that would never happen(PSR2 without Y coordinate). Also here renaming intel_dp_get_y_cord_status() to intel_dp_get_y_coord_required() as it more accurate to the name and function of bit according to eDP spec. Cc: Rodrigo Vivi <rodrigo.v...@intel.com> Reviewed-by: Dhinakaran Pandiyan <dhinakaran.pandi...@intel.com> Signed-off-by: José Roberto de Souza <jose.so...@intel.com> --- drivers/gpu/drm/i915/i915_drv.h | 1 - drivers/gpu/drm/i915/intel_psr.c | 46 +--- 2 files changed, 19 insertions(+), 28 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index fade9029b6f5..92cf6f4e9e00 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -604,7 +604,6 @@ struct i915_psr { unsigned busy_frontbuffer_bits; bool psr2_support; bool link_standby; - bool y_cord_support; bool colorimetry_support; bool alpm; bool has_hw_tracking; diff --git a/drivers/gpu/drm/i915/intel_psr.c b/drivers/gpu/drm/i915/intel_psr.c index c0a6f63b586f..fb2d0fe7106b 100644 --- a/drivers/gpu/drm/i915/intel_psr.c +++ b/drivers/gpu/drm/i915/intel_psr.c @@ -93,7 +93,7 @@ static void psr_aux_io_power_put(struct intel_dp *intel_dp) intel_display_power_put(dev_priv, psr_aux_domain(intel_dp)); } -static bool intel_dp_get_y_cord_status(struct intel_dp *intel_dp) +static bool intel_dp_get_y_coord_required(struct intel_dp *intel_dp) { uint8_t psr_caps = 0; @@ -130,22 +130,29 @@ void intel_psr_init_dpcd(struct intel_dp *intel_dp) drm_dp_dpcd_read(_dp->aux, DP_PSR_SUPPORT, intel_dp->psr_dpcd, sizeof(intel_dp->psr_dpcd)); - if (intel_dp->psr_dpcd[0] & DP_PSR_IS_SUPPORTED) { + if (intel_dp->psr_dpcd[0]) { dev_priv->psr.sink_support = true; DRM_DEBUG_KMS("Detected EDP PSR Panel.\n"); } if (INTEL_GEN(dev_priv) >= 9 && - (intel_dp->psr_dpcd[0] & DP_PSR2_IS_SUPPORTED)) { - - dev_priv->psr.sink_support = true; - dev_priv->psr.psr2_support = true; + (intel_dp->psr_dpcd[0] == DP_PSR2_WITH_Y_COORD_IS_SUPPORTED)) { + /* +* All panels that supports PSR version 03h (PSR2 + +* Y-coordinate) can handle Y-coordinates in VSC but we are +* only sure that it is going to be used when required by the +* panel. This way panel is capable to do selective update +* without a aux frame sync. +* +* To support PSR version 02h and PSR version 03h without +* Y-coordinate requirement panels we would need to enable +* GTC first. +*/ + dev_priv->psr.psr2_support = intel_dp_get_y_coord_required(intel_dp); DRM_DEBUG_KMS("PSR2 %s on sink", dev_priv->psr.psr2_support ? "supported" : "not supported"); if (dev_priv->psr.psr2_support) { - dev_priv->psr.y_cord_support = - intel_dp_get_y_cord_status(intel_dp); dev_priv->psr.colorimetry_support = intel_dp_get_colorimetry_status(intel_dp); dev_priv->psr.alpm = @@ -191,16 +198,12 @@ static void hsw_psr_setup_vsc(struct intel_dp *intel_dp, memset(_vsc, 0, sizeof(psr_vsc)); psr_vsc.sdp_header.HB0 = 0; psr_vsc.sdp_header.HB1 = 0x7; - if (dev_priv->psr.colorimetry_support && - dev_priv->psr.y_cord_support) { + if (dev_priv->psr.colorimetry_support) { psr_vsc.sdp_header.HB2 = 0x5; psr_vsc.sdp_header.HB3 = 0x13; - } else if (dev_priv->psr.y_cord_support) { + } else { psr_vsc.sdp_header.HB2 = 0x4; psr_vsc.sdp_header.HB3 = 0xe; - } else { - psr_vsc.sdp_header.HB2 = 0x3; - psr_vsc.sdp_header.HB3 = 0xc; } } else { /* Prepare VSC packet as
[PATCH v2 06/10] drm/i915/psr: Do not override PSR2 sink support
Sink can support our PSR2 requirements but userspace can request a resolution that PSR2 hardware do not support, in this case it was overwritten the PSR2 sink support. Adding another flag here, this way if requested resolution changed to a value that PSR2 hardware can handle, PSR2 can be enabled. Cc: Dhinakaran Pandiyan <dhinakaran.pandi...@intel.com> Reviewed-by: Rodrigo Vivi <rodrigo.v...@intel.com> Signed-off-by: José Roberto de Souza <jose.so...@intel.com> --- drivers/gpu/drm/i915/i915_debugfs.c | 4 ++-- drivers/gpu/drm/i915/i915_drv.h | 3 ++- drivers/gpu/drm/i915/intel_psr.c| 33 + 3 files changed, 21 insertions(+), 19 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 7816cd53100a..16f9977995df 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -2630,7 +2630,7 @@ static int i915_edp_psr_status(struct seq_file *m, void *data) yesno(work_busy(_priv->psr.work.work))); if (HAS_DDI(dev_priv)) { - if (dev_priv->psr.psr2_support) + if (dev_priv->psr.psr2_enabled) enabled = I915_READ(EDP_PSR2_CTL) & EDP_PSR2_ENABLE; else enabled = I915_READ(EDP_PSR_CTL) & EDP_PSR_ENABLE; @@ -2678,7 +2678,7 @@ static int i915_edp_psr_status(struct seq_file *m, void *data) seq_printf(m, "Performance_Counter: %u\n", psrperf); } - if (dev_priv->psr.psr2_support) { + if (dev_priv->psr.psr2_enabled) { u32 psr2 = I915_READ(EDP_PSR2_STATUS); seq_printf(m, "EDP_PSR2_STATUS: %x [%s]\n", diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 92cf6f4e9e00..46cae097201c 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -602,11 +602,12 @@ struct i915_psr { bool active; struct delayed_work work; unsigned busy_frontbuffer_bits; - bool psr2_support; + bool sink_psr2_support; bool link_standby; bool colorimetry_support; bool alpm; bool has_hw_tracking; + bool psr2_enabled; void (*enable_source)(struct intel_dp *, const struct intel_crtc_state *); diff --git a/drivers/gpu/drm/i915/intel_psr.c b/drivers/gpu/drm/i915/intel_psr.c index 84e1f8be5c48..5efddd920681 100644 --- a/drivers/gpu/drm/i915/intel_psr.c +++ b/drivers/gpu/drm/i915/intel_psr.c @@ -148,11 +148,12 @@ void intel_psr_init_dpcd(struct intel_dp *intel_dp) * Y-coordinate requirement panels we would need to enable * GTC first. */ - dev_priv->psr.psr2_support = intel_dp_get_y_coord_required(intel_dp); - DRM_DEBUG_KMS("PSR2 %s on sink", - dev_priv->psr.psr2_support ? "supported" : "not supported"); + dev_priv->psr.sink_psr2_support = + intel_dp_get_y_coord_required(intel_dp); + DRM_DEBUG_KMS("PSR2 %s on sink", dev_priv->psr.sink_psr2_support + ? "supported" : "not supported"); - if (dev_priv->psr.psr2_support) { + if (dev_priv->psr.sink_psr2_support) { dev_priv->psr.colorimetry_support = intel_dp_get_colorimetry_status(intel_dp); dev_priv->psr.alpm = @@ -193,7 +194,7 @@ static void hsw_psr_setup_vsc(struct intel_dp *intel_dp, struct drm_i915_private *dev_priv = to_i915(intel_dig_port->base.base.dev); struct edp_vsc_psr psr_vsc; - if (dev_priv->psr.psr2_support) { + if (dev_priv->psr.psr2_enabled) { /* Prepare VSC Header for SU as per EDP 1.4 spec, Table 6.11 */ memset(_vsc, 0, sizeof(psr_vsc)); psr_vsc.sdp_header.HB0 = 0; @@ -265,7 +266,7 @@ static void hsw_psr_enable_sink(struct intel_dp *intel_dp) struct drm_i915_private *dev_priv = to_i915(dev); /* Enable ALPM at sink for psr2 */ - if (dev_priv->psr.psr2_support && dev_priv->psr.alpm) + if (dev_priv->psr.psr2_enabled && dev_priv->psr.alpm) drm_dp_dpcd_writeb(_dp->aux, DP_RECEIVER_ALPM_CONFIG, DP_ALPM_ENABLE); @@ -424,7 +425,7 @@ static void hsw_psr_activate(struct intel_dp *intel_dp) */ /* psr1 and psr2 are mutually exclusive.*/ - if (dev_priv->psr.psr2_support) + if (dev_priv->psr.psr2_enabled) hsw_activate_psr2(intel_dp); else hsw_activate_psr1(intel_
[PATCH v2 05/10] drm/i915/psr/cnl: Enable Y-coordinate support in source
From: "Souza, Jose" <jose.so...@intel.com> For Geminilake and Cannonlake+ the Y-coordinate support must be enabled in PSR2_CTL too. Spec: 7713 and 7720 Cc: Dhinakaran Pandiyan <dhinakaran.pandi...@intel.com> Reviewed-by: Rodrigo Vivi <rodrigo.v...@intel.com> Signed-off-by: José Roberto de Souza <jose.so...@intel.com> --- drivers/gpu/drm/i915/i915_reg.h | 3 +++ drivers/gpu/drm/i915/intel_psr.c | 16 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 1bca695f404b..1c6f463bc919 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -4052,6 +4052,8 @@ enum { #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_500(0<<8) @@ -7058,6 +7060,7 @@ enum { #define CHICKEN_TRANS_A 0x420c0 #define CHICKEN_TRANS_B 0x420c4 #define CHICKEN_TRANS(trans) _MMIO_TRANS(trans, CHICKEN_TRANS_A, CHICKEN_TRANS_B) +#define VSC_DATA_SEL_SOFTWARE_CONTROL (1<<25) /* GLK and CNL+ */ #define DDI_TRAINING_OVERRIDE_ENABLE (1<<19) #define DDI_TRAINING_OVERRIDE_VALUE (1<<18) #define DDIE_TRAINING_OVERRIDE_ENABLE (1<<17) /* CHICKEN_TRANS_A only */ diff --git a/drivers/gpu/drm/i915/intel_psr.c b/drivers/gpu/drm/i915/intel_psr.c index fb2d0fe7106b..84e1f8be5c48 100644 --- a/drivers/gpu/drm/i915/intel_psr.c +++ b/drivers/gpu/drm/i915/intel_psr.c @@ -386,8 +386,10 @@ static void hsw_activate_psr2(struct intel_dp *intel_dp) /* 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; + val |= EDP_PSR2_ENABLE | EDP_SU_TRACK_ENABLE; + if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv)) { + val |= EDP_Y_COORDINATE_VALID | EDP_Y_COORDINATE_ENABLE; + } if (drm_dp_dpcd_readb(_dp->aux, DP_SYNCHRONIZATION_LATENCY_IN_SINK, @@ -569,8 +571,14 @@ static void hsw_psr_enable_source(struct intel_dp *intel_dp, hsw_psr_setup_aux(intel_dp); if (dev_priv->psr.psr2_support) { - u32 chicken = PSR2_VSC_ENABLE_PROG_HEADER - | PSR2_ADD_VERTICAL_LINE_COUNT; + u32 chicken = I915_READ(CHICKEN_TRANS(cpu_transcoder)); + + if (INTEL_GEN(dev_priv) == 9 && !IS_GEMINILAKE(dev_priv)) + chicken |= (PSR2_VSC_ENABLE_PROG_HEADER + | PSR2_ADD_VERTICAL_LINE_COUNT); + + else + chicken &= ~VSC_DATA_SEL_SOFTWARE_CONTROL; I915_WRITE(CHICKEN_TRANS(cpu_transcoder), chicken); I915_WRITE(EDP_PSR_DEBUG, -- 2.16.2 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH v2 09/10] drm/i915/psr: Set DPCD PSR2 enable bit when needed
In the 2 eDP1.4a pannels tested set or not set bit have no effect but is better set it and comply with specification. Signed-off-by: José Roberto de Souza <jose.so...@intel.com> Cc: Dhinakaran Pandiyan <dhinakaran.pandi...@intel.com> Reviewed-by: Rodrigo Vivi <rodrigo.v...@intel.com> --- drivers/gpu/drm/i915/intel_psr.c | 11 ++- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_psr.c b/drivers/gpu/drm/i915/intel_psr.c index d079cf0b034c..2d53f7398a6d 100644 --- a/drivers/gpu/drm/i915/intel_psr.c +++ b/drivers/gpu/drm/i915/intel_psr.c @@ -278,18 +278,19 @@ static void hsw_psr_enable_sink(struct intel_dp *intel_dp) struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); struct drm_device *dev = dig_port->base.base.dev; struct drm_i915_private *dev_priv = to_i915(dev); + u8 dpcd_val = DP_PSR_ENABLE; /* Enable ALPM at sink for psr2 */ if (dev_priv->psr.psr2_enabled && dev_priv->psr.alpm) drm_dp_dpcd_writeb(_dp->aux, DP_RECEIVER_ALPM_CONFIG, DP_ALPM_ENABLE); + + if (dev_priv->psr.psr2_enabled) + dpcd_val |= DP_PSR_ENABLE_PSR2; if (dev_priv->psr.link_standby) - drm_dp_dpcd_writeb(_dp->aux, DP_PSR_EN_CFG, - DP_PSR_ENABLE | DP_PSR_MAIN_LINK_ACTIVE); - else - drm_dp_dpcd_writeb(_dp->aux, DP_PSR_EN_CFG, - DP_PSR_ENABLE); + dpcd_val |= DP_PSR_MAIN_LINK_ACTIVE; + 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); } -- 2.16.2 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH v2 10/10] drm/i915/debugfs: Print sink PSR status
IGT tests could be improved with sink status, knowing for sure that hardware have activate or exit PSR. Cc: Dhinakaran Pandiyan <dhinakaran.pandi...@intel.com> Cc: Rodrigo Vivi <rodrigo.v...@intel.com> Signed-off-by: José Roberto de Souza <jose.so...@intel.com> --- drivers/gpu/drm/i915/i915_debugfs.c | 29 + 1 file changed, 29 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 16f9977995df..91a8f70ffdd3 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -2603,6 +2603,26 @@ static const char *psr2_live_status(u32 val) return "unknown"; } +static const char *psr_sink_self_refresh_status(u8 val) +{ + static const char * const sink_status[] = { + "inactive", + "transitioning to active", + "active", + "active receiving selective update", + "transitioning to inactive", + "reserved", + "reserved", + "sink internal error" + }; + + val &= DP_PSR_SINK_STATE_MASK; + if (val < ARRAY_SIZE(sink_status)) + return sink_status[val]; + + return "unknown"; +} + static int i915_edp_psr_status(struct seq_file *m, void *data) { struct drm_i915_private *dev_priv = node_to_i915(m->private); @@ -2684,6 +2704,15 @@ static int i915_edp_psr_status(struct seq_file *m, void *data) seq_printf(m, "EDP_PSR2_STATUS: %x [%s]\n", psr2, psr2_live_status(psr2)); } + + if (dev_priv->psr.enabled) { + struct drm_dp_aux *aux = _priv->psr.enabled->aux; + u8 val; + + if (drm_dp_dpcd_readb(aux, DP_PSR_STATUS, ) == 1) + seq_printf(m, "Sink self refresh status: 0x%x [%s]\n", + val, psr_sink_self_refresh_status(val)); + } mutex_unlock(_priv->psr.lock); intel_runtime_pm_put(dev_priv); -- 2.16.2 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH v2 01/10] drm: Add DP PSR2 sink enable bit
To comply with eDP1.4a this bit should be set when enabling PSR2. Signed-off-by: José Roberto de Souza <jose.so...@intel.com> Reviewed-by: Rodrigo Vivi <rodrigo.v...@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 62903bae0221..0bac0c7d0dec 100644 --- a/include/drm/drm_dp_helper.h +++ b/include/drm/drm_dp_helper.h @@ -478,6 +478,7 @@ # define DP_PSR_FRAME_CAPTURE (1 << 3) # define DP_PSR_SELECTIVE_UPDATE (1 << 4) # define DP_PSR_IRQ_HPD_WITH_CRC_ERRORS (1 << 5) +# define DP_PSR_ENABLE_PSR2(1 << 6) /* eDP 1.4a */ #define DP_ADAPTER_CTRL0x1a0 # define DP_ADAPTER_CTRL_FORCE_LOAD_SENSE (1 << 0) -- 2.16.2 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH v2 08/10] drm/i915/psr: Cache sink synchronization latency
This value do not change overtime so better cache it than fetch it every PSR enable. Cc: Dhinakaran Pandiyan <dhinakaran.pandi...@intel.com> Reviewed-by: Rodrigo Vivi <rodrigo.v...@intel.com> Signed-off-by: José Roberto de Souza <jose.so...@intel.com> --- drivers/gpu/drm/i915/i915_drv.h | 1 + drivers/gpu/drm/i915/intel_psr.c | 28 2 files changed, 17 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 46cae097201c..5373b171bb96 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -608,6 +608,7 @@ struct i915_psr { bool alpm; bool has_hw_tracking; bool psr2_enabled; + u8 sink_sync_latency; void (*enable_source)(struct intel_dp *, const struct intel_crtc_state *); diff --git a/drivers/gpu/drm/i915/intel_psr.c b/drivers/gpu/drm/i915/intel_psr.c index bec455e28943..d079cf0b034c 100644 --- a/drivers/gpu/drm/i915/intel_psr.c +++ b/drivers/gpu/drm/i915/intel_psr.c @@ -122,6 +122,18 @@ static bool intel_dp_get_alpm_status(struct intel_dp *intel_dp) return alpm_caps & DP_ALPM_CAP; } +static u8 intel_dp_get_sink_sync_latency(struct intel_dp *intel_dp) +{ + u8 val = 0; + + if (drm_dp_dpcd_readb(_dp->aux, + DP_SYNCHRONIZATION_LATENCY_IN_SINK, ) == 1) + val &= DP_MAX_RESYNC_FRAME_COUNT_MASK; + else + DRM_ERROR("Unable to get sink synchronization latency\n"); + return val; +} + void intel_psr_init_dpcd(struct intel_dp *intel_dp) { struct drm_i915_private *dev_priv = @@ -158,6 +170,8 @@ void intel_psr_init_dpcd(struct intel_dp *intel_dp) intel_dp_get_colorimetry_status(intel_dp); dev_priv->psr.alpm = intel_dp_get_alpm_status(intel_dp); + dev_priv->psr.sink_sync_latency = + intel_dp_get_sink_sync_latency(intel_dp); } } } @@ -379,10 +393,7 @@ static void hsw_activate_psr2(struct intel_dp *intel_dp) * with the 5 or 6 idle patterns. */ uint32_t idle_frames = max(6, dev_priv->vbt.psr.idle_frames); - uint32_t val; - uint8_t sink_latency; - - val = idle_frames << EDP_PSR2_IDLE_FRAME_SHIFT; + u32 val = idle_frames << EDP_PSR2_IDLE_FRAME_SHIFT; /* FIXME: selective update is probably totally broken because it doesn't * mesh at all with our frontbuffer tracking. And the hw alone isn't @@ -392,14 +403,7 @@ static void hsw_activate_psr2(struct intel_dp *intel_dp) val |= EDP_Y_COORDINATE_VALID | EDP_Y_COORDINATE_ENABLE; } - if (drm_dp_dpcd_readb(_dp->aux, - DP_SYNCHRONIZATION_LATENCY_IN_SINK, - _latency) == 1) { - sink_latency &= DP_MAX_RESYNC_FRAME_COUNT_MASK; - } else { - sink_latency = 0; - } - val |= EDP_PSR2_FRAME_BEFORE_SU(sink_latency + 1); + val |= EDP_PSR2_FRAME_BEFORE_SU(dev_priv->psr.sink_sync_latency + 1); if (dev_priv->vbt.psr.tp2_tp3_wakeup_time > 5) val |= EDP_PSR2_TP2_TIME_2500; -- 2.16.2 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH v2 02/10] drm: Add DP last received PSR SDP VSC register and bits
This is a register to help debug what is in the last SDP VSC packet revived by sink. Signed-off-by: José Roberto de Souza <jose.so...@intel.com> Reviewed-by: Rodrigo Vivi <rodrigo.v...@intel.com> --- include/drm/drm_dp_helper.h | 9 + 1 file changed, 9 insertions(+) diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h index 0bac0c7d0dec..91c9bcd4196f 100644 --- a/include/drm/drm_dp_helper.h +++ b/include/drm/drm_dp_helper.h @@ -795,6 +795,15 @@ # define DP_LAST_ACTUAL_SYNCHRONIZATION_LATENCY_MASK (0xf << 4) # define DP_LAST_ACTUAL_SYNCHRONIZATION_LATENCY_SHIFT 4 +#define DP_LAST_RECEIVED_PSR_SDP 0x200a /* eDP 1.2 */ +# define DP_PSR_STATE_BIT (1 << 0) /* eDP 1.2 */ +# define DP_UPDATE_RFB_BIT (1 << 1) /* eDP 1.2 */ +# define DP_CRC_VALID_BIT (1 << 2) /* eDP 1.2 */ +# define DP_SU_VALID (1 << 3) /* eDP 1.4 */ +# define DP_FIRST_SCAN_LINE_SU_REGION (1 << 4) /* eDP 1.4 */ +# define DP_LAST_SCAN_LINE_SU_REGION (1 << 5) /* eDP 1.4 */ +# define DP_Y_COORDINATE_VALID (1 << 6) /* eDP 1.4a */ + #define DP_RECEIVER_ALPM_STATUS0x200b /* eDP 1.4 */ # define DP_ALPM_LOCK_TIMEOUT_ERROR(1 << 0) -- 2.16.2 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH v2 07/10] drm/i915/psr: Use PSR2 macro for PSR2
Cosmetic change. Reviewed-by: Rodrigo Vivi <rodrigo.v...@intel.com> Signed-off-by: José Roberto de Souza <jose.so...@intel.com> --- drivers/gpu/drm/i915/i915_reg.h | 3 ++- drivers/gpu/drm/i915/intel_psr.c | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 1c6f463bc919..219a4da284aa 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -4063,8 +4063,9 @@ enum { #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_IDLE_MASK 0xf #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_STATUS_MMIO(0x6f940) #define EDP_PSR2_STATUS_STATE_MASK (0xf<<28) diff --git a/drivers/gpu/drm/i915/intel_psr.c b/drivers/gpu/drm/i915/intel_psr.c index 5efddd920681..bec455e28943 100644 --- a/drivers/gpu/drm/i915/intel_psr.c +++ b/drivers/gpu/drm/i915/intel_psr.c @@ -382,7 +382,7 @@ static void hsw_activate_psr2(struct intel_dp *intel_dp) uint32_t val; uint8_t sink_latency; - val = idle_frames << EDP_PSR_IDLE_FRAME_SHIFT; + val = idle_frames << EDP_PSR2_IDLE_FRAME_SHIFT; /* FIXME: selective update is probably totally broken because it doesn't * mesh at all with our frontbuffer tracking. And the hw alone isn't -- 2.16.2 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH 2/2] drm: Add DP last received PSR SDP VSC register and bits
This is a register to help debug what is in the last SDP VSC packet revived by sink. Signed-off-by: José Roberto de Souza <jose.so...@intel.com> --- include/drm/drm_dp_helper.h | 9 + 1 file changed, 9 insertions(+) diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h index 0bac0c7d0dec..91c9bcd4196f 100644 --- a/include/drm/drm_dp_helper.h +++ b/include/drm/drm_dp_helper.h @@ -795,6 +795,15 @@ # define DP_LAST_ACTUAL_SYNCHRONIZATION_LATENCY_MASK (0xf << 4) # define DP_LAST_ACTUAL_SYNCHRONIZATION_LATENCY_SHIFT 4 +#define DP_LAST_RECEIVED_PSR_SDP 0x200a /* eDP 1.2 */ +# define DP_PSR_STATE_BIT (1 << 0) /* eDP 1.2 */ +# define DP_UPDATE_RFB_BIT (1 << 1) /* eDP 1.2 */ +# define DP_CRC_VALID_BIT (1 << 2) /* eDP 1.2 */ +# define DP_SU_VALID (1 << 3) /* eDP 1.4 */ +# define DP_FIRST_SCAN_LINE_SU_REGION (1 << 4) /* eDP 1.4 */ +# define DP_LAST_SCAN_LINE_SU_REGION (1 << 5) /* eDP 1.4 */ +# define DP_Y_COORDINATE_VALID (1 << 6) /* eDP 1.4a */ + #define DP_RECEIVER_ALPM_STATUS0x200b /* eDP 1.4 */ # define DP_ALPM_LOCK_TIMEOUT_ERROR(1 << 0) -- 2.16.2 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH 1/2] drm: Add DP PSR2 sink enable bit
To comply with eDP1.4a this bit should be set when enabling PSR2. Signed-off-by: José Roberto de Souza <jose.so...@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 62903bae0221..0bac0c7d0dec 100644 --- a/include/drm/drm_dp_helper.h +++ b/include/drm/drm_dp_helper.h @@ -478,6 +478,7 @@ # define DP_PSR_FRAME_CAPTURE (1 << 3) # define DP_PSR_SELECTIVE_UPDATE (1 << 4) # define DP_PSR_IRQ_HPD_WITH_CRC_ERRORS (1 << 5) +# define DP_PSR_ENABLE_PSR2(1 << 6) /* eDP 1.4a */ #define DP_ADAPTER_CTRL0x1a0 # define DP_ADAPTER_CTRL_FORCE_LOAD_SENSE (1 << 0) -- 2.16.2 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH] drm: Add PSR version 3 macro
eDP 1.4a specification defines PSR version 3, it PSR2 with the addition of Y-coordinate support when doing selective update. Signed-off-by: José Roberto de Souza <jose.so...@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 4de97e94ef9d..62903bae0221 100644 --- a/include/drm/drm_dp_helper.h +++ b/include/drm/drm_dp_helper.h @@ -288,6 +288,7 @@ #define DP_PSR_SUPPORT 0x070 /* XXX 1.2? */ # define DP_PSR_IS_SUPPORTED1 # define DP_PSR2_IS_SUPPORTED 2 /* eDP 1.4 */ +# define DP_PSR2_WITH_Y_COORD_IS_SUPPORTED 3 /* eDP 1.4a */ #define DP_PSR_CAPS 0x071 /* XXX 1.2? */ # define DP_PSR_NO_TRAIN_ON_EXIT1 -- 2.16.2 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel