drm/i915: Relocate intel_atomic_setup_scalers()
authorjsg <jsg@openbsd.org>
Mon, 1 Jan 2024 23:48:31 +0000 (23:48 +0000)
committerjsg <jsg@openbsd.org>
Mon, 1 Jan 2024 23:48:31 +0000 (23:48 +0000)
From Ville Syrjala
b097184f80269f384e9f5556e6b3592441e955f4 in linux-6.1.y/6.1.70
8976b18249407df8bf6ea18ecae0640a15341a50 in mainline linux

sys/dev/pci/drm/i915/display/intel_atomic.c
sys/dev/pci/drm/i915/display/intel_atomic.h
sys/dev/pci/drm/i915/display/skl_scaler.c
sys/dev/pci/drm/i915/display/skl_scaler.h

index 61dda54..a502af0 100644 (file)
@@ -303,262 +303,6 @@ intel_crtc_destroy_state(struct drm_crtc *crtc,
        kfree(crtc_state);
 }
 
-static int intel_atomic_setup_scaler(struct intel_crtc_scaler_state *scaler_state,
-                                    int num_scalers_need, struct intel_crtc *intel_crtc,
-                                    const char *name, int idx,
-                                    struct intel_plane_state *plane_state,
-                                    int *scaler_id)
-{
-       struct drm_i915_private *dev_priv = to_i915(intel_crtc->base.dev);
-       int j;
-       u32 mode;
-
-       if (*scaler_id < 0) {
-               /* find a free scaler */
-               for (j = 0; j < intel_crtc->num_scalers; j++) {
-                       if (scaler_state->scalers[j].in_use)
-                               continue;
-
-                       *scaler_id = j;
-                       scaler_state->scalers[*scaler_id].in_use = 1;
-                       break;
-               }
-       }
-
-       if (drm_WARN(&dev_priv->drm, *scaler_id < 0,
-                    "Cannot find scaler for %s:%d\n", name, idx))
-               return -EINVAL;
-
-       /* set scaler mode */
-       if (plane_state && plane_state->hw.fb &&
-           plane_state->hw.fb->format->is_yuv &&
-           plane_state->hw.fb->format->num_planes > 1) {
-               struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
-               if (DISPLAY_VER(dev_priv) == 9) {
-                       mode = SKL_PS_SCALER_MODE_NV12;
-               } else if (icl_is_hdr_plane(dev_priv, plane->id)) {
-                       /*
-                        * On gen11+'s HDR planes we only use the scaler for
-                        * scaling. They have a dedicated chroma upsampler, so
-                        * we don't need the scaler to upsample the UV plane.
-                        */
-                       mode = PS_SCALER_MODE_NORMAL;
-               } else {
-                       struct intel_plane *linked =
-                               plane_state->planar_linked_plane;
-
-                       mode = PS_SCALER_MODE_PLANAR;
-
-                       if (linked)
-                               mode |= PS_PLANE_Y_SEL(linked->id);
-               }
-       } else if (DISPLAY_VER(dev_priv) >= 10) {
-               mode = PS_SCALER_MODE_NORMAL;
-       } else if (num_scalers_need == 1 && intel_crtc->num_scalers > 1) {
-               /*
-                * when only 1 scaler is in use on a pipe with 2 scalers
-                * scaler 0 operates in high quality (HQ) mode.
-                * In this case use scaler 0 to take advantage of HQ mode
-                */
-               scaler_state->scalers[*scaler_id].in_use = 0;
-               *scaler_id = 0;
-               scaler_state->scalers[0].in_use = 1;
-               mode = SKL_PS_SCALER_MODE_HQ;
-       } else {
-               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",
-                   intel_crtc->pipe, *scaler_id, name, idx);
-       scaler_state->scalers[*scaler_id].mode = mode;
-
-       return 0;
-}
-
-/**
- * intel_atomic_setup_scalers() - setup scalers for crtc per staged requests
- * @dev_priv: i915 device
- * @intel_crtc: intel crtc
- * @crtc_state: incoming crtc_state to validate and setup scalers
- *
- * This function sets up scalers based on staged scaling requests for
- * a @crtc and its planes. It is called from crtc level check path. If request
- * is a supportable request, it attaches scalers to requested planes and crtc.
- *
- * This function takes into account the current scaler(s) in use by any planes
- * not being part of this atomic state
- *
- *  Returns:
- *         0 - scalers were setup succesfully
- *         error code - otherwise
- */
-int intel_atomic_setup_scalers(struct drm_i915_private *dev_priv,
-                              struct intel_crtc *intel_crtc,
-                              struct intel_crtc_state *crtc_state)
-{
-       struct drm_plane *plane = NULL;
-       struct intel_plane *intel_plane;
-       struct intel_plane_state *plane_state = NULL;
-       struct intel_crtc_scaler_state *scaler_state =
-               &crtc_state->scaler_state;
-       struct drm_atomic_state *drm_state = crtc_state->uapi.state;
-       struct intel_atomic_state *intel_state = to_intel_atomic_state(drm_state);
-       int num_scalers_need;
-       int i;
-
-       num_scalers_need = hweight32(scaler_state->scaler_users);
-
-       /*
-        * High level flow:
-        * - staged scaler requests are already in scaler_state->scaler_users
-        * - check whether staged scaling requests can be supported
-        * - add planes using scalers that aren't in current transaction
-        * - assign scalers to requested users
-        * - as part of plane commit, scalers will be committed
-        *   (i.e., either attached or detached) to respective planes in hw
-        * - as part of crtc_commit, scaler will be either attached or detached
-        *   to crtc in hw
-        */
-
-       /* fail if required scalers > available scalers */
-       if (num_scalers_need > intel_crtc->num_scalers){
-               drm_dbg_kms(&dev_priv->drm,
-                           "Too many scaling requests %d > %d\n",
-                           num_scalers_need, intel_crtc->num_scalers);
-               return -EINVAL;
-       }
-
-       /* walkthrough scaler_users bits and start assigning scalers */
-       for (i = 0; i < sizeof(scaler_state->scaler_users) * 8; i++) {
-               int *scaler_id;
-               const char *name;
-               int idx, ret;
-
-               /* skip if scaler not required */
-               if (!(scaler_state->scaler_users & (1 << i)))
-                       continue;
-
-               if (i == SKL_CRTC_INDEX) {
-                       name = "CRTC";
-                       idx = intel_crtc->base.base.id;
-
-                       /* panel fitter case: assign as a crtc scaler */
-                       scaler_id = &scaler_state->scaler_id;
-               } else {
-                       name = "PLANE";
-
-                       /* plane scaler case: assign as a plane scaler */
-                       /* find the plane that set the bit as scaler_user */
-                       plane = drm_state->planes[i].ptr;
-
-                       /*
-                        * to enable/disable hq mode, add planes that are using scaler
-                        * into this transaction
-                        */
-                       if (!plane) {
-                               struct drm_plane_state *state;
-
-                               /*
-                                * GLK+ scalers don't have a HQ mode so it
-                                * isn't necessary to change between HQ and dyn mode
-                                * on those platforms.
-                                */
-                               if (DISPLAY_VER(dev_priv) >= 10)
-                                       continue;
-
-                               plane = drm_plane_from_index(&dev_priv->drm, i);
-                               state = drm_atomic_get_plane_state(drm_state, plane);
-                               if (IS_ERR(state)) {
-                                       drm_dbg_kms(&dev_priv->drm,
-                                                   "Failed to add [PLANE:%d] to drm_state\n",
-                                                   plane->base.id);
-                                       return PTR_ERR(state);
-                               }
-                       }
-
-                       intel_plane = to_intel_plane(plane);
-                       idx = plane->base.id;
-
-                       /* plane on different crtc cannot be a scaler user of this crtc */
-                       if (drm_WARN_ON(&dev_priv->drm,
-                                       intel_plane->pipe != intel_crtc->pipe))
-                               continue;
-
-                       plane_state = intel_atomic_get_new_plane_state(intel_state,
-                                                                      intel_plane);
-                       scaler_id = &plane_state->scaler_id;
-               }
-
-               ret = intel_atomic_setup_scaler(scaler_state, num_scalers_need,
-                                               intel_crtc, name, idx,
-                                               plane_state, scaler_id);
-               if (ret < 0)
-                       return ret;
-       }
-
-       return 0;
-}
-
 struct drm_atomic_state *
 intel_atomic_state_alloc(struct drm_device *dev)
 {
index 726f469..d1cd8dc 100644 (file)
@@ -54,8 +54,4 @@ struct intel_crtc_state *
 intel_atomic_get_crtc_state(struct drm_atomic_state *state,
                            struct intel_crtc *crtc);
 
-int intel_atomic_setup_scalers(struct drm_i915_private *dev_priv,
-                              struct intel_crtc *intel_crtc,
-                              struct intel_crtc_state *crtc_state);
-
 #endif /* __INTEL_ATOMIC_H__ */
index 90f42f6..83a61ef 100644 (file)
@@ -337,6 +337,263 @@ int skl_update_scaler_plane(struct intel_crtc_state *crtc_state,
        return 0;
 }
 
+static int intel_atomic_setup_scaler(struct intel_crtc_scaler_state *scaler_state,
+                                    int num_scalers_need, struct intel_crtc *intel_crtc,
+                                    const char *name, int idx,
+                                    struct intel_plane_state *plane_state,
+                                    int *scaler_id)
+{
+       struct drm_i915_private *dev_priv = to_i915(intel_crtc->base.dev);
+       int j;
+       u32 mode;
+
+       if (*scaler_id < 0) {
+               /* find a free scaler */
+               for (j = 0; j < intel_crtc->num_scalers; j++) {
+                       if (scaler_state->scalers[j].in_use)
+                               continue;
+
+                       *scaler_id = j;
+                       scaler_state->scalers[*scaler_id].in_use = 1;
+                       break;
+               }
+       }
+
+       if (drm_WARN(&dev_priv->drm, *scaler_id < 0,
+                    "Cannot find scaler for %s:%d\n", name, idx))
+               return -EINVAL;
+
+       /* set scaler mode */
+       if (plane_state && plane_state->hw.fb &&
+           plane_state->hw.fb->format->is_yuv &&
+           plane_state->hw.fb->format->num_planes > 1) {
+               struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
+
+               if (DISPLAY_VER(dev_priv) == 9) {
+                       mode = SKL_PS_SCALER_MODE_NV12;
+               } else if (icl_is_hdr_plane(dev_priv, plane->id)) {
+                       /*
+                        * On gen11+'s HDR planes we only use the scaler for
+                        * scaling. They have a dedicated chroma upsampler, so
+                        * we don't need the scaler to upsample the UV plane.
+                        */
+                       mode = PS_SCALER_MODE_NORMAL;
+               } else {
+                       struct intel_plane *linked =
+                               plane_state->planar_linked_plane;
+
+                       mode = PS_SCALER_MODE_PLANAR;
+
+                       if (linked)
+                               mode |= PS_PLANE_Y_SEL(linked->id);
+               }
+       } else if (DISPLAY_VER(dev_priv) >= 10) {
+               mode = PS_SCALER_MODE_NORMAL;
+       } else if (num_scalers_need == 1 && intel_crtc->num_scalers > 1) {
+               /*
+                * when only 1 scaler is in use on a pipe with 2 scalers
+                * scaler 0 operates in high quality (HQ) mode.
+                * In this case use scaler 0 to take advantage of HQ mode
+                */
+               scaler_state->scalers[*scaler_id].in_use = 0;
+               *scaler_id = 0;
+               scaler_state->scalers[0].in_use = 1;
+               mode = SKL_PS_SCALER_MODE_HQ;
+       } else {
+               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",
+                   intel_crtc->pipe, *scaler_id, name, idx);
+       scaler_state->scalers[*scaler_id].mode = mode;
+
+       return 0;
+}
+
+/**
+ * intel_atomic_setup_scalers() - setup scalers for crtc per staged requests
+ * @dev_priv: i915 device
+ * @intel_crtc: intel crtc
+ * @crtc_state: incoming crtc_state to validate and setup scalers
+ *
+ * This function sets up scalers based on staged scaling requests for
+ * a @crtc and its planes. It is called from crtc level check path. If request
+ * is a supportable request, it attaches scalers to requested planes and crtc.
+ *
+ * This function takes into account the current scaler(s) in use by any planes
+ * not being part of this atomic state
+ *
+ *  Returns:
+ *         0 - scalers were setup successfully
+ *         error code - otherwise
+ */
+int intel_atomic_setup_scalers(struct drm_i915_private *dev_priv,
+                              struct intel_crtc *intel_crtc,
+                              struct intel_crtc_state *crtc_state)
+{
+       struct drm_plane *plane = NULL;
+       struct intel_plane *intel_plane;
+       struct intel_plane_state *plane_state = NULL;
+       struct intel_crtc_scaler_state *scaler_state =
+               &crtc_state->scaler_state;
+       struct drm_atomic_state *drm_state = crtc_state->uapi.state;
+       struct intel_atomic_state *intel_state = to_intel_atomic_state(drm_state);
+       int num_scalers_need;
+       int i;
+
+       num_scalers_need = hweight32(scaler_state->scaler_users);
+
+       /*
+        * High level flow:
+        * - staged scaler requests are already in scaler_state->scaler_users
+        * - check whether staged scaling requests can be supported
+        * - add planes using scalers that aren't in current transaction
+        * - assign scalers to requested users
+        * - as part of plane commit, scalers will be committed
+        *   (i.e., either attached or detached) to respective planes in hw
+        * - as part of crtc_commit, scaler will be either attached or detached
+        *   to crtc in hw
+        */
+
+       /* fail if required scalers > available scalers */
+       if (num_scalers_need > intel_crtc->num_scalers) {
+               drm_dbg_kms(&dev_priv->drm,
+                           "Too many scaling requests %d > %d\n",
+                           num_scalers_need, intel_crtc->num_scalers);
+               return -EINVAL;
+       }
+
+       /* walkthrough scaler_users bits and start assigning scalers */
+       for (i = 0; i < sizeof(scaler_state->scaler_users) * 8; i++) {
+               int *scaler_id;
+               const char *name;
+               int idx, ret;
+
+               /* skip if scaler not required */
+               if (!(scaler_state->scaler_users & (1 << i)))
+                       continue;
+
+               if (i == SKL_CRTC_INDEX) {
+                       name = "CRTC";
+                       idx = intel_crtc->base.base.id;
+
+                       /* panel fitter case: assign as a crtc scaler */
+                       scaler_id = &scaler_state->scaler_id;
+               } else {
+                       name = "PLANE";
+
+                       /* plane scaler case: assign as a plane scaler */
+                       /* find the plane that set the bit as scaler_user */
+                       plane = drm_state->planes[i].ptr;
+
+                       /*
+                        * to enable/disable hq mode, add planes that are using scaler
+                        * into this transaction
+                        */
+                       if (!plane) {
+                               struct drm_plane_state *state;
+
+                               /*
+                                * GLK+ scalers don't have a HQ mode so it
+                                * isn't necessary to change between HQ and dyn mode
+                                * on those platforms.
+                                */
+                               if (DISPLAY_VER(dev_priv) >= 10)
+                                       continue;
+
+                               plane = drm_plane_from_index(&dev_priv->drm, i);
+                               state = drm_atomic_get_plane_state(drm_state, plane);
+                               if (IS_ERR(state)) {
+                                       drm_dbg_kms(&dev_priv->drm,
+                                                   "Failed to add [PLANE:%d] to drm_state\n",
+                                                   plane->base.id);
+                                       return PTR_ERR(state);
+                               }
+                       }
+
+                       intel_plane = to_intel_plane(plane);
+                       idx = plane->base.id;
+
+                       /* plane on different crtc cannot be a scaler user of this crtc */
+                       if (drm_WARN_ON(&dev_priv->drm,
+                                       intel_plane->pipe != intel_crtc->pipe))
+                               continue;
+
+                       plane_state = intel_atomic_get_new_plane_state(intel_state,
+                                                                      intel_plane);
+                       scaler_id = &plane_state->scaler_id;
+               }
+
+               ret = intel_atomic_setup_scaler(scaler_state, num_scalers_need,
+                                               intel_crtc, name, idx,
+                                               plane_state, scaler_id);
+               if (ret < 0)
+                       return ret;
+       }
+
+       return 0;
+}
+
 static int glk_coef_tap(int i)
 {
        return i % 7;
index 0097d5d..f040f6a 100644 (file)
@@ -8,17 +8,22 @@
 #include <linux/types.h>
 
 enum drm_scaling_filter;
+enum pipe;
 struct drm_i915_private;
+struct intel_crtc;
 struct intel_crtc_state;
-struct intel_plane_state;
 struct intel_plane;
-enum pipe;
+struct intel_plane_state;
 
 int skl_update_scaler_crtc(struct intel_crtc_state *crtc_state);
 
 int skl_update_scaler_plane(struct intel_crtc_state *crtc_state,
                            struct intel_plane_state *plane_state);
 
+int intel_atomic_setup_scalers(struct drm_i915_private *dev_priv,
+                              struct intel_crtc *intel_crtc,
+                              struct intel_crtc_state *crtc_state);
+
 void skl_pfit_enable(const struct intel_crtc_state *crtc_state);
 
 void skl_program_plane_scaler(struct intel_plane *plane,
@@ -26,4 +31,5 @@ void skl_program_plane_scaler(struct intel_plane *plane,
                              const struct intel_plane_state *plane_state);
 void skl_detach_scalers(const struct intel_crtc_state *crtc_state);
 void skl_scaler_disable(const struct intel_crtc_state *old_crtc_state);
+
 #endif