Commit 8d4312e2 authored by Luca Coelho's avatar Luca Coelho Committed by Radhakrishna Sripada

drm/i915/mtl: limit second scaler vertical scaling in ver >= 14

In newer hardware versions (i.e. display version >= 14), the second
scaler doesn't support vertical scaling.

The current implementation of the scaling limits is simplified and
only occurs when the planes are created, so we don't know which scaler
is being used.

In order to handle separate scaling limits for horizontal and vertical
scaling, and different limits per scaler, split the checks in two
phases.  We first do a simple check during plane creation and use the
best-case scenario (because we don't know the scaler that may be used
at a later point) and then do a more specific check when the scalers
are actually being set up.
Signed-off-by: default avatarLuca Coelho <luciano.coelho@intel.com>
Reviewed-by: default avatarStanislav Lisovskiy <stanislav.lisovskiy@intel.com>
Signed-off-by: default avatarRadhakrishna Sripada <radhakrishna.sripada@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20221223130509.43245-2-luciano.coelho@intel.com
parent a6fd6f94
...@@ -41,6 +41,7 @@ ...@@ -41,6 +41,7 @@
#include "intel_global_state.h" #include "intel_global_state.h"
#include "intel_hdcp.h" #include "intel_hdcp.h"
#include "intel_psr.h" #include "intel_psr.h"
#include "intel_fb.h"
#include "skl_universal_plane.h" #include "skl_universal_plane.h"
/** /**
...@@ -310,7 +311,7 @@ intel_crtc_destroy_state(struct drm_crtc *crtc, ...@@ -310,7 +311,7 @@ intel_crtc_destroy_state(struct drm_crtc *crtc,
kfree(crtc_state); kfree(crtc_state);
} }
static void intel_atomic_setup_scaler(struct intel_crtc_scaler_state *scaler_state, static int intel_atomic_setup_scaler(struct intel_crtc_scaler_state *scaler_state,
int num_scalers_need, struct intel_crtc *intel_crtc, int num_scalers_need, struct intel_crtc *intel_crtc,
const char *name, int idx, const char *name, int idx,
struct intel_plane_state *plane_state, struct intel_plane_state *plane_state,
...@@ -334,7 +335,7 @@ static void intel_atomic_setup_scaler(struct intel_crtc_scaler_state *scaler_sta ...@@ -334,7 +335,7 @@ static void intel_atomic_setup_scaler(struct intel_crtc_scaler_state *scaler_sta
if (drm_WARN(&dev_priv->drm, *scaler_id < 0, if (drm_WARN(&dev_priv->drm, *scaler_id < 0,
"Cannot find scaler for %s:%d\n", name, idx)) "Cannot find scaler for %s:%d\n", name, idx))
return; return -EINVAL;
/* set scaler mode */ /* set scaler mode */
if (plane_state && plane_state->hw.fb && if (plane_state && plane_state->hw.fb &&
...@@ -375,9 +376,71 @@ static void intel_atomic_setup_scaler(struct intel_crtc_scaler_state *scaler_sta ...@@ -375,9 +376,71 @@ static void intel_atomic_setup_scaler(struct intel_crtc_scaler_state *scaler_sta
mode = SKL_PS_SCALER_MODE_DYN; mode = SKL_PS_SCALER_MODE_DYN;
} }
/*
* FIXME: we should also check the scaler factors for pfit, so
* this shouldn't be tied directly to planes.
*/
if (plane_state && plane_state->hw.fb) {
const struct drm_framebuffer *fb = plane_state->hw.fb;
const struct drm_rect *src = &plane_state->uapi.src;
const struct drm_rect *dst = &plane_state->uapi.dst;
int hscale, vscale, max_vscale, max_hscale;
/*
* FIXME: When two scalers are needed, but only one of
* them needs to downscale, we should make sure that
* the one that needs downscaling support is assigned
* as the first scaler, so we don't reject downscaling
* unnecessarily.
*/
if (DISPLAY_VER(dev_priv) >= 14) {
/*
* On versions 14 and up, only the first
* scaler supports a vertical scaling factor
* of more than 1.0, while a horizontal
* scaling factor of 3.0 is supported.
*/
max_hscale = 0x30000 - 1;
if (*scaler_id == 0)
max_vscale = 0x30000 - 1;
else
max_vscale = 0x10000;
} else if (DISPLAY_VER(dev_priv) >= 10 ||
!intel_format_info_is_yuv_semiplanar(fb->format, fb->modifier)) {
max_hscale = 0x30000 - 1;
max_vscale = 0x30000 - 1;
} else {
max_hscale = 0x20000 - 1;
max_vscale = 0x20000 - 1;
}
/*
* FIXME: We should change the if-else block above to
* support HQ vs dynamic scaler properly.
*/
/* Check if required scaling is within limits */
hscale = drm_rect_calc_hscale(src, dst, 1, max_hscale);
vscale = drm_rect_calc_vscale(src, dst, 1, max_vscale);
if (hscale < 0 || vscale < 0) {
drm_dbg_kms(&dev_priv->drm,
"Scaler %d doesn't support required plane scaling\n",
*scaler_id);
drm_rect_debug_print("src: ", src, true);
drm_rect_debug_print("dst: ", dst, false);
return -EINVAL;
}
}
drm_dbg_kms(&dev_priv->drm, "Attached scaler id %u.%u to %s:%d\n", drm_dbg_kms(&dev_priv->drm, "Attached scaler id %u.%u to %s:%d\n",
intel_crtc->pipe, *scaler_id, name, idx); intel_crtc->pipe, *scaler_id, name, idx);
scaler_state->scalers[*scaler_id].mode = mode; scaler_state->scalers[*scaler_id].mode = mode;
return 0;
} }
/** /**
...@@ -437,7 +500,7 @@ int intel_atomic_setup_scalers(struct drm_i915_private *dev_priv, ...@@ -437,7 +500,7 @@ int intel_atomic_setup_scalers(struct drm_i915_private *dev_priv,
for (i = 0; i < sizeof(scaler_state->scaler_users) * 8; i++) { for (i = 0; i < sizeof(scaler_state->scaler_users) * 8; i++) {
int *scaler_id; int *scaler_id;
const char *name; const char *name;
int idx; int idx, ret;
/* skip if scaler not required */ /* skip if scaler not required */
if (!(scaler_state->scaler_users & (1 << i))) if (!(scaler_state->scaler_users & (1 << i)))
...@@ -494,9 +557,11 @@ int intel_atomic_setup_scalers(struct drm_i915_private *dev_priv, ...@@ -494,9 +557,11 @@ int intel_atomic_setup_scalers(struct drm_i915_private *dev_priv,
scaler_id = &plane_state->scaler_id; scaler_id = &plane_state->scaler_id;
} }
intel_atomic_setup_scaler(scaler_state, num_scalers_need, ret = intel_atomic_setup_scaler(scaler_state, num_scalers_need,
intel_crtc, name, idx, intel_crtc, name, idx,
plane_state, scaler_id); plane_state, scaler_id);
if (ret < 0)
return ret;
} }
return 0; return 0;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment