diff mbox series

[v3,4/6] drm/i915/panelreplay: Initializaton and compute config for panel replay

Message ID 20230728124609.2911830-5-animesh.manna@intel.com (mailing list archive)
State New, archived
Headers show
Series Panel replay phase1 implementation | expand

Commit Message

Manna, Animesh July 28, 2023, 12:46 p.m. UTC
Modify existing PSR implementation to enable panel replay feature of DP 2.0
which is similar to PSR feature of EDP panel. There is different DPCD
address to check panel capability compare to PSR and vsc sdp header
is different.

v1: Initial version.
v2:
- Set source_panel_replay_support flag under HAS_PNEL_REPLAY() check. [Jouni]
- Code restructured around intel_panel_replay_init
and renamed to intel_panel_replay_init_dpcd. [Jouni]
- Remove the initial code modification around has_psr2 flag. [Jouni]
- Add CAN_PANEL_REPLAY() in intel_encoder_can_psr which is used to
enable in intel_psr_post_plane_update. [Jouni]
v3:
- Initialize both psr and panel-replay. [Jouni]
- Initialize both panel replay and psr if detected. [Jouni]
- Refactoring psr function by introducing _psr_compute_config(). [Jouni]
- Add check for !is_edp while deriving source_panel_replay_support. [Jouni]
- Enable panel replay dpcd initialization in a separate patch. [Jouni]

Cc: Jouni Högander <jouni.hogander@intel.com>
Signed-off-by: Animesh Manna <animesh.manna@intel.com>
---
 .../drm/i915/display/intel_display_types.h    |  8 +-
 drivers/gpu/drm/i915/display/intel_dp.c       | 44 ++++++++--
 drivers/gpu/drm/i915/display/intel_psr.c      | 88 +++++++++++++------
 3 files changed, 104 insertions(+), 36 deletions(-)

Comments

kernel test robot July 28, 2023, 3:51 p.m. UTC | #1
Hi Animesh,

kernel test robot noticed the following build warnings:

[auto build test WARNING on drm-tip/drm-tip]

url:    https://github.com/intel-lab-lkp/linux/commits/Animesh-Manna/drm-panelreplay-dpcd-register-definition-for-panelreplay/20230728-205902
base:   git://anongit.freedesktop.org/drm/drm-tip drm-tip
patch link:    https://lore.kernel.org/r/20230728124609.2911830-5-animesh.manna%40intel.com
patch subject: [Intel-gfx] [PATCH v3 4/6] drm/i915/panelreplay: Initializaton and compute config for panel replay
config: x86_64-randconfig-x001-20230728 (https://download.01.org/0day-ci/archive/20230728/202307282318.EVEl6EsL-lkp@intel.com/config)
compiler: clang version 16.0.4 (https://github.com/llvm/llvm-project.git ae42196bc493ffe877a7e3dff8be32035dea4d07)
reproduce: (https://download.01.org/0day-ci/archive/20230728/202307282318.EVEl6EsL-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202307282318.EVEl6EsL-lkp@intel.com/

All warnings (new ones prefixed by >>):

>> drivers/gpu/drm/i915/display/intel_dp.c:3386:27: warning: overlapping comparisons always evaluate to true [-Wtautological-overlap-compare]
           if (vsc->revision != 0x5 || vsc->revision != 0x7)
               ~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~
   1 warning generated.


vim +3386 drivers/gpu/drm/i915/display/intel_dp.c

  3361	
  3362	static ssize_t intel_dp_vsc_sdp_pack(const struct drm_dp_vsc_sdp *vsc,
  3363					     struct dp_sdp *sdp, size_t size)
  3364	{
  3365		size_t length = sizeof(struct dp_sdp);
  3366	
  3367		if (size < length)
  3368			return -ENOSPC;
  3369	
  3370		memset(sdp, 0, size);
  3371	
  3372		/*
  3373		 * Prepare VSC Header for SU as per DP 1.4a spec, Table 2-119
  3374		 * VSC SDP Header Bytes
  3375		 */
  3376		sdp->sdp_header.HB0 = 0; /* Secondary-Data Packet ID = 0 */
  3377		sdp->sdp_header.HB1 = vsc->sdp_type; /* Secondary-data Packet Type */
  3378		sdp->sdp_header.HB2 = vsc->revision; /* Revision Number */
  3379		sdp->sdp_header.HB3 = vsc->length; /* Number of Valid Data Bytes */
  3380	
  3381		/*
  3382		 * Other than revision 0x5 which supports Pixel Encoding/Colorimetry
  3383		 * Format as per DP 1.4a spec, revision 0x7 also supports Pixel
  3384		 * Encoding/Colorimetry Format as per DP 2.0 spec.
  3385		 */
> 3386		if (vsc->revision != 0x5 || vsc->revision != 0x7)
  3387			goto out;
  3388	
  3389		/* VSC SDP Payload for DB16 through DB18 */
  3390		/* Pixel Encoding and Colorimetry Formats  */
  3391		sdp->db[16] = (vsc->pixelformat & 0xf) << 4; /* DB16[7:4] */
  3392		sdp->db[16] |= vsc->colorimetry & 0xf; /* DB16[3:0] */
  3393	
  3394		switch (vsc->bpc) {
  3395		case 6:
  3396			/* 6bpc: 0x0 */
  3397			break;
  3398		case 8:
  3399			sdp->db[17] = 0x1; /* DB17[3:0] */
  3400			break;
  3401		case 10:
  3402			sdp->db[17] = 0x2;
  3403			break;
  3404		case 12:
  3405			sdp->db[17] = 0x3;
  3406			break;
  3407		case 16:
  3408			sdp->db[17] = 0x4;
  3409			break;
  3410		default:
  3411			MISSING_CASE(vsc->bpc);
  3412			break;
  3413		}
  3414		/* Dynamic Range and Component Bit Depth */
  3415		if (vsc->dynamic_range == DP_DYNAMIC_RANGE_CTA)
  3416			sdp->db[17] |= 0x80;  /* DB17[7] */
  3417	
  3418		/* Content Type */
  3419		sdp->db[18] = vsc->content_type & 0x7;
  3420	
  3421	out:
  3422		return length;
  3423	}
  3424
Hogander, Jouni July 31, 2023, 6:47 a.m. UTC | #2
On Fri, 2023-07-28 at 18:16 +0530, Animesh Manna wrote:
> Modify existing PSR implementation to enable panel replay feature of
> DP 2.0
> which is similar to PSR feature of EDP panel. There is different DPCD
> address to check panel capability compare to PSR and vsc sdp header
> is different.
> 
> v1: Initial version.
> v2:
> - Set source_panel_replay_support flag under HAS_PNEL_REPLAY() check.
> [Jouni]
> - Code restructured around intel_panel_replay_init
> and renamed to intel_panel_replay_init_dpcd. [Jouni]
> - Remove the initial code modification around has_psr2 flag. [Jouni]
> - Add CAN_PANEL_REPLAY() in intel_encoder_can_psr which is used to
> enable in intel_psr_post_plane_update. [Jouni]
> v3:
> - Initialize both psr and panel-replay. [Jouni]
> - Initialize both panel replay and psr if detected. [Jouni]
> - Refactoring psr function by introducing _psr_compute_config().
> [Jouni]
> - Add check for !is_edp while deriving source_panel_replay_support.
> [Jouni]
> - Enable panel replay dpcd initialization in a separate patch.
> [Jouni]
> 
> Cc: Jouni Högander <jouni.hogander@intel.com>
> Signed-off-by: Animesh Manna <animesh.manna@intel.com>
> ---
>  .../drm/i915/display/intel_display_types.h    |  8 +-
>  drivers/gpu/drm/i915/display/intel_dp.c       | 44 ++++++++--
>  drivers/gpu/drm/i915/display/intel_psr.c      | 88 +++++++++++++----
> --
>  3 files changed, 104 insertions(+), 36 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h
> b/drivers/gpu/drm/i915/display/intel_display_types.h
> index 731f2ec04d5c..1ff7e6c03b44 100644
> --- a/drivers/gpu/drm/i915/display/intel_display_types.h
> +++ b/drivers/gpu/drm/i915/display/intel_display_types.h
> @@ -1202,6 +1202,7 @@ struct intel_crtc_state {
>         bool has_psr2;
>         bool enable_psr2_sel_fetch;
>         bool req_psr2_sdp_prior_scanline;
> +       bool has_pr;
>         bool wm_level_disabled;
>         u32 dc3co_exitline;
>         u16 su_y_granularity;
> @@ -1693,6 +1694,8 @@ struct intel_psr {
>         bool irq_aux_error;
>         u16 su_w_granularity;
>         u16 su_y_granularity;
> +       bool source_panel_replay_support;
> +       bool sink_panel_replay_support;
>         u32 dc3co_exitline;
>         u32 dc3co_exit_delay;
>         struct delayed_work dc3co_work;
> @@ -1983,12 +1986,15 @@ dp_to_lspcon(struct intel_dp *intel_dp)
>  #define CAN_PSR(intel_dp) ((intel_dp)->psr.sink_support && \
>                            (intel_dp)->psr.source_support)
>  
> +#define CAN_PANEL_REPLAY(intel_dp) ((intel_dp)-
> >psr.sink_panel_replay_support && \
> +                         (intel_dp)-
> >psr.source_panel_replay_support)
> +
>  static inline bool intel_encoder_can_psr(struct intel_encoder
> *encoder)
>  {
>         if (!intel_encoder_is_dp(encoder))
>                 return false;
>  
> -       return CAN_PSR(enc_to_intel_dp(encoder));
> +       return CAN_PSR(enc_to_intel_dp(encoder)) ||
> CAN_PANEL_REPLAY(enc_to_intel_dp(encoder));
>  }
>  
>  static inline struct intel_digital_port *
> diff --git a/drivers/gpu/drm/i915/display/intel_dp.c
> b/drivers/gpu/drm/i915/display/intel_dp.c
> index 03675620e3ea..0ba231ee6e34 100644
> --- a/drivers/gpu/drm/i915/display/intel_dp.c
> +++ b/drivers/gpu/drm/i915/display/intel_dp.c
> @@ -1946,12 +1946,22 @@ static void
> intel_dp_compute_vsc_colorimetry(const struct intel_crtc_state *crtc
>         struct intel_crtc *crtc = to_intel_crtc(crtc_state-
> >uapi.crtc);
>         struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
>  
> -       /*
> -        * Prepare VSC Header for SU as per DP 1.4 spec, Table 2-118
> -        * VSC SDP supporting 3D stereo, PSR2, and Pixel Encoding/
> -        * Colorimetry Format indication.
> -        */
> -       vsc->revision = 0x5;
> +       if (crtc_state->has_pr) {
> +               /*
> +                * Prepare VSC Header for SU as per DP 2.0 spec,
> Table 2-223
> +                * VSC SDP supporting 3D stereo, Panel Replay, and
> Pixel
> +                * Encoding/Colorimetry Format indication.
> +                */
> +               vsc->revision = 0x7;
> +       } else {
> +               /*
> +                * Prepare VSC Header for SU as per DP 1.4 spec,
> Table 2-118
> +                * VSC SDP supporting 3D stereo, PSR2, and Pixel
> Encoding/
> +                * Colorimetry Format indication.
> +                */
> +               vsc->revision = 0x5;
> +       }
> +
>         vsc->length = 0x13;
>  
>         /* DP 1.4a spec, Table 2-120 */
> @@ -2060,6 +2070,21 @@ void intel_dp_compute_psr_vsc_sdp(struct
> intel_dp *intel_dp,
>                         vsc->revision = 0x4;
>                         vsc->length = 0xe;
>                 }
> +       } else if (crtc_state->has_pr) {
> +               if (intel_dp->psr.colorimetry_support &&
> +                   intel_dp_needs_vsc_sdp(crtc_state, conn_state)) {
> +                       /* [Panel Replay with colorimetry info] */
> +                       intel_dp_compute_vsc_colorimetry(crtc_state,
> conn_state,
> +                                                        vsc);
> +               } else {
> +                       /*
> +                        * [Panel Replay without colorimetry info]
> +                        * Prepare VSC Header for SU as per DP 2.0
> spec, Table 2-223
> +                        * VSC SDP supporting 3D stereo + Panel
> Replay.
> +                        */
> +                       vsc->revision = 0x6;
> +                       vsc->length = 0x10;
> +               }
>         } else {
>                 /*
>                  * [PSR1]
> @@ -3354,10 +3379,11 @@ static ssize_t intel_dp_vsc_sdp_pack(const
> struct drm_dp_vsc_sdp *vsc,
>         sdp->sdp_header.HB3 = vsc->length; /* Number of Valid Data
> Bytes */
>  
>         /*
> -        * Only revision 0x5 supports Pixel Encoding/Colorimetry
> Format as
> -        * per DP 1.4a spec.
> +        * Other than revision 0x5 which supports Pixel
> Encoding/Colorimetry
> +        * Format as per DP 1.4a spec, revision 0x7 also supports
> Pixel
> +        * Encoding/Colorimetry Format as per DP 2.0 spec.
>          */
> -       if (vsc->revision != 0x5)
> +       if (vsc->revision != 0x5 || vsc->revision != 0x7)
>                 goto out;
>  
>         /* VSC SDP Payload for DB16 through DB18 */
> diff --git a/drivers/gpu/drm/i915/display/intel_psr.c
> b/drivers/gpu/drm/i915/display/intel_psr.c
> index 9fbcb4b93f11..7508e6c967e2 100644
> --- a/drivers/gpu/drm/i915/display/intel_psr.c
> +++ b/drivers/gpu/drm/i915/display/intel_psr.c
> @@ -472,6 +472,27 @@ static void intel_dp_get_su_granularity(struct
> intel_dp *intel_dp)
>         intel_dp->psr.su_y_granularity = y;
>  }
>  
> +static void _panel_replay_init_dpcd(struct intel_dp *intel_dp)
> +{
> +       struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
> +       u8 pr_dpcd = 0;
> +
> +       if (!HAS_PANEL_REPLAY(dev_priv))
> +               return;
> +
> +       drm_dp_dpcd_readb(&intel_dp->aux, DP_PANEL_REPLAY_CAP,
> &pr_dpcd);
> +
> +       if (!(pr_dpcd & DP_PANEL_REPLAY_SUPPORT)) {
> +               drm_dbg_kms(&dev_priv->drm,
> +                           "Panel replay is not supported by
> panel\n");
> +               return;
> +       }
> +
> +       drm_dbg_kms(&dev_priv->drm,
> +                   "Panel replay is supported by panel\n");
> +       intel_dp->psr.sink_panel_replay_support = true;
> +}
> +
>  static void _psr_init_dpcd(struct intel_dp *intel_dp)
>  {
>         struct drm_i915_private *i915 =
> @@ -521,12 +542,13 @@ static void _psr_init_dpcd(struct intel_dp
> *intel_dp)
>  
>  void intel_psr_init_dpcd(struct intel_dp *intel_dp)
>  {
> +       _panel_replay_init_dpcd(intel_dp);
> +
>         drm_dp_dpcd_read(&intel_dp->aux, DP_PSR_SUPPORT, intel_dp-
> >psr_dpcd,
>                          sizeof(intel_dp->psr_dpcd));
>  
>         if (intel_dp->psr_dpcd[0])
>                 _psr_init_dpcd(intel_dp);
> -       /* TODO: Add PR case here */
>  
>         if (intel_dp->psr.sink_psr2_support) {
>                 intel_dp->psr.colorimetry_support =
> @@ -1207,13 +1229,11 @@ static bool intel_psr2_config_valid(struct
> intel_dp *intel_dp,
>         return false;
>  }
>  
> -void intel_psr_compute_config(struct intel_dp *intel_dp,
> -                             struct intel_crtc_state *crtc_state,
> -                             struct drm_connector_state *conn_state)
> +static bool _psr_compute_config(struct intel_dp *intel_dp,
> +                               struct intel_crtc_state *crtc_state)
>  {
>         struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
> -       const struct drm_display_mode *adjusted_mode =
> -               &crtc_state->hw.adjusted_mode;
> +       const struct drm_display_mode *adjusted_mode = &crtc_state-
> >hw.adjusted_mode;
>         int psr_setup_time;
>  
>         /*
> @@ -1221,10 +1241,36 @@ void intel_psr_compute_config(struct intel_dp
> *intel_dp,
>          * So if VRR is enabled, do not enable PSR.
>          */
>         if (crtc_state->vrr.enable)
> -               return;
> +               return false;
>  
>         if (!CAN_PSR(intel_dp))
> -               return;
> +               return false;
> +
> +       psr_setup_time = drm_dp_psr_setup_time(intel_dp->psr_dpcd);
> +       if (psr_setup_time < 0) {
> +               drm_dbg_kms(&dev_priv->drm,
> +                           "PSR condition failed: Invalid PSR setup
> time (0x%02x)\n",
> +                           intel_dp->psr_dpcd[1]);
> +               return false;
> +       }
> +
> +       if (intel_usecs_to_scanlines(adjusted_mode, psr_setup_time) >
> +           adjusted_mode->crtc_vtotal - adjusted_mode->crtc_vdisplay
> - 1) {
> +               drm_dbg_kms(&dev_priv->drm,
> +                           "PSR condition failed: PSR setup time (%d
> us) too long\n",
> +                           psr_setup_time);
> +               return false;
> +       }
> +
> +       return true;
> +}
> +
> +void intel_psr_compute_config(struct intel_dp *intel_dp,
> +                             struct intel_crtc_state *crtc_state,
> +                             struct drm_connector_state *conn_state)
> +{
> +       struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
> +       const struct drm_display_mode *adjusted_mode = &crtc_state-
> >hw.adjusted_mode;
>  
>         if (!psr_global_enabled(intel_dp)) {
>                 drm_dbg_kms(&dev_priv->drm, "PSR disabled by
> flag\n");
> @@ -1234,7 +1280,6 @@ void intel_psr_compute_config(struct intel_dp
> *intel_dp,
>         if (intel_dp->psr.sink_not_reliable) {
>                 drm_dbg_kms(&dev_priv->drm,
>                             "PSR sink implementation is not
> reliable\n");
> -               return;
>         }
>  
>         if (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) {
> @@ -1243,23 +1288,11 @@ void intel_psr_compute_config(struct intel_dp
> *intel_dp,
>                 return;
>         }
>  
> -       psr_setup_time = drm_dp_psr_setup_time(intel_dp->psr_dpcd);
> -       if (psr_setup_time < 0) {
> -               drm_dbg_kms(&dev_priv->drm,
> -                           "PSR condition failed: Invalid PSR setup
> time (0x%02x)\n",
> -                           intel_dp->psr_dpcd[1]);
> -               return;
> -       }
> -
> -       if (intel_usecs_to_scanlines(adjusted_mode, psr_setup_time) >
> -           adjusted_mode->crtc_vtotal - adjusted_mode->crtc_vdisplay
> - 1) {
> -               drm_dbg_kms(&dev_priv->drm,
> -                           "PSR condition failed: PSR setup time (%d
> us) too long\n",
> -                           psr_setup_time);
> -               return;
> -       }
> +       if (CAN_PANEL_REPLAY(intel_dp))
> +               crtc_state->has_pr = true;
> +       else
> +               crtc_state->has_psr = _psr_compute_config(intel_dp,
> crtc_state);
>  
> -       crtc_state->has_psr = true;
>         crtc_state->has_psr2 = intel_psr2_config_valid(intel_dp,
> crtc_state);
>  
>         crtc_state->infoframes.enable |=
> intel_hdmi_infoframe_enable(DP_SDP_VSC);
> @@ -2699,7 +2732,7 @@ void intel_psr_init(struct intel_dp *intel_dp)
>         struct intel_digital_port *dig_port =
> dp_to_dig_port(intel_dp);
>         struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
>  
> -       if (!HAS_PSR(dev_priv))
> +       if (!(HAS_PSR(dev_priv) || HAS_PANEL_REPLAY(dev_priv)))
>                 return;
>  
>         /*
> @@ -2719,6 +2752,9 @@ void intel_psr_init(struct intel_dp *intel_dp)
>  
>         intel_dp->psr.source_support = true;
>  
> +       if (HAS_PANEL_REPLAY(dev_priv) && !intel_dp_is_edp(intel_dp))
> +               intel_dp->psr.source_panel_replay_support = true;

I don't think it's correct to have both intel_dp->psr.source_support
and intel_dp->psr.source_panel_replay_support set. E.g.:

	if (HAS_PANEL_REPLAY(dev_priv) && !intel_dp_is_edp(intel_dp))
		intel_dp->psr.source_panel_replay_support = true;
	else
		intel_dp->psr.source_support = true;

BR,

Jouni Högander

>  
> +       if (HAS_PANEL_REPLAY(dev_priv) && !intel_dp_is_edp(intel_dp))
> +               intel_dp->psr.source_panel_replay_support = true;
> +
>         /* Set link_standby x link_off defaults */
>         if (DISPLAY_VER(dev_priv) < 12)
>                 /* For new platforms up to TGL let's respect VBT back
> again */
Hogander, Jouni Aug. 10, 2023, 11:02 a.m. UTC | #3
On Fri, 2023-07-28 at 18:16 +0530, Animesh Manna wrote:
> Modify existing PSR implementation to enable panel replay feature of
> DP 2.0
> which is similar to PSR feature of EDP panel. There is different DPCD
> address to check panel capability compare to PSR and vsc sdp header
> is different.
> 
> v1: Initial version.
> v2:
> - Set source_panel_replay_support flag under HAS_PNEL_REPLAY() check.
> [Jouni]
> - Code restructured around intel_panel_replay_init
> and renamed to intel_panel_replay_init_dpcd. [Jouni]
> - Remove the initial code modification around has_psr2 flag. [Jouni]
> - Add CAN_PANEL_REPLAY() in intel_encoder_can_psr which is used to
> enable in intel_psr_post_plane_update. [Jouni]
> v3:
> - Initialize both psr and panel-replay. [Jouni]
> - Initialize both panel replay and psr if detected. [Jouni]
> - Refactoring psr function by introducing _psr_compute_config().
> [Jouni]
> - Add check for !is_edp while deriving source_panel_replay_support.
> [Jouni]
> - Enable panel replay dpcd initialization in a separate patch.
> [Jouni]
> 
> Cc: Jouni Högander <jouni.hogander@intel.com>
> Signed-off-by: Animesh Manna <animesh.manna@intel.com>
> ---
>  .../drm/i915/display/intel_display_types.h    |  8 +-
>  drivers/gpu/drm/i915/display/intel_dp.c       | 44 ++++++++--
>  drivers/gpu/drm/i915/display/intel_psr.c      | 88 +++++++++++++----
> --
>  3 files changed, 104 insertions(+), 36 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h
> b/drivers/gpu/drm/i915/display/intel_display_types.h
> index 731f2ec04d5c..1ff7e6c03b44 100644
> --- a/drivers/gpu/drm/i915/display/intel_display_types.h
> +++ b/drivers/gpu/drm/i915/display/intel_display_types.h
> @@ -1202,6 +1202,7 @@ struct intel_crtc_state {
>         bool has_psr2;
>         bool enable_psr2_sel_fetch;
>         bool req_psr2_sdp_prior_scanline;
> +       bool has_pr;
>         bool wm_level_disabled;
>         u32 dc3co_exitline;
>         u16 su_y_granularity;
> @@ -1693,6 +1694,8 @@ struct intel_psr {
>         bool irq_aux_error;
>         u16 su_w_granularity;
>         u16 su_y_granularity;
> +       bool source_panel_replay_support;
> +       bool sink_panel_replay_support;
>         u32 dc3co_exitline;
>         u32 dc3co_exit_delay;
>         struct delayed_work dc3co_work;
> @@ -1983,12 +1986,15 @@ dp_to_lspcon(struct intel_dp *intel_dp)
>  #define CAN_PSR(intel_dp) ((intel_dp)->psr.sink_support && \
>                            (intel_dp)->psr.source_support)
>  
> +#define CAN_PANEL_REPLAY(intel_dp) ((intel_dp)-
> >psr.sink_panel_replay_support && \
> +                         (intel_dp)-
> >psr.source_panel_replay_support)
> +
>  static inline bool intel_encoder_can_psr(struct intel_encoder
> *encoder)
>  {
>         if (!intel_encoder_is_dp(encoder))
>                 return false;
>  
> -       return CAN_PSR(enc_to_intel_dp(encoder));
> +       return CAN_PSR(enc_to_intel_dp(encoder)) ||
> CAN_PANEL_REPLAY(enc_to_intel_dp(encoder));
>  }
>  
>  static inline struct intel_digital_port *
> diff --git a/drivers/gpu/drm/i915/display/intel_dp.c
> b/drivers/gpu/drm/i915/display/intel_dp.c
> index 03675620e3ea..0ba231ee6e34 100644
> --- a/drivers/gpu/drm/i915/display/intel_dp.c
> +++ b/drivers/gpu/drm/i915/display/intel_dp.c
> @@ -1946,12 +1946,22 @@ static void
> intel_dp_compute_vsc_colorimetry(const struct intel_crtc_state *crtc
>         struct intel_crtc *crtc = to_intel_crtc(crtc_state-
> >uapi.crtc);
>         struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
>  
> -       /*
> -        * Prepare VSC Header for SU as per DP 1.4 spec, Table 2-118
> -        * VSC SDP supporting 3D stereo, PSR2, and Pixel Encoding/
> -        * Colorimetry Format indication.
> -        */
> -       vsc->revision = 0x5;
> +       if (crtc_state->has_pr) {
> +               /*
> +                * Prepare VSC Header for SU as per DP 2.0 spec,
> Table 2-223
> +                * VSC SDP supporting 3D stereo, Panel Replay, and
> Pixel
> +                * Encoding/Colorimetry Format indication.
> +                */
> +               vsc->revision = 0x7;
> +       } else {
> +               /*
> +                * Prepare VSC Header for SU as per DP 1.4 spec,
> Table 2-118
> +                * VSC SDP supporting 3D stereo, PSR2, and Pixel
> Encoding/
> +                * Colorimetry Format indication.
> +                */
> +               vsc->revision = 0x5;
> +       }
> +
>         vsc->length = 0x13;
>  
>         /* DP 1.4a spec, Table 2-120 */
> @@ -2060,6 +2070,21 @@ void intel_dp_compute_psr_vsc_sdp(struct
> intel_dp *intel_dp,
>                         vsc->revision = 0x4;
>                         vsc->length = 0xe;
>                 }
> +       } else if (crtc_state->has_pr) {
> +               if (intel_dp->psr.colorimetry_support &&
> +                   intel_dp_needs_vsc_sdp(crtc_state, conn_state)) {
> +                       /* [Panel Replay with colorimetry info] */
> +                       intel_dp_compute_vsc_colorimetry(crtc_state,
> conn_state,
> +                                                        vsc);
> +               } else {
> +                       /*
> +                        * [Panel Replay without colorimetry info]
> +                        * Prepare VSC Header for SU as per DP 2.0
> spec, Table 2-223
> +                        * VSC SDP supporting 3D stereo + Panel
> Replay.
> +                        */
> +                       vsc->revision = 0x6;
> +                       vsc->length = 0x10;
> +               }
>         } else {
>                 /*
>                  * [PSR1]
> @@ -3354,10 +3379,11 @@ static ssize_t intel_dp_vsc_sdp_pack(const
> struct drm_dp_vsc_sdp *vsc,
>         sdp->sdp_header.HB3 = vsc->length; /* Number of Valid Data
> Bytes */
>  
>         /*
> -        * Only revision 0x5 supports Pixel Encoding/Colorimetry
> Format as
> -        * per DP 1.4a spec.
> +        * Other than revision 0x5 which supports Pixel
> Encoding/Colorimetry
> +        * Format as per DP 1.4a spec, revision 0x7 also supports
> Pixel
> +        * Encoding/Colorimetry Format as per DP 2.0 spec.
>          */
> -       if (vsc->revision != 0x5)
> +       if (vsc->revision != 0x5 || vsc->revision != 0x7)
>                 goto out;
>  
>         /* VSC SDP Payload for DB16 through DB18 */
> diff --git a/drivers/gpu/drm/i915/display/intel_psr.c
> b/drivers/gpu/drm/i915/display/intel_psr.c
> index 9fbcb4b93f11..7508e6c967e2 100644
> --- a/drivers/gpu/drm/i915/display/intel_psr.c
> +++ b/drivers/gpu/drm/i915/display/intel_psr.c
> @@ -472,6 +472,27 @@ static void intel_dp_get_su_granularity(struct
> intel_dp *intel_dp)
>         intel_dp->psr.su_y_granularity = y;
>  }
>  
> +static void _panel_replay_init_dpcd(struct intel_dp *intel_dp)
> +{
> +       struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
> +       u8 pr_dpcd = 0;
> +
> +       if (!HAS_PANEL_REPLAY(dev_priv))
> +               return;

This check is not needed. It is ok to check sink capabilities regardles
of if it's supported by the source.

BR,

Jouni Högander

> +
> +       drm_dp_dpcd_readb(&intel_dp->aux, DP_PANEL_REPLAY_CAP,
> &pr_dpcd);
> +
> +       if (!(pr_dpcd & DP_PANEL_REPLAY_SUPPORT)) {
> +               drm_dbg_kms(&dev_priv->drm,
> +                           "Panel replay is not supported by
> panel\n");
> +               return;
> +       }
> +
> +       drm_dbg_kms(&dev_priv->drm,
> +                   "Panel replay is supported by panel\n");
> +       intel_dp->psr.sink_panel_replay_support = true;
> +}
> +
>  static void _psr_init_dpcd(struct intel_dp *intel_dp)
>  {
>         struct drm_i915_private *i915 =
> @@ -521,12 +542,13 @@ static void _psr_init_dpcd(struct intel_dp
> *intel_dp)
>  
>  void intel_psr_init_dpcd(struct intel_dp *intel_dp)
>  {
> +       _panel_replay_init_dpcd(intel_dp);
> +
>         drm_dp_dpcd_read(&intel_dp->aux, DP_PSR_SUPPORT, intel_dp-
> >psr_dpcd,
>                          sizeof(intel_dp->psr_dpcd));
>  
>         if (intel_dp->psr_dpcd[0])
>                 _psr_init_dpcd(intel_dp);
> -       /* TODO: Add PR case here */
>  
>         if (intel_dp->psr.sink_psr2_support) {
>                 intel_dp->psr.colorimetry_support =
> @@ -1207,13 +1229,11 @@ static bool intel_psr2_config_valid(struct
> intel_dp *intel_dp,
>         return false;
>  }
>  
> -void intel_psr_compute_config(struct intel_dp *intel_dp,
> -                             struct intel_crtc_state *crtc_state,
> -                             struct drm_connector_state *conn_state)
> +static bool _psr_compute_config(struct intel_dp *intel_dp,
> +                               struct intel_crtc_state *crtc_state)
>  {
>         struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
> -       const struct drm_display_mode *adjusted_mode =
> -               &crtc_state->hw.adjusted_mode;
> +       const struct drm_display_mode *adjusted_mode = &crtc_state-
> >hw.adjusted_mode;
>         int psr_setup_time;
>  
>         /*
> @@ -1221,10 +1241,36 @@ void intel_psr_compute_config(struct intel_dp
> *intel_dp,
>          * So if VRR is enabled, do not enable PSR.
>          */
>         if (crtc_state->vrr.enable)
> -               return;
> +               return false;
>  
>         if (!CAN_PSR(intel_dp))
> -               return;
> +               return false;
> +
> +       psr_setup_time = drm_dp_psr_setup_time(intel_dp->psr_dpcd);
> +       if (psr_setup_time < 0) {
> +               drm_dbg_kms(&dev_priv->drm,
> +                           "PSR condition failed: Invalid PSR setup
> time (0x%02x)\n",
> +                           intel_dp->psr_dpcd[1]);
> +               return false;
> +       }
> +
> +       if (intel_usecs_to_scanlines(adjusted_mode, psr_setup_time) >
> +           adjusted_mode->crtc_vtotal - adjusted_mode->crtc_vdisplay
> - 1) {
> +               drm_dbg_kms(&dev_priv->drm,
> +                           "PSR condition failed: PSR setup time (%d
> us) too long\n",
> +                           psr_setup_time);
> +               return false;
> +       }
> +
> +       return true;
> +}
> +
> +void intel_psr_compute_config(struct intel_dp *intel_dp,
> +                             struct intel_crtc_state *crtc_state,
> +                             struct drm_connector_state *conn_state)
> +{
> +       struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
> +       const struct drm_display_mode *adjusted_mode = &crtc_state-
> >hw.adjusted_mode;
>  
>         if (!psr_global_enabled(intel_dp)) {
>                 drm_dbg_kms(&dev_priv->drm, "PSR disabled by
> flag\n");
> @@ -1234,7 +1280,6 @@ void intel_psr_compute_config(struct intel_dp
> *intel_dp,
>         if (intel_dp->psr.sink_not_reliable) {
>                 drm_dbg_kms(&dev_priv->drm,
>                             "PSR sink implementation is not
> reliable\n");
> -               return;
>         }
>  
>         if (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) {
> @@ -1243,23 +1288,11 @@ void intel_psr_compute_config(struct intel_dp
> *intel_dp,
>                 return;
>         }
>  
> -       psr_setup_time = drm_dp_psr_setup_time(intel_dp->psr_dpcd);
> -       if (psr_setup_time < 0) {
> -               drm_dbg_kms(&dev_priv->drm,
> -                           "PSR condition failed: Invalid PSR setup
> time (0x%02x)\n",
> -                           intel_dp->psr_dpcd[1]);
> -               return;
> -       }
> -
> -       if (intel_usecs_to_scanlines(adjusted_mode, psr_setup_time) >
> -           adjusted_mode->crtc_vtotal - adjusted_mode->crtc_vdisplay
> - 1) {
> -               drm_dbg_kms(&dev_priv->drm,
> -                           "PSR condition failed: PSR setup time (%d
> us) too long\n",
> -                           psr_setup_time);
> -               return;
> -       }
> +       if (CAN_PANEL_REPLAY(intel_dp))
> +               crtc_state->has_pr = true;
> +       else
> +               crtc_state->has_psr = _psr_compute_config(intel_dp,
> crtc_state);
>  
> -       crtc_state->has_psr = true;
>         crtc_state->has_psr2 = intel_psr2_config_valid(intel_dp,
> crtc_state);
>  
>         crtc_state->infoframes.enable |=
> intel_hdmi_infoframe_enable(DP_SDP_VSC);
> @@ -2699,7 +2732,7 @@ void intel_psr_init(struct intel_dp *intel_dp)
>         struct intel_digital_port *dig_port =
> dp_to_dig_port(intel_dp);
>         struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
>  
> -       if (!HAS_PSR(dev_priv))
> +       if (!(HAS_PSR(dev_priv) || HAS_PANEL_REPLAY(dev_priv)))
>                 return;
>  
>         /*
> @@ -2719,6 +2752,9 @@ void intel_psr_init(struct intel_dp *intel_dp)
>  
>         intel_dp->psr.source_support = true;
>  
> +       if (HAS_PANEL_REPLAY(dev_priv) && !intel_dp_is_edp(intel_dp))
> +               intel_dp->psr.source_panel_replay_support = true;
> +
>         /* Set link_standby x link_off defaults */
>         if (DISPLAY_VER(dev_priv) < 12)
>                 /* For new platforms up to TGL let's respect VBT back
> again */
diff mbox series

Patch

diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h
index 731f2ec04d5c..1ff7e6c03b44 100644
--- a/drivers/gpu/drm/i915/display/intel_display_types.h
+++ b/drivers/gpu/drm/i915/display/intel_display_types.h
@@ -1202,6 +1202,7 @@  struct intel_crtc_state {
 	bool has_psr2;
 	bool enable_psr2_sel_fetch;
 	bool req_psr2_sdp_prior_scanline;
+	bool has_pr;
 	bool wm_level_disabled;
 	u32 dc3co_exitline;
 	u16 su_y_granularity;
@@ -1693,6 +1694,8 @@  struct intel_psr {
 	bool irq_aux_error;
 	u16 su_w_granularity;
 	u16 su_y_granularity;
+	bool source_panel_replay_support;
+	bool sink_panel_replay_support;
 	u32 dc3co_exitline;
 	u32 dc3co_exit_delay;
 	struct delayed_work dc3co_work;
@@ -1983,12 +1986,15 @@  dp_to_lspcon(struct intel_dp *intel_dp)
 #define CAN_PSR(intel_dp) ((intel_dp)->psr.sink_support && \
 			   (intel_dp)->psr.source_support)
 
+#define CAN_PANEL_REPLAY(intel_dp) ((intel_dp)->psr.sink_panel_replay_support && \
+			  (intel_dp)->psr.source_panel_replay_support)
+
 static inline bool intel_encoder_can_psr(struct intel_encoder *encoder)
 {
 	if (!intel_encoder_is_dp(encoder))
 		return false;
 
-	return CAN_PSR(enc_to_intel_dp(encoder));
+	return CAN_PSR(enc_to_intel_dp(encoder)) || CAN_PANEL_REPLAY(enc_to_intel_dp(encoder));
 }
 
 static inline struct intel_digital_port *
diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c
index 03675620e3ea..0ba231ee6e34 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -1946,12 +1946,22 @@  static void intel_dp_compute_vsc_colorimetry(const struct intel_crtc_state *crtc
 	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
 	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
 
-	/*
-	 * Prepare VSC Header for SU as per DP 1.4 spec, Table 2-118
-	 * VSC SDP supporting 3D stereo, PSR2, and Pixel Encoding/
-	 * Colorimetry Format indication.
-	 */
-	vsc->revision = 0x5;
+	if (crtc_state->has_pr) {
+		/*
+		 * Prepare VSC Header for SU as per DP 2.0 spec, Table 2-223
+		 * VSC SDP supporting 3D stereo, Panel Replay, and Pixel
+		 * Encoding/Colorimetry Format indication.
+		 */
+		vsc->revision = 0x7;
+	} else {
+		/*
+		 * Prepare VSC Header for SU as per DP 1.4 spec, Table 2-118
+		 * VSC SDP supporting 3D stereo, PSR2, and Pixel Encoding/
+		 * Colorimetry Format indication.
+		 */
+		vsc->revision = 0x5;
+	}
+
 	vsc->length = 0x13;
 
 	/* DP 1.4a spec, Table 2-120 */
@@ -2060,6 +2070,21 @@  void intel_dp_compute_psr_vsc_sdp(struct intel_dp *intel_dp,
 			vsc->revision = 0x4;
 			vsc->length = 0xe;
 		}
+	} else if (crtc_state->has_pr) {
+		if (intel_dp->psr.colorimetry_support &&
+		    intel_dp_needs_vsc_sdp(crtc_state, conn_state)) {
+			/* [Panel Replay with colorimetry info] */
+			intel_dp_compute_vsc_colorimetry(crtc_state, conn_state,
+							 vsc);
+		} else {
+			/*
+			 * [Panel Replay without colorimetry info]
+			 * Prepare VSC Header for SU as per DP 2.0 spec, Table 2-223
+			 * VSC SDP supporting 3D stereo + Panel Replay.
+			 */
+			vsc->revision = 0x6;
+			vsc->length = 0x10;
+		}
 	} else {
 		/*
 		 * [PSR1]
@@ -3354,10 +3379,11 @@  static ssize_t intel_dp_vsc_sdp_pack(const struct drm_dp_vsc_sdp *vsc,
 	sdp->sdp_header.HB3 = vsc->length; /* Number of Valid Data Bytes */
 
 	/*
-	 * Only revision 0x5 supports Pixel Encoding/Colorimetry Format as
-	 * per DP 1.4a spec.
+	 * Other than revision 0x5 which supports Pixel Encoding/Colorimetry
+	 * Format as per DP 1.4a spec, revision 0x7 also supports Pixel
+	 * Encoding/Colorimetry Format as per DP 2.0 spec.
 	 */
-	if (vsc->revision != 0x5)
+	if (vsc->revision != 0x5 || vsc->revision != 0x7)
 		goto out;
 
 	/* VSC SDP Payload for DB16 through DB18 */
diff --git a/drivers/gpu/drm/i915/display/intel_psr.c b/drivers/gpu/drm/i915/display/intel_psr.c
index 9fbcb4b93f11..7508e6c967e2 100644
--- a/drivers/gpu/drm/i915/display/intel_psr.c
+++ b/drivers/gpu/drm/i915/display/intel_psr.c
@@ -472,6 +472,27 @@  static void intel_dp_get_su_granularity(struct intel_dp *intel_dp)
 	intel_dp->psr.su_y_granularity = y;
 }
 
+static void _panel_replay_init_dpcd(struct intel_dp *intel_dp)
+{
+	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
+	u8 pr_dpcd = 0;
+
+	if (!HAS_PANEL_REPLAY(dev_priv))
+		return;
+
+	drm_dp_dpcd_readb(&intel_dp->aux, DP_PANEL_REPLAY_CAP, &pr_dpcd);
+
+	if (!(pr_dpcd & DP_PANEL_REPLAY_SUPPORT)) {
+		drm_dbg_kms(&dev_priv->drm,
+			    "Panel replay is not supported by panel\n");
+		return;
+	}
+
+	drm_dbg_kms(&dev_priv->drm,
+		    "Panel replay is supported by panel\n");
+	intel_dp->psr.sink_panel_replay_support = true;
+}
+
 static void _psr_init_dpcd(struct intel_dp *intel_dp)
 {
 	struct drm_i915_private *i915 =
@@ -521,12 +542,13 @@  static void _psr_init_dpcd(struct intel_dp *intel_dp)
 
 void intel_psr_init_dpcd(struct intel_dp *intel_dp)
 {
+	_panel_replay_init_dpcd(intel_dp);
+
 	drm_dp_dpcd_read(&intel_dp->aux, DP_PSR_SUPPORT, intel_dp->psr_dpcd,
 			 sizeof(intel_dp->psr_dpcd));
 
 	if (intel_dp->psr_dpcd[0])
 		_psr_init_dpcd(intel_dp);
-	/* TODO: Add PR case here */
 
 	if (intel_dp->psr.sink_psr2_support) {
 		intel_dp->psr.colorimetry_support =
@@ -1207,13 +1229,11 @@  static bool intel_psr2_config_valid(struct intel_dp *intel_dp,
 	return false;
 }
 
-void intel_psr_compute_config(struct intel_dp *intel_dp,
-			      struct intel_crtc_state *crtc_state,
-			      struct drm_connector_state *conn_state)
+static bool _psr_compute_config(struct intel_dp *intel_dp,
+				struct intel_crtc_state *crtc_state)
 {
 	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
-	const struct drm_display_mode *adjusted_mode =
-		&crtc_state->hw.adjusted_mode;
+	const struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode;
 	int psr_setup_time;
 
 	/*
@@ -1221,10 +1241,36 @@  void intel_psr_compute_config(struct intel_dp *intel_dp,
 	 * So if VRR is enabled, do not enable PSR.
 	 */
 	if (crtc_state->vrr.enable)
-		return;
+		return false;
 
 	if (!CAN_PSR(intel_dp))
-		return;
+		return false;
+
+	psr_setup_time = drm_dp_psr_setup_time(intel_dp->psr_dpcd);
+	if (psr_setup_time < 0) {
+		drm_dbg_kms(&dev_priv->drm,
+			    "PSR condition failed: Invalid PSR setup time (0x%02x)\n",
+			    intel_dp->psr_dpcd[1]);
+		return false;
+	}
+
+	if (intel_usecs_to_scanlines(adjusted_mode, psr_setup_time) >
+	    adjusted_mode->crtc_vtotal - adjusted_mode->crtc_vdisplay - 1) {
+		drm_dbg_kms(&dev_priv->drm,
+			    "PSR condition failed: PSR setup time (%d us) too long\n",
+			    psr_setup_time);
+		return false;
+	}
+
+	return true;
+}
+
+void intel_psr_compute_config(struct intel_dp *intel_dp,
+			      struct intel_crtc_state *crtc_state,
+			      struct drm_connector_state *conn_state)
+{
+	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
+	const struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode;
 
 	if (!psr_global_enabled(intel_dp)) {
 		drm_dbg_kms(&dev_priv->drm, "PSR disabled by flag\n");
@@ -1234,7 +1280,6 @@  void intel_psr_compute_config(struct intel_dp *intel_dp,
 	if (intel_dp->psr.sink_not_reliable) {
 		drm_dbg_kms(&dev_priv->drm,
 			    "PSR sink implementation is not reliable\n");
-		return;
 	}
 
 	if (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) {
@@ -1243,23 +1288,11 @@  void intel_psr_compute_config(struct intel_dp *intel_dp,
 		return;
 	}
 
-	psr_setup_time = drm_dp_psr_setup_time(intel_dp->psr_dpcd);
-	if (psr_setup_time < 0) {
-		drm_dbg_kms(&dev_priv->drm,
-			    "PSR condition failed: Invalid PSR setup time (0x%02x)\n",
-			    intel_dp->psr_dpcd[1]);
-		return;
-	}
-
-	if (intel_usecs_to_scanlines(adjusted_mode, psr_setup_time) >
-	    adjusted_mode->crtc_vtotal - adjusted_mode->crtc_vdisplay - 1) {
-		drm_dbg_kms(&dev_priv->drm,
-			    "PSR condition failed: PSR setup time (%d us) too long\n",
-			    psr_setup_time);
-		return;
-	}
+	if (CAN_PANEL_REPLAY(intel_dp))
+		crtc_state->has_pr = true;
+	else
+		crtc_state->has_psr = _psr_compute_config(intel_dp, crtc_state);
 
-	crtc_state->has_psr = true;
 	crtc_state->has_psr2 = intel_psr2_config_valid(intel_dp, crtc_state);
 
 	crtc_state->infoframes.enable |= intel_hdmi_infoframe_enable(DP_SDP_VSC);
@@ -2699,7 +2732,7 @@  void intel_psr_init(struct intel_dp *intel_dp)
 	struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
 	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
 
-	if (!HAS_PSR(dev_priv))
+	if (!(HAS_PSR(dev_priv) || HAS_PANEL_REPLAY(dev_priv)))
 		return;
 
 	/*
@@ -2719,6 +2752,9 @@  void intel_psr_init(struct intel_dp *intel_dp)
 
 	intel_dp->psr.source_support = true;
 
+	if (HAS_PANEL_REPLAY(dev_priv) && !intel_dp_is_edp(intel_dp))
+		intel_dp->psr.source_panel_replay_support = true;
+
 	/* Set link_standby x link_off defaults */
 	if (DISPLAY_VER(dev_priv) < 12)
 		/* For new platforms up to TGL let's respect VBT back again */