All of lore.kernel.org
 help / color / mirror / Atom feed
From: Rodrigo Vivi <rodrigo.vivi@intel.com>
To: <intel-gfx@lists.freedesktop.org>,
	<intel-xe@lists.freedesktop.org>, <jani.nikula@linux.intel.com>,
	<vinay.belgaumkar@intel.com>
Cc: Rodrigo Vivi <rodrigo.vivi@intel.com>,
	Jani Nikula <jani.nikula@intel.com>,
	Lucas De Marchi <lucas.demarchi@intel.com>
Subject: [RFC 1/3] drm/i915/display: Introduce intel_display_guc_metrics
Date: Tue, 27 Feb 2024 09:58:29 -0500	[thread overview]
Message-ID: <20240227145833.490328-2-rodrigo.vivi@intel.com> (raw)
In-Reply-To: <20240227145833.490328-1-rodrigo.vivi@intel.com>

This is a generic component part of intel_display that collects
display information that could be used with GuC SLPC for a optimal
frequency selection.

This is also an experimental way to share the code with Xe without
a compact-headers, on an attempt to move towards the full detachment
of the intel_display from the i915.

Cc: Jani Nikula <jani.nikula@intel.com>
Cc: Lucas De Marchi <lucas.demarchi@intel.com>
Cc: Vinay Belgaumkar <vinay.belgaumkar@intel.com>
Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com>
---
 drivers/gpu/drm/i915/Makefile                 |   1 +
 drivers/gpu/drm/i915/display/intel_display.c  |  14 +-
 .../gpu/drm/i915/display/intel_display_core.h |   2 +
 .../i915/display/intel_display_guc_metrics.c  | 153 ++++++++++++++++++
 .../i915/display/intel_display_guc_metrics.h  |  26 +++
 .../display/intel_display_guc_metrics_types.h |  32 ++++
 .../gpu/drm/i915/display/intel_display_irq.c  |   3 +
 .../drm/i915/display/skl_universal_plane.c    |   3 +
 drivers/gpu/drm/xe/Makefile                   |   1 +
 9 files changed, 234 insertions(+), 1 deletion(-)
 create mode 100644 drivers/gpu/drm/i915/display/intel_display_guc_metrics.c
 create mode 100644 drivers/gpu/drm/i915/display/intel_display_guc_metrics.h
 create mode 100644 drivers/gpu/drm/i915/display/intel_display_guc_metrics_types.h

diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
index c13f14edb508..3bd77d61d956 100644
--- a/drivers/gpu/drm/i915/Makefile
+++ b/drivers/gpu/drm/i915/Makefile
@@ -262,6 +262,7 @@ i915-y += \
 	display/intel_display.o \
 	display/intel_display_driver.o \
 	display/intel_display_irq.o \
+	display/intel_display_guc_metrics.o \
 	display/intel_display_params.o \
 	display/intel_display_power.o \
 	display/intel_display_power_map.o \
diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c
index 7db0655d8c9e..8c659561e729 100644
--- a/drivers/gpu/drm/i915/display/intel_display.c
+++ b/drivers/gpu/drm/i915/display/intel_display.c
@@ -67,6 +67,7 @@
 #include "intel_ddi.h"
 #include "intel_de.h"
 #include "intel_display_driver.h"
+#include "intel_display_guc_metrics.h"
 #include "intel_display_power.h"
 #include "intel_display_types.h"
 #include "intel_dmc.h"
@@ -1020,11 +1021,15 @@ static void intel_post_plane_update(struct intel_atomic_state *state,
 				    struct intel_crtc *crtc)
 {
 	struct drm_i915_private *dev_priv = to_i915(state->base.dev);
+	struct intel_display *display = &dev_priv->display;
 	const struct intel_crtc_state *old_crtc_state =
 		intel_atomic_get_old_crtc_state(state, crtc);
 	const struct intel_crtc_state *new_crtc_state =
 		intel_atomic_get_new_crtc_state(state, crtc);
 	enum pipe pipe = crtc->pipe;
+	const struct intel_plane_state __maybe_unused *plane_state;
+	struct intel_plane *plane;
+	int i;
 
 	intel_psr_post_plane_update(state, crtc);
 
@@ -1056,6 +1061,10 @@ static void intel_post_plane_update(struct intel_atomic_state *state,
 
 	if (audio_enabling(old_crtc_state, new_crtc_state))
 		intel_encoders_audio_enable(state, crtc);
+
+	for_each_new_intel_plane_in_state(state, plane, plane_state, i)
+		intel_display_guc_metrics_flip(display, new_crtc_state,
+					       plane->id, false);
 }
 
 static void intel_crtc_enable_flip_done(struct intel_atomic_state *state,
@@ -7066,6 +7075,7 @@ static void intel_atomic_commit_tail(struct intel_atomic_state *state)
 {
 	struct drm_device *dev = state->base.dev;
 	struct drm_i915_private *dev_priv = to_i915(dev);
+	struct intel_display *display = &dev_priv->display;
 	struct intel_crtc_state *new_crtc_state, *old_crtc_state;
 	struct intel_crtc *crtc;
 	struct intel_power_domain_mask put_domains[I915_MAX_PIPES] = {};
@@ -7112,8 +7122,10 @@ static void intel_atomic_commit_tail(struct intel_atomic_state *state)
 	for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state,
 					    new_crtc_state, i) {
 		if (intel_crtc_needs_modeset(new_crtc_state) ||
-		    intel_crtc_needs_fastset(new_crtc_state))
+		    intel_crtc_needs_fastset(new_crtc_state)) {
 			intel_modeset_get_crtc_power_domains(new_crtc_state, &put_domains[crtc->pipe]);
+			intel_display_guc_metrics_refresh_info(display, new_crtc_state);
+		}
 	}
 
 	intel_commit_modeset_disables(state);
diff --git a/drivers/gpu/drm/i915/display/intel_display_core.h b/drivers/gpu/drm/i915/display/intel_display_core.h
index fdeaac994e17..58bb0e9d40dc 100644
--- a/drivers/gpu/drm/i915/display/intel_display_core.h
+++ b/drivers/gpu/drm/i915/display/intel_display_core.h
@@ -43,6 +43,7 @@ struct intel_color_funcs;
 struct intel_crtc;
 struct intel_crtc_state;
 struct intel_dmc;
+struct intel_display_guc_metrics;
 struct intel_dpll_funcs;
 struct intel_dpll_mgr;
 struct intel_fbdev;
@@ -529,6 +530,7 @@ struct intel_display {
 	struct intel_fbc *fbc[I915_MAX_FBCS];
 	struct intel_frontbuffer_tracking fb_tracking;
 	struct intel_hotplug hotplug;
+	struct intel_display_guc_metrics *guc_metrics;
 	struct intel_opregion *opregion;
 	struct intel_overlay *overlay;
 	struct intel_display_params params;
diff --git a/drivers/gpu/drm/i915/display/intel_display_guc_metrics.c b/drivers/gpu/drm/i915/display/intel_display_guc_metrics.c
new file mode 100644
index 000000000000..037421e61b90
--- /dev/null
+++ b/drivers/gpu/drm/i915/display/intel_display_guc_metrics.c
@@ -0,0 +1,153 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright © 2024 Intel Corporation
+ */
+
+#include "intel_display_guc_metrics.h"
+#include "intel_display_guc_metrics_types.h"
+
+#include <drm/drm_modes.h>
+
+#include "i915_drv.h"
+#include "intel_de.h"
+#include "intel_display_types.h"
+
+/**
+ * Display GuC Metrics
+ *
+ * GuC SLPC has many optimized strategies to best select the running GT
+ * frequency.
+ * One common strategy is to take display metrics as input through a shared
+ * data buffer. The GuC SLPC will then use these metrics for a optimal balance
+ * between power savings and performance.
+ *
+ * This intel_display_guc_metrics, provides a generic interface where xe_guc_pc
+ * or i915's intel_guc_slpc could register themselves in order to recieve the
+ * metrics from the running intel_display.
+ *
+ * Since this is a generic interface, it won't take any further action, but only
+ * pass the generic display information about refresh_info, flips and vblank.
+ * The GuC SLPC component of the registered driver (Xe or i915) will then be
+ * responsible for allocating the shared display buffer, for collecting the
+ * right timestamp registers of the GT, and for programming the shared buffer
+ * as requested by GuC.
+ *
+ * The Display Shared Data is a block of global GTT memory into which the host
+ * continually writes display related information for SLPC to read and use in
+ * its algorithms.
+ *
+ * The programming flow is as follows.
+ *
+ * The host allocates sufficient memory in the global GTT for the Display
+ * Shared Data.
+ *
+ * The host initializes the Display Shared Data by setting the Version,
+ * Number of Pipes, and Number of Planes per Pipe fields in the Global Info.
+ * All other fields should start at 0.
+ *
+ * The host provides the Display Shared Data memory address in the Shared Data
+ * while (re-)activating SLPC through the GUC_ACTION_HOST2GUC_PCV2_SLPC_REQUEST
+ * Reset event. SLPC will now begin reading the Display Shared Data as part of
+ * its periodic processing. It reads the Global Info section and proceeds to the
+ * other sections only if a change count has been incremented.
+ *
+ * On a display connection to a pipe, the host writes the Refresh Info for the
+ * given pipe, then increments the Refresh Info Change Count field of the Global
+ * Info to alert SLPC to the change. This is also done if an existing display
+ * changes its refresh configuration.
+ *
+ * On a vblank event, the host updates the Vblank Metrics for the given pipe,
+ * then increments the Vblank Metrics Change Count field of the Global Info to
+ * alert SLPC to the change.
+ *
+ * On a flip event, the host updates the Flip Metrics for the given plane on the
+ * given pipe, then increments the Flip Metrics Change Count field of the Global
+ * Info to alert SLPC to the change.
+ */
+
+/**
+ * intel_display_guc_metrics_init - For device driver registration (i915 or xe)
+ * @gfx_device: Back pointer to whatever device is driving display (i915 or xe).
+ * @display: Pointer to the intel_display struct that was initialized by gfx_device.
+ * @guc_metrics: Struct with the callback function pointers to get notication from display.
+ */
+void intel_display_guc_metrics_init(void *gfx_device,
+				    struct intel_display *display,
+				    struct intel_display_guc_metrics *guc_metrics)
+{
+	guc_metrics->gfx_device = gfx_device;
+	display->guc_metrics = guc_metrics;
+}
+
+/**
+ * intel_display_guc_metrics_refresh_info - Refresh rate information
+ * @display: Pointer to the intel_display struct that is in use by the gfx device.
+ * @crtc_state: New CRTC state upon a modeset.
+ *
+ * To be called on a modeset. It gets current refresh interval in micro seconds
+ * and pass back to the gfx device if the refresh_info_update callback is registered.
+ */
+void intel_display_guc_metrics_refresh_info(struct intel_display *display,
+					    struct intel_crtc_state *crtc_state)
+{
+	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
+	struct drm_display_mode *mode = &crtc_state->hw.adjusted_mode;
+	struct intel_display_guc_metrics *guc_metrics = display->guc_metrics;
+	u32 interval_us;
+
+	if (!guc_metrics)
+		return;
+
+	interval_us = crtc_state->hw.active ? DIV_ROUND_UP(1000000,
+						drm_mode_vrefresh(mode)) : 0;
+
+	if (guc_metrics->refresh_info_update)
+		guc_metrics->refresh_info_update(guc_metrics->gfx_device,
+						 crtc->pipe, interval_us,
+						 crtc_state->vrr.enable);
+}
+
+/**
+ * intel_display_guc_metrics_vblank - Vblank information
+ * @display: Pointer to the intel_display struct that is in use by the gfx device.
+ * @crtc: The Intel CRTC that received the vblank interrupt.
+ *
+ * To be called when a vblank is passed. It extracts the pipe from the intel_crtc
+ * and pass back to the gfx device if the vblank_update callback is registered.
+ */
+void intel_display_guc_metrics_vblank(struct intel_display *display,
+				      struct intel_crtc *crtc)
+{
+	struct intel_display_guc_metrics *guc_metrics = display->guc_metrics;
+
+	if (!guc_metrics)
+		return;
+
+	if (guc_metrics->vblank_update)
+		guc_metrics->vblank_update(guc_metrics->gfx_device, crtc->pipe);
+}
+
+/**
+ * intel_display_guc_metrics_flip - Flip information
+ * @display: Pointer to the intel_display struct that is in use by the gfx device.
+ * @crtc_state: New CRTC state upon a page flip.
+ * @plane: Which plane ID got the page flip.
+ * @async_flip: A boolean to indicate if the page flip was async.
+ *
+ * To be called on a page flip. Then it pass the relevant information
+ * to the gfx device if the flip_update callback is registered.
+ */
+void intel_display_guc_metrics_flip(struct intel_display *display,
+				    const struct intel_crtc_state *crtc_state,
+				    int plane, bool async_flip)
+{
+	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
+	struct intel_display_guc_metrics *guc_metrics = display->guc_metrics;
+
+	if (!guc_metrics)
+		return;
+
+	if (guc_metrics->flip_update)
+		guc_metrics->flip_update(guc_metrics->gfx_device,
+					 crtc->pipe, plane, async_flip);
+}
diff --git a/drivers/gpu/drm/i915/display/intel_display_guc_metrics.h b/drivers/gpu/drm/i915/display/intel_display_guc_metrics.h
new file mode 100644
index 000000000000..9a9b8673f2b0
--- /dev/null
+++ b/drivers/gpu/drm/i915/display/intel_display_guc_metrics.h
@@ -0,0 +1,26 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright © 2024 Intel Corporation
+ */
+
+#ifndef __INTEL_DISPLAY_GUC_METRICS_H__
+#define __INTEL_DISPLAY_GUC_METRICS_H__
+
+#include <linux/types.h>
+
+struct intel_crtc;
+struct intel_crtc_state;
+struct intel_display;
+struct intel_display_guc_metrics;
+
+void intel_display_guc_metrics_init(void *gfx_device,
+				    struct intel_display *display,
+				    struct intel_display_guc_metrics *guc_metrics);
+void intel_display_guc_metrics_refresh_info(struct intel_display *display,
+					    struct intel_crtc_state *crtc_state);
+void intel_display_guc_metrics_vblank(struct intel_display *display,
+				      struct intel_crtc *intel_crtc);
+void intel_display_guc_metrics_flip(struct intel_display *display,
+				    const struct intel_crtc_state *crtc_state,
+				    int plane, bool async_flip);
+#endif
diff --git a/drivers/gpu/drm/i915/display/intel_display_guc_metrics_types.h b/drivers/gpu/drm/i915/display/intel_display_guc_metrics_types.h
new file mode 100644
index 000000000000..036cf55d58a0
--- /dev/null
+++ b/drivers/gpu/drm/i915/display/intel_display_guc_metrics_types.h
@@ -0,0 +1,32 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright © 2024 Intel Corporation
+ */
+
+#ifndef __INTEL_DISPLAY_GUC_METRICS_TYPES_H__
+#define __INTEL_DISPLAY_GUC_METRICS_TYPES_H__
+
+/**
+ * struct intel_display_guc_metrics - Intel Display GuC Metrics main struct
+ *
+ * The graphics device can register with intel_display to get information
+ * about display events that will then be used with GuC SLPC.
+ */
+struct intel_display_guc_metrics {
+	/**
+	 * @gfx_device: A pointer to the private device,
+	 * either to struct drm_i915_private or to struct xe_device.
+	 */
+	void *gfx_device;
+
+	/** @refresh_info_update: Callback for getting refresh information on modeset */
+	void (*refresh_info_update)(void *gfx_device, int pipe,
+				    u32 refresh_interval, bool vrr_enabled);
+	/** @vblank_update: Callback for getting vblank information updates */
+	void (*vblank_update)(void *gfx_device, int pipe);
+	/** @flip_update: Callback for getting page flip information updates */
+	void (*flip_update)(void *gfx_device, int pipe, int plane,
+			    bool async_flip);
+};
+
+#endif
diff --git a/drivers/gpu/drm/i915/display/intel_display_irq.c b/drivers/gpu/drm/i915/display/intel_display_irq.c
index f846c5b108b5..339bfbbe9314 100644
--- a/drivers/gpu/drm/i915/display/intel_display_irq.c
+++ b/drivers/gpu/drm/i915/display/intel_display_irq.c
@@ -10,6 +10,7 @@
 #include "icl_dsi_regs.h"
 #include "intel_crtc.h"
 #include "intel_de.h"
+#include "intel_display_guc_metrics.h"
 #include "intel_display_irq.h"
 #include "intel_display_trace.h"
 #include "intel_display_types.h"
@@ -25,8 +26,10 @@
 static void
 intel_handle_vblank(struct drm_i915_private *dev_priv, enum pipe pipe)
 {
+	struct intel_display *display = &dev_priv->display;
 	struct intel_crtc *crtc = intel_crtc_for_pipe(dev_priv, pipe);
 
+	intel_display_guc_metrics_vblank(display, crtc);
 	drm_crtc_handle_vblank(&crtc->base);
 }
 
diff --git a/drivers/gpu/drm/i915/display/skl_universal_plane.c b/drivers/gpu/drm/i915/display/skl_universal_plane.c
index e941e2e4fd14..0e98ec0665b9 100644
--- a/drivers/gpu/drm/i915/display/skl_universal_plane.c
+++ b/drivers/gpu/drm/i915/display/skl_universal_plane.c
@@ -12,6 +12,7 @@
 #include "i915_reg.h"
 #include "intel_atomic_plane.h"
 #include "intel_de.h"
+#include "intel_display_guc_metrics.h"
 #include "intel_display_irq.h"
 #include "intel_display_types.h"
 #include "intel_fb.h"
@@ -1392,6 +1393,7 @@ skl_plane_async_flip(struct intel_plane *plane,
 		     bool async_flip)
 {
 	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
+	struct intel_display *display = &dev_priv->display;
 	enum plane_id plane_id = plane->id;
 	enum pipe pipe = plane->pipe;
 	u32 plane_ctl = plane_state->ctl;
@@ -1404,6 +1406,7 @@ skl_plane_async_flip(struct intel_plane *plane,
 	intel_de_write_fw(dev_priv, PLANE_CTL(pipe, plane_id), plane_ctl);
 	intel_de_write_fw(dev_priv, PLANE_SURF(pipe, plane_id),
 			  skl_plane_surf(plane_state, 0));
+	intel_display_guc_metrics_flip(display, crtc_state, plane_id, async_flip);
 }
 
 static bool intel_format_is_p01x(u32 format)
diff --git a/drivers/gpu/drm/xe/Makefile b/drivers/gpu/drm/xe/Makefile
index c531210695db..e5b62cfbac8b 100644
--- a/drivers/gpu/drm/xe/Makefile
+++ b/drivers/gpu/drm/xe/Makefile
@@ -224,6 +224,7 @@ xe-$(CONFIG_DRM_XE_DISPLAY) += \
 	i915-display/intel_display_device.o \
 	i915-display/intel_display_driver.o \
 	i915-display/intel_display_irq.o \
+	i915-display/intel_display_guc_metrics.o \
 	i915-display/intel_display_params.o \
 	i915-display/intel_display_power.o \
 	i915-display/intel_display_power_map.o \
-- 
2.43.2


  reply	other threads:[~2024-02-27 14:58 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-02-27 14:58 [RFC 0/3] Display experiment + GuC Display Metrics Rodrigo Vivi
2024-02-27 14:58 ` Rodrigo Vivi [this message]
2024-02-27 14:58 ` [RFC 2/3] drm/i915: Add experimental GuC SLPC display metrics Rodrigo Vivi
2024-02-27 14:58 ` [RFC 3/3] drm/xe: Add GuC SLPC Display Metrics Rodrigo Vivi
2024-02-27 15:15 ` ✗ CI.Patch_applied: failure for Display experiment + GuC " Patchwork
2024-02-27 19:09 ` ✗ Fi.CI.BUILD: " Patchwork

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20240227145833.490328-2-rodrigo.vivi@intel.com \
    --to=rodrigo.vivi@intel.com \
    --cc=intel-gfx@lists.freedesktop.org \
    --cc=intel-xe@lists.freedesktop.org \
    --cc=jani.nikula@intel.com \
    --cc=jani.nikula@linux.intel.com \
    --cc=lucas.demarchi@intel.com \
    --cc=vinay.belgaumkar@intel.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.