RE: [PATCH v2 04/21] drm/i915/dp: Add support to notify MST connectors to retry modesets

2024-02-22 Thread Shankar, Uma


> -Original Message-
> From: Intel-gfx  On Behalf Of Imre
> Deak
> Sent: Wednesday, February 21, 2024 2:48 AM
> To: intel-...@lists.freedesktop.org; dri-devel@lists.freedesktop.org
> Cc: Hogander, Jouni 
> Subject: [PATCH v2 04/21] drm/i915/dp: Add support to notify MST connectors to
> retry modesets
> 
> On shared (Thunderbolt) links with DP tunnels, the modeset may need to be
> retried on all connectors on the link due to a link BW limitation arising 
> only after
> the atomic check phase. To support this add a helper function queuing a work 
> to
> retry the modeset on a given port's connector and at the same time any MST
> connector with streams through the same port. A follow-up change enabling the
> DP tunnel Bandwidth Allocation Mode will take this into use.
> 
> v2:
> - Send the uevent only to enabled MST connectors. (Jouni)

Looks Good to me.
Reviewed-by: Uma Shankar 

> Cc: Jouni Högander 
> Signed-off-by: Imre Deak 
> ---
>  drivers/gpu/drm/i915/display/intel_display.c  |  5 ++-
>  drivers/gpu/drm/i915/display/intel_dp.c   | 45 ++-
>  drivers/gpu/drm/i915/display/intel_dp.h   |  6 +++
>  .../drm/i915/display/intel_dp_link_training.c |  3 +-
>  drivers/gpu/drm/i915/display/intel_dp_mst.c   |  2 +
>  5 files changed, 55 insertions(+), 6 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/display/intel_display.c
> b/drivers/gpu/drm/i915/display/intel_display.c
> index 485c38d71f106..2ee26d19c200b 100644
> --- a/drivers/gpu/drm/i915/display/intel_display.c
> +++ b/drivers/gpu/drm/i915/display/intel_display.c
> @@ -8085,8 +8085,9 @@ void intel_hpd_poll_fini(struct drm_i915_private
> *i915)
>   /* Kill all the work that may have been queued by hpd. */
>   drm_connector_list_iter_begin(>drm, _iter);
>   for_each_intel_connector_iter(connector, _iter) {
> - if (connector->modeset_retry_work.func)
> - cancel_work_sync(>modeset_retry_work);
> + if (connector->modeset_retry_work.func &&
> + cancel_work_sync(>modeset_retry_work))
> + drm_connector_put(>base);
>   if (connector->hdcp.shim) {
>   cancel_delayed_work_sync(
> >hdcp.check_work);
>   cancel_work_sync(>hdcp.prop_work);
> diff --git a/drivers/gpu/drm/i915/display/intel_dp.c
> b/drivers/gpu/drm/i915/display/intel_dp.c
> index 217196196e50a..88606e336a920 100644
> --- a/drivers/gpu/drm/i915/display/intel_dp.c
> +++ b/drivers/gpu/drm/i915/display/intel_dp.c
> @@ -2842,6 +2842,40 @@ intel_dp_audio_compute_config(struct intel_encoder
> *encoder,
>   intel_dp_is_uhbr(pipe_config);
>  }
> 
> +void intel_dp_queue_modeset_retry_work(struct intel_connector
> +*connector) {
> + struct drm_i915_private *i915 = to_i915(connector->base.dev);
> +
> + drm_connector_get(>base);
> + if (!queue_work(i915->unordered_wq, 
> >modeset_retry_work))
> + drm_connector_put(>base);
> +}
> +
> +void
> +intel_dp_queue_modeset_retry_for_link(struct intel_atomic_state *state,
> +   struct intel_encoder *encoder,
> +   const struct intel_crtc_state 
> *crtc_state) {
> + struct intel_connector *connector;
> + struct intel_digital_connector_state *conn_state;
> + struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
> + int i;
> +
> + if (!intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DP_MST)) {
> + intel_dp_queue_modeset_retry_work(intel_dp-
> >attached_connector);
> +
> + return;
> + }
> +
> + for_each_new_intel_connector_in_state(state, connector, conn_state, i) {
> + if (!conn_state->base.crtc)
> + continue;
> +
> + if (connector->mst_port == intel_dp)
> + intel_dp_queue_modeset_retry_work(connector);
> + }
> +}
> +
>  int
>  intel_dp_compute_config(struct intel_encoder *encoder,
>   struct intel_crtc_state *pipe_config, @@ -6441,6
> +6475,14 @@ static void intel_dp_modeset_retry_work_fn(struct work_struct
> *work)
>   mutex_unlock(>dev->mode_config.mutex);
>   /* Send Hotplug uevent so userspace can reprobe */
>   drm_kms_helper_connector_hotplug_event(connector);
> +
> + drm_connector_put(connector);
> +}
> +
> +void intel_dp_init_modeset_retry_work(struct intel_connector
> +*connector) {
> + INIT_WORK(>modeset_retry_work,
> +   intel_dp_modeset_retry_work_fn);
>  }
> 
>  bool
> @@ -6457,8 +6499,7 @@ intel_dp_init_connector(struct intel_digital_port
> *dig_port,
>   int type;
> 
>   /* Initialize the work for modeset in case of link train failure */
> - INIT_WORK(_connector->modeset_retry_work,
> -   intel_dp_modeset_retry_work_fn);
> + intel_dp_init_modeset_retry_work(intel_connector);
> 
>   if (drm_WARN(dev, dig_port->max_lanes < 1,
>"Not enough lanes (%d) 

Re: [PATCH 1/3] drm/amdgpu: Refuse to create a KMS FB for non-P2P exported dma-bufs

2024-02-22 Thread Christian König

Am 22.02.24 um 18:28 schrieb Michel Dänzer:

From: Michel Dänzer 

Pinning the BO storage to VRAM for scanout would make it inaccessible
to non-P2P dma-buf importers.


Thinking more about it I don't think we can do this.

Using the BO in a ping/pong fashion for scanout and DMA-buf is actually 
valid, you just can't do both at the same time.


And if I'm not completely mistaken we actually have use cases for this 
at the moment, only as fallback but it would still break existing 
userspace and that is a no-go.


So rejecting things during CS and atomic commit is the best thing we can do.

Regards,
Christian.



Closes: https://gitlab.freedesktop.org/mesa/mesa/-/issues/10635
Signed-off-by: Michel Dänzer 
---
  drivers/gpu/drm/amd/amdgpu/amdgpu_display.c | 38 ++---
  1 file changed, 33 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c
index b8fbe97efe1d3..514a5b2159815 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c
@@ -1255,13 +1255,41 @@ amdgpu_display_user_framebuffer_create(struct 
drm_device *dev,
return ERR_PTR(-ENOENT);
}
  
-	/* Handle is imported dma-buf, so cannot be migrated to VRAM for scanout */

bo = gem_to_amdgpu_bo(obj);
domains = amdgpu_display_supported_domains(drm_to_adev(dev), bo->flags);
-   if (obj->import_attach && !(domains & AMDGPU_GEM_DOMAIN_GTT)) {
-   drm_dbg_kms(dev, "Cannot create framebuffer from imported 
dma_buf\n");
-   drm_gem_object_put(obj);
-   return ERR_PTR(-EINVAL);
+   if (!(domains & AMDGPU_GEM_DOMAIN_GTT)) {
+   bool can_pin = true;
+
+   mutex_lock(_priv->prime.lock);
+
+   /* Handle is imported dma-buf, so cannot be migrated to VRAM 
for scanout */
+   if (obj->import_attach) {
+   drm_dbg_kms(dev, "Cannot create framebuffer from imported 
dma_buf\n");
+   can_pin = false;
+   } else if (obj->dma_buf) {
+   struct dma_buf *dmabuf = obj->dma_buf;
+   struct dma_buf_attachment *attachment;
+
+   dma_resv_lock(dmabuf->resv, NULL);
+
+   list_for_each_entry(attachment, >attachments, 
node) {
+   if (IS_ENABLED(CONFIG_DMABUF_MOVE_NOTIFY) && 
attachment->peer2peer)
+   continue;
+
+   drm_dbg_kms(dev, "Cannot create framebuffer from 
non-P2P exported dma_buf\n");
+   can_pin = false;
+   break;
+   }
+
+   dma_resv_unlock(dmabuf->resv);
+   }
+
+   mutex_unlock(_priv->prime.lock);
+
+   if (!can_pin) {
+   drm_gem_object_put(obj);
+   return ERR_PTR(-EINVAL);
+   }
}
  
  	amdgpu_fb = kzalloc(sizeof(*amdgpu_fb), GFP_KERNEL);




RE: [PATCH v2 03/21] drm/i915: Fix display bpp limit computation during system resume

2024-02-22 Thread Shankar, Uma



> -Original Message-
> From: dri-devel  On Behalf Of Imre
> Deak
> Sent: Wednesday, February 21, 2024 2:48 AM
> To: intel-...@lists.freedesktop.org; dri-devel@lists.freedesktop.org
> Subject: [PATCH v2 03/21] drm/i915: Fix display bpp limit computation during
> system resume
> 
> The system resume display mode restoration should happen with an output
> configuration matching that of the suspend time saved mode. Since the restored
> mode configuration is subject to the bpp fallback logic, starting out with an
> unlimited bpp and reducing the bpp as required by any (MST) link BW limit, the
> resulting bpp will match the one during suspend only if the BW limit checks 
> during
> suspend and resume are applied in an identical way. The latter is not 
> guaranteed
> at the moment, since the pre-suspend MST topology may not be in place during
> resume (for instance if the MST sink was disconnected while being suspended),
> which makes the MST link BW check accept the unlimited bpp mode
> configuration unconditionally without ensuring that the required BW fits into 
> the
> available MST link BW.
> 
> To fix the above, initialize the bpp fallback logic with the max link bpp / 
> force-FEC
> limits left behind by the suspend time mode save.

Looks Good to me.
Reviewed-by: Uma Shankar 

> Signed-off-by: Imre Deak 
> ---
>  drivers/gpu/drm/i915/display/intel_display.c |  3 +--
> drivers/gpu/drm/i915/display/intel_link_bw.c | 22 
> drivers/gpu/drm/i915/display/intel_link_bw.h |  2 +-
>  3 files changed, 20 insertions(+), 7 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/display/intel_display.c
> b/drivers/gpu/drm/i915/display/intel_display.c
> index 00ac65a140298..485c38d71f106 100644
> --- a/drivers/gpu/drm/i915/display/intel_display.c
> +++ b/drivers/gpu/drm/i915/display/intel_display.c
> @@ -6252,12 +6252,11 @@ static int intel_atomic_check_config(struct
> intel_atomic_state *state,
> 
>  static int intel_atomic_check_config_and_link(struct intel_atomic_state 
> *state)  {
> - struct drm_i915_private *i915 = to_i915(state->base.dev);
>   struct intel_link_bw_limits new_limits;
>   struct intel_link_bw_limits old_limits;
>   int ret;
> 
> - intel_link_bw_init_limits(i915, _limits);
> + intel_link_bw_init_limits(state, _limits);
>   old_limits = new_limits;
> 
>   while (true) {
> diff --git a/drivers/gpu/drm/i915/display/intel_link_bw.c
> b/drivers/gpu/drm/i915/display/intel_link_bw.c
> index 9c6d35a405a18..27ea858897c9f 100644
> --- a/drivers/gpu/drm/i915/display/intel_link_bw.c
> +++ b/drivers/gpu/drm/i915/display/intel_link_bw.c
> @@ -6,6 +6,7 @@
>  #include "i915_drv.h"
> 
>  #include "intel_atomic.h"
> +#include "intel_crtc.h"
>  #include "intel_display_types.h"
>  #include "intel_dp_mst.h"
>  #include "intel_fdi.h"
> @@ -13,19 +14,32 @@
> 
>  /**
>   * intel_link_bw_init_limits - initialize BW limits
> - * @i915: device instance
> + * @state: Atomic state
>   * @limits: link BW limits
>   *
>   * Initialize @limits.
>   */
> -void intel_link_bw_init_limits(struct drm_i915_private *i915, struct
> intel_link_bw_limits *limits)
> +void intel_link_bw_init_limits(struct intel_atomic_state *state,
> +struct intel_link_bw_limits *limits)
>  {
> + struct drm_i915_private *i915 = to_i915(state->base.dev);
>   enum pipe pipe;
> 
>   limits->force_fec_pipes = 0;
>   limits->bpp_limit_reached_pipes = 0;
> - for_each_pipe(i915, pipe)
> - limits->max_bpp_x16[pipe] = INT_MAX;
> + for_each_pipe(i915, pipe) {
> + const struct intel_crtc_state *crtc_state =
> + intel_atomic_get_new_crtc_state(state,
> +
>   intel_crtc_for_pipe(i915, pipe));
> +
> + if (state->base.duplicated && crtc_state) {
> + limits->max_bpp_x16[pipe] = crtc_state-
> >max_link_bpp_x16;
> + if (crtc_state->fec_enable)
> + limits->force_fec_pipes |= BIT(pipe);
> + } else {
> + limits->max_bpp_x16[pipe] = INT_MAX;
> + }
> + }
>  }
> 
>  /**
> diff --git a/drivers/gpu/drm/i915/display/intel_link_bw.h
> b/drivers/gpu/drm/i915/display/intel_link_bw.h
> index 2cf57307cc249..6b0ccfff59dab 100644
> --- a/drivers/gpu/drm/i915/display/intel_link_bw.h
> +++ b/drivers/gpu/drm/i915/display/intel_link_bw.h
> @@ -22,7 +22,7 @@ struct intel_link_bw_limits {
>   int max_bpp_x16[I915_MAX_PIPES];
>  };
> 
> -void intel_link_bw_init_limits(struct drm_i915_private *i915,
> +void intel_link_bw_init_limits(struct intel_atomic_state *state,
>  struct intel_link_bw_limits *limits);  int
> intel_link_bw_reduce_bpp(struct intel_atomic_state *state,
>struct intel_link_bw_limits *limits,
> --
> 2.39.2



RE: [PATCH v2 02/21] drm/dp: Add support for DP tunneling

2024-02-22 Thread Shankar, Uma


> -Original Message-
> From: Intel-gfx  On Behalf Of Imre
> Deak
> Sent: Wednesday, February 21, 2024 2:48 AM
> To: intel-...@lists.freedesktop.org; dri-devel@lists.freedesktop.org
> Cc: Ville Syrjälä 
> Subject: [PATCH v2 02/21] drm/dp: Add support for DP tunneling
> 
> Add support for Display Port tunneling. For now this includes the
> support for Bandwidth Allocation Mode (BWA), leaving adding Panel Replay
> support for later.
> 
> BWA allows using displays that share the same (Thunderbolt) link with
> their maximum resolution. Atm, this may not be possible due to the
> coarse granularity of partitioning the link BW among the displays on the
> link: the BW allocation policy is in a SW/FW/HW component on the link
> (on Thunderbolt it's the SW or FW Connection Manager), independent of
> the driver. This policy will set the DPRX maximum rate and lane count
> DPCD registers the GFX driver will see (0x0, 0x1, 0x02200,
> 0x02201) based on the available link BW.
> 
> The granularity of the current BW allocation policy is coarse, based on
> the required link rate in the 1.62Gbs..8.1Gbps range and it may prevent
> using higher resolutions all together: the display connected first will
> get a share of the link BW which corresponds to its full DPRX capability
> (regardless of the actual mode it uses). A subsequent display connected
> will only get the remaining BW, which could be well below its full
> capability.
> 
> BWA solves the above coarse granularity (reducing it to a 250Mbs..1Gps
> range) and first-come/first-served issues by letting the driver request
> the BW for each display on a link which reflects the actual modes the
> displays use.
> 
> This patch adds the DRM core helper functions, while a follow-up change
> in the patchset takes them into use in the i915 driver.
> 
> v2:
> - Fix prepare_to_wait vs. wake-up cond check order in
>   allocate_tunnel_bw(). (Ville)
> - Move tunnel==NULL checks from callers in drivers to here. (Ville)
> - Avoid var inits in declaration blocks that can fail or have
>   side-effects. (Ville)
> - Use u8 for driver and group IDs. (Ville)
> - Simplify API removing drm_dp_tunnel_get/put_untracked(). (Ville)
> - Reuse str_yes_no() instead of a local yes_no_chr(). (Ville)
> - s/drm_dp_tunnel_atomic_clear_state()/free_tunnel_state() and unexport
>   the function. (Ville)
> - s/clear_tunnel_group_state()/free_group_state() and move kfree() to
>   this function. (Ville)
> - Add separate group_free_bw() helper and describe what the tunnel
>   estimated BW includes. (Ville)
> - Improve help text for CONFIG_DRM_DISPLAY_DP_TUNNEL. (Ville)
> - Add code comment explaining the purpose of DPCD reg read helpers.
>   (Ville)
> - Add code comment describing the tunnel group name prefix format.
>   (Ville)
> - Report the allocated BW as undetermined until the first allocation
>   request.
> - Skip allocation requests matching the previous request.
> - Clear any stale BW request status flags before a new request.
> - Add missing error return check of drm_dp_tunnel_atomic_get_group_state()
>   in drm_dp_tunnel_atomic_set_stream_bw().
> - Add drm_dp_tunnel_get_allocated_bw().
> -
> s/drm_dp_tunnel_atomic_get_tunnel_bw/drm_dp_tunnel_atomic_get_required_
> bw
> - Fix return value description in function doc of drm_dp_tunnel_detect().
> - Add function documentation to all exported functions.
> 
> Cc: Ville Syrjälä 
> Signed-off-by: Imre Deak 
> ---
>  drivers/gpu/drm/display/Kconfig |   21 +
>  drivers/gpu/drm/display/Makefile|2 +
>  drivers/gpu/drm/display/drm_dp_tunnel.c | 1929 +++
>  include/drm/display/drm_dp.h|   60 +
>  include/drm/display/drm_dp_tunnel.h |  248 +++
>  5 files changed, 2260 insertions(+)
>  create mode 100644 drivers/gpu/drm/display/drm_dp_tunnel.c
>  create mode 100644 include/drm/display/drm_dp_tunnel.h
> 
> diff --git a/drivers/gpu/drm/display/Kconfig b/drivers/gpu/drm/display/Kconfig
> index 09712b88a5b83..c0f56888c3280 100644
> --- a/drivers/gpu/drm/display/Kconfig
> +++ b/drivers/gpu/drm/display/Kconfig
> @@ -17,6 +17,27 @@ config DRM_DISPLAY_DP_HELPER
>   help
> DRM display helpers for DisplayPort.
> 
> +config DRM_DISPLAY_DP_TUNNEL
> + bool
> + select DRM_DISPLAY_DP_HELPER
> + help
> +   Enable support for DisplayPort tunnels. This allows drivers to use
> +   DP tunnel features like the Bandwidth Allocation mode to maximize the
> +   BW utilization for display streams on Thunderbolt links.
> +
> +config DRM_DISPLAY_DEBUG_DP_TUNNEL_STATE
> + bool "Enable debugging the DP tunnel state"
> + depends on REF_TRACKER
> + depends on DRM_DISPLAY_DP_TUNNEL
> + depends on DEBUG_KERNEL
> + depends on EXPERT
> + help
> +   Enables debugging the DP tunnel manager's state, including the
> +   consistency of all managed tunnels' reference counting and the state 
> of
> +   streams contained in tunnels.
> +
> +   If in doubt, say "N".
> 

Re: drm_format_helper_test fails Subtest: drm_test_fb_xrgb8888_to_xrgb2101010 on Big Endian machines (kernel 6.7.5, ppc64)

2024-02-22 Thread Christophe Leroy
Hi,

Le 20/02/2024 à 00:45, Erhard Furtner a écrit :
> Greetings!
> 
> I ran some kernel drm/ttm unit tests to check for quirks in the drm/ttm 
> subsystem. One thing I found out that the drm_format_helper_test fails 
> Subtest: drm_test_fb_xrgb_to_xrgb2101010 on my Talos II (ppc64) which I 
> run in BigEndian mode:
> 
> [...]
>   KTAP version 1
>   # Subtest: drm_test_fb_xrgb_to_xrgb2101010
>   # drm_test_fb_xrgb_to_xrgb2101010: EXPECTATION FAILED at 
> drivers/gpu/drm/tests/drm_format_helper_test.c:995
>   Expected buf == result->expected, but
>   buf ==
>   <00><00><3f>
>   result->expected ==
>   <3f><00><00>
>   not ok 1 single_pixel_source_buffer
>   # drm_test_fb_xrgb_to_xrgb2101010: EXPECTATION FAILED at 
> drivers/gpu/drm/tests/drm_format_helper_test.c:995
>   Expected buf == result->expected, but
>   buf ==
>   <00><00><3f>
>   result->expected ==
>   <3f><00><00>
>   not ok 2 single_pixel_clip_rectangle
>   # drm_test_fb_xrgb_to_xrgb2101010: EXPECTATION FAILED at 
> drivers/gpu/drm/tests/drm_format_helper_test.c:995
>   Expected buf == result->expected, but
>   buf ==
>ff  ff <3f> 00  00  00  00 <00><00><3f> 00 <0f> 00
>   <03><00><00><03><3f><00><3f><0f><00>
>   result->expected ==
>   <3f> ff  ff  00  00  00  00 <3f><00><00> 00 <0f> 00
>   <00><00><03><3f><03><3f><00><00><0f>
>   not ok 3 well_known_colors
>   # drm_test_fb_xrgb_to_xrgb2101010: EXPECTATION FAILED at 
> drivers/gpu/drm/tests/drm_format_helper_test.c:995
>   Expected buf == result->expected, but
>   buf ==
>   <72><46><84><03><14><44><04><0c><3c><2f><2a> 00  00  00  00
>00  00  00  00 <0d><1f><1b><72><46><84><03><14><44><04>
>00  00  00  00  00  00  00  00 <0c><30><20><2a><0d><1f><1b>
>   <72><46><84><03> 00  00  00  00  00  00  00  00
>   result->expected ==
>   <03><84><46><72><04><44><14><2a><2f><3c><0c> 00  00  00  00
>00  00  00  00 <1b><1f><0d><03><84><46><72><04><44><14>
>00  00  00  00  00  00  00  00 <2a><20><30><0c><1b><1f><0d>
>   <03><84><46><72> 00  00  00  00  00  00  00  00
>   not ok 4 destination_pitch
>   # drm_test_fb_xrgb_to_xrgb2101010: pass:0 fail:4 skip:0 total:4
>   not ok 9 drm_test_fb_xrgb_to_xrgb2101010
> [...]
> 
> Looking at these results I suspect this to be an endian issue, probably 
> affecting other BE arches too.
> 
> Full dmesg + kernel .config attached.

Doing a build with C=2 I get the following warning. Fix this warning and 
it should work on all endiannesses:

   CC  drivers/gpu/drm/tests/drm_format_helper_test.o
   CHECK   drivers/gpu/drm/tests/drm_format_helper_test.c
drivers/gpu/drm/tests/drm_format_helper_test.c:994:36: warning: 
incorrect type in argument 2 (different base types)
drivers/gpu/drm/tests/drm_format_helper_test.c:994:36:expected 
restricted __le32 const [usertype] *buf
drivers/gpu/drm/tests/drm_format_helper_test.c:994:36:got unsigned 
int [usertype] *[assigned] buf


Christophe


Re: [PATCH v3 1/1] drm/mediatek: Filter modes according to hardware capability

2024-02-22 Thread 胡俊光


Re: Re: [PATCH] drm/xe: Prefer struct_size over open coded arithmetic

2024-02-22 Thread Lucas De Marchi

On Sat, Feb 10, 2024 at 10:49:57AM -0600, Gustavo A. R. Silva wrote:



On 2/10/24 08:19, Erick Archer wrote:

This is an effort to get rid of all multiplications from allocation
functions in order to prevent integer overflows [1].

As the "q" variable is a pointer to "struct xe_exec_queue" and this
structure ends in a flexible array:

struct xe_exec_queue {
[...]
struct xe_lrc lrc[];
};

the preferred way in the kernel is to use the struct_size() helper to
do the arithmetic instead of the argument "size + size * count" in the
kzalloc() function.

This way, the code is more readable and more safer.

Link: 
https://www.kernel.org/doc/html/latest/process/deprecated.html#open-coded-arithmetic-in-allocator-arguments
 [1]
Link: https://github.com/KSPP/linux/issues/160 [2]
Signed-off-by: Erick Archer 


LGTM:

Reviewed-by: Gustavo A. R. Silva 


applied to drm-xe-next. Thanks for the patch and review.

Lucas De Marchi


[linux-next:master] BUILD REGRESSION e31185ce00a96232308300008db193416ceb9769

2024-02-22 Thread kernel test robot
tree/branch: 
https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git master
branch HEAD: e31185ce00a9623230838db193416ceb9769  Add linux-next specific 
files for 20240222

Error/Warning reports:

https://lore.kernel.org/oe-kbuild-all/20240223.h9rfmyj4-...@intel.com
https://lore.kernel.org/oe-kbuild-all/20240314.j6a7eb4b-...@intel.com
https://lore.kernel.org/oe-kbuild-all/202402230537.2s6nhfsn-...@intel.com

Error/Warning: (recently discovered and may have been fixed)

arch/arm/boot/compressed/misc.c:157:6: warning: no previous prototype for 
function '__fortify_panic' [-Wmissing-prototypes]
arch/arm/boot/compressed/misc.h:13:36: error: macro "fortify_panic" requires 2 
arguments, but only 1 given
arch/sh/boot/compressed/../../../../lib/decompress_unxz.c:350:(.text+0x20b4): 
undefined reference to `__ubsan_handle_out_of_bounds'
sh4-linux-ld: 
arch/sh/boot/compressed/../../../../lib/xz/xz_dec_lzma2.c:751:(.text+0x904): 
undefined reference to `__ubsan_handle_out_of_bounds'

Error/Warning ids grouped by kconfigs:

gcc_recent_errors
|-- alpha-allyesconfig
|   `-- 
drivers-gpu-drm-nouveau-nvkm-subdev-gsp-r535.c:warning:Function-parameter-or-struct-member-gsp-not-described-in-nvkm_gsp_radix3_sg
|-- arc-allmodconfig
|   `-- 
drivers-gpu-drm-nouveau-nvkm-subdev-gsp-r535.c:warning:Function-parameter-or-struct-member-gsp-not-described-in-nvkm_gsp_radix3_sg
|-- arc-allyesconfig
|   `-- 
drivers-gpu-drm-nouveau-nvkm-subdev-gsp-r535.c:warning:Function-parameter-or-struct-member-gsp-not-described-in-nvkm_gsp_radix3_sg
|-- arc-randconfig-001-20240222
|   `-- fs-ntfs3-frecord.c:warning:unused-variable-i_size
|-- arc-randconfig-002-20240222
|   `-- fs-ntfs3-frecord.c:warning:unused-variable-i_size
|-- arc-randconfig-r122-20240223
|   |-- 
drivers-video-backlight-ktd2801-backlight.c:sparse:sparse:symbol-ktd2801_timing-was-not-declared.-Should-it-be-static
|   |-- fs-ntfs3-frecord.c:warning:unused-variable-i_size
|   |-- fs-ntfs3-fslog.c:sparse:sparse:restricted-__le32-degrades-to-integer
|   |-- 
include-trace-..-..-drivers-bus-mhi-host-trace.h:sparse:sparse:cast-to-restricted-__le32
|   |-- 
include-trace-..-..-drivers-bus-mhi-host-trace.h:sparse:sparse:cast-to-restricted-__le64
|   |-- 
include-trace-..-..-drivers-bus-mhi-host-trace.h:sparse:sparse:restricted-__le32-degrades-to-integer
|   |-- 
include-trace-..-..-drivers-bus-mhi-host-trace.h:sparse:sparse:restricted-__le64-degrades-to-integer
|   `-- io_uring-io_uring.c:sparse:sparse:cast-to-restricted-io_req_flags_t
|-- arc-randconfig-r133-20240223
|   |-- 
drivers-leds-flash-leds-ktd2692.c:sparse:sparse:symbol-ktd2692_timing-was-not-declared.-Should-it-be-static
|   |-- fs-ntfs3-frecord.c:warning:unused-variable-i_size
|   |-- fs-ntfs3-fslog.c:sparse:sparse:restricted-__le32-degrades-to-integer
|   |-- io_uring-io_uring.c:sparse:sparse:cast-to-restricted-io_req_flags_t
|   |-- 
sound-core-sound_kunit.c:sparse:sparse:incorrect-type-in-argument-(different-base-types)-expected-restricted-snd_pcm_format_t-usertype-format-got-int
|   `-- 
sound-core-sound_kunit.c:sparse:sparse:restricted-snd_pcm_format_t-degrades-to-integer
|-- arm-allyesconfig
|   `-- 
drivers-gpu-drm-nouveau-nvkm-subdev-gsp-r535.c:warning:Function-parameter-or-struct-member-gsp-not-described-in-nvkm_gsp_radix3_sg
|-- arm-aspeed_g5_defconfig
|   `-- 
arch-arm-boot-compressed-misc.h:error:macro-fortify_panic-requires-arguments-but-only-given
|-- arm-multi_v7_defconfig
|   `-- 
drivers-gpu-drm-nouveau-nvkm-subdev-gsp-r535.c:warning:Function-parameter-or-struct-member-gsp-not-described-in-nvkm_gsp_radix3_sg
|-- arm-randconfig-001-20240222
|   `-- fs-ntfs3-frecord.c:warning:unused-variable-i_size
|-- arm-tegra_defconfig
|   `-- 
drivers-gpu-drm-nouveau-nvkm-subdev-gsp-r535.c:warning:Function-parameter-or-struct-member-gsp-not-described-in-nvkm_gsp_radix3_sg
|-- arm64-defconfig
|   `-- 
drivers-gpu-drm-nouveau-nvkm-subdev-gsp-r535.c:warning:Function-parameter-or-struct-member-gsp-not-described-in-nvkm_gsp_radix3_sg
|-- csky-allmodconfig
|   `-- 
drivers-gpu-drm-nouveau-nvkm-subdev-gsp-r535.c:warning:Function-parameter-or-struct-member-gsp-not-described-in-nvkm_gsp_radix3_sg
|-- csky-allyesconfig
|   `-- 
drivers-gpu-drm-nouveau-nvkm-subdev-gsp-r535.c:warning:Function-parameter-or-struct-member-gsp-not-described-in-nvkm_gsp_radix3_sg
|-- csky-randconfig-001-20240222
|   `-- 
drivers-gpu-drm-nouveau-nvkm-subdev-gsp-r535.c:warning:Function-parameter-or-struct-member-gsp-not-described-in-nvkm_gsp_radix3_sg
|-- csky-randconfig-002-20240222
|   `-- fs-ntfs3-frecord.c:warning:unused-variable-i_size
|-- i386-allmodconfig
|   `-- 
drivers-gpu-drm-nouveau-nvkm-subdev-gsp-r535.c:warning:Function-parameter-or-struct-member-gsp-not-described-in-nvkm_gsp_radix3_sg
|-- i386-allyesconfig
|   `-- 
drivers-gpu-drm-nouveau-nvkm-subdev-gsp-r535.c:warning:Function-parameter-or-struct-member-gsp-not-described-in-nvkm_gsp_radix3_sg
|-- i386-buildonly-randconfig-006-20240222
|   `-- 
drivers-gpu-d

[git pull] drm fixes for 6.8-rc6

2024-02-22 Thread Dave Airlie
Hi Linus,

This is the weekly drm fixes. Non-drivers there is a fbdev/sparc fix,
syncobj, ttm and buddy fixes.
On the driver side, ivpu, meson, i915 have a small fix each. Then
amdgpu and xe have a bunch. Nouveau has some minor uapi additions to
give userspace some useful info along with a Kconfig change to allow
the new GSP firmware paths to be used by default on the GPUs it
supports.

Seems about the usual amount for this time of release cycle.

Dave.

drm-fixes-2024-02-23:
drm fixes for 6.8-rc6

fbdev:
- fix sparc undefined reference

syncobj:
- fix sync obj fence waiting
- handle NULL fence in syncobj eventfd code

ttm:
- fix invalid free

buddy:
- fix list handling
- fix 32-bit build

meson:
- don't remove bridges from other drivers

nouveau:
- fix build warnings
- add two minor info parameters
- add a Kconfig to allow GSP by default on some GPUs

ivpu:
- allow fw to do initial tile config

i915:
- fix TV mode

amdgpu:
- Suspend/resume fixes
- Backlight error fix
- DCN 3.5 fixes
- Misc fixes

xe:
- Remove support for persistent exec_queues
- Drop a reduntant sysfs newline printout
- A three-patch fix for a VM_BIND rebind optimization path
- Fix a modpost warning on an xe KUNIT module
The following changes since commit b401b621758e46812da61fa58a67c3fd8d91de0d:

  Linux 6.8-rc5 (2024-02-18 12:56:25 -0800)

are available in the Git repository at:

  git://anongit.freedesktop.org/drm/drm tags/drm-fixes-2024-02-23

for you to fetch changes up to 72fa02fdf83306c52bc1eede28359e3fa32a151a:

  nouveau: add an ioctl to report vram usage (2024-02-23 10:20:07 +1000)


drm fixes for 6.8-rc6

fbdev:
- fix sparc undefined reference

syncobj:
- fix sync obj fence waiting
- handle NULL fence in syncobj eventfd code

ttm:
- fix invalid free

buddy:
- fix list handling
- fix 32-bit build

meson:
- don't remove bridges from other drivers

nouveau:
- fix build warnings
- add two minor info parameters
- add a Kconfig to allow GSP by default on some GPUs

ivpu:
- allow fw to do initial tile config

i915:
- fix TV mode

amdgpu:
- Suspend/resume fixes
- Backlight error fix
- DCN 3.5 fixes
- Misc fixes

xe:
- Remove support for persistent exec_queues
- Drop a reduntant sysfs newline printout
- A three-patch fix for a VM_BIND rebind optimization path
- Fix a modpost warning on an xe KUNIT module


Andrzej Kacprowski (1):
  accel/ivpu: Don't enable any tiles by default on VPU40xx

Armin Wolf (1):
  drm/amd/display: Fix memory leak in dm_sw_fini()

Arnd Bergmann (1):
  nouveau: fix function cast warnings

Arunpravin Paneer Selvam (1):
  drm/buddy: Modify duplicate list_splice_tail call

Ashutosh Dixit (2):
  drm/xe/xe_gt_idle: Drop redundant newline in name
  drm/xe: Fix modpost warning on xe_mocs kunit module

Dan Carpenter (1):
  drm/nouveau/mmu/r535: uninitialized variable in r535_bar_new_()

Dave Airlie (7):
  Merge tag 'drm-misc-fixes-2024-02-22' of
git://anongit.freedesktop.org/drm/drm-misc into drm-fixes
  Merge tag 'drm-intel-fixes-2024-02-22' of
git://anongit.freedesktop.org/drm/drm-intel into drm-fixes
  Merge tag 'amd-drm-fixes-6.8-2024-02-22' of
https://gitlab.freedesktop.org/agd5f/linux into drm-fixes
  Merge tag 'drm-xe-fixes-2024-02-22' of
https://gitlab.freedesktop.org/drm/xe/kernel into drm-fixes
  nouveau/gsp: add kconfig option to enable GSP paths by default
  nouveau: add an ioctl to return vram bar size.
  nouveau: add an ioctl to report vram usage

Erik Kurzinger (2):
  drm/syncobj: call drm_syncobj_fence_add_wait when WAIT_AVAILABLE
flag is set
  drm/syncobj: handle NULL fence in syncobj_eventfd_entry_func

Javier Martinez Canillas (1):
  sparc: Fix undefined reference to fb_is_primary_device

Lewis Huang (1):
  drm/amd/display: Only allow dig mapping to pwrseq in new asic

Ma Jun (1):
  drm/amdgpu: Fix the runtime resume failure issue

Martin Blumenstingl (1):
  drm/meson: Don't remove bridges which are created by other drivers

Matthew Auld (1):
  drm/tests/drm_buddy: fix 32b build

Matthew Brost (3):
  drm/xe: Fix xe_vma_set_pte_size
  drm/xe: Add XE_VMA_PTE_64K VMA flag
  drm/xe: Return 2MB page size for compact 64k PTEs

Maxime Ripard (1):
  drm/i915/tv: Fix TV mode

Melissa Wen (1):
  drm/amd/display: fix null-pointer dereference on edid reading

Srinivasan Shanmugam (1):
  drm/amd/display: Fix potential null pointer dereference in dc_dmub_srv

Swapnil Patel (1):
  drm/amd/display: fix input states translation error for dcn35 & dcn351

Thomas Hellström (2):
  drm/xe/uapi: Remove support for persistent exec_queues
  drm/ttm: Fix an invalid freeing on already freed page in error path

Wayne Lin (1):
  drm/amd/display: adjust few initialization order in dm

 arch/sparc/Makefile|  2 +-
 arch/sparc/video/Makefile   

Re: [PATCH 2/3] arch: Remove struct fb_info from video helpers

2024-02-22 Thread kernel test robot
Hi Thomas,

kernel test robot noticed the following build errors:

[auto build test ERROR on tip/x86/core]
[also build test ERROR on deller-parisc/for-next arnd-asm-generic/master 
linus/master v6.8-rc5]
[cannot apply to next-20240222]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:
https://github.com/intel-lab-lkp/linux/commits/Thomas-Zimmermann/arch-Select-fbdev-helpers-with-CONFIG_VIDEO/20240222-001622
base:   tip/x86/core
patch link:
https://lore.kernel.org/r/20240221161431.8245-3-tzimmermann%40suse.de
patch subject: [PATCH 2/3] arch: Remove struct fb_info from video helpers
config: x86_64-rhel-8.3 
(https://download.01.org/0day-ci/archive/20240223/202402230941.jzdvhhex-...@intel.com/config)
compiler: gcc-12 (Debian 12.2.0-14) 12.2.0
reproduce (this is a W=1 build): 
(https://download.01.org/0day-ci/archive/20240223/202402230941.jzdvhhex-...@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 
| Closes: 
https://lore.kernel.org/oe-kbuild-all/202402230941.jzdvhhex-...@intel.com/

All errors (new ones prefixed by >>):

   ld: vmlinux.o: in function `fbcon_select_primary':
>> drivers/video/fbdev/core/fbcon.c:2944: undefined reference to 
>> `video_is_primary_device'
   ld: vmlinux.o: in function `fb_io_mmap':
   drivers/video/fbdev/core/fb_io_fops.c:164: undefined reference to 
`pgprot_framebuffer'


vim +2944 drivers/video/fbdev/core/fbcon.c

  2939  
  2940  #ifdef CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY
  2941  static void fbcon_select_primary(struct fb_info *info)
  2942  {
  2943  if (!map_override && primary_device == -1 &&
> 2944  video_is_primary_device(info->device)) {
  2945  int i;
  2946  
  2947  printk(KERN_INFO "fbcon: %s (fb%i) is primary device\n",
  2948 info->fix.id, info->node);
  2949  primary_device = info->node;
  2950  
  2951  for (i = first_fb_vc; i <= last_fb_vc; i++)
  2952  con2fb_map_boot[i] = primary_device;
  2953  
  2954  if (con_is_bound(_con)) {
  2955  printk(KERN_INFO "fbcon: Remapping primary 
device, "
  2956 "fb%i, to tty %i-%i\n", info->node,
  2957 first_fb_vc + 1, last_fb_vc + 1);
  2958  info_idx = primary_device;
  2959  }
  2960  }
  2961  

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki


[PATCH] accel/qaic: Constify aic100_channels

2024-02-22 Thread Jeff Johnson
MHI allows the channel configs to be const, so constify
aic100_channels to prevent runtime modification.

Signed-off-by: Jeff Johnson 
---
 drivers/accel/qaic/mhi_controller.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/accel/qaic/mhi_controller.c 
b/drivers/accel/qaic/mhi_controller.c
index cb77d048ed54..3f81d6396c85 100644
--- a/drivers/accel/qaic/mhi_controller.c
+++ b/drivers/accel/qaic/mhi_controller.c
@@ -20,7 +20,7 @@ static unsigned int mhi_timeout_ms = 2000; /* 2 sec default */
 module_param(mhi_timeout_ms, uint, 0600);
 MODULE_PARM_DESC(mhi_timeout_ms, "MHI controller timeout value");
 
-static struct mhi_channel_config aic100_channels[] = {
+static const struct mhi_channel_config aic100_channels[] = {
{
.name = "QAIC_LOOPBACK",
.num = 0,

---
base-commit: 3ab6aff5793c3c7bdf6535d9b0024544a4abbdd5
change-id: 20240222-mhi-const-accel-qaic-3889157be7ac



Re: [PATCH] drm/nouveau: use dedicated wq for fence uevents work

2024-02-22 Thread Dave Airlie
On Fri, 23 Feb 2024 at 00:45, Danilo Krummrich  wrote:
>
> Using the kernel global workqueue to signal fences can lead to
> unexpected deadlocks. Some other work (e.g. from a different driver)
> could directly or indirectly depend on this fence to be signaled.
> However, if the WQ_MAX_ACTIVE limit is reached by waiters, this can
> prevent the work signaling the fence from running.
>
> While this seems fairly unlikely, it's potentially exploitable.

LGTM

Reviewed-by: Dave Airlie 

probably should go into drm-misc-fixes?

>
> Fixes: 39126abc5e20 ("nouveau: offload fence uevents work to workqueue")
> Signed-off-by: Danilo Krummrich 
> ---
>  drivers/gpu/drm/nouveau/nouveau_drm.c   | 13 +++--
>  drivers/gpu/drm/nouveau/nouveau_drv.h   |  3 +++
>  drivers/gpu/drm/nouveau/nouveau_fence.c |  3 ++-
>  drivers/gpu/drm/nouveau/nouveau_fence.h |  2 ++
>  4 files changed, 18 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.c 
> b/drivers/gpu/drm/nouveau/nouveau_drm.c
> index 6f6c31a9937b..6be202081077 100644
> --- a/drivers/gpu/drm/nouveau/nouveau_drm.c
> +++ b/drivers/gpu/drm/nouveau/nouveau_drm.c
> @@ -598,9 +598,15 @@ nouveau_drm_device_init(struct drm_device *dev)
> goto fail_alloc;
> }
>
> +   drm->fence_wq = alloc_workqueue("nouveau_fence_wq", 0, WQ_MAX_ACTIVE);
> +   if (!drm->fence_wq) {
> +   ret = -ENOMEM;
> +   goto fail_sched_wq;
> +   }
> +
> ret = nouveau_cli_init(drm, "DRM-master", >master);
> if (ret)
> -   goto fail_wq;
> +   goto fail_fence_wq;
>
> ret = nouveau_cli_init(drm, "DRM", >client);
> if (ret)
> @@ -670,7 +676,9 @@ nouveau_drm_device_init(struct drm_device *dev)
> nouveau_cli_fini(>client);
>  fail_master:
> nouveau_cli_fini(>master);
> -fail_wq:
> +fail_fence_wq:
> +   destroy_workqueue(drm->fence_wq);
> +fail_sched_wq:
> destroy_workqueue(drm->sched_wq);
>  fail_alloc:
> nvif_parent_dtor(>parent);
> @@ -725,6 +733,7 @@ nouveau_drm_device_fini(struct drm_device *dev)
>
> nouveau_cli_fini(>client);
> nouveau_cli_fini(>master);
> +   destroy_workqueue(drm->fence_wq);
> destroy_workqueue(drm->sched_wq);
> nvif_parent_dtor(>parent);
> mutex_destroy(>clients_lock);
> diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h 
> b/drivers/gpu/drm/nouveau/nouveau_drv.h
> index 8a6d94c8b163..b43619a213a4 100644
> --- a/drivers/gpu/drm/nouveau/nouveau_drv.h
> +++ b/drivers/gpu/drm/nouveau/nouveau_drv.h
> @@ -261,6 +261,9 @@ struct nouveau_drm {
> /* Workqueue used for channel schedulers. */
> struct workqueue_struct *sched_wq;
>
> +   /* Workqueue used to signal fences. */
> +   struct workqueue_struct *fence_wq;
> +
> /* context for accelerated drm-internal operations */
> struct nouveau_channel *cechan;
> struct nouveau_channel *channel;
> diff --git a/drivers/gpu/drm/nouveau/nouveau_fence.c 
> b/drivers/gpu/drm/nouveau/nouveau_fence.c
> index 93f08f9479d8..c3ea3cd933cd 100644
> --- a/drivers/gpu/drm/nouveau/nouveau_fence.c
> +++ b/drivers/gpu/drm/nouveau/nouveau_fence.c
> @@ -174,7 +174,7 @@ static int
>  nouveau_fence_wait_uevent_handler(struct nvif_event *event, void *repv, u32 
> repc)
>  {
> struct nouveau_fence_chan *fctx = container_of(event, typeof(*fctx), 
> event);
> -   schedule_work(>uevent_work);
> +   queue_work(fctx->wq, >uevent_work);
> return NVIF_EVENT_KEEP;
>  }
>
> @@ -194,6 +194,7 @@ nouveau_fence_context_new(struct nouveau_channel *chan, 
> struct nouveau_fence_cha
> INIT_LIST_HEAD(>pending);
> spin_lock_init(>lock);
> fctx->context = chan->drm->runl[chan->runlist].context_base + 
> chan->chid;
> +   fctx->wq = chan->drm->fence_wq;
>
> if (chan == chan->drm->cechan)
> strcpy(fctx->name, "copy engine channel");
> diff --git a/drivers/gpu/drm/nouveau/nouveau_fence.h 
> b/drivers/gpu/drm/nouveau/nouveau_fence.h
> index 8bc065acfe35..bc13110bdfa4 100644
> --- a/drivers/gpu/drm/nouveau/nouveau_fence.h
> +++ b/drivers/gpu/drm/nouveau/nouveau_fence.h
> @@ -44,7 +44,9 @@ struct nouveau_fence_chan {
> u32 context;
> char name[32];
>
> +   struct workqueue_struct *wq;
> struct work_struct uevent_work;
> +
> struct nvif_event event;
> int notify_ref, dead, killed;
>  };
>
> base-commit: 1f4c6f11a557642505e5f403e0dfabbaff9c529a
> --
> 2.43.0
>


Re: [PATCH 1/8] dt-bindings: arm-smmu: Add QCM2290 GPU SMMU

2024-02-22 Thread Rob Herring


On Mon, 19 Feb 2024 14:35:46 +0100, Konrad Dybcio wrote:
> The GPU SMMU on QCM2290 nicely fits into the description we already have
> for SM61[12]5. Add it.
> 
> Signed-off-by: Konrad Dybcio 
> ---
>  Documentation/devicetree/bindings/iommu/arm,smmu.yaml | 3 ++-
>  1 file changed, 2 insertions(+), 1 deletion(-)
> 

Acked-by: Rob Herring 



Re: [PATCH v2 4/4] dt-bindings: display: simple: hardware can use several properties

2024-02-22 Thread Rob Herring
On Sat, Feb 17, 2024 at 12:02:58PM +0100, Raphael Gallais-Pou wrote:
> Setting a panel-timing in the device-tree overwrite the one specified in
> the driver and set it as preferred.  In that case 'height-mm',
> 'width-mm' and 'panel-timing' are properties that can be use for simple
> panels, according to panel-common.yaml
> 
> Fixes following warnings:
> arch/arm/boot/dts/st/stm32mp135f-dk.dtb: panel-rgb: 'height-mm', 
> 'panel-timing', 'width-mm' do not match any of the regexes: 'pinctrl-[0-9]+'
>   from schema $id: 
> http://devicetree.org/schemas/display/panel/panel-simple.yaml#
> 
> Signed-off-by: Raphael Gallais-Pou 
> ---
>  Documentation/devicetree/bindings/display/panel/panel-simple.yaml | 3 +++
>  1 file changed, 3 insertions(+)
> 
> diff --git 
> a/Documentation/devicetree/bindings/display/panel/panel-simple.yaml 
> b/Documentation/devicetree/bindings/display/panel/panel-simple.yaml
> index 634a10c6f2dd..c02cbbc7a100 100644
> --- a/Documentation/devicetree/bindings/display/panel/panel-simple.yaml
> +++ b/Documentation/devicetree/bindings/display/panel/panel-simple.yaml
> @@ -352,6 +352,9 @@ properties:
>no-hpd: true
>hpd-gpios: true
>data-mapping: true
> +  height-mm: true
> +  width-mm: true
> +  panel-timing: true

Instead, just change 'additionalProperties' to 'unevaluateProperties' 
and drop all these 'prop: true' lines. Pretty much anything from 
panel-common.yaml should be allowed.

Rob


Re: [PATCH 3/3] arch: Rename fbdev header and source files

2024-02-22 Thread kernel test robot
Hi Thomas,

kernel test robot noticed the following build errors:

[auto build test ERROR on tip/x86/core]
[also build test ERROR on deller-parisc/for-next arnd-asm-generic/master 
linus/master v6.8-rc5]
[cannot apply to next-20240222]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:
https://github.com/intel-lab-lkp/linux/commits/Thomas-Zimmermann/arch-Select-fbdev-helpers-with-CONFIG_VIDEO/20240222-001622
base:   tip/x86/core
patch link:
https://lore.kernel.org/r/20240221161431.8245-4-tzimmermann%40suse.de
patch subject: [PATCH 3/3] arch: Rename fbdev header and source files
config: um-randconfig-002-20240222 
(https://download.01.org/0day-ci/archive/20240223/202402230737.e7gwpgup-...@intel.com/config)
compiler: clang version 19.0.0git (https://github.com/llvm/llvm-project 
edd4aee4dd9b5b98b2576a6f783e4086173d902a)
reproduce (this is a W=1 build): 
(https://download.01.org/0day-ci/archive/20240223/202402230737.e7gwpgup-...@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 
| Closes: 
https://lore.kernel.org/oe-kbuild-all/202402230737.e7gwpgup-...@intel.com/

All errors (new ones prefixed by >>):

   /usr/bin/ld: warning: .tmp_vmlinux.kallsyms1 has a LOAD segment with RWX 
permissions
   /usr/bin/ld: drivers/video/fbdev/core/fb_io_fops.o: in function `fb_io_mmap':
>> drivers/video/fbdev/core/fb_io_fops.c:164: undefined reference to 
>> `pgprot_framebuffer'
   clang: error: linker command failed with exit code 1 (use -v to see 
invocation)


vim +164 drivers/video/fbdev/core/fb_io_fops.c

6b180f66c0dd62 Thomas Zimmermann 2023-09-27  140  
33253d9e01d405 Thomas Zimmermann 2023-11-27  141  int fb_io_mmap(struct fb_info 
*info, struct vm_area_struct *vma)
33253d9e01d405 Thomas Zimmermann 2023-11-27  142  {
33253d9e01d405 Thomas Zimmermann 2023-11-27  143unsigned long start = 
info->fix.smem_start;
33253d9e01d405 Thomas Zimmermann 2023-11-27  144u32 len = 
info->fix.smem_len;
33253d9e01d405 Thomas Zimmermann 2023-11-27  145unsigned long 
mmio_pgoff = PAGE_ALIGN((start & ~PAGE_MASK) + len) >> PAGE_SHIFT;
33253d9e01d405 Thomas Zimmermann 2023-11-27  146  
b3e8813773c568 Thomas Zimmermann 2023-11-27  147if (info->flags & 
FBINFO_VIRTFB)
b3e8813773c568 Thomas Zimmermann 2023-11-27  148
fb_warn_once(info, "Framebuffer is not in I/O address space.");
b3e8813773c568 Thomas Zimmermann 2023-11-27  149  
33253d9e01d405 Thomas Zimmermann 2023-11-27  150/*
33253d9e01d405 Thomas Zimmermann 2023-11-27  151 * This can be either 
the framebuffer mapping, or if pgoff points
33253d9e01d405 Thomas Zimmermann 2023-11-27  152 * past it, the mmio 
mapping.
33253d9e01d405 Thomas Zimmermann 2023-11-27  153 */
33253d9e01d405 Thomas Zimmermann 2023-11-27  154if (vma->vm_pgoff >= 
mmio_pgoff) {
33253d9e01d405 Thomas Zimmermann 2023-11-27  155if 
(info->var.accel_flags)
33253d9e01d405 Thomas Zimmermann 2023-11-27  156return 
-EINVAL;
33253d9e01d405 Thomas Zimmermann 2023-11-27  157  
33253d9e01d405 Thomas Zimmermann 2023-11-27  158vma->vm_pgoff 
-= mmio_pgoff;
33253d9e01d405 Thomas Zimmermann 2023-11-27  159start = 
info->fix.mmio_start;
33253d9e01d405 Thomas Zimmermann 2023-11-27  160len = 
info->fix.mmio_len;
33253d9e01d405 Thomas Zimmermann 2023-11-27  161}
33253d9e01d405 Thomas Zimmermann 2023-11-27  162  
33253d9e01d405 Thomas Zimmermann 2023-11-27  163vma->vm_page_prot = 
vm_get_page_prot(vma->vm_flags);
33253d9e01d405 Thomas Zimmermann 2023-11-27 @164vma->vm_page_prot = 
pgprot_framebuffer(vma->vm_page_prot, vma->vm_start,
33253d9e01d405 Thomas Zimmermann 2023-11-27  165
   vma->vm_end, start);
33253d9e01d405 Thomas Zimmermann 2023-11-27  166  
33253d9e01d405 Thomas Zimmermann 2023-11-27  167return 
vm_iomap_memory(vma, start, len);
33253d9e01d405 Thomas Zimmermann 2023-11-27  168  }
33253d9e01d405 Thomas Zimmermann 2023-11-27  169  EXPORT_SYMBOL(fb_io_mmap);
33253d9e01d405 Thomas Zimmermann 2023-11-27  170  

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki


Re: [PATCH] drm/i915/guc: Add Compute context hint

2024-02-22 Thread Belgaumkar, Vinay



On 2/22/2024 7:32 AM, Tvrtko Ursulin wrote:


On 21/02/2024 21:28, Rodrigo Vivi wrote:

On Wed, Feb 21, 2024 at 09:42:34AM +, Tvrtko Ursulin wrote:


On 21/02/2024 00:14, Vinay Belgaumkar wrote:

Allow user to provide a context hint. When this is set, KMD will
send a hint to GuC which results in special handling for this
context. SLPC will ramp the GT frequency aggressively every time
it switches to this context. The down freq threshold will also be
lower so GuC will ramp down the GT freq for this context more slowly.
We also disable waitboost for this context as that will interfere with
the strategy.

We need to enable the use of Compute strategy during SLPC init, but
it will apply only to contexts that set this bit during context
creation.

Userland can check whether this feature is supported using a new 
param-
I915_PARAM_HAS_COMPUTE_CONTEXT. This flag is true for all guc 
submission

enabled platforms since they use SLPC for freq management.

The Mesa usage model for this flag is here -
https://gitlab.freedesktop.org/sushmave/mesa/-/commits/compute_hint


This allows for setting it for the whole application, correct? Upsides,
downsides? Are there any plans for per context?


Currently there's no extension on a high level API 
(Vulkan/OpenGL/OpenCL/etc)
that would allow the application to hint for power/freq/latency. So 
Mesa cannot
decide when to hint. So their solution was to use .drirc and make 
per-application

decision.

I would prefer a high level extension for a more granular and 
informative

decision. We need to work with that goal, but for now I don't see any
cons on this approach.


In principle yeah I doesn't harm to have the option. I am just not 
sure how useful this intermediate step this is with its lack of 
intra-process granularity.



Cc: Rodrigo Vivi 
Signed-off-by: Vinay Belgaumkar 
---
   drivers/gpu/drm/i915/gem/i915_gem_context.c   |  8 +++
   .../gpu/drm/i915/gem/i915_gem_context_types.h |  1 +
   drivers/gpu/drm/i915/gt/intel_rps.c   |  8 +++
   .../drm/i915/gt/uc/abi/guc_actions_slpc_abi.h | 21 
+++

   drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c   | 17 +++
   drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h   |  1 +
   .../gpu/drm/i915/gt/uc/intel_guc_submission.c |  7 +++
   drivers/gpu/drm/i915/i915_getparam.c  | 11 ++
   include/uapi/drm/i915_drm.h   | 15 +
   9 files changed, 89 insertions(+)

diff --git a/drivers/gpu/drm/i915/gem/i915_gem_context.c 
b/drivers/gpu/drm/i915/gem/i915_gem_context.c

index dcbfe32fd30c..ceab7dbe9b47 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_context.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_context.c
@@ -879,6 +879,7 @@ static int set_proto_ctx_param(struct 
drm_i915_file_private *fpriv,

  struct i915_gem_proto_context *pc,
  struct drm_i915_gem_context_param *args)
   {
+    struct drm_i915_private *i915 = fpriv->i915;
   int ret = 0;
   switch (args->param) {
@@ -904,6 +905,13 @@ static int set_proto_ctx_param(struct 
drm_i915_file_private *fpriv,

   pc->user_flags &= ~BIT(UCONTEXT_BANNABLE);
   break;
+    case I915_CONTEXT_PARAM_IS_COMPUTE:
+    if (!intel_uc_uses_guc_submission(_gt(i915)->uc))
+    ret = -EINVAL;
+    else
+    pc->user_flags |= BIT(UCONTEXT_COMPUTE);
+    break;
+
   case I915_CONTEXT_PARAM_RECOVERABLE:
   if (args->size)
   ret = -EINVAL;
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_context_types.h 
b/drivers/gpu/drm/i915/gem/i915_gem_context_types.h

index 03bc7f9d191b..db86d6f6245f 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_context_types.h
+++ b/drivers/gpu/drm/i915/gem/i915_gem_context_types.h
@@ -338,6 +338,7 @@ struct i915_gem_context {
   #define UCONTEXT_BANNABLE    2
   #define UCONTEXT_RECOVERABLE    3
   #define UCONTEXT_PERSISTENCE    4
+#define UCONTEXT_COMPUTE    5


What is the GuC behaviour when SLPC_CTX_FREQ_REQ_IS_COMPUTE is set for
non-compute engines? Wondering if per intel_context is what we want 
instead.

(Which could then be the i915_context_param_engines extension to mark
individual contexts as compute strategy.)


Perhaps we should rename this? This is a freq-decision-strategy inside
GuC that is there mostly targeting compute workloads that needs lower
latency with short burst execution. But the engine itself doesn't 
matter.

It can be applied to any engine.


I have no idea if it makes sense for other engines, such as video, and 
what would be pros and cons in terms of PnP. But in the case we end up 
allowing it on any engine, then at least userspace name shouldn't be 
compute. :)
Yes, one of the suggestions from Daniele was to have something along the 
lines of UCONTEXT_HIFREQ or something along those lines so we don't 
confuse it with the Compute Engine.


Or if we decide to call it compute and only apply to compute engines, 
then I would strongly 

Re: (subset) [linux][PATCH v6 3/3] dt-bindings: mfd: atmel,hlcdc: Convert to DT schema format

2024-02-22 Thread Rob Herring
On Tue, Feb 20, 2024 at 08:30:38AM +, dharm...@microchip.com wrote:
> Hi Lee,
> 
> On 20/02/24 1:50 pm, Lee Jones wrote:
> > EXTERNAL EMAIL: Do not click links or open attachments unless you know the 
> > content is safe
> > 
> > On Tue, 20 Feb 2024, dharm...@microchip.com wrote:
> > 
> >> Hi Krzysztof,
> >>
> >> On 12/02/24 3:53 pm, Krzysztof Kozlowski wrote:
> >>> EXTERNAL EMAIL: Do not click links or open attachments unless you know 
> >>> the content is safe
> >>>
> >>> On 08/02/2024 11:43, Lee Jones wrote:
>  On Fri, 02 Feb 2024 05:47:33 +0530, Dharma Balasubiramani wrote:
> > Convert the atmel,hlcdc binding to DT schema format.
> >
> > Align clocks and clock-names properties to clearly indicate that the LCD
> > controller expects lvds_pll_clk when interfaced with the lvds display. 
> > This
> > alignment with the specific hardware requirements ensures accurate 
> > device tree
> > configuration for systems utilizing the HLCDC IP.
> >
> > [...]
> 
>  Applied, thanks!
> 
>  [3/3] dt-bindings: mfd: atmel,hlcdc: Convert to DT schema format
>  commit: cb946db1335b599ece363d33966bf653ed0fa58a
> 
> >>>
> >>> Next is still failing.
> >>>
> >>> Dharma,
> >>> You must explain and clearly mark dependencies between patches.
> >>
> >> I sincerely apologize for any confusion caused by the oversight. I have
> >> organized the patches according to their dependencies in the patch
> >> series, but unfortunately, I neglected to explicitly mention these
> >> dependencies. I understand the importance of clear communication in our
> >> collaborative efforts. Please feel free to provide guidance on how I can
> >> assist you further in resolving this matter.
> > 
> > If this continues to be an issue, I can just remove the commit.
> 
> There won't be any issue if both pwm and display binding goes before the 
> mfd binding.
> 
> Could you please pick the display binding as well?

As this is still not resolved, I've applied the display binding. Not 
ideal, but should fix next.

Rob


Re: [PATCH v5 13/19] drm/msm/dp: add VSC SDP support for YUV420 over DP

2024-02-22 Thread Paloma Arellano



On 2/22/2024 1:56 PM, Dmitry Baryshkov wrote:

On Thu, 22 Feb 2024 at 23:28, Paloma Arellano  wrote:


On 2/22/2024 1:18 PM, Dmitry Baryshkov wrote:

On Thu, 22 Feb 2024 at 21:40, Paloma Arellano  wrote:

Add support to pack and send the VSC SDP packet for DP. This therefore
allows the transmision of format information to the sinks which is
needed for YUV420 support over DP.

Changes in v5:
  - Slightly modify use of drm_dp_vsc_sdp_pack()
  - Remove dp_catalog NULL checks
  - Modify dp_utils_pack_sdp_header() to more clearly pack the
header buffer
  - Move dp_utils_pack_sdp_header() inside of
dp_catalog_panel_send_vsc_sdp to clearly show the relationship
between the header buffer and the vsc_sdp struct
  - Due to the last point, remove the dp_utils_pack_vsc_sdp()
function and only call drm_dp_vsc_sdp_pack() in
dp_panel_setup_vsc_sdp_yuv_420()

Changes in v4:
  - Remove struct msm_dp_sdp_with_parity
  - Use dp_utils_pack_sdp_header() to pack the SDP header and
parity bytes into a buffer
  - Use this buffer when writing the VSC SDP data in
dp_catalog_panel_send_vsc_sdp()
  - Write to all of the MMSS_DP_GENERIC0 registers instead of just
the ones with non-zero values

Changes in v3:
  - Create a new struct, msm_dp_sdp_with_parity, which holds the
packing information for VSC SDP
  - Use drm_dp_vsc_sdp_pack() to pack the data into the new
msm_dp_sdp_with_parity struct instead of specifically packing
for YUV420 format
  - Modify dp_catalog_panel_send_vsc_sdp() to send the VSC SDP
data using the new msm_dp_sdp_with_parity struct

Changes in v2:
  - Rename GENERIC0_SDPSIZE macro to GENERIC0_SDPSIZE_VALID
  - Remove dp_sdp from the dp_catalog struct since this data is
being allocated at the point used
  - Create a new function in dp_utils to pack the VSC SDP data
into a buffer
  - Create a new function that packs the SDP header bytes into a
buffer. This function is made generic so that it can be
utilized by dp_audio
header bytes into a buffer
  - Create a new function in dp_utils that takes the packed buffer
and writes to the DP_GENERIC0_* registers
  - Split the dp_catalog_panel_config_vsc_sdp() function into two
to disable/enable sending VSC SDP packets
  - Check the DP HW version using the original useage of
dp_catalog_hw_revision() and correct the version checking
logic
  - Rename dp_panel_setup_vsc_sdp() to
dp_panel_setup_vsc_sdp_yuv_420() to explicitly state that
currently VSC SDP is only being set up to support YUV420 modes

Signed-off-by: Paloma Arellano 
---
   drivers/gpu/drm/msm/dp/dp_catalog.c | 93 +
   drivers/gpu/drm/msm/dp/dp_catalog.h |  6 ++
   drivers/gpu/drm/msm/dp/dp_ctrl.c|  4 ++
   drivers/gpu/drm/msm/dp/dp_panel.c   | 52 
   drivers/gpu/drm/msm/dp/dp_reg.h |  3 +
   drivers/gpu/drm/msm/dp/dp_utils.c   | 25 
   drivers/gpu/drm/msm/dp/dp_utils.h   | 14 +
   7 files changed, 197 insertions(+)

diff --git a/drivers/gpu/drm/msm/dp/dp_catalog.c 
b/drivers/gpu/drm/msm/dp/dp_catalog.c
index 5d84c089e520a..bfc6f53ae167f 100644
--- a/drivers/gpu/drm/msm/dp/dp_catalog.c
+++ b/drivers/gpu/drm/msm/dp/dp_catalog.c
@@ -901,6 +901,99 @@ int dp_catalog_panel_timing_cfg(struct dp_catalog 
*dp_catalog)
  return 0;
   }

+static void dp_catalog_panel_send_vsc_sdp(struct dp_catalog *dp_catalog, 
struct dp_sdp *vsc_sdp)
+{
+   struct dp_catalog_private *catalog;
+   u32 header[2];
+   u32 val;
+   int i;
+
+   catalog = container_of(dp_catalog, struct dp_catalog_private, 
dp_catalog);
+
+   dp_utils_pack_sdp_header(_sdp->sdp_header, header);
+
+   dp_write_link(catalog, MMSS_DP_GENERIC0_0, header[0]);
+   dp_write_link(catalog, MMSS_DP_GENERIC0_1, header[1]);
+
+   for (i = 0; i < sizeof(vsc_sdp->db); i += 4) {
+   val = ((vsc_sdp->db[i]) | (vsc_sdp->db[i + 1] << 8) | (vsc_sdp->db[i 
+ 2] << 16) |
+  (vsc_sdp->db[i + 3] << 24));
+   dp_write_link(catalog, MMSS_DP_GENERIC0_2 + i, val);
+   }
+}
+
+static void dp_catalog_panel_update_sdp(struct dp_catalog *dp_catalog)
+{
+   struct dp_catalog_private *catalog;
+   u32 hw_revision;
+
+   catalog = container_of(dp_catalog, struct dp_catalog_private, 
dp_catalog);
+
+   hw_revision = dp_catalog_hw_revision(dp_catalog);
+   if (hw_revision < DP_HW_VERSION_1_2 && hw_revision >= 
DP_HW_VERSION_1_0) {
+   dp_write_link(catalog, MMSS_DP_SDP_CFG3, 0x01);
+   dp_write_link(catalog, MMSS_DP_SDP_CFG3, 0x00);
+   }
+}
+
+void 

Re: [PATCH v2 2/2] drm/i915/gt: Enable only one CCS for compute workload

2024-02-22 Thread Matt Roper
On Thu, Feb 22, 2024 at 11:03:27PM +0100, Andi Shyti wrote:
> Hi Matt,
> 
> first of all thanks a lot for the observations you are raising.
> 
> On Wed, Feb 21, 2024 at 12:51:04PM -0800, Matt Roper wrote:
> > On Wed, Feb 21, 2024 at 01:12:18AM +0100, Andi Shyti wrote:
> > > On Tue, Feb 20, 2024 at 03:39:18PM -0800, Matt Roper wrote:
> > > > On Tue, Feb 20, 2024 at 03:35:26PM +0100, Andi Shyti wrote:
> 
> ...
> 
> > > > > diff --git a/drivers/gpu/drm/i915/gt/intel_gt.c 
> > > > > b/drivers/gpu/drm/i915/gt/intel_gt.c
> > > > > index a425db5ed3a2..e19df4ef47f6 100644
> > > > > --- a/drivers/gpu/drm/i915/gt/intel_gt.c
> > > > > +++ b/drivers/gpu/drm/i915/gt/intel_gt.c
> > > > > @@ -168,6 +168,14 @@ static void init_unused_rings(struct intel_gt 
> > > > > *gt)
> > > > >   }
> > > > >  }
> > > > >  
> > > > > +static void intel_gt_apply_ccs_mode(struct intel_gt *gt)
> > > > > +{
> > > > > + if (!IS_DG2(gt->i915))
> > > > > + return;
> > > > > +
> > > > > + intel_uncore_write(gt->uncore, XEHP_CCS_MODE, 0);
> > > > 
> > > > This doesn't look right to me.  A value of 0 means every cslice gets
> > > > associated with CCS0.
> > > 
> > > Yes, that's what I'm trying to do. The behavior I'm looking for
> > > is this one:
> > > 
> > >/*
> > > ...
> > >   * With 1 engine (ccs0):
> > >   *   slice 0, 1, 2, 3: ccs0
> > >   *
> > >   * With 2 engines (ccs0, ccs1):
> > >   *   slice 0, 2: ccs0
> > >   *   slice 1, 3: ccs1
> > >   *
> > >   * With 4 engines (ccs0, ccs1, ccs2, ccs3):
> > >   *   slice 0: ccs0
> > >   *   slice 1: ccs1
> > >   *   slice 2: ccs2
> > >   *   slice 3: ccs3
> > > ...
> > > */
> > > 
> > > where the user can configure runtime the mode, making sure that
> > > no client is connected to i915.
> > > 
> > > But, this needs to be written 
> > > 
> > > As we are now forcing mode '1', then all cslices are connected
> > > with ccs0.
> > 
> > Right --- and that's what I'm pointing out as illegal.  I think that
> > code comment above was taken out of context from a different RFC series;
> > that's not an accurate description of the behavior we want here.
> > 
> > First, the above comment is using ccs# to refer to userspace engines,
> > not hardware engines.  As a simple example, DG2-G11 only ever has a
> > single CCS which userspace sees as "instance 0" but which is actually
> > CCS1 at the hardware level.  If you try to follow the comment above when
> > programming CCS_MODE, you've assigned all of the cslices to a
> > non-existent engine and assigned no cslices to the CCS engine that
> > actually exists.  For DG2-G10 (and I think DG2-G12), there are different
> > combinations of fused-off / not-fused-off engines that will always show
> > up in userspace as CCS0-CCSn, even if those don't match the hardware
> > IDs.
> > 
> > Second, the above comment is assuming that you have a part with a
> > maximum fusing config (i.e., all cslices present).  Using DG2-G11 again
> > as an example, there's also only a single cslice (cslice1), so if you
> > tell CCS1 that it's allowed to use EUs from non-existent cslice0,
> > cslice2, and cslice3, you might not get the behavior you were hoping
> > for.
> 
> if the hardware slices are fused off we wouldn't see them in a
> first place, right? And that's anyway a permanent configuration
> that wouldn't affect the patch.

There are physically four possible cslices in the IP design.  The
presence/absence of each of those cslices can vary both by SKU and by
part-specific fusing.  Some SKUs (DG2-G11) wind up only ever having a
single possible configuration as far as I know, but the larger SKUs have
more part-to-part variation in terms of exactly which specific subset of
DSS (and by extension cslices) are present/absent.  The KMD determines
the configuration at runtime by reading the DSS fuse registers and
deriving the cslice presence/absence from that.

The register you're writing in this patch tells the CCS engine which
cslice(s) it can use to execute work.  If the KMD already knows that
cslice doesn't exist, but it tells CCS that it can go ahead and
use it anyway, things probably won't work properly.  That's why the spec
mandates that we always program 0x7 in the register for any cslices that
we know aren't present so that none of the CCS engines will incorrectly
try to utilize them.  If we ignore that rule, then it's a driver bug.

> 
> BTW, is there any machine I can test this scenario?

There should differently-fused DG2 systems in our internal pool,
although I'm not sure what the breakdown is.  I don't think the
reservation system makes the low-level cslice configuration immediately
obvious on the summary page, so you might just need to log into a few
systems and read the fuse registers to check which ones are best for
testing these cases.

> 
> > > > On a DG2-G11 platform, that will flat out break
> > > > compute since CCS0 is never present 

Re: [PATCH v2 2/2] drm/i915/gt: Enable only one CCS for compute workload

2024-02-22 Thread Andi Shyti
Hi Matt,

first of all thanks a lot for the observations you are raising.

On Wed, Feb 21, 2024 at 12:51:04PM -0800, Matt Roper wrote:
> On Wed, Feb 21, 2024 at 01:12:18AM +0100, Andi Shyti wrote:
> > On Tue, Feb 20, 2024 at 03:39:18PM -0800, Matt Roper wrote:
> > > On Tue, Feb 20, 2024 at 03:35:26PM +0100, Andi Shyti wrote:

...

> > > > diff --git a/drivers/gpu/drm/i915/gt/intel_gt.c 
> > > > b/drivers/gpu/drm/i915/gt/intel_gt.c
> > > > index a425db5ed3a2..e19df4ef47f6 100644
> > > > --- a/drivers/gpu/drm/i915/gt/intel_gt.c
> > > > +++ b/drivers/gpu/drm/i915/gt/intel_gt.c
> > > > @@ -168,6 +168,14 @@ static void init_unused_rings(struct intel_gt *gt)
> > > > }
> > > >  }
> > > >  
> > > > +static void intel_gt_apply_ccs_mode(struct intel_gt *gt)
> > > > +{
> > > > +   if (!IS_DG2(gt->i915))
> > > > +   return;
> > > > +
> > > > +   intel_uncore_write(gt->uncore, XEHP_CCS_MODE, 0);
> > > 
> > > This doesn't look right to me.  A value of 0 means every cslice gets
> > > associated with CCS0.
> > 
> > Yes, that's what I'm trying to do. The behavior I'm looking for
> > is this one:
> > 
> >  /*
> >   ...
> >   * With 1 engine (ccs0):
> >   *   slice 0, 1, 2, 3: ccs0
> >   *
> >   * With 2 engines (ccs0, ccs1):
> >   *   slice 0, 2: ccs0
> >   *   slice 1, 3: ccs1
> >   *
> >   * With 4 engines (ccs0, ccs1, ccs2, ccs3):
> >   *   slice 0: ccs0
> >   *   slice 1: ccs1
> >   *   slice 2: ccs2
> >   *   slice 3: ccs3
> >   ...
> >   */
> > 
> > where the user can configure runtime the mode, making sure that
> > no client is connected to i915.
> > 
> > But, this needs to be written 
> > 
> > As we are now forcing mode '1', then all cslices are connected
> > with ccs0.
> 
> Right --- and that's what I'm pointing out as illegal.  I think that
> code comment above was taken out of context from a different RFC series;
> that's not an accurate description of the behavior we want here.
> 
> First, the above comment is using ccs# to refer to userspace engines,
> not hardware engines.  As a simple example, DG2-G11 only ever has a
> single CCS which userspace sees as "instance 0" but which is actually
> CCS1 at the hardware level.  If you try to follow the comment above when
> programming CCS_MODE, you've assigned all of the cslices to a
> non-existent engine and assigned no cslices to the CCS engine that
> actually exists.  For DG2-G10 (and I think DG2-G12), there are different
> combinations of fused-off / not-fused-off engines that will always show
> up in userspace as CCS0-CCSn, even if those don't match the hardware
> IDs.
> 
> Second, the above comment is assuming that you have a part with a
> maximum fusing config (i.e., all cslices present).  Using DG2-G11 again
> as an example, there's also only a single cslice (cslice1), so if you
> tell CCS1 that it's allowed to use EUs from non-existent cslice0,
> cslice2, and cslice3, you might not get the behavior you were hoping
> for.

if the hardware slices are fused off we wouldn't see them in a
first place, right? And that's anyway a permanent configuration
that wouldn't affect the patch.

BTW, is there any machine I can test this scenario?

> > > On a DG2-G11 platform, that will flat out break
> > > compute since CCS0 is never present (G11 only has a single CCS and it's
> > > always the hardware's CCS1).  Even on a G10 or G12 this could also break
> > > things depending on the fusing of your card if the hardware CCS0 happens
> > > to be missing.
> > > 
> > > Also, the register says that we need a field value of 0x7 for each
> > > cslice that's fused off.  By passing 0, we're telling the CCS engine
> > > that it can use cslices that may not actually exist.
> > 
> > does it? Or do I need to write the id (0x0-0x3) of the user
> > engine? That's how the mode is calculated in this algorithm.
> 
> 0x0 - 0x3 are how you specify that a specific CCS engine can use the
> cslice.  If the cslice can't be used at all (i.e., it's fused off), then
> you need to program a 0x7 to ensure no engines try to use the
> non-existent DSS/EUs.

I planned to limit this to the only DG2 (and ATSM, of course).
Do you think it would it help?

Andi


Re: [PATCH 1/2] devm-helpers: Add resource managed version of mutex init

2024-02-22 Thread andy . shevchenko
Thu, Feb 22, 2024 at 03:58:37PM +0100, Marek Behún kirjoitti:
> A few drivers are doing resource-managed mutex initialization by
> implementing ad-hoc one-liner mutex dropping functions and using them
> with devm_add_action_or_reset(). Help drivers avoid these repeated
> one-liners by adding managed version of mutex initialization.
> 
> Use the new function devm_mutex_init() in the following drivers:
>   drivers/gpio/gpio-pisosr.c
>   drivers/gpio/gpio-sim.c
>   drivers/gpu/drm/xe/xe_hwmon.c
>   drivers/hwmon/nzxt-smart2.c
>   drivers/leds/leds-is31fl319x.c
>   drivers/power/supply/mt6370-charger.c
>   drivers/power/supply/rt9467-charger.c

Pardon me, but why?

https://lore.kernel.org/linux-leds/20231214173614.2820929-1-gnst...@salutedevices.com/

Can you cooperate, folks, instead of doing something independently?


> --- a/include/linux/devm-helpers.h
> +++ b/include/linux/devm-helpers.h
> @@ -24,6 +24,8 @@
>   */
>  
>  #include 
> +#include 
> +#include 
>  #include 
>  
>  static inline void devm_delayed_work_drop(void *res)
> @@ -76,4 +78,34 @@ static inline int devm_work_autocancel(struct device *dev,
>   return devm_add_action(dev, devm_work_drop, w);
>  }
>  
> +static inline void devm_mutex_drop(void *res)
> +{
> + mutex_destroy(res);
> +}
> +
> +/**
> + * devm_mutex_init - Resource managed mutex initialization
> + * @dev: Device which lifetime mutex is bound to
> + * @lock:Mutex to be initialized (and automatically destroyed)
> + *
> + * Initialize mutex which is automatically destroyed when driver is detached.
> + * A few drivers initialize mutexes which they want destroyed before driver 
> is
> + * detached, for debugging purposes.
> + * devm_mutex_init() can be used to omit the explicit mutex_destroy() call 
> when
> + * driver is detached.
> + */
> +static inline int devm_mutex_init(struct device *dev, struct mutex *lock)
> +{
> + mutex_init(lock);
> +
> + /*
> +  * mutex_destroy() is an empty function if CONFIG_DEBUG_MUTEXES is
> +  * disabled. No need to allocate an action in that case.
> +  */
> + if (IS_ENABLED(CONFIG_DEBUG_MUTEXES))
> + return devm_add_action_or_reset(dev, devm_mutex_drop, lock);
> + else
> + return 0;
> +}

Cc: George Stark 

-- 
With Best Regards,
Andy Shevchenko




Re: [PATCH v5] drm/msm/dpu: add current resource allocation to dumped state

2024-02-22 Thread Dmitry Baryshkov
On Thu, 22 Feb 2024 at 23:53, Abhinav Kumar  wrote:
>
>
>
> On 2/22/2024 1:47 PM, Dmitry Baryshkov wrote:
> > Provide atomic_print_state callback to the DPU's private object. This
> > way the debugfs/dri/0/state will also include RM's internal state.
> >
> > Example output (RB5 board, HDMI and writeback encoder enabled)
> >
> > resource mapping:
> >   pingpong=31 36 # # # # - - - - -
> >   mixer=31 36 # # # # -
> >   ctl=# # 31 36 # #
> >   dspp=# # # #
> >   dsc=# # # # - -
> >   cdm=#
> >
>
> Thanks, this LGTM now, one nit below.
>
> > Signed-off-by: Dmitry Baryshkov 
> > ---
> > Changes in v5:
> > - Extracted the common helper for printing RM state
> > - Changed the code to print '#' for unused/unmapped blocks (Abhinav)
> > - Link to v4: 
> > https://lore.kernel.org/r/20240219-fd-rm-state-v4-1-b47f14ef2...@linaro.org
> >
> > Changes in v4:
> > - Split the patch from the virual wide planes series
> > - Reworked the output format
> > - Added the CDM block into the dump
> > ---
> >   drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 12 +++
> >   drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h |  2 ++
> >   drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c  | 56 
> > +
> >   drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h  |  8 +
> >   4 files changed, 78 insertions(+)
> >
> > diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c 
> > b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
> > index 723cc1d82143..9f3697e1eacb 100644
> > --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
> > +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
> > @@ -353,9 +353,18 @@ static void dpu_kms_global_destroy_state(struct 
> > drm_private_obj *obj,
> >   kfree(dpu_state);
> >   }
> >
> > +static void dpu_kms_global_print_state(struct drm_printer *p,
> > +const struct drm_private_state *state)
> > +{
> > + const struct dpu_global_state *global_state = 
> > to_dpu_global_state(state);
> > +
> > + dpu_rm_print_state(p, global_state);
> > +}
> > +
> >   static const struct drm_private_state_funcs dpu_kms_global_state_funcs = {
> >   .atomic_duplicate_state = dpu_kms_global_duplicate_state,
> >   .atomic_destroy_state = dpu_kms_global_destroy_state,
> > + .atomic_print_state = dpu_kms_global_print_state,
> >   };
> >
> >   static int dpu_kms_global_obj_init(struct dpu_kms *dpu_kms)
> > @@ -371,6 +380,9 @@ static int dpu_kms_global_obj_init(struct dpu_kms 
> > *dpu_kms)
> >   drm_atomic_private_obj_init(dpu_kms->dev, _kms->global_state,
> >   >base,
> >   _kms_global_state_funcs);
> > +
> > + state->rm = _kms->rm;
> > +
> >   return 0;
> >   }
> >
> > diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h 
> > b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
> > index d1207f4ec3ae..2512c9bd08df 100644
> > --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
> > +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
> > @@ -131,6 +131,8 @@ struct vsync_info {
> >   struct dpu_global_state {
> >   struct drm_private_state base;
> >
> > + struct dpu_rm *rm;
> > +
> >   uint32_t pingpong_to_enc_id[PINGPONG_MAX - PINGPONG_0];
> >   uint32_t mixer_to_enc_id[LM_MAX - LM_0];
> >   uint32_t ctl_to_enc_id[CTL_MAX - CTL_0];
> > diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c 
> > b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
> > index 724537ab776d..1a56ddca536d 100644
> > --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
> > +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
> > @@ -634,3 +634,59 @@ int dpu_rm_get_assigned_resources(struct dpu_rm *rm,
> >
> >   return num_blks;
> >   }
> > +
> > +static void dpu_rm_print_state_helper(struct drm_printer *p,
> > + struct dpu_hw_blk *blk,
> > + uint32_t mapping)
>
> Not sure if its the mail client, but is this aligned with the opening brace?

No, it is shifted to the right. Will fix while applying.

>
> Please double check once. Rest LGTM.
>
> Reviewed-by: Abhinav Kumar 



-- 
With best wishes
Dmitry


Re: [PATCH v5 13/19] drm/msm/dp: add VSC SDP support for YUV420 over DP

2024-02-22 Thread Dmitry Baryshkov
On Thu, 22 Feb 2024 at 23:28, Paloma Arellano  wrote:
>
>
> On 2/22/2024 1:18 PM, Dmitry Baryshkov wrote:
> > On Thu, 22 Feb 2024 at 21:40, Paloma Arellano  
> > wrote:
> >> Add support to pack and send the VSC SDP packet for DP. This therefore
> >> allows the transmision of format information to the sinks which is
> >> needed for YUV420 support over DP.
> >>
> >> Changes in v5:
> >>  - Slightly modify use of drm_dp_vsc_sdp_pack()
> >>  - Remove dp_catalog NULL checks
> >>  - Modify dp_utils_pack_sdp_header() to more clearly pack the
> >>header buffer
> >>  - Move dp_utils_pack_sdp_header() inside of
> >>dp_catalog_panel_send_vsc_sdp to clearly show the relationship
> >>between the header buffer and the vsc_sdp struct
> >>  - Due to the last point, remove the dp_utils_pack_vsc_sdp()
> >>function and only call drm_dp_vsc_sdp_pack() in
> >>dp_panel_setup_vsc_sdp_yuv_420()
> >>
> >> Changes in v4:
> >>  - Remove struct msm_dp_sdp_with_parity
> >>  - Use dp_utils_pack_sdp_header() to pack the SDP header and
> >>parity bytes into a buffer
> >>  - Use this buffer when writing the VSC SDP data in
> >>dp_catalog_panel_send_vsc_sdp()
> >>  - Write to all of the MMSS_DP_GENERIC0 registers instead of just
> >>the ones with non-zero values
> >>
> >> Changes in v3:
> >>  - Create a new struct, msm_dp_sdp_with_parity, which holds the
> >>packing information for VSC SDP
> >>  - Use drm_dp_vsc_sdp_pack() to pack the data into the new
> >>msm_dp_sdp_with_parity struct instead of specifically packing
> >>for YUV420 format
> >>  - Modify dp_catalog_panel_send_vsc_sdp() to send the VSC SDP
> >>data using the new msm_dp_sdp_with_parity struct
> >>
> >> Changes in v2:
> >>  - Rename GENERIC0_SDPSIZE macro to GENERIC0_SDPSIZE_VALID
> >>  - Remove dp_sdp from the dp_catalog struct since this data is
> >>being allocated at the point used
> >>  - Create a new function in dp_utils to pack the VSC SDP data
> >>into a buffer
> >>  - Create a new function that packs the SDP header bytes into a
> >>buffer. This function is made generic so that it can be
> >>utilized by dp_audio
> >>header bytes into a buffer
> >>  - Create a new function in dp_utils that takes the packed buffer
> >>and writes to the DP_GENERIC0_* registers
> >>  - Split the dp_catalog_panel_config_vsc_sdp() function into two
> >>to disable/enable sending VSC SDP packets
> >>  - Check the DP HW version using the original useage of
> >>dp_catalog_hw_revision() and correct the version checking
> >>logic
> >>  - Rename dp_panel_setup_vsc_sdp() to
> >>dp_panel_setup_vsc_sdp_yuv_420() to explicitly state that
> >>currently VSC SDP is only being set up to support YUV420 modes
> >>
> >> Signed-off-by: Paloma Arellano 
> >> ---
> >>   drivers/gpu/drm/msm/dp/dp_catalog.c | 93 +
> >>   drivers/gpu/drm/msm/dp/dp_catalog.h |  6 ++
> >>   drivers/gpu/drm/msm/dp/dp_ctrl.c|  4 ++
> >>   drivers/gpu/drm/msm/dp/dp_panel.c   | 52 
> >>   drivers/gpu/drm/msm/dp/dp_reg.h |  3 +
> >>   drivers/gpu/drm/msm/dp/dp_utils.c   | 25 
> >>   drivers/gpu/drm/msm/dp/dp_utils.h   | 14 +
> >>   7 files changed, 197 insertions(+)
> >>
> >> diff --git a/drivers/gpu/drm/msm/dp/dp_catalog.c 
> >> b/drivers/gpu/drm/msm/dp/dp_catalog.c
> >> index 5d84c089e520a..bfc6f53ae167f 100644
> >> --- a/drivers/gpu/drm/msm/dp/dp_catalog.c
> >> +++ b/drivers/gpu/drm/msm/dp/dp_catalog.c
> >> @@ -901,6 +901,99 @@ int dp_catalog_panel_timing_cfg(struct dp_catalog 
> >> *dp_catalog)
> >>  return 0;
> >>   }
> >>
> >> +static void dp_catalog_panel_send_vsc_sdp(struct dp_catalog *dp_catalog, 
> >> struct dp_sdp *vsc_sdp)
> >> +{
> >> +   struct dp_catalog_private *catalog;
> >> +   u32 header[2];
> >> +   u32 val;
> >> +   int i;
> >> +
> >> +   catalog = container_of(dp_catalog, struct dp_catalog_private, 
> >> dp_catalog);
> >> +
> >> +   dp_utils_pack_sdp_header(_sdp->sdp_header, header);
> >> +
> >> +   dp_write_link(catalog, MMSS_DP_GENERIC0_0, header[0]);
> >> +   dp_write_link(catalog, MMSS_DP_GENERIC0_1, header[1]);
> >> +
> >> +   for (i = 0; i < sizeof(vsc_sdp->db); i += 4) {
> >> +   val = ((vsc_sdp->db[i]) | (vsc_sdp->db[i + 1] << 8) | 
> >> (vsc_sdp->db[i + 2] << 16) |
> >> +  (vsc_sdp->db[i + 3] << 24));
> >> +   dp_write_link(catalog, MMSS_DP_GENERIC0_2 + i, val);
> >> +   }
> >> +}
> >> +
> >> +static void dp_catalog_panel_update_sdp(struct dp_catalog *dp_catalog)
> >> +{
> >> +   struct dp_catalog_private *catalog;
> >> +

Re: [PATCH v5] drm/msm/dpu: add current resource allocation to dumped state

2024-02-22 Thread Abhinav Kumar




On 2/22/2024 1:47 PM, Dmitry Baryshkov wrote:

Provide atomic_print_state callback to the DPU's private object. This
way the debugfs/dri/0/state will also include RM's internal state.

Example output (RB5 board, HDMI and writeback encoder enabled)

resource mapping:
pingpong=31 36 # # # # - - - - -
mixer=31 36 # # # # -
ctl=# # 31 36 # #
dspp=# # # #
dsc=# # # # - -
cdm=#



Thanks, this LGTM now, one nit below.


Signed-off-by: Dmitry Baryshkov 
---
Changes in v5:
- Extracted the common helper for printing RM state
- Changed the code to print '#' for unused/unmapped blocks (Abhinav)
- Link to v4: 
https://lore.kernel.org/r/20240219-fd-rm-state-v4-1-b47f14ef2...@linaro.org

Changes in v4:
- Split the patch from the virual wide planes series
- Reworked the output format
- Added the CDM block into the dump
---
  drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 12 +++
  drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h |  2 ++
  drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c  | 56 +
  drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h  |  8 +
  4 files changed, 78 insertions(+)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
index 723cc1d82143..9f3697e1eacb 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
@@ -353,9 +353,18 @@ static void dpu_kms_global_destroy_state(struct 
drm_private_obj *obj,
kfree(dpu_state);
  }
  
+static void dpu_kms_global_print_state(struct drm_printer *p,

+  const struct drm_private_state *state)
+{
+   const struct dpu_global_state *global_state = 
to_dpu_global_state(state);
+
+   dpu_rm_print_state(p, global_state);
+}
+
  static const struct drm_private_state_funcs dpu_kms_global_state_funcs = {
.atomic_duplicate_state = dpu_kms_global_duplicate_state,
.atomic_destroy_state = dpu_kms_global_destroy_state,
+   .atomic_print_state = dpu_kms_global_print_state,
  };
  
  static int dpu_kms_global_obj_init(struct dpu_kms *dpu_kms)

@@ -371,6 +380,9 @@ static int dpu_kms_global_obj_init(struct dpu_kms *dpu_kms)
drm_atomic_private_obj_init(dpu_kms->dev, _kms->global_state,
>base,
_kms_global_state_funcs);
+
+   state->rm = _kms->rm;
+
return 0;
  }
  
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h

index d1207f4ec3ae..2512c9bd08df 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
@@ -131,6 +131,8 @@ struct vsync_info {
  struct dpu_global_state {
struct drm_private_state base;
  
+	struct dpu_rm *rm;

+
uint32_t pingpong_to_enc_id[PINGPONG_MAX - PINGPONG_0];
uint32_t mixer_to_enc_id[LM_MAX - LM_0];
uint32_t ctl_to_enc_id[CTL_MAX - CTL_0];
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
index 724537ab776d..1a56ddca536d 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
@@ -634,3 +634,59 @@ int dpu_rm_get_assigned_resources(struct dpu_rm *rm,
  
  	return num_blks;

  }
+
+static void dpu_rm_print_state_helper(struct drm_printer *p,
+   struct dpu_hw_blk *blk,
+   uint32_t mapping)


Not sure if its the mail client, but is this aligned with the opening brace?

Please double check once. Rest LGTM.

Reviewed-by: Abhinav Kumar 


[PATCH v5] drm/msm/dpu: add current resource allocation to dumped state

2024-02-22 Thread Dmitry Baryshkov
Provide atomic_print_state callback to the DPU's private object. This
way the debugfs/dri/0/state will also include RM's internal state.

Example output (RB5 board, HDMI and writeback encoder enabled)

resource mapping:
pingpong=31 36 # # # # - - - - -
mixer=31 36 # # # # -
ctl=# # 31 36 # #
dspp=# # # #
dsc=# # # # - -
cdm=#

Signed-off-by: Dmitry Baryshkov 
---
Changes in v5:
- Extracted the common helper for printing RM state
- Changed the code to print '#' for unused/unmapped blocks (Abhinav)
- Link to v4: 
https://lore.kernel.org/r/20240219-fd-rm-state-v4-1-b47f14ef2...@linaro.org

Changes in v4:
- Split the patch from the virual wide planes series
- Reworked the output format
- Added the CDM block into the dump
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 12 +++
 drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h |  2 ++
 drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c  | 56 +
 drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h  |  8 +
 4 files changed, 78 insertions(+)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
index 723cc1d82143..9f3697e1eacb 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
@@ -353,9 +353,18 @@ static void dpu_kms_global_destroy_state(struct 
drm_private_obj *obj,
kfree(dpu_state);
 }
 
+static void dpu_kms_global_print_state(struct drm_printer *p,
+  const struct drm_private_state *state)
+{
+   const struct dpu_global_state *global_state = 
to_dpu_global_state(state);
+
+   dpu_rm_print_state(p, global_state);
+}
+
 static const struct drm_private_state_funcs dpu_kms_global_state_funcs = {
.atomic_duplicate_state = dpu_kms_global_duplicate_state,
.atomic_destroy_state = dpu_kms_global_destroy_state,
+   .atomic_print_state = dpu_kms_global_print_state,
 };
 
 static int dpu_kms_global_obj_init(struct dpu_kms *dpu_kms)
@@ -371,6 +380,9 @@ static int dpu_kms_global_obj_init(struct dpu_kms *dpu_kms)
drm_atomic_private_obj_init(dpu_kms->dev, _kms->global_state,
>base,
_kms_global_state_funcs);
+
+   state->rm = _kms->rm;
+
return 0;
 }
 
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
index d1207f4ec3ae..2512c9bd08df 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
@@ -131,6 +131,8 @@ struct vsync_info {
 struct dpu_global_state {
struct drm_private_state base;
 
+   struct dpu_rm *rm;
+
uint32_t pingpong_to_enc_id[PINGPONG_MAX - PINGPONG_0];
uint32_t mixer_to_enc_id[LM_MAX - LM_0];
uint32_t ctl_to_enc_id[CTL_MAX - CTL_0];
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
index 724537ab776d..1a56ddca536d 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
@@ -634,3 +634,59 @@ int dpu_rm_get_assigned_resources(struct dpu_rm *rm,
 
return num_blks;
 }
+
+static void dpu_rm_print_state_helper(struct drm_printer *p,
+   struct dpu_hw_blk *blk,
+   uint32_t mapping)
+{
+   if (!blk)
+   drm_puts(p, "- ");
+   else if (!mapping)
+   drm_puts(p, "# ");
+   else
+   drm_printf(p, "%d ", mapping);
+}
+
+
+void dpu_rm_print_state(struct drm_printer *p,
+   const struct dpu_global_state *global_state)
+{
+   const struct dpu_rm *rm = global_state->rm;
+   int i;
+
+   drm_puts(p, "resource mapping:\n");
+   drm_puts(p, "\tpingpong=");
+   for (i = 0; i < ARRAY_SIZE(global_state->pingpong_to_enc_id); i++)
+   dpu_rm_print_state_helper(p, rm->pingpong_blks[i],
+ global_state->pingpong_to_enc_id[i]);
+   drm_puts(p, "\n");
+
+   drm_puts(p, "\tmixer=");
+   for (i = 0; i < ARRAY_SIZE(global_state->mixer_to_enc_id); i++)
+   dpu_rm_print_state_helper(p, rm->mixer_blks[i],
+ global_state->mixer_to_enc_id[i]);
+   drm_puts(p, "\n");
+
+   drm_puts(p, "\tctl=");
+   for (i = 0; i < ARRAY_SIZE(global_state->ctl_to_enc_id); i++)
+   dpu_rm_print_state_helper(p, rm->ctl_blks[i],
+ global_state->ctl_to_enc_id[i]);
+   drm_puts(p, "\n");
+
+   drm_puts(p, "\tdspp=");
+   for (i = 0; i < ARRAY_SIZE(global_state->dspp_to_enc_id); i++)
+   dpu_rm_print_state_helper(p, rm->dspp_blks[i],
+ global_state->dspp_to_enc_id[i]);
+   drm_puts(p, "\n");
+
+   drm_puts(p, "\tdsc=");
+   for (i = 0; i < ARRAY_SIZE(global_state->dsc_to_enc_id); i++)
+ 

Re: Re: [PATCH v3 1/3] bits: introduce fixed-type genmasks

2024-02-22 Thread Yury Norov
On Thu, Feb 22, 2024 at 05:04:10PM +0200, Andy Shevchenko wrote:
> On Thu, Feb 22, 2024 at 06:49:59AM -0800, Yury Norov wrote:
> > On Wed, Feb 21, 2024 at 03:59:06PM -0600, Lucas De Marchi wrote:
> 
> ...
> 
> > +#define __GENMASK(t, h, l) \
> > +   ((~0 - (1 << (l)) + 1) & (~0 >> (BITS_PER_LONG - 1 - (h
> 
> What's wrong on using the UL/ULL() macros?

Nothing wrong except that in the !__ASSEMBLY section they all are
useless. And having that in mind, useless macros may hurt readability.
 
> Also it would be really good to avoid bifurcation of the implementations of
> __GENMASK() for both cases.

Not exactly. It would be really good if GENMASK_XX() will share the
implementation (and they do). The underscored helper macro is not
intended to be used directly, and I think nobody cares.

> ...
> 
> > -#define __GENMASK(h, l) \
> > -   (((~UL(0)) - (UL(1) << (l)) + 1) & \
> > -(~UL(0) >> (BITS_PER_LONG - 1 - (h
> 
> This at bare minimum can be left untouched for asm case, no?

As soon as we have to have different versions for the macro depending
on __ASSEMBLY__, I would prefer to remove all compatibility black
magic. After all, the  machinery to me is about the same
level of abstraction as the stuff in , and in future we
can try to remove dependency on it.

This all is not a big deal to me. I can keep the old implementation
for the asm, if you think it's really important.

What are you thinking guys?

Thanks,
Yury


Re: [PATCH v5 13/19] drm/msm/dp: add VSC SDP support for YUV420 over DP

2024-02-22 Thread Paloma Arellano



On 2/22/2024 1:18 PM, Dmitry Baryshkov wrote:

On Thu, 22 Feb 2024 at 21:40, Paloma Arellano  wrote:

Add support to pack and send the VSC SDP packet for DP. This therefore
allows the transmision of format information to the sinks which is
needed for YUV420 support over DP.

Changes in v5:
 - Slightly modify use of drm_dp_vsc_sdp_pack()
 - Remove dp_catalog NULL checks
 - Modify dp_utils_pack_sdp_header() to more clearly pack the
   header buffer
 - Move dp_utils_pack_sdp_header() inside of
   dp_catalog_panel_send_vsc_sdp to clearly show the relationship
   between the header buffer and the vsc_sdp struct
 - Due to the last point, remove the dp_utils_pack_vsc_sdp()
   function and only call drm_dp_vsc_sdp_pack() in
   dp_panel_setup_vsc_sdp_yuv_420()

Changes in v4:
 - Remove struct msm_dp_sdp_with_parity
 - Use dp_utils_pack_sdp_header() to pack the SDP header and
   parity bytes into a buffer
 - Use this buffer when writing the VSC SDP data in
   dp_catalog_panel_send_vsc_sdp()
 - Write to all of the MMSS_DP_GENERIC0 registers instead of just
   the ones with non-zero values

Changes in v3:
 - Create a new struct, msm_dp_sdp_with_parity, which holds the
   packing information for VSC SDP
 - Use drm_dp_vsc_sdp_pack() to pack the data into the new
   msm_dp_sdp_with_parity struct instead of specifically packing
   for YUV420 format
 - Modify dp_catalog_panel_send_vsc_sdp() to send the VSC SDP
   data using the new msm_dp_sdp_with_parity struct

Changes in v2:
 - Rename GENERIC0_SDPSIZE macro to GENERIC0_SDPSIZE_VALID
 - Remove dp_sdp from the dp_catalog struct since this data is
   being allocated at the point used
 - Create a new function in dp_utils to pack the VSC SDP data
   into a buffer
 - Create a new function that packs the SDP header bytes into a
   buffer. This function is made generic so that it can be
   utilized by dp_audio
   header bytes into a buffer
 - Create a new function in dp_utils that takes the packed buffer
   and writes to the DP_GENERIC0_* registers
 - Split the dp_catalog_panel_config_vsc_sdp() function into two
   to disable/enable sending VSC SDP packets
 - Check the DP HW version using the original useage of
   dp_catalog_hw_revision() and correct the version checking
   logic
 - Rename dp_panel_setup_vsc_sdp() to
   dp_panel_setup_vsc_sdp_yuv_420() to explicitly state that
   currently VSC SDP is only being set up to support YUV420 modes

Signed-off-by: Paloma Arellano 
---
  drivers/gpu/drm/msm/dp/dp_catalog.c | 93 +
  drivers/gpu/drm/msm/dp/dp_catalog.h |  6 ++
  drivers/gpu/drm/msm/dp/dp_ctrl.c|  4 ++
  drivers/gpu/drm/msm/dp/dp_panel.c   | 52 
  drivers/gpu/drm/msm/dp/dp_reg.h |  3 +
  drivers/gpu/drm/msm/dp/dp_utils.c   | 25 
  drivers/gpu/drm/msm/dp/dp_utils.h   | 14 +
  7 files changed, 197 insertions(+)

diff --git a/drivers/gpu/drm/msm/dp/dp_catalog.c 
b/drivers/gpu/drm/msm/dp/dp_catalog.c
index 5d84c089e520a..bfc6f53ae167f 100644
--- a/drivers/gpu/drm/msm/dp/dp_catalog.c
+++ b/drivers/gpu/drm/msm/dp/dp_catalog.c
@@ -901,6 +901,99 @@ int dp_catalog_panel_timing_cfg(struct dp_catalog 
*dp_catalog)
 return 0;
  }

+static void dp_catalog_panel_send_vsc_sdp(struct dp_catalog *dp_catalog, 
struct dp_sdp *vsc_sdp)
+{
+   struct dp_catalog_private *catalog;
+   u32 header[2];
+   u32 val;
+   int i;
+
+   catalog = container_of(dp_catalog, struct dp_catalog_private, 
dp_catalog);
+
+   dp_utils_pack_sdp_header(_sdp->sdp_header, header);
+
+   dp_write_link(catalog, MMSS_DP_GENERIC0_0, header[0]);
+   dp_write_link(catalog, MMSS_DP_GENERIC0_1, header[1]);
+
+   for (i = 0; i < sizeof(vsc_sdp->db); i += 4) {
+   val = ((vsc_sdp->db[i]) | (vsc_sdp->db[i + 1] << 8) | (vsc_sdp->db[i 
+ 2] << 16) |
+  (vsc_sdp->db[i + 3] << 24));
+   dp_write_link(catalog, MMSS_DP_GENERIC0_2 + i, val);
+   }
+}
+
+static void dp_catalog_panel_update_sdp(struct dp_catalog *dp_catalog)
+{
+   struct dp_catalog_private *catalog;
+   u32 hw_revision;
+
+   catalog = container_of(dp_catalog, struct dp_catalog_private, 
dp_catalog);
+
+   hw_revision = dp_catalog_hw_revision(dp_catalog);
+   if (hw_revision < DP_HW_VERSION_1_2 && hw_revision >= 
DP_HW_VERSION_1_0) {
+   dp_write_link(catalog, MMSS_DP_SDP_CFG3, 0x01);
+   dp_write_link(catalog, MMSS_DP_SDP_CFG3, 0x00);
+   }
+}
+
+void dp_catalog_panel_enable_vsc_sdp(struct dp_catalog *dp_catalog, struct 
dp_sdp *vsc_sdp)
+{
+   struct dp_catalog_private *catalog;
+   u32 cfg, cfg2, misc;
+
+   

Re: [PATCH 1/9] drm/msm/dp: Add DP support to combo instance in SC7280

2024-02-22 Thread Dmitry Baryshkov
On Thu, 22 Feb 2024 at 06:01, Dmitry Baryshkov
 wrote:
>
> On Thu, 22 Feb 2024 at 05:47, Bjorn Andersson  
> wrote:
> >
> > On Thu, Feb 22, 2024 at 01:38:45AM +0200, Dmitry Baryshkov wrote:
> > > On Thu, 22 Feb 2024 at 01:19, Bjorn Andersson  
> > > wrote:
> > > >
> > > > When upstreamed the SC7280 DP controllers where described as one being
> > > > DP and one eDP, but they can infact both be DP or eDP.
> > > >
> > > > Extend the list of DP controllers to cover both instances, and rely on
> > > > the newly introduced mechanism for selecting which mode they should
> > > > operate in.
> > > >
> > > > Move qcom,sc7280-edp to a dedicated list, to ensure existing DeviceTree
> > > > will continue to select eDP.
> > > >
> > > > Signed-off-by: Bjorn Andersson 
> > > > ---
> > > >  drivers/gpu/drm/msm/dp/dp_display.c | 9 +++--
> > > >  1 file changed, 7 insertions(+), 2 deletions(-)
> > > >
> > > > diff --git a/drivers/gpu/drm/msm/dp/dp_display.c 
> > > > b/drivers/gpu/drm/msm/dp/dp_display.c
> > > > index 7b8c695d521a..1792ba9f7259 100644
> > > > --- a/drivers/gpu/drm/msm/dp/dp_display.c
> > > > +++ b/drivers/gpu/drm/msm/dp/dp_display.c
> > > > @@ -129,7 +129,12 @@ static const struct msm_dp_desc sc7180_dp_descs[] 
> > > > = {
> > > >  };
> > > >
> > > >  static const struct msm_dp_desc sc7280_dp_descs[] = {
> > > > -   { .io_start = 0x0ae9, .id = MSM_DP_CONTROLLER_0, 
> > > > .connector_type = DRM_MODE_CONNECTOR_DisplayPort, .wide_bus_en = true },
> > > > +   { .io_start = 0x0ae9, .id = MSM_DP_CONTROLLER_0, 
> > > > .wide_bus_en = true },
> > > > +   { .io_start = 0x0aea, .id = MSM_DP_CONTROLLER_1, 
> > > > .wide_bus_en = true },
> > >
> > > I think we need to keep .connector_type here, don't we?
> > >
> >
> > No, Abel removes the need for that in his patches - and while that logic
> > is slightly broken in the RFC I think it looks good.
>
> Let's see v2 first.

Reviewed-by: Dmitry Baryshkov 



>
> >
> > Regards,
> > Bjorn
> >
> > > > +   {}
> > > > +};
> > > > +
> > > > +static const struct msm_dp_desc sc7280_edp_descs[] = {
> > > > { .io_start = 0x0aea, .id = MSM_DP_CONTROLLER_1, 
> > > > .connector_type = DRM_MODE_CONNECTOR_eDP, .wide_bus_en = true },
> > > > {}
> > > >  };
> > > > @@ -182,7 +187,7 @@ static const struct msm_dp_desc x1e80100_dp_descs[] 
> > > > = {
> > > >  static const struct of_device_id dp_dt_match[] = {
> > > > { .compatible = "qcom,sc7180-dp", .data = _dp_descs },
> > > > { .compatible = "qcom,sc7280-dp", .data = _dp_descs },
> > > > -   { .compatible = "qcom,sc7280-edp", .data = _dp_descs },
> > > > +   { .compatible = "qcom,sc7280-edp", .data = _edp_descs },
> > > > { .compatible = "qcom,sc8180x-dp", .data = _dp_descs },
> > > > { .compatible = "qcom,sc8180x-edp", .data = _dp_descs },
> > > > { .compatible = "qcom,sc8280xp-dp", .data = _dp_descs 
> > > > },
> > > >
> > > > --
> > > > 2.25.1
> > > >
> > >
> > >
> > > --
> > > With best wishes
> > > Dmitry
>
>
>
> --
> With best wishes
> Dmitry



-- 
With best wishes
Dmitry


Re: [PATCH v5 13/19] drm/msm/dp: add VSC SDP support for YUV420 over DP

2024-02-22 Thread Dmitry Baryshkov
On Thu, 22 Feb 2024 at 21:40, Paloma Arellano  wrote:
>
> Add support to pack and send the VSC SDP packet for DP. This therefore
> allows the transmision of format information to the sinks which is
> needed for YUV420 support over DP.
>
> Changes in v5:
> - Slightly modify use of drm_dp_vsc_sdp_pack()
> - Remove dp_catalog NULL checks
> - Modify dp_utils_pack_sdp_header() to more clearly pack the
>   header buffer
> - Move dp_utils_pack_sdp_header() inside of
>   dp_catalog_panel_send_vsc_sdp to clearly show the relationship
>   between the header buffer and the vsc_sdp struct
> - Due to the last point, remove the dp_utils_pack_vsc_sdp()
>   function and only call drm_dp_vsc_sdp_pack() in
>   dp_panel_setup_vsc_sdp_yuv_420()
>
> Changes in v4:
> - Remove struct msm_dp_sdp_with_parity
> - Use dp_utils_pack_sdp_header() to pack the SDP header and
>   parity bytes into a buffer
> - Use this buffer when writing the VSC SDP data in
>   dp_catalog_panel_send_vsc_sdp()
> - Write to all of the MMSS_DP_GENERIC0 registers instead of just
>   the ones with non-zero values
>
> Changes in v3:
> - Create a new struct, msm_dp_sdp_with_parity, which holds the
>   packing information for VSC SDP
> - Use drm_dp_vsc_sdp_pack() to pack the data into the new
>   msm_dp_sdp_with_parity struct instead of specifically packing
>   for YUV420 format
> - Modify dp_catalog_panel_send_vsc_sdp() to send the VSC SDP
>   data using the new msm_dp_sdp_with_parity struct
>
> Changes in v2:
> - Rename GENERIC0_SDPSIZE macro to GENERIC0_SDPSIZE_VALID
> - Remove dp_sdp from the dp_catalog struct since this data is
>   being allocated at the point used
> - Create a new function in dp_utils to pack the VSC SDP data
>   into a buffer
> - Create a new function that packs the SDP header bytes into a
>   buffer. This function is made generic so that it can be
>   utilized by dp_audio
>   header bytes into a buffer
> - Create a new function in dp_utils that takes the packed buffer
>   and writes to the DP_GENERIC0_* registers
> - Split the dp_catalog_panel_config_vsc_sdp() function into two
>   to disable/enable sending VSC SDP packets
> - Check the DP HW version using the original useage of
>   dp_catalog_hw_revision() and correct the version checking
>   logic
> - Rename dp_panel_setup_vsc_sdp() to
>   dp_panel_setup_vsc_sdp_yuv_420() to explicitly state that
>   currently VSC SDP is only being set up to support YUV420 modes
>
> Signed-off-by: Paloma Arellano 
> ---
>  drivers/gpu/drm/msm/dp/dp_catalog.c | 93 +
>  drivers/gpu/drm/msm/dp/dp_catalog.h |  6 ++
>  drivers/gpu/drm/msm/dp/dp_ctrl.c|  4 ++
>  drivers/gpu/drm/msm/dp/dp_panel.c   | 52 
>  drivers/gpu/drm/msm/dp/dp_reg.h |  3 +
>  drivers/gpu/drm/msm/dp/dp_utils.c   | 25 
>  drivers/gpu/drm/msm/dp/dp_utils.h   | 14 +
>  7 files changed, 197 insertions(+)
>
> diff --git a/drivers/gpu/drm/msm/dp/dp_catalog.c 
> b/drivers/gpu/drm/msm/dp/dp_catalog.c
> index 5d84c089e520a..bfc6f53ae167f 100644
> --- a/drivers/gpu/drm/msm/dp/dp_catalog.c
> +++ b/drivers/gpu/drm/msm/dp/dp_catalog.c
> @@ -901,6 +901,99 @@ int dp_catalog_panel_timing_cfg(struct dp_catalog 
> *dp_catalog)
> return 0;
>  }
>
> +static void dp_catalog_panel_send_vsc_sdp(struct dp_catalog *dp_catalog, 
> struct dp_sdp *vsc_sdp)
> +{
> +   struct dp_catalog_private *catalog;
> +   u32 header[2];
> +   u32 val;
> +   int i;
> +
> +   catalog = container_of(dp_catalog, struct dp_catalog_private, 
> dp_catalog);
> +
> +   dp_utils_pack_sdp_header(_sdp->sdp_header, header);
> +
> +   dp_write_link(catalog, MMSS_DP_GENERIC0_0, header[0]);
> +   dp_write_link(catalog, MMSS_DP_GENERIC0_1, header[1]);
> +
> +   for (i = 0; i < sizeof(vsc_sdp->db); i += 4) {
> +   val = ((vsc_sdp->db[i]) | (vsc_sdp->db[i + 1] << 8) | 
> (vsc_sdp->db[i + 2] << 16) |
> +  (vsc_sdp->db[i + 3] << 24));
> +   dp_write_link(catalog, MMSS_DP_GENERIC0_2 + i, val);
> +   }
> +}
> +
> +static void dp_catalog_panel_update_sdp(struct dp_catalog *dp_catalog)
> +{
> +   struct dp_catalog_private *catalog;
> +   u32 hw_revision;
> +
> +   catalog = container_of(dp_catalog, struct dp_catalog_private, 
> dp_catalog);
> +
> +   hw_revision = dp_catalog_hw_revision(dp_catalog);
> +   if (hw_revision < DP_HW_VERSION_1_2 && hw_revision >= 
> DP_HW_VERSION_1_0) {
> +   dp_write_link(catalog, MMSS_DP_SDP_CFG3, 0x01);
> +   dp_write_link(catalog, MMSS_DP_SDP_CFG3, 0x00);
> +   }
> +}
> +
> +void dp_catalog_panel_enable_vsc_sdp(struct dp_catalog 

Re: [PATCH 6/6] phy: qcom-qmp-combo: fix type-c switch registration

2024-02-22 Thread Dmitry Baryshkov
On Sat, 17 Feb 2024 at 17:03, Johan Hovold  wrote:
>
> Due to a long-standing issue in driver core, drivers may not probe defer
> after having registered child devices to avoid triggering a probe
> deferral loop (see fbc35b45f9f6 ("Add documentation on meaning of
> -EPROBE_DEFER")).
>
> Move registration of the typec switch to after looking up clocks and
> other resources.
>
> Note that PHY creation can in theory also trigger a probe deferral when
> a 'phy' supply is used. This does not seem to affect the QMP PHY driver
> but the PHY subsystem should be reworked to address this (i.e. by
> separating initialisation and registration of the PHY).
>
> Fixes: 2851117f8f42 ("phy: qcom-qmp-combo: Introduce orientation switching")
> Cc: sta...@vger.kernel.org  # 6.5
> Cc: Bjorn Andersson 
> Signed-off-by: Johan Hovold 
> ---
>  drivers/phy/qualcomm/phy-qcom-qmp-combo.c | 8 
>  1 file changed, 4 insertions(+), 4 deletions(-)

Reviewed-by: Dmitry Baryshkov 

Note to myself (or to anybody else, who has spare hands), we should
probably implement the same changes for phy-qcom-qmp-usbc.c

>
> diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-combo.c 
> b/drivers/phy/qualcomm/phy-qcom-qmp-combo.c
> index e19d6a084f10..17c4ad7553a5 100644
> --- a/drivers/phy/qualcomm/phy-qcom-qmp-combo.c
> +++ b/drivers/phy/qualcomm/phy-qcom-qmp-combo.c
> @@ -3562,10 +3562,6 @@ static int qmp_combo_probe(struct platform_device 
> *pdev)
> if (ret)
> return ret;
>
> -   ret = qmp_combo_typec_switch_register(qmp);
> -   if (ret)
> -   return ret;
> -
> /* Check for legacy binding with child nodes. */
> usb_np = of_get_child_by_name(dev->of_node, "usb3-phy");
> if (usb_np) {
> @@ -3585,6 +3581,10 @@ static int qmp_combo_probe(struct platform_device 
> *pdev)
> if (ret)
> goto err_node_put;
>
> +   ret = qmp_combo_typec_switch_register(qmp);
> +   if (ret)
> +   goto err_node_put;
> +
> ret = drm_aux_bridge_register(dev);
> if (ret)
> goto err_node_put;
> --
> 2.43.0
>


-- 
With best wishes
Dmitry


Re: [PATCH 5/6] phy: qcom-qmp-combo: fix drm bridge registration

2024-02-22 Thread Dmitry Baryshkov
On Sat, 17 Feb 2024 at 17:03, Johan Hovold  wrote:
>
> Due to a long-standing issue in driver core, drivers may not probe defer
> after having registered child devices to avoid triggering a probe
> deferral loop (see fbc35b45f9f6 ("Add documentation on meaning of
> -EPROBE_DEFER")).
>
> This could potentially also trigger a bug in the DRM bridge
> implementation which does not expect bridges to go away even if device
> links may avoid triggering this (when enabled).
>
> Move registration of the DRM aux bridge to after looking up clocks and
> other resources.
>
> Note that PHY creation can in theory also trigger a probe deferral when
> a 'phy' supply is used. This does not seem to affect the QMP PHY driver
> but the PHY subsystem should be reworked to address this (i.e. by
> separating initialisation and registration of the PHY).
>
> Fixes: 35921910bbd0 ("phy: qcom: qmp-combo: switch to DRM_AUX_BRIDGE")
> Fixes: 1904c3f578dc ("phy: qcom-qmp-combo: Introduce drm_bridge")
> Cc: sta...@vger.kernel.org  # 6.5
> Cc: Bjorn Andersson 
> Cc: Dmitry Baryshkov 
> Signed-off-by: Johan Hovold 
> ---
>  drivers/phy/qualcomm/phy-qcom-qmp-combo.c | 8 
>  1 file changed, 4 insertions(+), 4 deletions(-)
>
Reviewed-by: Dmitry Baryshkov 


-- 
With best wishes
Dmitry


Re: [PATCH 4/6] soc: qcom: pmic_glink: Fix boot when QRTR=m

2024-02-22 Thread Dmitry Baryshkov
On Sat, 17 Feb 2024 at 17:03, Johan Hovold  wrote:
>
> From: Rob Clark 
>
> We need to bail out before adding/removing devices if we are going to
> -EPROBE_DEFER. Otherwise boot can get stuck in a probe deferral loop due
> to a long-standing issue in driver core (see fbc35b45f9f6 ("Add
> documentation on meaning of -EPROBE_DEFER")).
>
> Deregistering the altmode child device can potentially also trigger bugs
> in the DRM bridge implementation, which does not expect bridges to go
> away.
>
> Suggested-by: Dmitry Baryshkov 
> Signed-off-by: Rob Clark 
> Link: https://lore.kernel.org/r/20231213210644.8702-1-robdcl...@gmail.com
> [ johan: rebase on 6.8-rc4, amend commit message and mention DRM ]
> Fixes: 58ef4ece1e41 ("soc: qcom: pmic_glink: Introduce base PMIC GLINK 
> driver")
> Cc: sta...@vger.kernel.org  # 6.3
> Cc: Bjorn Andersson 
> Signed-off-by: Johan Hovold 
> ---
>  drivers/soc/qcom/pmic_glink.c | 21 +++--
>  1 file changed, 11 insertions(+), 10 deletions(-)
>

Reviewed-by: Dmitry Baryshkov 

-- 
With best wishes
Dmitry


Re: [PATCH 3/6] soc: qcom: pmic_glink_altmode: fix drm bridge use-after-free

2024-02-22 Thread Dmitry Baryshkov
On Sat, 17 Feb 2024 at 17:03, Johan Hovold  wrote:
>
> A recent DRM series purporting to simplify support for "transparent
> bridges" and handling of probe deferrals ironically exposed a
> use-after-free issue on pmic_glink_altmode probe deferral.
>
> This has manifested itself as the display subsystem occasionally failing
> to initialise and NULL-pointer dereferences during boot of machines like
> the Lenovo ThinkPad X13s.
>
> Specifically, the dp-hpd bridge is currently registered before all
> resources have been acquired which means that it can also be
> deregistered on probe deferrals.
>
> In the meantime there is a race window where the new aux bridge driver
> (or PHY driver previously) may have looked up the dp-hpd bridge and
> stored a (non-reference-counted) pointer to the bridge which is about to
> be deallocated.
>
> When the display controller is later initialised, this triggers a
> use-after-free when attaching the bridges:
>
> dp -> aux -> dp-hpd (freed)
>
> which may, for example, result in the freed bridge failing to attach:
>
> [drm:drm_bridge_attach [drm]] *ERROR* failed to attach bridge 
> /soc@0/phy@88eb000 to encoder TMDS-31: -16
>
> or a NULL-pointer dereference:
>
> Unable to handle kernel NULL pointer dereference at virtual address 
> 
> ...
> Call trace:
>   drm_bridge_attach+0x70/0x1a8 [drm]
>   drm_aux_bridge_attach+0x24/0x38 [aux_bridge]
>   drm_bridge_attach+0x80/0x1a8 [drm]
>   dp_bridge_init+0xa8/0x15c [msm]
>   msm_dp_modeset_init+0x28/0xc4 [msm]
>
> The DRM bridge implementation is clearly fragile and implicitly built on
> the assumption that bridges may never go away. In this case, the fix is
> to move the bridge registration in the pmic_glink_altmode driver to
> after all resources have been looked up.
>
> Incidentally, with the new dp-hpd bridge implementation, which registers
> child devices, this is also a requirement due to a long-standing issue
> in driver core that can otherwise lead to a probe deferral loop (see
> fbc35b45f9f6 ("Add documentation on meaning of -EPROBE_DEFER")).
>
> Fixes: 080b4e24852b ("soc: qcom: pmic_glink: Introduce altmode support")
> Fixes: 2bcca96abfbf ("soc: qcom: pmic-glink: switch to DRM_AUX_HPD_BRIDGE")
> Cc: sta...@vger.kernel.org  # 6.3
> Cc: Bjorn Andersson 
> Cc: Dmitry Baryshkov 
> Signed-off-by: Johan Hovold 
> ---
>  drivers/soc/qcom/pmic_glink_altmode.c | 16 +---
>  1 file changed, 13 insertions(+), 3 deletions(-)
>

Reviewed-by: Dmitry Baryshkov 


-- 
With best wishes
Dmitry


Re: [PATCH 2/2] drm/i915: Support replaying GPU hangs with captured context image

2024-02-22 Thread Rodrigo Vivi
On Wed, Feb 21, 2024 at 02:22:45PM +, Tvrtko Ursulin wrote:
> From: Tvrtko Ursulin 
> 
> When debugging GPU hangs Mesa developers are finding it useful to replay
> the captured error state against the simulator. But due various simulator
> limitations which prevent replicating all hangs, one step further is being
> able to replay against a real GPU.
> 
> This is almost doable today with the missing part being able to upload the
> captured context image into the driver state prior to executing the
> uploaded hanging batch and all the buffers.
> 
> To enable this last part we add a new context parameter called
> I915_CONTEXT_PARAM_CONTEXT_IMAGE. It follows the existing SSEU
> configuration pattern of being able to select which context to apply
> against, paired with the actual image and its size.
> 
> Since this is adding a new concept of debug only uapi, we hide it behind
> a new kconfig option and also require activation with a module parameter.
> Together with a warning banner printed at driver load, all those combined
> should be sufficient to guard against inadvertently enabling the feature.
> 
> In terms of implementation we allow the legacy context set param to be
> used since that removes the need to record the per context data in the
> proto context, while still allowing flexibility of specifying context
> images for any context.
> 
> Mesa MR using the uapi can be seen at:
>   https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/27594
> 
> v2:
>  * Fix whitespace alignment as per checkpatch.
>  * Added warning on userspace misuse.
>  * Rebase for extracting ce->default_state shadowing.
> 
> Signed-off-by: Tvrtko Ursulin 
> Cc: Lionel Landwerlin 
> Cc: Carlos Santa 
> Cc: Rodrigo Vivi 
> Reviewed-by: Rodrigo Vivi  # v1

still valid for v2. Thanks for splitting the patch.

> ---
>  drivers/gpu/drm/i915/Kconfig.debug|  17 +++
>  drivers/gpu/drm/i915/gem/i915_gem_context.c   | 113 ++
>  drivers/gpu/drm/i915/gt/intel_context.c   |   2 +
>  drivers/gpu/drm/i915/gt/intel_context.h   |  22 
>  drivers/gpu/drm/i915/gt/intel_context_types.h |   1 +
>  drivers/gpu/drm/i915/gt/intel_lrc.c   |   3 +-
>  .../gpu/drm/i915/gt/intel_ring_submission.c   |   3 +-
>  drivers/gpu/drm/i915/i915_params.c|   5 +
>  drivers/gpu/drm/i915/i915_params.h|   3 +-
>  include/uapi/drm/i915_drm.h   |  27 +
>  10 files changed, 193 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/Kconfig.debug 
> b/drivers/gpu/drm/i915/Kconfig.debug
> index 5b7162076850..32e9f70e91ed 100644
> --- a/drivers/gpu/drm/i915/Kconfig.debug
> +++ b/drivers/gpu/drm/i915/Kconfig.debug
> @@ -16,6 +16,23 @@ config DRM_I915_WERROR
>  
> If in doubt, say "N".
>  
> +config DRM_I915_REPLAY_GPU_HANGS_API
> + bool "Enable GPU hang replay userspace API"
> + depends on DRM_I915
> + depends on EXPERT
> + default n
> + help
> +   Choose this option if you want to enable special and unstable
> +   userspace API used for replaying GPU hangs on a running system.
> +
> +   This API is intended to be used by userspace graphics stack developers
> +   and provides no stability guarantees.
> +
> +   The API needs to be activated at boot time using the
> +   enable_debug_only_api module parameter.
> +
> +   If in doubt, say "N".
> +
>  config DRM_I915_DEBUG
>   bool "Enable additional driver debugging"
>   depends on DRM_I915
> diff --git a/drivers/gpu/drm/i915/gem/i915_gem_context.c 
> b/drivers/gpu/drm/i915/gem/i915_gem_context.c
> index dcbfe32fd30c..481aacbc1772 100644
> --- a/drivers/gpu/drm/i915/gem/i915_gem_context.c
> +++ b/drivers/gpu/drm/i915/gem/i915_gem_context.c
> @@ -78,6 +78,7 @@
>  #include "gt/intel_engine_user.h"
>  #include "gt/intel_gpu_commands.h"
>  #include "gt/intel_ring.h"
> +#include "gt/shmem_utils.h"
>  
>  #include "pxp/intel_pxp.h"
>  
> @@ -949,6 +950,7 @@ static int set_proto_ctx_param(struct 
> drm_i915_file_private *fpriv,
>   case I915_CONTEXT_PARAM_NO_ZEROMAP:
>   case I915_CONTEXT_PARAM_BAN_PERIOD:
>   case I915_CONTEXT_PARAM_RINGSIZE:
> + case I915_CONTEXT_PARAM_CONTEXT_IMAGE:
>   default:
>   ret = -EINVAL;
>   break;
> @@ -2092,6 +2094,95 @@ static int get_protected(struct i915_gem_context *ctx,
>   return 0;
>  }
>  
> +static int set_context_image(struct i915_gem_context *ctx,
> +  struct drm_i915_gem_context_param *args)
> +{
> + struct i915_gem_context_param_context_image user;
> + struct intel_context *ce;
> + struct file *shmem_state;
> + unsigned long lookup;
> + void *state;
> + int ret = 0;
> +
> + if (!IS_ENABLED(CONFIG_DRM_I915_REPLAY_GPU_HANGS_API))
> + return -EINVAL;
> +
> + if (!ctx->i915->params.enable_debug_only_api)
> + return -EINVAL;
> +
> + if (args->size < sizeof(user))
> + return -EINVAL;
> +

Re: [PATCH 1/2] drm/i915: Shadow default engine context image in the context

2024-02-22 Thread Rodrigo Vivi
On Wed, Feb 21, 2024 at 02:22:44PM +, Tvrtko Ursulin wrote:
> From: Tvrtko Ursulin 
> 
> To enable adding override of the default engine context image let us start
> shadowing the per engine state in the context.
> 
> Signed-off-by: Tvrtko Ursulin 
> Cc: Lionel Landwerlin 
> Cc: Carlos Santa 
> Cc: Rodrigo Vivi 

Reviewed-by: Rodrigo Vivi 

> ---
>  drivers/gpu/drm/i915/gt/intel_context_types.h   | 2 ++
>  drivers/gpu/drm/i915/gt/intel_lrc.c | 7 ---
>  drivers/gpu/drm/i915/gt/intel_ring_submission.c | 7 ---
>  3 files changed, 10 insertions(+), 6 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/gt/intel_context_types.h 
> b/drivers/gpu/drm/i915/gt/intel_context_types.h
> index 7eccbd70d89f..b179178680a5 100644
> --- a/drivers/gpu/drm/i915/gt/intel_context_types.h
> +++ b/drivers/gpu/drm/i915/gt/intel_context_types.h
> @@ -99,6 +99,8 @@ struct intel_context {
>   struct i915_address_space *vm;
>   struct i915_gem_context __rcu *gem_context;
>  
> + struct file *default_state;
> +
>   /*
>* @signal_lock protects the list of requests that need signaling,
>* @signals. While there are any requests that need signaling,
> diff --git a/drivers/gpu/drm/i915/gt/intel_lrc.c 
> b/drivers/gpu/drm/i915/gt/intel_lrc.c
> index 7c367ba8d9dc..d4eb822d20ae 100644
> --- a/drivers/gpu/drm/i915/gt/intel_lrc.c
> +++ b/drivers/gpu/drm/i915/gt/intel_lrc.c
> @@ -1060,9 +1060,8 @@ void lrc_init_state(struct intel_context *ce,
>  
>   set_redzone(state, engine);
>  
> - if (engine->default_state) {
> - shmem_read(engine->default_state, 0,
> -state, engine->context_size);
> + if (ce->default_state) {
> + shmem_read(ce->default_state, 0, state, engine->context_size);
>   __set_bit(CONTEXT_VALID_BIT, >flags);
>   inhibit = false;
>   }
> @@ -1174,6 +1173,8 @@ int lrc_alloc(struct intel_context *ce, struct 
> intel_engine_cs *engine)
>  
>   GEM_BUG_ON(ce->state);
>  
> + ce->default_state = engine->default_state;
> +
>   vma = __lrc_alloc_state(ce, engine);
>   if (IS_ERR(vma))
>   return PTR_ERR(vma);
> diff --git a/drivers/gpu/drm/i915/gt/intel_ring_submission.c 
> b/drivers/gpu/drm/i915/gt/intel_ring_submission.c
> index 92085ffd23de..8625e88e785f 100644
> --- a/drivers/gpu/drm/i915/gt/intel_ring_submission.c
> +++ b/drivers/gpu/drm/i915/gt/intel_ring_submission.c
> @@ -474,8 +474,7 @@ static int ring_context_init_default_state(struct 
> intel_context *ce,
>   if (IS_ERR(vaddr))
>   return PTR_ERR(vaddr);
>  
> - shmem_read(ce->engine->default_state, 0,
> -vaddr, ce->engine->context_size);
> + shmem_read(ce->default_state, 0, vaddr, ce->engine->context_size);
>  
>   i915_gem_object_flush_map(obj);
>   __i915_gem_object_release_map(obj);
> @@ -491,7 +490,7 @@ static int ring_context_pre_pin(struct intel_context *ce,
>   struct i915_address_space *vm;
>   int err = 0;
>  
> - if (ce->engine->default_state &&
> + if (ce->default_state &&
>   !test_bit(CONTEXT_VALID_BIT, >flags)) {
>   err = ring_context_init_default_state(ce, ww);
>   if (err)
> @@ -570,6 +569,8 @@ static int ring_context_alloc(struct intel_context *ce)
>  {
>   struct intel_engine_cs *engine = ce->engine;
>  
> + ce->default_state = engine->default_state;
> +
>   /* One ringbuffer to rule them all */
>   GEM_BUG_ON(!engine->legacy.ring);
>   ce->ring = engine->legacy.ring;
> -- 
> 2.40.1
> 


Re: [PATCH 1/6] drm/bridge: aux-hpd: fix OF node leaks

2024-02-22 Thread Dmitry Baryshkov
On Sat, 17 Feb 2024 at 17:03, Johan Hovold  wrote:
>
> The two device node references taken during allocation need to be
> dropped when the auxiliary device is freed.
>
> Fixes: 6914968a0b52 ("drm/bridge: properly refcount DT nodes in aux bridge 
> drivers")
> Cc: Dmitry Baryshkov 
> Cc: Neil Armstrong 
> Signed-off-by: Johan Hovold 

Reviewed-by: Dmitry Baryshkov 

> ---
>  drivers/gpu/drm/bridge/aux-hpd-bridge.c | 3 +++
>  1 file changed, 3 insertions(+)


-- 
With best wishes
Dmitry


Re: [PATCH 1/9] kunit: test: Log the correct filter string in executor_test

2024-02-22 Thread Rae Moar
On Wed, Feb 21, 2024 at 4:28 AM David Gow  wrote:
>
> KUnit's executor_test logs the filter string in KUNIT_ASSERT_EQ_MSG(),
> but passed a random character from the filter, rather than the whole
> string.
>
> This was found by annotating KUNIT_ASSERT_EQ_MSG() to let gcc validate
> the format string.
>
> Fixes: 76066f93f1df ("kunit: add tests for filtering attributes")
> Signed-off-by: David Gow 

Hello!

This change looks good to me. Thanks for fixing this mistake.

Thanks!
-Rae

Reviewed-by: Rae Moar 

> ---
>  lib/kunit/executor_test.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/lib/kunit/executor_test.c b/lib/kunit/executor_test.c
> index 22d4ee86dbed..3f7f967e3688 100644
> --- a/lib/kunit/executor_test.c
> +++ b/lib/kunit/executor_test.c
> @@ -129,7 +129,7 @@ static void parse_filter_attr_test(struct kunit *test)
> GFP_KERNEL);
> for (j = 0; j < filter_count; j++) {
> parsed_filters[j] = kunit_next_attr_filter(, );
> -   KUNIT_ASSERT_EQ_MSG(test, err, 0, "failed to parse filter 
> '%s'", filters[j]);
> +   KUNIT_ASSERT_EQ_MSG(test, err, 0, "failed to parse filter 
> from '%s'", filters);
> }
>
> KUNIT_EXPECT_STREQ(test, kunit_attr_filter_name(parsed_filters[0]), 
> "speed");
> --
> 2.44.0.rc0.258.g7320e95886-goog
>


Re: [PATCH 2/6] drm/bridge: aux-hpd: separate allocation and registration

2024-02-22 Thread Dmitry Baryshkov
On Sat, 17 Feb 2024 at 17:03, Johan Hovold  wrote:
>
> Combining allocation and registration is an anti-pattern that should be
> avoided. Add two new functions for allocating and registering an dp-hpd
> bridge with a proper 'devm' prefix so that it is clear that these are
> device managed interfaces.
>
> devm_drm_dp_hpd_bridge_alloc()
> devm_drm_dp_hpd_bridge_add()
>
> The new interface will be used to fix a use-after-free bug in the
> Qualcomm PMIC GLINK driver and may prevent similar issues from being
> introduced elsewhere.
>
> The existing drm_dp_hpd_bridge_register() is reimplemented using the
> above and left in place for now.
>
> Signed-off-by: Johan Hovold 

Reviewed-by: Dmitry Baryshkov 

Minor nit below.

> ---
>  drivers/gpu/drm/bridge/aux-hpd-bridge.c | 67 +++--
>  include/drm/bridge/aux-bridge.h | 15 ++
>  2 files changed, 67 insertions(+), 15 deletions(-)
>
> diff --git a/drivers/gpu/drm/bridge/aux-hpd-bridge.c 
> b/drivers/gpu/drm/bridge/aux-hpd-bridge.c
> index 9e71daf95bde..6886db2d9e00 100644
> --- a/drivers/gpu/drm/bridge/aux-hpd-bridge.c
> +++ b/drivers/gpu/drm/bridge/aux-hpd-bridge.c
> @@ -30,16 +30,13 @@ static void drm_aux_hpd_bridge_release(struct device *dev)
> kfree(adev);
>  }
>
> -static void drm_aux_hpd_bridge_unregister_adev(void *_adev)
> +static void drm_aux_hpd_bridge_free_adev(void *_adev)
>  {
> -   struct auxiliary_device *adev = _adev;
> -
> -   auxiliary_device_delete(adev);
> -   auxiliary_device_uninit(adev);
> +   auxiliary_device_uninit(_adev);
>  }
>
>  /**
> - * drm_dp_hpd_bridge_register - Create a simple HPD DisplayPort bridge
> + * devm_drm_dp_hpd_bridge_alloc - allocate a HPD DisplayPort bridge
>   * @parent: device instance providing this bridge
>   * @np: device node pointer corresponding to this bridge instance
>   *
> @@ -47,11 +44,9 @@ static void drm_aux_hpd_bridge_unregister_adev(void *_adev)
>   * DRM_MODE_CONNECTOR_DisplayPort, which terminates the bridge chain and is
>   * able to send the HPD events.
>   *
> - * Return: device instance that will handle created bridge or an error code
> - * encoded into the pointer.
> + * Return: bridge auxiliary device pointer or an error pointer
>   */
> -struct device *drm_dp_hpd_bridge_register(struct device *parent,
> - struct device_node *np)
> +struct auxiliary_device *devm_drm_dp_hpd_bridge_alloc(struct device *parent, 
> struct device_node *np)
>  {
> struct auxiliary_device *adev;
> int ret;
> @@ -82,13 +77,55 @@ struct device *drm_dp_hpd_bridge_register(struct device 
> *parent,
> return ERR_PTR(ret);
> }
>
> -   ret = auxiliary_device_add(adev);
> -   if (ret) {
> -   auxiliary_device_uninit(adev);
> +   ret = devm_add_action_or_reset(parent, drm_aux_hpd_bridge_free_adev, 
> adev);
> +   if (ret)
> return ERR_PTR(ret);
> -   }
>
> -   ret = devm_add_action_or_reset(parent, 
> drm_aux_hpd_bridge_unregister_adev, adev);
> +   return adev;
> +}
> +EXPORT_SYMBOL_GPL(devm_drm_dp_hpd_bridge_alloc);
> +
> +static void drm_aux_hpd_bridge_del_adev(void *_adev)
> +{
> +   auxiliary_device_delete(_adev);
> +}
> +
> +/**
> + * devm_drm_dp_hpd_bridge_add - register a HDP DisplayPort bridge
> + * @dev: struct device to tie registration lifetime to
> + * @adev: bridge auxiliary device to be registered
> + *
> + * Returns: zero on success or a negative errno
> + */
> +int devm_drm_dp_hpd_bridge_add(struct device *dev, struct auxiliary_device 
> *adev)
> +{
> +   int ret;
> +
> +   ret = auxiliary_device_add(adev);
> +   if (ret)
> +   return ret;
> +
> +   return devm_add_action_or_reset(dev, drm_aux_hpd_bridge_del_adev, 
> adev);
> +}
> +EXPORT_SYMBOL_GPL(devm_drm_dp_hpd_bridge_add);
> +
> +/**
> + * drm_dp_hpd_bridge_register - allocate and register a HDP DisplayPort 
> bridge
> + * @parent: device instance providing this bridge
> + * @np: device node pointer corresponding to this bridge instance
> + *
> + * Return: device instance that will handle created bridge or an error 
> pointer
> + */
> +struct device *drm_dp_hpd_bridge_register(struct device *parent, struct 
> device_node *np)
> +{
> +   struct auxiliary_device *adev;
> +   int ret;
> +
> +   adev = devm_drm_dp_hpd_bridge_alloc(parent, np);
> +   if (IS_ERR(adev))
> +   return ERR_CAST(adev);
> +
> +   ret = devm_drm_dp_hpd_bridge_add(parent, adev);
> if (ret)
> return ERR_PTR(ret);
>
> diff --git a/include/drm/bridge/aux-bridge.h b/include/drm/bridge/aux-bridge.h
> index c4c423e97f06..4453906105ca 100644
> --- a/include/drm/bridge/aux-bridge.h
> +++ b/include/drm/bridge/aux-bridge.h
> @@ -9,6 +9,8 @@
>
>  #include 
>
> +struct auxiliary_device;
> +
>  #if IS_ENABLED(CONFIG_DRM_AUX_BRIDGE)
>  int drm_aux_bridge_register(struct device *parent);
>  #else
> @@ -19,10 

Re: [PATCH 3/3] drm/sun4i: Fix layer zpos change/atomic modesetting

2024-02-22 Thread Jernej Škrabec
Dne sreda, 21. februar 2024 ob 14:45:20 CET je Maxime Ripard napisal(a):
> Hi,
> 
> On Fri, Feb 16, 2024 at 08:04:26PM +0100, Ondřej Jirman wrote:
> > From: Ondrej Jirman 
> > 
> > Identical configurations of planes can lead to different (and wrong)
> > layer -> pipe routing at HW level, depending on the order of atomic
> > plane changes.
> > 
> > For example:
> > 
> > - Layer 1 is configured to zpos 0 and thus uses pipe 0. No other layer
> >   is enabled. This is a typical situation at boot.
> > 
> > - When a compositor takes over and layer 3 is enabled,
> >   sun8i_ui_layer_enable() will get called with old_zpos=0 zpos=1, which
> >   will lead to incorrect disabling of pipe 0 and enabling of pipe 1.
> > 
> > What happens is that sun8i_ui_layer_enable() function may disable
> > blender pipes even if it is no longer assigned to its layer.
> > 
> > To correct this, move the routing setup out of individual plane's
> > atomic_update into crtc's atomic_update, where it can be calculated
> > and updated all at once.
> > 
> > Remove the atomic_disable callback because it is no longer needed.
> > 
> > Signed-off-by: Ondrej Jirman 
> 
> I don't have enough knowledge about the mixers code to comment on your
> patch, so I'll let Jernej review it. However, this feels to me like the
> pipe assignment is typically the sort of things that should be dealt
> with device-wide, and in atomic_check.

In DE2 and DE3.0, you cannot move planes between mixers (crtcs), because each
one is hardwired to specific mixer. Movable planes are the feature of DE3.3
and one of the pain points for upstreaming the code. Anyway, this commit only
addresses current issue of enabling and disabling planes and handling zpos.

In atomic check you can only precalculate final register values, but I don't
see any benefit doing that. I think that this code elegantly solves current
issue of enabling or disabling wrong plane in certain situations, so:

Reviewed-by: Jernej Skrabec 

Note, if there is new revision, please rewrite blender regmap_update_bits()
to regmap_write(). Since there is HW issue with reads, I would like to
get rid of regmap_update_bits() calls eventually.

Best regards,
Jernej

> 
> If I'm talking non-sense, it would be great to mention at least why that
> can't be an option in the commit log.
> 
> Maxime
> 






[pull] amdgpu drm-fixes-6.8

2024-02-22 Thread Alex Deucher
Hi Dave, Sima,

Fixes for 6.8.

The following changes since commit b401b621758e46812da61fa58a67c3fd8d91de0d:

  Linux 6.8-rc5 (2024-02-18 12:56:25 -0800)

are available in the Git repository at:

  https://gitlab.freedesktop.org/agd5f/linux.git 
tags/amd-drm-fixes-6.8-2024-02-22

for you to fetch changes up to bbfaf2aea7164db59739728d62d9cc91d64ff856:

  drm/amdgpu: Fix the runtime resume failure issue (2024-02-22 12:28:27 -0500)


amd-drm-fixes-6.8-2024-02-22:

amdgpu:
- Suspend/resume fixes
- Backlight error fix
- DCN 3.5 fixes
- Misc fixes


Armin Wolf (1):
  drm/amd/display: Fix memory leak in dm_sw_fini()

Lewis Huang (1):
  drm/amd/display: Only allow dig mapping to pwrseq in new asic

Ma Jun (1):
  drm/amdgpu: Fix the runtime resume failure issue

Melissa Wen (1):
  drm/amd/display: fix null-pointer dereference on edid reading

Srinivasan Shanmugam (1):
  drm/amd/display: Fix potential null pointer dereference in dc_dmub_srv

Swapnil Patel (1):
  drm/amd/display: fix input states translation error for dcn35 & dcn351

Wayne Lin (1):
  drm/amd/display: adjust few initialization order in dm

 drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c   |  3 ++
 drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c  | 57 +-
 drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c   |  7 ++-
 .../gpu/drm/amd/display/dc/dce/dce_panel_cntl.c|  1 +
 .../drm/amd/display/dc/dcn301/dcn301_panel_cntl.c  |  1 +
 .../drm/amd/display/dc/dcn31/dcn31_panel_cntl.c| 18 ++-
 .../amd/display/dc/dml2/dml2_translation_helper.c  |  9 +++-
 drivers/gpu/drm/amd/display/dc/inc/hw/panel_cntl.h |  2 +-
 drivers/gpu/drm/amd/display/dc/link/link_factory.c | 26 +-
 9 files changed, 71 insertions(+), 53 deletions(-)


[PATCH v5 06/19] drm/msm/dp: rename wide_bus_en to wide_bus_supported

2024-02-22 Thread Paloma Arellano
Rename wide_bus_en to wide_bus_supported in dp_display_private to
correctly establish that the parameter is referencing if wide bus is
supported instead of enabled.

Signed-off-by: Paloma Arellano 
Reviewed-by: Dmitry Baryshkov 
---
 drivers/gpu/drm/msm/dp/dp_display.c | 42 ++---
 1 file changed, 21 insertions(+), 21 deletions(-)

diff --git a/drivers/gpu/drm/msm/dp/dp_display.c 
b/drivers/gpu/drm/msm/dp/dp_display.c
index c8e1bbebdffe2..792191f67717f 100644
--- a/drivers/gpu/drm/msm/dp/dp_display.c
+++ b/drivers/gpu/drm/msm/dp/dp_display.c
@@ -114,7 +114,7 @@ struct dp_display_private {
struct dp_event event_list[DP_EVENT_Q_MAX];
spinlock_t event_lock;
 
-   bool wide_bus_en;
+   bool wide_bus_supported;
 
struct dp_audio *audio;
 };
@@ -123,7 +123,7 @@ struct msm_dp_desc {
phys_addr_t io_start;
unsigned int id;
unsigned int connector_type;
-   bool wide_bus_en;
+   bool wide_bus_supported;
 };
 
 static const struct msm_dp_desc sc7180_dp_descs[] = {
@@ -132,8 +132,8 @@ static const struct msm_dp_desc sc7180_dp_descs[] = {
 };
 
 static const struct msm_dp_desc sc7280_dp_descs[] = {
-   { .io_start = 0x0ae9, .id = MSM_DP_CONTROLLER_0, .connector_type = 
DRM_MODE_CONNECTOR_DisplayPort, .wide_bus_en = true },
-   { .io_start = 0x0aea, .id = MSM_DP_CONTROLLER_1, .connector_type = 
DRM_MODE_CONNECTOR_eDP, .wide_bus_en = true },
+   { .io_start = 0x0ae9, .id = MSM_DP_CONTROLLER_0, .connector_type = 
DRM_MODE_CONNECTOR_DisplayPort, .wide_bus_supported = true },
+   { .io_start = 0x0aea, .id = MSM_DP_CONTROLLER_1, .connector_type = 
DRM_MODE_CONNECTOR_eDP, .wide_bus_supported = true },
{}
 };
 
@@ -145,22 +145,22 @@ static const struct msm_dp_desc sc8180x_dp_descs[] = {
 };
 
 static const struct msm_dp_desc sc8280xp_dp_descs[] = {
-   { .io_start = 0x0ae9, .id = MSM_DP_CONTROLLER_0, .connector_type = 
DRM_MODE_CONNECTOR_DisplayPort, .wide_bus_en = true },
-   { .io_start = 0x0ae98000, .id = MSM_DP_CONTROLLER_1, .connector_type = 
DRM_MODE_CONNECTOR_DisplayPort, .wide_bus_en = true },
-   { .io_start = 0x0ae9a000, .id = MSM_DP_CONTROLLER_2, .connector_type = 
DRM_MODE_CONNECTOR_DisplayPort, .wide_bus_en = true },
-   { .io_start = 0x0aea, .id = MSM_DP_CONTROLLER_3, .connector_type = 
DRM_MODE_CONNECTOR_DisplayPort, .wide_bus_en = true },
-   { .io_start = 0x2209, .id = MSM_DP_CONTROLLER_0, .connector_type = 
DRM_MODE_CONNECTOR_DisplayPort, .wide_bus_en = true },
-   { .io_start = 0x22098000, .id = MSM_DP_CONTROLLER_1, .connector_type = 
DRM_MODE_CONNECTOR_DisplayPort, .wide_bus_en = true },
-   { .io_start = 0x2209a000, .id = MSM_DP_CONTROLLER_2, .connector_type = 
DRM_MODE_CONNECTOR_DisplayPort, .wide_bus_en = true },
-   { .io_start = 0x220a, .id = MSM_DP_CONTROLLER_3, .connector_type = 
DRM_MODE_CONNECTOR_DisplayPort, .wide_bus_en = true },
+   { .io_start = 0x0ae9, .id = MSM_DP_CONTROLLER_0, .connector_type = 
DRM_MODE_CONNECTOR_DisplayPort, .wide_bus_supported = true },
+   { .io_start = 0x0ae98000, .id = MSM_DP_CONTROLLER_1, .connector_type = 
DRM_MODE_CONNECTOR_DisplayPort, .wide_bus_supported = true },
+   { .io_start = 0x0ae9a000, .id = MSM_DP_CONTROLLER_2, .connector_type = 
DRM_MODE_CONNECTOR_DisplayPort, .wide_bus_supported = true },
+   { .io_start = 0x0aea, .id = MSM_DP_CONTROLLER_3, .connector_type = 
DRM_MODE_CONNECTOR_DisplayPort, .wide_bus_supported = true },
+   { .io_start = 0x2209, .id = MSM_DP_CONTROLLER_0, .connector_type = 
DRM_MODE_CONNECTOR_DisplayPort, .wide_bus_supported = true },
+   { .io_start = 0x22098000, .id = MSM_DP_CONTROLLER_1, .connector_type = 
DRM_MODE_CONNECTOR_DisplayPort, .wide_bus_supported = true },
+   { .io_start = 0x2209a000, .id = MSM_DP_CONTROLLER_2, .connector_type = 
DRM_MODE_CONNECTOR_DisplayPort, .wide_bus_supported = true },
+   { .io_start = 0x220a, .id = MSM_DP_CONTROLLER_3, .connector_type = 
DRM_MODE_CONNECTOR_DisplayPort, .wide_bus_supported = true },
{}
 };
 
 static const struct msm_dp_desc sc8280xp_edp_descs[] = {
-   { .io_start = 0x0ae9a000, .id = MSM_DP_CONTROLLER_2, .connector_type = 
DRM_MODE_CONNECTOR_eDP, .wide_bus_en = true },
-   { .io_start = 0x0aea, .id = MSM_DP_CONTROLLER_3, .connector_type = 
DRM_MODE_CONNECTOR_eDP, .wide_bus_en = true },
-   { .io_start = 0x2209a000, .id = MSM_DP_CONTROLLER_2, .connector_type = 
DRM_MODE_CONNECTOR_eDP, .wide_bus_en = true },
-   { .io_start = 0x220a, .id = MSM_DP_CONTROLLER_3, .connector_type = 
DRM_MODE_CONNECTOR_eDP, .wide_bus_en = true },
+   { .io_start = 0x0ae9a000, .id = MSM_DP_CONTROLLER_2, .connector_type = 
DRM_MODE_CONNECTOR_eDP, .wide_bus_supported = true },
+   { .io_start = 0x0aea, .id = MSM_DP_CONTROLLER_3, .connector_type = 
DRM_MODE_CONNECTOR_eDP, .wide_bus_supported = true },
+   { .io_start = 0x2209a000, .id = 

[PATCH v5 10/19] drm/msm/dp: program config ctrl for YUV420 over DP

2024-02-22 Thread Paloma Arellano
Change relevant DP controller related programming for YUV420 cases.
Program the configuration control register to indicate YUV420.

Changes in v2:
- Create a new patch only for configuration control programming

Signed-off-by: Paloma Arellano 
Reviewed-by: Dmitry Baryshkov 
---
 drivers/gpu/drm/msm/dp/dp_ctrl.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/gpu/drm/msm/dp/dp_ctrl.c b/drivers/gpu/drm/msm/dp/dp_ctrl.c
index fb588fde298a2..6692d81adb195 100644
--- a/drivers/gpu/drm/msm/dp/dp_ctrl.c
+++ b/drivers/gpu/drm/msm/dp/dp_ctrl.c
@@ -128,6 +128,9 @@ static void dp_ctrl_config_ctrl(struct dp_ctrl_private 
*ctrl)
/* Default-> LSCLK DIV: 1/4 LCLK  */
config |= (2 << DP_CONFIGURATION_CTRL_LSCLK_DIV_SHIFT);
 
+   if (ctrl->panel->dp_mode.out_fmt_is_yuv_420)
+   config |= DP_CONFIGURATION_CTRL_RGB_YUV; /* YUV420 */
+
/* Scrambler reset enable */
if (drm_dp_alternate_scrambler_reset_cap(dpcd))
config |= DP_CONFIGURATION_CTRL_ASSR;
-- 
2.39.2



[PATCH v5 19/19] drm/msm/dp: allow YUV420 mode for DP connector when CDM available

2024-02-22 Thread Paloma Arellano
All the components of YUV420 over DP are added. Therefore, let's mark the
connector property as true for DP connector when the DP type is not eDP
and when there is a CDM block available.

Changes in v3:
- Move setting the connector's ycbcr_420_allowed parameter so
  that it is not dependent on if the dp_display is not eDP

Changes in v2:
- Check for if dp_catalog has a CDM block available instead of
  checking if VSC SDP is allowed when setting the dp connector's
  ycbcr_420_allowed parameter

Signed-off-by: Paloma Arellano 
Reviewed-by: Dmitry Baryshkov 
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 4 +++-
 drivers/gpu/drm/msm/dp/dp_display.c | 4 ++--
 drivers/gpu/drm/msm/dp/dp_drm.c | 6 +-
 drivers/gpu/drm/msm/dp/dp_drm.h | 3 ++-
 drivers/gpu/drm/msm/msm_drv.h   | 5 +++--
 5 files changed, 15 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
index 723cc1d821431..8d326fb36550a 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
@@ -565,6 +565,7 @@ static int _dpu_kms_initialize_displayport(struct 
drm_device *dev,
 {
struct drm_encoder *encoder = NULL;
struct msm_display_info info;
+   bool yuv_supported;
int rc;
int i;
 
@@ -583,7 +584,8 @@ static int _dpu_kms_initialize_displayport(struct 
drm_device *dev,
return PTR_ERR(encoder);
}
 
-   rc = msm_dp_modeset_init(priv->dp[i], dev, encoder);
+   yuv_supported = !!dpu_kms->catalog->cdm;
+   rc = msm_dp_modeset_init(priv->dp[i], dev, encoder, 
yuv_supported);
if (rc) {
DPU_ERROR("modeset_init failed for DP, rc = %d\n", rc);
return rc;
diff --git a/drivers/gpu/drm/msm/dp/dp_display.c 
b/drivers/gpu/drm/msm/dp/dp_display.c
index b5a67835ce6d1..a435847f1d948 100644
--- a/drivers/gpu/drm/msm/dp/dp_display.c
+++ b/drivers/gpu/drm/msm/dp/dp_display.c
@@ -1472,7 +1472,7 @@ static int dp_display_get_next_bridge(struct msm_dp *dp)
 }
 
 int msm_dp_modeset_init(struct msm_dp *dp_display, struct drm_device *dev,
-   struct drm_encoder *encoder)
+   struct drm_encoder *encoder, bool yuv_supported)
 {
struct dp_display_private *dp_priv;
int ret;
@@ -1488,7 +1488,7 @@ int msm_dp_modeset_init(struct msm_dp *dp_display, struct 
drm_device *dev,
return ret;
}
 
-   dp_display->connector = dp_drm_connector_init(dp_display, encoder);
+   dp_display->connector = dp_drm_connector_init(dp_display, encoder, 
yuv_supported);
if (IS_ERR(dp_display->connector)) {
ret = PTR_ERR(dp_display->connector);
DRM_DEV_ERROR(dev->dev,
diff --git a/drivers/gpu/drm/msm/dp/dp_drm.c b/drivers/gpu/drm/msm/dp/dp_drm.c
index 46e6889037e88..a819a4ff76a9f 100644
--- a/drivers/gpu/drm/msm/dp/dp_drm.c
+++ b/drivers/gpu/drm/msm/dp/dp_drm.c
@@ -353,7 +353,8 @@ int dp_bridge_init(struct msm_dp *dp_display, struct 
drm_device *dev,
 }
 
 /* connector initialization */
-struct drm_connector *dp_drm_connector_init(struct msm_dp *dp_display, struct 
drm_encoder *encoder)
+struct drm_connector *dp_drm_connector_init(struct msm_dp *dp_display, struct 
drm_encoder *encoder,
+   bool yuv_supported)
 {
struct drm_connector *connector = NULL;
 
@@ -364,6 +365,9 @@ struct drm_connector *dp_drm_connector_init(struct msm_dp 
*dp_display, struct dr
if (!dp_display->is_edp)
drm_connector_attach_dp_subconnector_property(connector);
 
+   if (yuv_supported)
+   connector->ycbcr_420_allowed = true;
+
drm_connector_attach_encoder(connector, encoder);
 
return connector;
diff --git a/drivers/gpu/drm/msm/dp/dp_drm.h b/drivers/gpu/drm/msm/dp/dp_drm.h
index b3d684db2383b..45e57ac25a4d9 100644
--- a/drivers/gpu/drm/msm/dp/dp_drm.h
+++ b/drivers/gpu/drm/msm/dp/dp_drm.h
@@ -19,7 +19,8 @@ struct msm_dp_bridge {
 
 #define to_dp_bridge(x) container_of((x), struct msm_dp_bridge, bridge)
 
-struct drm_connector *dp_drm_connector_init(struct msm_dp *dp_display, struct 
drm_encoder *encoder);
+struct drm_connector *dp_drm_connector_init(struct msm_dp *dp_display, struct 
drm_encoder *encoder,
+   bool yuv_supported);
 int dp_bridge_init(struct msm_dp *dp_display, struct drm_device *dev,
struct drm_encoder *encoder);
 
diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h
index b876ebd48effe..37335777f5c09 100644
--- a/drivers/gpu/drm/msm/msm_drv.h
+++ b/drivers/gpu/drm/msm/msm_drv.h
@@ -385,7 +385,7 @@ static inline struct drm_dsc_config 
*msm_dsi_get_dsc_config(struct msm_dsi *msm_
 int __init msm_dp_register(void);
 void __exit msm_dp_unregister(void);
 

[PATCH v5 08/19] drm/msm/dp: check if VSC SDP is supported in DP programming

2024-02-22 Thread Paloma Arellano
In the DP driver, check if VSC SDP is supported and propagate this value
to dp_panel. In dp_display's dp_mode, the out_fmt_is_yuv_420 parameter
must also utilize this value since YUV420 is only allowed when VSC SDP
is supported.

Changes in v2:
- Move DP programming when VSC SDP is supported to this patch

Signed-off-by: Paloma Arellano 
Reviewed-by: Dmitry Baryshkov 
---
 drivers/gpu/drm/msm/dp/dp_display.c | 5 -
 drivers/gpu/drm/msm/dp/dp_panel.c   | 1 +
 drivers/gpu/drm/msm/dp/dp_panel.h   | 1 +
 3 files changed, 6 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/msm/dp/dp_display.c 
b/drivers/gpu/drm/msm/dp/dp_display.c
index 1a84f68e2b59a..4b1b79b74bc72 100644
--- a/drivers/gpu/drm/msm/dp/dp_display.c
+++ b/drivers/gpu/drm/msm/dp/dp_display.c
@@ -1596,8 +1596,10 @@ void dp_bridge_mode_set(struct drm_bridge *drm_bridge,
struct msm_dp_bridge *dp_bridge = to_dp_bridge(drm_bridge);
struct msm_dp *dp = dp_bridge->dp_display;
struct dp_display_private *dp_display;
+   struct dp_panel *dp_panel;
 
dp_display = container_of(dp, struct dp_display_private, dp_display);
+   dp_panel = dp_display->panel;
 
memset(_display->dp_mode, 0x0, sizeof(struct dp_display_mode));
 
@@ -1618,7 +1620,8 @@ void dp_bridge_mode_set(struct drm_bridge *drm_bridge,
!!(dp_display->dp_mode.drm_mode.flags & DRM_MODE_FLAG_NHSYNC);
 
dp_display->dp_mode.out_fmt_is_yuv_420 =
-   drm_mode_is_420_only(>connector->display_info, 
adjusted_mode);
+   drm_mode_is_420_only(>connector->display_info, 
adjusted_mode) &&
+   dp_panel->vsc_sdp_supported;
 
/* populate wide_bus_support to different layers */
dp_display->ctrl->wide_bus_en =
diff --git a/drivers/gpu/drm/msm/dp/dp_panel.c 
b/drivers/gpu/drm/msm/dp/dp_panel.c
index 127f6af995cd1..db1942794f1a4 100644
--- a/drivers/gpu/drm/msm/dp/dp_panel.c
+++ b/drivers/gpu/drm/msm/dp/dp_panel.c
@@ -53,6 +53,7 @@ static int dp_panel_read_dpcd(struct dp_panel *dp_panel)
if (rc)
return rc;
 
+   dp_panel->vsc_sdp_supported = drm_dp_vsc_sdp_supported(panel->aux, 
dpcd);
link_info = _panel->link_info;
link_info->revision = dpcd[DP_DPCD_REV];
major = (link_info->revision >> 4) & 0x0f;
diff --git a/drivers/gpu/drm/msm/dp/dp_panel.h 
b/drivers/gpu/drm/msm/dp/dp_panel.h
index 6ec68be9f2366..e843f5062d1f6 100644
--- a/drivers/gpu/drm/msm/dp/dp_panel.h
+++ b/drivers/gpu/drm/msm/dp/dp_panel.h
@@ -46,6 +46,7 @@ struct dp_panel {
struct dp_display_mode dp_mode;
struct dp_panel_psr psr_cap;
bool video_test;
+   bool vsc_sdp_supported;
 
u32 vic;
u32 max_dp_lanes;
-- 
2.39.2



[PATCH v5 14/19] drm/msm/dpu: add support of new peripheral flush mechanism

2024-02-22 Thread Paloma Arellano
From: Kuogee Hsieh 

Introduce a peripheral flushing mechanism to decouple peripheral
metadata flushing from timing engine related flush.

Changes in v2:
- Fixed some misalignment issues

Signed-off-by: Kuogee Hsieh 
Signed-off-by: Paloma Arellano 
Reviewed-by: Dmitry Baryshkov 
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c | 17 +
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h | 10 ++
 2 files changed, 27 insertions(+)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c
index e76565c3e6a43..a06f69d0b257d 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c
@@ -39,6 +39,7 @@
 #define   CTL_WB_FLUSH  0x108
 #define   CTL_INTF_FLUSH0x110
 #define   CTL_CDM_FLUSH0x114
+#define   CTL_PERIPH_FLUSH  0x128
 #define   CTL_INTF_MASTER   0x134
 #define   CTL_DSPP_n_FLUSH(n)   ((0x13C) + ((n) * 4))
 
@@ -49,6 +50,7 @@
 #define  MERGE_3D_IDX   23
 #define  DSC_IDX22
 #define CDM_IDX 26
+#define  PERIPH_IDX 30
 #define  INTF_IDX   31
 #define WB_IDX  16
 #define  DSPP_IDX   29  /* From DPU hw rev 7.x.x */
@@ -151,6 +153,10 @@ static inline void dpu_hw_ctl_trigger_flush_v1(struct 
dpu_hw_ctl *ctx)
ctx->pending_dspp_flush_mask[dspp - DSPP_0]);
}
 
+   if (ctx->pending_flush_mask & BIT(PERIPH_IDX))
+   DPU_REG_WRITE(>hw, CTL_PERIPH_FLUSH,
+ ctx->pending_periph_flush_mask);
+
if (ctx->pending_flush_mask & BIT(DSC_IDX))
DPU_REG_WRITE(>hw, CTL_DSC_FLUSH,
  ctx->pending_dsc_flush_mask);
@@ -311,6 +317,13 @@ static void dpu_hw_ctl_update_pending_flush_intf_v1(struct 
dpu_hw_ctl *ctx,
ctx->pending_flush_mask |= BIT(INTF_IDX);
 }
 
+static void dpu_hw_ctl_update_pending_flush_periph_v1(struct dpu_hw_ctl *ctx,
+ enum dpu_intf intf)
+{
+   ctx->pending_periph_flush_mask |= BIT(intf - INTF_0);
+   ctx->pending_flush_mask |= BIT(PERIPH_IDX);
+}
+
 static void dpu_hw_ctl_update_pending_flush_merge_3d_v1(struct dpu_hw_ctl *ctx,
enum dpu_merge_3d merge_3d)
 {
@@ -680,6 +693,10 @@ static void _setup_ctl_ops(struct dpu_hw_ctl_ops *ops,
ops->reset_intf_cfg = dpu_hw_ctl_reset_intf_cfg_v1;
ops->update_pending_flush_intf =
dpu_hw_ctl_update_pending_flush_intf_v1;
+
+   ops->update_pending_flush_periph =
+   dpu_hw_ctl_update_pending_flush_periph_v1;
+
ops->update_pending_flush_merge_3d =
dpu_hw_ctl_update_pending_flush_merge_3d_v1;
ops->update_pending_flush_wb = 
dpu_hw_ctl_update_pending_flush_wb_v1;
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h
index ff85b5ee0acf8..ef56280bea932 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h
@@ -122,6 +122,15 @@ struct dpu_hw_ctl_ops {
void (*update_pending_flush_intf)(struct dpu_hw_ctl *ctx,
enum dpu_intf blk);
 
+   /**
+* OR in the given flushbits to the cached pending_(periph_)flush_mask
+* No effect on hardware
+* @ctx   : ctl path ctx pointer
+* @blk   : interface block index
+*/
+   void (*update_pending_flush_periph)(struct dpu_hw_ctl *ctx,
+   enum dpu_intf blk);
+
/**
 * OR in the given flushbits to the cached pending_(merge_3d_)flush_mask
 * No effect on hardware
@@ -264,6 +273,7 @@ struct dpu_hw_ctl {
u32 pending_flush_mask;
u32 pending_intf_flush_mask;
u32 pending_wb_flush_mask;
+   u32 pending_periph_flush_mask;
u32 pending_merge_3d_flush_mask;
u32 pending_dspp_flush_mask[DSPP_MAX - DSPP_0];
u32 pending_dsc_flush_mask;
-- 
2.39.2



[PATCH v5 09/19] drm/msm/dpu: move widebus logic to its own API

2024-02-22 Thread Paloma Arellano
Widebus enablement is decided by the interfaces based on their specific
checks and that already happens with DSI/DP specific helpers. Let's
invoke these helpers from dpu_encoder_is_widebus_enabled() to make it
cleaner overall.

Signed-off-by: Paloma Arellano 
Reviewed-by: Dmitry Baryshkov 
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 29 -
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h |  4 +++
 2 files changed, 20 insertions(+), 13 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
index 1905e8653b77a..b53a1b545742b 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
@@ -221,9 +221,21 @@ static u32 dither_matrix[DITHER_MATRIX_SZ] = {
 
 bool dpu_encoder_is_widebus_enabled(const struct drm_encoder *drm_enc)
 {
-   const struct dpu_encoder_virt *dpu_enc = to_dpu_encoder_virt(drm_enc);
+   const struct dpu_encoder_virt *dpu_enc;
+   struct msm_drm_private *priv = drm_enc->dev->dev_private;
+   const struct msm_display_info *disp_info;
+   int index;
+
+   dpu_enc = to_dpu_encoder_virt(drm_enc);
+   disp_info = _enc->disp_info;
+   index = disp_info->h_tile_instance[0];
+
+   if (disp_info->intf_type == INTF_DP)
+   return msm_dp_wide_bus_available(priv->dp[index]);
+   else if (disp_info->intf_type == INTF_DSI)
+   return msm_dsi_wide_bus_enabled(priv->dsi[index]);
 
-   return dpu_enc->wide_bus_en;
+   return false;
 }
 
 bool dpu_encoder_is_dsc_enabled(const struct drm_encoder *drm_enc)
@@ -1195,26 +1207,17 @@ static void dpu_encoder_virt_atomic_enable(struct 
drm_encoder *drm_enc,
struct dpu_encoder_virt *dpu_enc = NULL;
int ret = 0;
struct drm_display_mode *cur_mode = NULL;
-   struct msm_drm_private *priv = drm_enc->dev->dev_private;
-   struct msm_display_info *disp_info;
-   int index;
 
dpu_enc = to_dpu_encoder_virt(drm_enc);
-   disp_info = _enc->disp_info;
-   index = disp_info->h_tile_instance[0];
-
dpu_enc->dsc = dpu_encoder_get_dsc_config(drm_enc);
 
atomic_set(_enc->frame_done_timeout_cnt, 0);
 
-   if (disp_info->intf_type == INTF_DP)
-   dpu_enc->wide_bus_en = 
msm_dp_wide_bus_available(priv->dp[index]);
-   else if (disp_info->intf_type == INTF_DSI)
-   dpu_enc->wide_bus_en = 
msm_dsi_wide_bus_enabled(priv->dsi[index]);
-
mutex_lock(_enc->enc_lock);
cur_mode = _enc->base.crtc->state->adjusted_mode;
 
+   dpu_enc->wide_bus_en = dpu_encoder_is_widebus_enabled(drm_enc);
+
trace_dpu_enc_enable(DRMID(drm_enc), cur_mode->hdisplay,
 cur_mode->vdisplay);
 
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h
index fe6b1d312a742..67aef59c1f99c 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h
@@ -156,6 +156,10 @@ int dpu_encoder_get_linecount(struct drm_encoder *drm_enc);
  */
 int dpu_encoder_get_vsync_count(struct drm_encoder *drm_enc);
 
+/**
+ * dpu_encoder_is_widebus_enabled - return bool value if widebus is enabled
+ * @drm_enc:Pointer to previously created drm encoder structure
+ */
 bool dpu_encoder_is_widebus_enabled(const struct drm_encoder *drm_enc);
 
 /**
-- 
2.39.2



[PATCH v5 18/19] drm/msm/dpu: reserve CDM blocks for DP if mode is YUV420

2024-02-22 Thread Paloma Arellano
Reserve CDM blocks for DP if the mode format is YUV420. Currently this
reservation only works for writeback and DP if the format is YUV420. But
this can be easily extented to other YUV formats for DP.

Changes in v2:
- Minor code simplification

Signed-off-by: Paloma Arellano 
Reviewed-by: Dmitry Baryshkov 
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 22 +
 1 file changed, 14 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
index 84778adc7f791..e636215c8f834 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
@@ -635,6 +635,7 @@ static int dpu_encoder_virt_atomic_check(
struct dpu_kms *dpu_kms;
struct drm_display_mode *adj_mode;
struct msm_display_topology topology;
+   struct msm_display_info *disp_info;
struct dpu_global_state *global_state;
struct drm_framebuffer *fb;
struct drm_dsc_config *dsc;
@@ -651,6 +652,7 @@ static int dpu_encoder_virt_atomic_check(
DPU_DEBUG_ENC(dpu_enc, "\n");
 
priv = drm_enc->dev->dev_private;
+   disp_info = _enc->disp_info;
dpu_kms = to_dpu_kms(priv->kms);
adj_mode = _state->adjusted_mode;
global_state = dpu_kms_get_global_state(crtc_state->state);
@@ -678,21 +680,24 @@ static int dpu_encoder_virt_atomic_check(
topology = dpu_encoder_get_topology(dpu_enc, dpu_kms, adj_mode, 
crtc_state, dsc);
 
/*
-* Use CDM only for writeback at the moment as other interfaces cannot 
handle it.
-* if writeback itself cannot handle cdm for some reason it will fail 
in its atomic_check()
+* Use CDM only for writeback or DP at the moment as other interfaces 
cannot handle it.
+* If writeback itself cannot handle cdm for some reason it will fail 
in its atomic_check()
 * earlier.
 */
-   if (dpu_enc->disp_info.intf_type == INTF_WB && 
conn_state->writeback_job) {
+   if (disp_info->intf_type == INTF_WB && conn_state->writeback_job) {
fb = conn_state->writeback_job->fb;
 
if (fb && 
DPU_FORMAT_IS_YUV(to_dpu_format(msm_framebuffer_format(fb
topology.needs_cdm = true;
-   if (topology.needs_cdm && !dpu_enc->cur_master->hw_cdm)
-   crtc_state->mode_changed = true;
-   else if (!topology.needs_cdm && dpu_enc->cur_master->hw_cdm)
-   crtc_state->mode_changed = true;
+   } else if (disp_info->intf_type == INTF_DP) {
+   if 
(msm_dp_is_yuv_420_enabled(priv->dp[disp_info->h_tile_instance[0]], adj_mode))
+   topology.needs_cdm = true;
}
 
+   if (topology.needs_cdm && !dpu_enc->cur_master->hw_cdm)
+   crtc_state->mode_changed = true;
+   else if (!topology.needs_cdm && dpu_enc->cur_master->hw_cdm)
+   crtc_state->mode_changed = true;
/*
 * Release and Allocate resources on every modeset
 * Dont allocate when active is false.
@@ -1133,7 +1138,8 @@ static void dpu_encoder_virt_atomic_mode_set(struct 
drm_encoder *drm_enc,
 
dpu_enc->dsc_mask = dsc_mask;
 
-   if (dpu_enc->disp_info.intf_type == INTF_WB && 
conn_state->writeback_job) {
+   if ((dpu_enc->disp_info.intf_type == INTF_WB && 
conn_state->writeback_job) ||
+   dpu_enc->disp_info.intf_type == INTF_DP) {
struct dpu_hw_blk *hw_cdm = NULL;
 
dpu_rm_get_assigned_resources(_kms->rm, global_state,
-- 
2.39.2



[PATCH v5 16/19] drm/msm/dpu: modify encoder programming for CDM over DP

2024-02-22 Thread Paloma Arellano
Adjust the encoder format programming in the case of video mode for DP
to accommodate CDM related changes.

Changes in v4:
- Remove hw_cdm check in dpu_encoder_needs_periph_flush()
- Remove hw_cdm check when getting the fmt_fourcc in
  dpu_encoder_phys_vid_enable()

Changes in v2:
- Move timing engine programming to a separate patch from this
  one
- Move update_pending_flush_periph() invocation completely to
  this patch
- Change the logic of dpu_encoder_get_drm_fmt() so that it only
  calls drm_mode_is_420_only() instead of doing additional
  unnecessary checks
- Create new functions msm_dp_needs_periph_flush() and it's
  supporting function dpu_encoder_needs_periph_flush() to check
  if the mode is YUV420 and VSC SDP is enabled before doing a
  peripheral flush

Signed-off-by: Paloma Arellano 
Reviewed-by: Dmitry Baryshkov 
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c   | 35 +++
 .../gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h  | 13 +++
 .../drm/msm/disp/dpu1/dpu_encoder_phys_vid.c  | 16 +
 drivers/gpu/drm/msm/dp/dp_display.c   | 18 ++
 drivers/gpu/drm/msm/msm_drv.h | 17 -
 5 files changed, 98 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
index b53a1b545742b..84778adc7f791 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
@@ -218,6 +218,41 @@ static u32 dither_matrix[DITHER_MATRIX_SZ] = {
15, 7, 13, 5, 3, 11, 1, 9, 12, 4, 14, 6, 0, 8, 2, 10
 };
 
+u32 dpu_encoder_get_drm_fmt(struct dpu_encoder_phys *phys_enc)
+{
+   struct drm_encoder *drm_enc;
+   struct dpu_encoder_virt *dpu_enc;
+   struct drm_display_info *info;
+   struct drm_display_mode *mode;
+
+   drm_enc = phys_enc->parent;
+   dpu_enc = to_dpu_encoder_virt(drm_enc);
+   info = _enc->connector->display_info;
+   mode = _enc->cached_mode;
+
+   if (drm_mode_is_420_only(info, mode))
+   return DRM_FORMAT_YUV420;
+
+   return DRM_FORMAT_RGB888;
+}
+
+bool dpu_encoder_needs_periph_flush(struct dpu_encoder_phys *phys_enc)
+{
+   struct drm_encoder *drm_enc;
+   struct dpu_encoder_virt *dpu_enc;
+   struct msm_display_info *disp_info;
+   struct msm_drm_private *priv;
+   struct drm_display_mode *mode;
+
+   drm_enc = phys_enc->parent;
+   dpu_enc = to_dpu_encoder_virt(drm_enc);
+   disp_info = _enc->disp_info;
+   priv = drm_enc->dev->dev_private;
+   mode = _enc->cached_mode;
+
+   return phys_enc->hw_intf->cap->type == INTF_DP &&
+  
msm_dp_needs_periph_flush(priv->dp[disp_info->h_tile_instance[0]], mode);
+}
 
 bool dpu_encoder_is_widebus_enabled(const struct drm_encoder *drm_enc)
 {
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
index f43d57d9c74e1..211a3d90eb690 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
@@ -341,6 +341,19 @@ static inline enum dpu_3d_blend_mode 
dpu_encoder_helper_get_3d_blend_mode(
  */
 unsigned int dpu_encoder_helper_get_dsc(struct dpu_encoder_phys *phys_enc);
 
+/**
+ * dpu_encoder_get_drm_fmt - return DRM fourcc format
+ * @phys_enc: Pointer to physical encoder structure
+ */
+u32 dpu_encoder_get_drm_fmt(struct dpu_encoder_phys *phys_enc);
+
+/**
+ * dpu_encoder_needs_periph_flush - return true if physical encoder requires
+ * peripheral flush
+ * @phys_enc: Pointer to physical encoder structure
+ */
+bool dpu_encoder_needs_periph_flush(struct dpu_encoder_phys *phys_enc);
+
 /**
  * dpu_encoder_helper_split_config - split display configuration helper 
function
  * This helper function may be used by physical encoders to configure
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c
index f02411b062c4c..86c57c8b7e784 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c
@@ -415,8 +415,12 @@ static int dpu_encoder_phys_vid_control_vblank_irq(
 static void dpu_encoder_phys_vid_enable(struct dpu_encoder_phys *phys_enc)
 {
struct dpu_hw_ctl *ctl;
+   const struct dpu_format *fmt;
+   u32 fmt_fourcc;
 
ctl = phys_enc->hw_ctl;
+   fmt_fourcc = dpu_encoder_get_drm_fmt(phys_enc);
+   fmt = dpu_get_dpu_format(fmt_fourcc);
 
DPU_DEBUG_VIDENC(phys_enc, "\n");
 
@@ -425,6 +429,8 @@ static void dpu_encoder_phys_vid_enable(struct 
dpu_encoder_phys *phys_enc)
 
dpu_encoder_helper_split_config(phys_enc, phys_enc->hw_intf->idx);
 
+   dpu_encoder_helper_phys_setup_cdm(phys_enc, fmt, CDM_CDWN_OUTPUT_HDMI);
+
dpu_encoder_phys_vid_setup_timing_engine(phys_enc);
 
   

[PATCH v5 07/19] drm/msm/dp: store mode YUV420 information to be used by rest of DP

2024-02-22 Thread Paloma Arellano
Wide bus is not supported when the mode is YUV420 in DP. In preparation
for changing the DPU programming to reflect this, the value and
assignment location of wide_bus_en for the DP submodules must be
changed. Move it from boot time in dp_init_sub_modules() to run time in
dp_display_mode_set.

Signed-off-by: Paloma Arellano 
Reviewed-by: Dmitry Baryshkov 
---
 drivers/gpu/drm/msm/dp/dp_display.c | 17 +
 drivers/gpu/drm/msm/dp/dp_panel.h   |  1 +
 2 files changed, 14 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/msm/dp/dp_display.c 
b/drivers/gpu/drm/msm/dp/dp_display.c
index 792191f67717f..1a84f68e2b59a 100644
--- a/drivers/gpu/drm/msm/dp/dp_display.c
+++ b/drivers/gpu/drm/msm/dp/dp_display.c
@@ -785,10 +785,6 @@ static int dp_init_sub_modules(struct dp_display_private 
*dp)
goto error_ctrl;
}
 
-   /* populate wide_bus_supported to different layers */
-   dp->ctrl->wide_bus_en = dp->wide_bus_supported;
-   dp->catalog->wide_bus_en = dp->wide_bus_supported;
-
return rc;
 
 error_ctrl:
@@ -809,6 +805,7 @@ static int dp_display_set_mode(struct msm_dp *dp_display,
drm_mode_copy(>panel->dp_mode.drm_mode, >drm_mode);
dp->panel->dp_mode.bpp = mode->bpp;
dp->panel->dp_mode.capabilities = mode->capabilities;
+   dp->panel->dp_mode.out_fmt_is_yuv_420 = mode->out_fmt_is_yuv_420;
dp_panel_init_panel_info(dp->panel);
return 0;
 }
@@ -1403,6 +1400,9 @@ bool msm_dp_wide_bus_available(const struct msm_dp 
*dp_display)
 
dp = container_of(dp_display, struct dp_display_private, dp_display);
 
+   if (dp->dp_mode.out_fmt_is_yuv_420)
+   return false;
+
return dp->wide_bus_supported;
 }
 
@@ -1616,6 +1616,15 @@ void dp_bridge_mode_set(struct drm_bridge *drm_bridge,
 
dp_display->dp_mode.h_active_low =
!!(dp_display->dp_mode.drm_mode.flags & DRM_MODE_FLAG_NHSYNC);
+
+   dp_display->dp_mode.out_fmt_is_yuv_420 =
+   drm_mode_is_420_only(>connector->display_info, 
adjusted_mode);
+
+   /* populate wide_bus_support to different layers */
+   dp_display->ctrl->wide_bus_en =
+   dp_display->dp_mode.out_fmt_is_yuv_420 ? false : 
dp_display->wide_bus_supported;
+   dp_display->catalog->wide_bus_en =
+   dp_display->dp_mode.out_fmt_is_yuv_420 ? false : 
dp_display->wide_bus_supported;
 }
 
 void dp_bridge_hpd_enable(struct drm_bridge *bridge)
diff --git a/drivers/gpu/drm/msm/dp/dp_panel.h 
b/drivers/gpu/drm/msm/dp/dp_panel.h
index a0dfc579c5f9f..6ec68be9f2366 100644
--- a/drivers/gpu/drm/msm/dp/dp_panel.h
+++ b/drivers/gpu/drm/msm/dp/dp_panel.h
@@ -19,6 +19,7 @@ struct dp_display_mode {
u32 bpp;
u32 h_active_low;
u32 v_active_low;
+   bool out_fmt_is_yuv_420;
 };
 
 struct dp_panel_in {
-- 
2.39.2



[PATCH v5 05/19] drm/msm/dpu: move dpu_encoder_helper_phys_setup_cdm to dpu_encoder

2024-02-22 Thread Paloma Arellano
Move dpu_encoder_helper_phys_setup_cdm to dpu_encoder in preparation for
implementing YUV420 over DP, which requires CDM compatibility.

Changes in v2:
- Slightly change the wording of the commit text to make clear
  that YUV over DP requires CDM

Signed-off-by: Paloma Arellano 
Reviewed-by: Dmitry Baryshkov 
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c   | 78 +
 .../gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h  |  9 ++
 .../drm/msm/disp/dpu1/dpu_encoder_phys_wb.c   | 83 ---
 3 files changed, 87 insertions(+), 83 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
index 8932f38a41b2d..1905e8653b77a 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
@@ -2117,6 +2117,84 @@ void dpu_encoder_helper_phys_cleanup(struct 
dpu_encoder_phys *phys_enc)
ctl->ops.clear_pending_flush(ctl);
 }
 
+void dpu_encoder_helper_phys_setup_cdm(struct dpu_encoder_phys *phys_enc,
+  const struct dpu_format *dpu_fmt,
+  u32 output_type)
+{
+   struct dpu_hw_cdm *hw_cdm;
+   struct dpu_hw_cdm_cfg *cdm_cfg;
+   struct dpu_hw_pingpong *hw_pp;
+   int ret;
+
+   if (!phys_enc)
+   return;
+
+   cdm_cfg = _enc->cdm_cfg;
+   hw_pp = phys_enc->hw_pp;
+   hw_cdm = phys_enc->hw_cdm;
+
+   if (!hw_cdm)
+   return;
+
+   if (!DPU_FORMAT_IS_YUV(dpu_fmt)) {
+   DPU_DEBUG("[enc:%d] cdm_disable fmt:%x\n", 
DRMID(phys_enc->parent),
+ dpu_fmt->base.pixel_format);
+   if (hw_cdm->ops.bind_pingpong_blk)
+   hw_cdm->ops.bind_pingpong_blk(hw_cdm, PINGPONG_NONE);
+
+   return;
+   }
+
+   memset(cdm_cfg, 0, sizeof(struct dpu_hw_cdm_cfg));
+
+   cdm_cfg->output_width = phys_enc->cached_mode.hdisplay;
+   cdm_cfg->output_height = phys_enc->cached_mode.vdisplay;
+   cdm_cfg->output_fmt = dpu_fmt;
+   cdm_cfg->output_type = output_type;
+   cdm_cfg->output_bit_depth = DPU_FORMAT_IS_DX(dpu_fmt) ?
+   CDM_CDWN_OUTPUT_10BIT : CDM_CDWN_OUTPUT_8BIT;
+   cdm_cfg->csc_cfg = _csc10_rgb2yuv_601l;
+
+   /* enable 10 bit logic */
+   switch (cdm_cfg->output_fmt->chroma_sample) {
+   case DPU_CHROMA_RGB:
+   cdm_cfg->h_cdwn_type = CDM_CDWN_DISABLE;
+   cdm_cfg->v_cdwn_type = CDM_CDWN_DISABLE;
+   break;
+   case DPU_CHROMA_H2V1:
+   cdm_cfg->h_cdwn_type = CDM_CDWN_COSITE;
+   cdm_cfg->v_cdwn_type = CDM_CDWN_DISABLE;
+   break;
+   case DPU_CHROMA_420:
+   cdm_cfg->h_cdwn_type = CDM_CDWN_COSITE;
+   cdm_cfg->v_cdwn_type = CDM_CDWN_OFFSITE;
+   break;
+   case DPU_CHROMA_H1V2:
+   default:
+   DPU_ERROR("[enc:%d] unsupported chroma sampling type\n",
+ DRMID(phys_enc->parent));
+   cdm_cfg->h_cdwn_type = CDM_CDWN_DISABLE;
+   cdm_cfg->v_cdwn_type = CDM_CDWN_DISABLE;
+   break;
+   }
+
+   DPU_DEBUG("[enc:%d] cdm_enable:%d,%d,%X,%d,%d,%d,%d]\n",
+ DRMID(phys_enc->parent), cdm_cfg->output_width,
+ cdm_cfg->output_height, 
cdm_cfg->output_fmt->base.pixel_format,
+ cdm_cfg->output_type, cdm_cfg->output_bit_depth,
+ cdm_cfg->h_cdwn_type, cdm_cfg->v_cdwn_type);
+
+   if (hw_cdm->ops.enable) {
+   cdm_cfg->pp_id = hw_pp->idx;
+   ret = hw_cdm->ops.enable(hw_cdm, cdm_cfg);
+   if (ret < 0) {
+   DPU_ERROR("[enc:%d] failed to enable CDM; ret:%d\n",
+ DRMID(phys_enc->parent), ret);
+   return;
+   }
+   }
+}
+
 #ifdef CONFIG_DEBUG_FS
 static int _dpu_encoder_status_show(struct seq_file *s, void *data)
 {
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
index 204d7cc3c1de8..f43d57d9c74e1 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
@@ -381,6 +381,15 @@ int dpu_encoder_helper_wait_for_irq(struct 
dpu_encoder_phys *phys_enc,
  */
 void dpu_encoder_helper_phys_cleanup(struct dpu_encoder_phys *phys_enc);
 
+/**
+ * dpu_encoder_helper_phys_setup_cdm - setup chroma down sampling block
+ * @phys_enc: Pointer to physical encoder
+ * @output_type: HDMI/WB
+ */
+void dpu_encoder_helper_phys_setup_cdm(struct dpu_encoder_phys *phys_enc,
+  const struct dpu_format *dpu_fmt,
+  u32 output_type);
+
 /**
  * dpu_encoder_vblank_callback - Notify virtual encoder of vblank IRQ reception
  * @drm_enc:Pointer to drm encoder structure
diff --git 

[PATCH v5 17/19] drm/msm/dpu: modify timing engine programming for YUV420 over DP

2024-02-22 Thread Paloma Arellano
Adjust the encoder timing engine setup programming in the case of video
mode for YUV420 over DP to accommodate CDM.

Changes in v3:
- Move drm_display_mode's hskew division to another patch
- Minor cleanup

Changes in v2:
- Move timing engine programming to this patch

Signed-off-by: Paloma Arellano 
Reviewed-by: Dmitry Baryshkov 
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c | 8 ++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c
index 86c57c8b7e784..5cb816ea4dcc0 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c
@@ -236,7 +236,7 @@ static void dpu_encoder_phys_vid_setup_timing_engine(
struct drm_display_mode mode;
struct dpu_hw_intf_timing_params timing_params = { 0 };
const struct dpu_format *fmt = NULL;
-   u32 fmt_fourcc = DRM_FORMAT_RGB888;
+   u32 fmt_fourcc;
unsigned long lock_flags;
struct dpu_hw_intf_cfg intf_cfg = { 0 };
 
@@ -255,7 +255,9 @@ static void dpu_encoder_phys_vid_setup_timing_engine(
DPU_DEBUG_VIDENC(phys_enc, "enabling mode:\n");
drm_mode_debug_printmodeline();
 
-   if (phys_enc->split_role != ENC_ROLE_SOLO) {
+   fmt_fourcc = dpu_encoder_get_drm_fmt(phys_enc);
+
+   if (phys_enc->split_role != ENC_ROLE_SOLO || fmt_fourcc == 
DRM_FORMAT_YUV420) {
mode.hdisplay >>= 1;
mode.htotal >>= 1;
mode.hsync_start >>= 1;
@@ -275,6 +277,8 @@ static void dpu_encoder_phys_vid_setup_timing_engine(
fmt = dpu_get_dpu_format(fmt_fourcc);
DPU_DEBUG_VIDENC(phys_enc, "fmt_fourcc 0x%X\n", fmt_fourcc);
 
+   if (phys_enc->hw_cdm)
+   intf_cfg.cdm = phys_enc->hw_cdm->idx;
intf_cfg.intf = phys_enc->hw_intf->idx;
intf_cfg.intf_mode_sel = DPU_CTL_MODE_SEL_VID;
intf_cfg.stream_sel = 0; /* Don't care value for video mode */
-- 
2.39.2



[PATCH v5 15/19] drm/msm/dp: enable SDP and SDE periph flush update

2024-02-22 Thread Paloma Arellano
DP controller can be setup to operate in either SDP update flush mode or
peripheral flush mode based on the DP controller hardware version.

Starting in DP v1.2, the hardware documents require the use of
peripheral flush mode for SDP packets such as PPS OR VSC SDP packets.

In-line with this guidance, lets program the DP controller to use
peripheral flush mode starting DP v1.2

Changes in v4:
- Clear up that DP_MAINLINK_CTRL_FLUSH_MODE register requires
  the use of bits [24:23]
- Modify macros DP_MAINLINK_FLUSH_MODE_UPDATE_SDP and
  DP_MAINLINK_FLUSH_MODE_SDP_PERIPH_UPDATE to explicitly set
  their values in the bits of DP_MAINLINK_CTRL_FLUSH_MODE_MASK

Changes in v3:
- Clear up that the DP_MAINLINK_FLUSH_MODE_SDE_PERIPH_UPDATE
  macro is setting bits [24:23] to a value of 3

Changes in v2:
- Use the original dp_catalog_hw_revision() function to
  correctly check the DP HW version

Signed-off-by: Paloma Arellano 
Reviewed-by: Dmitry Baryshkov 
---
 drivers/gpu/drm/msm/dp/dp_catalog.c | 17 +
 drivers/gpu/drm/msm/dp/dp_catalog.h |  1 +
 drivers/gpu/drm/msm/dp/dp_ctrl.c|  1 +
 drivers/gpu/drm/msm/dp/dp_reg.h |  6 ++
 4 files changed, 25 insertions(+)

diff --git a/drivers/gpu/drm/msm/dp/dp_catalog.c 
b/drivers/gpu/drm/msm/dp/dp_catalog.c
index bfc6f53ae167f..e5e7c04557707 100644
--- a/drivers/gpu/drm/msm/dp/dp_catalog.c
+++ b/drivers/gpu/drm/msm/dp/dp_catalog.c
@@ -440,6 +440,23 @@ void dp_catalog_ctrl_config_misc(struct dp_catalog 
*dp_catalog,
dp_write_link(catalog, REG_DP_MISC1_MISC0, misc_val);
 }
 
+void dp_catalog_setup_peripheral_flush(struct dp_catalog *dp_catalog)
+{
+   u32 mainlink_ctrl, hw_revision;
+   struct dp_catalog_private *catalog = container_of(dp_catalog,
+   struct dp_catalog_private, dp_catalog);
+
+   mainlink_ctrl = dp_read_link(catalog, REG_DP_MAINLINK_CTRL);
+
+   hw_revision = dp_catalog_hw_revision(dp_catalog);
+   if (hw_revision >= DP_HW_VERSION_1_2)
+   mainlink_ctrl |= DP_MAINLINK_FLUSH_MODE_SDE_PERIPH_UPDATE;
+   else
+   mainlink_ctrl |= DP_MAINLINK_FLUSH_MODE_UPDATE_SDP;
+
+   dp_write_link(catalog, REG_DP_MAINLINK_CTRL, mainlink_ctrl);
+}
+
 void dp_catalog_ctrl_config_msa(struct dp_catalog *dp_catalog,
u32 rate, u32 stream_rate_khz,
bool fixed_nvid, bool is_ycbcr_420)
diff --git a/drivers/gpu/drm/msm/dp/dp_catalog.h 
b/drivers/gpu/drm/msm/dp/dp_catalog.h
index 3605252effb59..47f80bb39ccd3 100644
--- a/drivers/gpu/drm/msm/dp/dp_catalog.h
+++ b/drivers/gpu/drm/msm/dp/dp_catalog.h
@@ -98,6 +98,7 @@ void dp_catalog_ctrl_config_ctrl(struct dp_catalog 
*dp_catalog, u32 config);
 void dp_catalog_ctrl_lane_mapping(struct dp_catalog *dp_catalog);
 void dp_catalog_ctrl_mainlink_ctrl(struct dp_catalog *dp_catalog, bool enable);
 void dp_catalog_ctrl_psr_mainlink_enable(struct dp_catalog *dp_catalog, bool 
enable);
+void dp_catalog_setup_peripheral_flush(struct dp_catalog *dp_catalog);
 void dp_catalog_ctrl_config_misc(struct dp_catalog *dp_catalog, u32 cc, u32 
tb);
 void dp_catalog_ctrl_config_msa(struct dp_catalog *dp_catalog, u32 rate,
u32 stream_rate_khz, bool fixed_nvid, bool 
is_ycbcr_420);
diff --git a/drivers/gpu/drm/msm/dp/dp_ctrl.c b/drivers/gpu/drm/msm/dp/dp_ctrl.c
index a42b29f9902c1..a17b9a22858da 100644
--- a/drivers/gpu/drm/msm/dp/dp_ctrl.c
+++ b/drivers/gpu/drm/msm/dp/dp_ctrl.c
@@ -165,6 +165,7 @@ static void dp_ctrl_configure_source_params(struct 
dp_ctrl_private *ctrl)
 
dp_catalog_ctrl_lane_mapping(ctrl->catalog);
dp_catalog_ctrl_mainlink_ctrl(ctrl->catalog, true);
+   dp_catalog_setup_peripheral_flush(ctrl->catalog);
 
dp_ctrl_config_ctrl(ctrl);
 
diff --git a/drivers/gpu/drm/msm/dp/dp_reg.h b/drivers/gpu/drm/msm/dp/dp_reg.h
index aa9f6c3e4ddeb..3835c7f5cb984 100644
--- a/drivers/gpu/drm/msm/dp/dp_reg.h
+++ b/drivers/gpu/drm/msm/dp/dp_reg.h
@@ -6,6 +6,9 @@
 #ifndef _DP_REG_H_
 #define _DP_REG_H_
 
+#include 
+#include 
+
 /* DP_TX Registers */
 #define REG_DP_HW_VERSION  (0x)
 
@@ -102,6 +105,9 @@
 #define DP_MAINLINK_CTRL_ENABLE(0x0001)
 #define DP_MAINLINK_CTRL_RESET (0x0002)
 #define DP_MAINLINK_CTRL_SW_BYPASS_SCRAMBLER   (0x0010)
+#define DP_MAINLINK_CTRL_FLUSH_MODE_MASK   GENMASK(24, 23)
+#define DP_MAINLINK_FLUSH_MODE_UPDATE_SDP  
FIELD_PREP(DP_MAINLINK_CTRL_FLUSH_MODE_MASK, 1)
+#define DP_MAINLINK_FLUSH_MODE_SDE_PERIPH_UPDATE   
FIELD_PREP(DP_MAINLINK_CTRL_FLUSH_MODE_MASK, 3)
 #define DP_MAINLINK_FB_BOUNDARY_SEL(0x0200)
 
 #define REG_DP_STATE_CTRL  (0x0004)
-- 
2.39.2



[PATCH v5 13/19] drm/msm/dp: add VSC SDP support for YUV420 over DP

2024-02-22 Thread Paloma Arellano
Add support to pack and send the VSC SDP packet for DP. This therefore
allows the transmision of format information to the sinks which is
needed for YUV420 support over DP.

Changes in v5:
- Slightly modify use of drm_dp_vsc_sdp_pack()
- Remove dp_catalog NULL checks
- Modify dp_utils_pack_sdp_header() to more clearly pack the
  header buffer
- Move dp_utils_pack_sdp_header() inside of
  dp_catalog_panel_send_vsc_sdp to clearly show the relationship
  between the header buffer and the vsc_sdp struct
- Due to the last point, remove the dp_utils_pack_vsc_sdp()
  function and only call drm_dp_vsc_sdp_pack() in
  dp_panel_setup_vsc_sdp_yuv_420()

Changes in v4:
- Remove struct msm_dp_sdp_with_parity
- Use dp_utils_pack_sdp_header() to pack the SDP header and
  parity bytes into a buffer
- Use this buffer when writing the VSC SDP data in
  dp_catalog_panel_send_vsc_sdp()
- Write to all of the MMSS_DP_GENERIC0 registers instead of just
  the ones with non-zero values

Changes in v3:
- Create a new struct, msm_dp_sdp_with_parity, which holds the
  packing information for VSC SDP
- Use drm_dp_vsc_sdp_pack() to pack the data into the new
  msm_dp_sdp_with_parity struct instead of specifically packing
  for YUV420 format
- Modify dp_catalog_panel_send_vsc_sdp() to send the VSC SDP
  data using the new msm_dp_sdp_with_parity struct

Changes in v2:
- Rename GENERIC0_SDPSIZE macro to GENERIC0_SDPSIZE_VALID
- Remove dp_sdp from the dp_catalog struct since this data is
  being allocated at the point used
- Create a new function in dp_utils to pack the VSC SDP data
  into a buffer
- Create a new function that packs the SDP header bytes into a
  buffer. This function is made generic so that it can be
  utilized by dp_audio
  header bytes into a buffer
- Create a new function in dp_utils that takes the packed buffer
  and writes to the DP_GENERIC0_* registers
- Split the dp_catalog_panel_config_vsc_sdp() function into two
  to disable/enable sending VSC SDP packets
- Check the DP HW version using the original useage of
  dp_catalog_hw_revision() and correct the version checking
  logic
- Rename dp_panel_setup_vsc_sdp() to
  dp_panel_setup_vsc_sdp_yuv_420() to explicitly state that
  currently VSC SDP is only being set up to support YUV420 modes

Signed-off-by: Paloma Arellano 
---
 drivers/gpu/drm/msm/dp/dp_catalog.c | 93 +
 drivers/gpu/drm/msm/dp/dp_catalog.h |  6 ++
 drivers/gpu/drm/msm/dp/dp_ctrl.c|  4 ++
 drivers/gpu/drm/msm/dp/dp_panel.c   | 52 
 drivers/gpu/drm/msm/dp/dp_reg.h |  3 +
 drivers/gpu/drm/msm/dp/dp_utils.c   | 25 
 drivers/gpu/drm/msm/dp/dp_utils.h   | 14 +
 7 files changed, 197 insertions(+)

diff --git a/drivers/gpu/drm/msm/dp/dp_catalog.c 
b/drivers/gpu/drm/msm/dp/dp_catalog.c
index 5d84c089e520a..bfc6f53ae167f 100644
--- a/drivers/gpu/drm/msm/dp/dp_catalog.c
+++ b/drivers/gpu/drm/msm/dp/dp_catalog.c
@@ -901,6 +901,99 @@ int dp_catalog_panel_timing_cfg(struct dp_catalog 
*dp_catalog)
return 0;
 }
 
+static void dp_catalog_panel_send_vsc_sdp(struct dp_catalog *dp_catalog, 
struct dp_sdp *vsc_sdp)
+{
+   struct dp_catalog_private *catalog;
+   u32 header[2];
+   u32 val;
+   int i;
+
+   catalog = container_of(dp_catalog, struct dp_catalog_private, 
dp_catalog);
+
+   dp_utils_pack_sdp_header(_sdp->sdp_header, header);
+
+   dp_write_link(catalog, MMSS_DP_GENERIC0_0, header[0]);
+   dp_write_link(catalog, MMSS_DP_GENERIC0_1, header[1]);
+
+   for (i = 0; i < sizeof(vsc_sdp->db); i += 4) {
+   val = ((vsc_sdp->db[i]) | (vsc_sdp->db[i + 1] << 8) | 
(vsc_sdp->db[i + 2] << 16) |
+  (vsc_sdp->db[i + 3] << 24));
+   dp_write_link(catalog, MMSS_DP_GENERIC0_2 + i, val);
+   }
+}
+
+static void dp_catalog_panel_update_sdp(struct dp_catalog *dp_catalog)
+{
+   struct dp_catalog_private *catalog;
+   u32 hw_revision;
+
+   catalog = container_of(dp_catalog, struct dp_catalog_private, 
dp_catalog);
+
+   hw_revision = dp_catalog_hw_revision(dp_catalog);
+   if (hw_revision < DP_HW_VERSION_1_2 && hw_revision >= 
DP_HW_VERSION_1_0) {
+   dp_write_link(catalog, MMSS_DP_SDP_CFG3, 0x01);
+   dp_write_link(catalog, MMSS_DP_SDP_CFG3, 0x00);
+   }
+}
+
+void dp_catalog_panel_enable_vsc_sdp(struct dp_catalog *dp_catalog, struct 
dp_sdp *vsc_sdp)
+{
+   struct dp_catalog_private *catalog;
+   u32 cfg, cfg2, misc;
+
+   catalog = container_of(dp_catalog, struct dp_catalog_private, 
dp_catalog);
+
+   cfg = dp_read_link(catalog, MMSS_DP_SDP_CFG);
+   cfg2 = 

[PATCH v5 04/19] drm/msm/dpu: allow dpu_encoder_helper_phys_setup_cdm to work for DP

2024-02-22 Thread Paloma Arellano
Generalize dpu_encoder_helper_phys_setup_cdm to be compatible with DP.

Changes in v2:
- Minor formatting changes
- Move the modification of the dimensions for CDM setup to a new
  patch

Signed-off-by: Paloma Arellano 
Reviewed-by: Dmitry Baryshkov 
---
 .../gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h  |  4 +--
 .../drm/msm/disp/dpu1/dpu_encoder_phys_wb.c   | 27 ++-
 2 files changed, 16 insertions(+), 15 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
index 993f263433314..204d7cc3c1de8 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
@@ -154,6 +154,7 @@ enum dpu_intr_idx {
  * @hw_wb: Hardware interface to the wb registers
  * @hw_cdm:Hardware interface to the CDM registers
  * @dpu_kms:   Pointer to the dpu_kms top level
+ * @cdm_cfg:   CDM block config needed to store WB/DP block's CDM 
configuration
  * @cached_mode:   DRM mode cached at mode_set time, acted on in enable
  * @vblank_ctl_lock:   Vblank ctl mutex lock to protect vblank_refcount
  * @enabled:   Whether the encoder has enabled and running a mode
@@ -184,6 +185,7 @@ struct dpu_encoder_phys {
struct dpu_hw_wb *hw_wb;
struct dpu_hw_cdm *hw_cdm;
struct dpu_kms *dpu_kms;
+   struct dpu_hw_cdm_cfg cdm_cfg;
struct drm_display_mode cached_mode;
struct mutex vblank_ctl_lock;
enum dpu_enc_split_role split_role;
@@ -213,7 +215,6 @@ static inline int dpu_encoder_phys_inc_pending(struct 
dpu_encoder_phys *phys)
  * @wbirq_refcount: Reference count of writeback interrupt
  * @wb_done_timeout_cnt: number of wb done irq timeout errors
  * @wb_cfg:  writeback block config to store fb related details
- * @cdm_cfg: cdm block config needed to store writeback block's CDM 
configuration
  * @wb_conn: backpointer to writeback connector
  * @wb_job: backpointer to current writeback job
  * @dest:   dpu buffer layout for current writeback output buffer
@@ -223,7 +224,6 @@ struct dpu_encoder_phys_wb {
atomic_t wbirq_refcount;
int wb_done_timeout_cnt;
struct dpu_hw_wb_cfg wb_cfg;
-   struct dpu_hw_cdm_cfg cdm_cfg;
struct drm_writeback_connector *wb_conn;
struct drm_writeback_job *wb_job;
struct dpu_hw_fmt_layout dest;
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c
index ec9e053d3947d..072fc6950e496 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c
@@ -269,28 +269,21 @@ static void dpu_encoder_phys_wb_setup_ctl(struct 
dpu_encoder_phys *phys_enc)
  * This API does not handle 
DPU_CHROMA_H1V2.
  * @phys_enc:Pointer to physical encoder
  */
-static void dpu_encoder_helper_phys_setup_cdm(struct dpu_encoder_phys 
*phys_enc)
+static void dpu_encoder_helper_phys_setup_cdm(struct dpu_encoder_phys 
*phys_enc,
+ const struct dpu_format *dpu_fmt,
+ u32 output_type)
 {
struct dpu_hw_cdm *hw_cdm;
struct dpu_hw_cdm_cfg *cdm_cfg;
struct dpu_hw_pingpong *hw_pp;
-   struct dpu_encoder_phys_wb *wb_enc;
-   const struct msm_format *format;
-   const struct dpu_format *dpu_fmt;
-   struct drm_writeback_job *wb_job;
int ret;
 
if (!phys_enc)
return;
 
-   wb_enc = to_dpu_encoder_phys_wb(phys_enc);
-   cdm_cfg = _enc->cdm_cfg;
+   cdm_cfg = _enc->cdm_cfg;
hw_pp = phys_enc->hw_pp;
hw_cdm = phys_enc->hw_cdm;
-   wb_job = wb_enc->wb_job;
-
-   format = msm_framebuffer_format(wb_enc->wb_job->fb);
-   dpu_fmt = dpu_get_dpu_format_ext(format->pixel_format, 
wb_job->fb->modifier);
 
if (!hw_cdm)
return;
@@ -309,7 +302,7 @@ static void dpu_encoder_helper_phys_setup_cdm(struct 
dpu_encoder_phys *phys_enc)
cdm_cfg->output_width = phys_enc->cached_mode.hdisplay;
cdm_cfg->output_height = phys_enc->cached_mode.vdisplay;
cdm_cfg->output_fmt = dpu_fmt;
-   cdm_cfg->output_type = CDM_CDWN_OUTPUT_WB;
+   cdm_cfg->output_type = output_type;
cdm_cfg->output_bit_depth = DPU_FORMAT_IS_DX(dpu_fmt) ?
CDM_CDWN_OUTPUT_10BIT : CDM_CDWN_OUTPUT_8BIT;
cdm_cfg->csc_cfg = _csc10_rgb2yuv_601l;
@@ -462,6 +455,14 @@ static void dpu_encoder_phys_wb_setup(
struct dpu_hw_wb *hw_wb = phys_enc->hw_wb;
struct drm_display_mode mode = phys_enc->cached_mode;
struct drm_framebuffer *fb = NULL;
+   struct dpu_encoder_phys_wb *wb_enc = to_dpu_encoder_phys_wb(phys_enc);
+   struct drm_writeback_job *wb_job;
+   const struct msm_format *format;
+   const struct dpu_format *dpu_fmt;
+
+   

[PATCH v5 11/19] drm/msm/dp: change clock related programming for YUV420 over DP

2024-02-22 Thread Paloma Arellano
Change all relevant DP controller related programming for YUV420 cases.
Namely, change the pixel clock math to consider YUV420 and modify the
MVID programming to consider YUV420.

Changes in v2:
- Move configuration control programming to a different commit
- Slight code simplification
- Add VSC SDP check when doing mode_pclk_khz division in
  dp_bridge_mode_valid

Signed-off-by: Paloma Arellano 
Reviewed-by: Dmitry Baryshkov 
---
 drivers/gpu/drm/msm/dp/dp_catalog.c | 5 -
 drivers/gpu/drm/msm/dp/dp_catalog.h | 2 +-
 drivers/gpu/drm/msm/dp/dp_ctrl.c| 9 ++---
 drivers/gpu/drm/msm/dp/dp_display.c | 4 
 4 files changed, 15 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/msm/dp/dp_catalog.c 
b/drivers/gpu/drm/msm/dp/dp_catalog.c
index 5142aeb705a44..5d84c089e520a 100644
--- a/drivers/gpu/drm/msm/dp/dp_catalog.c
+++ b/drivers/gpu/drm/msm/dp/dp_catalog.c
@@ -442,7 +442,7 @@ void dp_catalog_ctrl_config_misc(struct dp_catalog 
*dp_catalog,
 
 void dp_catalog_ctrl_config_msa(struct dp_catalog *dp_catalog,
u32 rate, u32 stream_rate_khz,
-   bool fixed_nvid)
+   bool fixed_nvid, bool is_ycbcr_420)
 {
u32 pixel_m, pixel_n;
u32 mvid, nvid, pixel_div = 0, dispcc_input_rate;
@@ -485,6 +485,9 @@ void dp_catalog_ctrl_config_msa(struct dp_catalog 
*dp_catalog,
nvid = temp;
}
 
+   if (is_ycbcr_420)
+   mvid /= 2;
+
if (link_rate_hbr2 == rate)
nvid *= 2;
 
diff --git a/drivers/gpu/drm/msm/dp/dp_catalog.h 
b/drivers/gpu/drm/msm/dp/dp_catalog.h
index 38786e855b51a..6cb5e2a243de2 100644
--- a/drivers/gpu/drm/msm/dp/dp_catalog.h
+++ b/drivers/gpu/drm/msm/dp/dp_catalog.h
@@ -96,7 +96,7 @@ void dp_catalog_ctrl_mainlink_ctrl(struct dp_catalog 
*dp_catalog, bool enable);
 void dp_catalog_ctrl_psr_mainlink_enable(struct dp_catalog *dp_catalog, bool 
enable);
 void dp_catalog_ctrl_config_misc(struct dp_catalog *dp_catalog, u32 cc, u32 
tb);
 void dp_catalog_ctrl_config_msa(struct dp_catalog *dp_catalog, u32 rate,
-   u32 stream_rate_khz, bool fixed_nvid);
+   u32 stream_rate_khz, bool fixed_nvid, bool 
is_ycbcr_420);
 int dp_catalog_ctrl_set_pattern_state_bit(struct dp_catalog *dp_catalog, u32 
pattern);
 u32 dp_catalog_hw_revision(const struct dp_catalog *dp_catalog);
 void dp_catalog_ctrl_reset(struct dp_catalog *dp_catalog);
diff --git a/drivers/gpu/drm/msm/dp/dp_ctrl.c b/drivers/gpu/drm/msm/dp/dp_ctrl.c
index 6692d81adb195..bffb7bac2c2c8 100644
--- a/drivers/gpu/drm/msm/dp/dp_ctrl.c
+++ b/drivers/gpu/drm/msm/dp/dp_ctrl.c
@@ -955,7 +955,7 @@ static void dp_ctrl_calc_tu_parameters(struct 
dp_ctrl_private *ctrl,
in.hporch = drm_mode->htotal - drm_mode->hdisplay;
in.nlanes = ctrl->link->link_params.num_lanes;
in.bpp = ctrl->panel->dp_mode.bpp;
-   in.pixel_enc = 444;
+   in.pixel_enc = ctrl->panel->dp_mode.out_fmt_is_yuv_420 ? 420 : 444;
in.dsc_en = 0;
in.async_en = 0;
in.fec_en = 0;
@@ -1761,6 +1761,8 @@ int dp_ctrl_on_link(struct dp_ctrl *dp_ctrl)
ctrl->link->link_params.rate = rate;
ctrl->link->link_params.num_lanes =
ctrl->panel->link_info.num_lanes;
+   if (ctrl->panel->dp_mode.out_fmt_is_yuv_420)
+   pixel_rate >>= 1;
}
 
drm_dbg_dp(ctrl->drm_dev, "rate=%d, num_lanes=%d, pixel_rate=%lu\n",
@@ -1876,7 +1878,7 @@ int dp_ctrl_on_stream(struct dp_ctrl *dp_ctrl, bool 
force_link_train)
 
pixel_rate = pixel_rate_orig = ctrl->panel->dp_mode.drm_mode.clock;
 
-   if (dp_ctrl->wide_bus_en)
+   if (dp_ctrl->wide_bus_en || ctrl->panel->dp_mode.out_fmt_is_yuv_420)
pixel_rate >>= 1;
 
drm_dbg_dp(ctrl->drm_dev, "rate=%d, num_lanes=%d, pixel_rate=%lu\n",
@@ -1915,7 +1917,8 @@ int dp_ctrl_on_stream(struct dp_ctrl *dp_ctrl, bool 
force_link_train)
 
dp_catalog_ctrl_config_msa(ctrl->catalog,
ctrl->link->link_params.rate,
-   pixel_rate_orig, dp_ctrl_use_fixed_nvid(ctrl));
+   pixel_rate_orig, dp_ctrl_use_fixed_nvid(ctrl),
+   ctrl->panel->dp_mode.out_fmt_is_yuv_420);
 
dp_ctrl_setup_tr_unit(ctrl);
 
diff --git a/drivers/gpu/drm/msm/dp/dp_display.c 
b/drivers/gpu/drm/msm/dp/dp_display.c
index 4b1b79b74bc72..3b7c3a7fd4993 100644
--- a/drivers/gpu/drm/msm/dp/dp_display.c
+++ b/drivers/gpu/drm/msm/dp/dp_display.c
@@ -934,6 +934,10 @@ enum drm_mode_status dp_bridge_mode_valid(struct 
drm_bridge *bridge,
dp_display = container_of(dp, struct dp_display_private, dp_display);
link_info = _display->panel->link_info;
 
+   if (drm_mode_is_420_only(>connector->display_info, mode) &&
+   dp_display->panel->vsc_sdp_supported)
+   mode_pclk_khz /= 2;
+

[PATCH v5 12/19] drm/msm/dp: move parity calculation to dp_utils

2024-02-22 Thread Paloma Arellano
Parity calculation is necessary for VSC SDP implementation. Therefore
create new files dp_utils.c and dp_utils.h and move the parity
calculating functions here. This ensures that they are usable by SDP
programming in both dp_catalog.c and dp_audio.c

Changes in v3:
- Change ordering of the header byte macros

Changes in v2:
- Create new files dp_utils.c and dp_utils.h
- Move the parity calculation to these new files instead of
  having them in dp_catalog.c and dp_catalog.h

Signed-off-by: Paloma Arellano 
Reviewed-by: Dmitry Baryshkov 
---
 drivers/gpu/drm/msm/Makefile  |   3 +-
 drivers/gpu/drm/msm/dp/dp_audio.c | 101 +-
 drivers/gpu/drm/msm/dp/dp_utils.c |  73 +
 drivers/gpu/drm/msm/dp/dp_utils.h |  22 +++
 4 files changed, 112 insertions(+), 87 deletions(-)
 create mode 100644 drivers/gpu/drm/msm/dp/dp_utils.c
 create mode 100644 drivers/gpu/drm/msm/dp/dp_utils.h

diff --git a/drivers/gpu/drm/msm/Makefile b/drivers/gpu/drm/msm/Makefile
index b1173128b5b97..998b155e4a979 100644
--- a/drivers/gpu/drm/msm/Makefile
+++ b/drivers/gpu/drm/msm/Makefile
@@ -129,7 +129,8 @@ msm-$(CONFIG_DRM_MSM_DP)+= dp/dp_aux.o \
dp/dp_panel.o \
dp/dp_parser.o \
dp/dp_power.o \
-   dp/dp_audio.o
+   dp/dp_audio.o \
+   dp/dp_utils.o
 
 msm-$(CONFIG_DRM_FBDEV_EMULATION) += msm_fbdev.o
 
diff --git a/drivers/gpu/drm/msm/dp/dp_audio.c 
b/drivers/gpu/drm/msm/dp/dp_audio.c
index 4a2e479723a85..7634e4b742084 100644
--- a/drivers/gpu/drm/msm/dp/dp_audio.c
+++ b/drivers/gpu/drm/msm/dp/dp_audio.c
@@ -15,13 +15,7 @@
 #include "dp_audio.h"
 #include "dp_panel.h"
 #include "dp_display.h"
-
-#define HEADER_BYTE_2_BIT   0
-#define PARITY_BYTE_2_BIT   8
-#define HEADER_BYTE_1_BIT  16
-#define PARITY_BYTE_1_BIT  24
-#define HEADER_BYTE_3_BIT  16
-#define PARITY_BYTE_3_BIT  24
+#include "dp_utils.h"
 
 struct dp_audio_private {
struct platform_device *audio_pdev;
@@ -36,71 +30,6 @@ struct dp_audio_private {
struct dp_audio dp_audio;
 };
 
-static u8 dp_audio_get_g0_value(u8 data)
-{
-   u8 c[4];
-   u8 g[4];
-   u8 ret_data = 0;
-   u8 i;
-
-   for (i = 0; i < 4; i++)
-   c[i] = (data >> i) & 0x01;
-
-   g[0] = c[3];
-   g[1] = c[0] ^ c[3];
-   g[2] = c[1];
-   g[3] = c[2];
-
-   for (i = 0; i < 4; i++)
-   ret_data = ((g[i] & 0x01) << i) | ret_data;
-
-   return ret_data;
-}
-
-static u8 dp_audio_get_g1_value(u8 data)
-{
-   u8 c[4];
-   u8 g[4];
-   u8 ret_data = 0;
-   u8 i;
-
-   for (i = 0; i < 4; i++)
-   c[i] = (data >> i) & 0x01;
-
-   g[0] = c[0] ^ c[3];
-   g[1] = c[0] ^ c[1] ^ c[3];
-   g[2] = c[1] ^ c[2];
-   g[3] = c[2] ^ c[3];
-
-   for (i = 0; i < 4; i++)
-   ret_data = ((g[i] & 0x01) << i) | ret_data;
-
-   return ret_data;
-}
-
-static u8 dp_audio_calculate_parity(u32 data)
-{
-   u8 x0 = 0;
-   u8 x1 = 0;
-   u8 ci = 0;
-   u8 iData = 0;
-   u8 i = 0;
-   u8 parity_byte;
-   u8 num_byte = (data & 0xFF00) > 0 ? 8 : 2;
-
-   for (i = 0; i < num_byte; i++) {
-   iData = (data >> i*4) & 0xF;
-
-   ci = iData ^ x1;
-   x1 = x0 ^ dp_audio_get_g1_value(ci);
-   x0 = dp_audio_get_g0_value(ci);
-   }
-
-   parity_byte = x1 | (x0 << 4);
-
-   return parity_byte;
-}
-
 static u32 dp_audio_get_header(struct dp_catalog *catalog,
enum dp_catalog_audio_sdp_type sdp,
enum dp_catalog_audio_header_type header)
@@ -134,7 +63,7 @@ static void dp_audio_stream_sdp(struct dp_audio_private 
*audio)
DP_AUDIO_SDP_STREAM, DP_AUDIO_SDP_HEADER_1);
 
new_value = 0x02;
-   parity_byte = dp_audio_calculate_parity(new_value);
+   parity_byte = dp_utils_calculate_parity(new_value);
value |= ((new_value << HEADER_BYTE_1_BIT)
| (parity_byte << PARITY_BYTE_1_BIT));
drm_dbg_dp(audio->drm_dev,
@@ -147,7 +76,7 @@ static void dp_audio_stream_sdp(struct dp_audio_private 
*audio)
value = dp_audio_get_header(catalog,
DP_AUDIO_SDP_STREAM, DP_AUDIO_SDP_HEADER_2);
new_value = value;
-   parity_byte = dp_audio_calculate_parity(new_value);
+   parity_byte = dp_utils_calculate_parity(new_value);
value |= ((new_value << HEADER_BYTE_2_BIT)
| (parity_byte << PARITY_BYTE_2_BIT));
drm_dbg_dp(audio->drm_dev,
@@ -162,7 +91,7 @@ static void dp_audio_stream_sdp(struct dp_audio_private 
*audio)
DP_AUDIO_SDP_STREAM, DP_AUDIO_SDP_HEADER_3);
 
new_value = audio->channels - 1;
-   parity_byte = dp_audio_calculate_parity(new_value);
+   parity_byte = dp_utils_calculate_parity(new_value);
value |= ((new_value << HEADER_BYTE_3_BIT)
| 

[PATCH v5 03/19] drm/msm/dpu: pass mode dimensions instead of fb size in CDM setup

2024-02-22 Thread Paloma Arellano
Modify the output width and height parameters of hw_cdm to utilize the
physical encoder's data instead of obtaining the information from the
framebuffer. CDM is to be set up to utilize the actual output data since
at CDM setup, there is no difference between the two sources.

Changes in v2:
- Move the modification of the dimensions for CDM setup to this
  new patch

Signed-off-by: Paloma Arellano 
Reviewed-by: Dmitry Baryshkov 
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c
index 4cd2d9e3131a4..ec9e053d3947d 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c
@@ -306,8 +306,8 @@ static void dpu_encoder_helper_phys_setup_cdm(struct 
dpu_encoder_phys *phys_enc)
 
memset(cdm_cfg, 0, sizeof(struct dpu_hw_cdm_cfg));
 
-   cdm_cfg->output_width = wb_job->fb->width;
-   cdm_cfg->output_height = wb_job->fb->height;
+   cdm_cfg->output_width = phys_enc->cached_mode.hdisplay;
+   cdm_cfg->output_height = phys_enc->cached_mode.vdisplay;
cdm_cfg->output_fmt = dpu_fmt;
cdm_cfg->output_type = CDM_CDWN_OUTPUT_WB;
cdm_cfg->output_bit_depth = DPU_FORMAT_IS_DX(dpu_fmt) ?
-- 
2.39.2



[PATCH v5 02/19] drm/msm/dpu: add division of drm_display_mode's hskew parameter

2024-02-22 Thread Paloma Arellano
Setting up the timing engine when the physical encoder has a split role
neglects dividing the drm_display_mode's hskew parameter. Let's fix this
since this must also be done in preparation for implementing YUV420 over
DP.

Fixes: 25fdd5933e4c ("drm/msm: Add SDM845 DPU support")
Signed-off-by: Paloma Arellano 
Reviewed-by: Dmitry Baryshkov 
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c | 6 --
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c
index f562beb6f7971..f02411b062c4c 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c
@@ -260,12 +260,14 @@ static void dpu_encoder_phys_vid_setup_timing_engine(
mode.htotal >>= 1;
mode.hsync_start >>= 1;
mode.hsync_end >>= 1;
+   mode.hskew >>= 1;
 
DPU_DEBUG_VIDENC(phys_enc,
-   "split_role %d, halve horizontal %d %d %d %d\n",
+   "split_role %d, halve horizontal %d %d %d %d %d\n",
phys_enc->split_role,
mode.hdisplay, mode.htotal,
-   mode.hsync_start, mode.hsync_end);
+   mode.hsync_start, mode.hsync_end,
+   mode.hskew);
}
 
drm_mode_to_intf_timing_params(phys_enc, , _params);
-- 
2.39.2



[PATCH v5 01/19] drm/msm/dpu: allow certain formats for CDM for DP

2024-02-22 Thread Paloma Arellano
CDM block supports formats other than H1V2 for DP. Since we are now
adding support for CDM over DP, relax the checks to allow all other
formats for DP other than H1V2.

Changes in v2:
- Add fixes tag
- Move patch to top of series

Fixes: 0afac0ba6024 ("drm/msm/dpu: add dpu_hw_cdm abstraction for CDM block")
Signed-off-by: Paloma Arellano 
Reviewed-by: Dmitry Baryshkov 
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.c
index e9cdc7934a499..9016b3ade6bc3 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.c
@@ -186,7 +186,7 @@ static int dpu_hw_cdm_enable(struct dpu_hw_cdm *ctx, struct 
dpu_hw_cdm_cfg *cdm)
dpu_hw_cdm_setup_cdwn(ctx, cdm);
 
if (cdm->output_type == CDM_CDWN_OUTPUT_HDMI) {
-   if (fmt->chroma_sample != DPU_CHROMA_H1V2)
+   if (fmt->chroma_sample == DPU_CHROMA_H1V2)
return -EINVAL; /*unsupported format */
opmode = CDM_HDMI_PACK_OP_MODE_EN;
opmode |= (fmt->chroma_sample << 1);
-- 
2.39.2



[PATCH v5 00/19] Add support for CDM over DP

2024-02-22 Thread Paloma Arellano
The Chroma Down Sampling (CDM) block is a hardware component in the DPU
pipeline that includes a CSC block capable of converting RGB input from
the DPU to YUV data.

This block can be used with either HDMI, DP, or writeback interfaces.
This series adds support for the CDM block to be used with DP in
YUV420 mode format.

This series allows selection of the YUV420 format for monitors which support
certain resolutions only in YUV420 thus unblocking the validation of many
other resolutions which were previously filtered out if the connector did
not support YUV420.

This was validated using a DP connected monitor requiring the use of
YUV420 format.

This series is dependent on [1], [2], and [3]:
[1] https://patchwork.freedesktop.org/series/118831/
[2] https://patchwork.freedesktop.org/series/129395/
[3] https://patchwork.freedesktop.org/series/129864/

Changes in v5:
- Slightly modify use of drm_dp_vsc_sdp_pack()
- Remove dp_catalog NULL checks
- Modify dp_utils_pack_sdp_header() to cleanly pack the header
  buffer
- Remove the dp_utils_pack_vsc_sdp() function and only call
  drm_dp_vsc_sdp_pack() in dp_panel_setup_vsc_sdp_yuv_420()
- To clearly show the relationship between the header buffer and
  vsc_sdp struct, move dp_utils_pack_sdp_header() inside of
  dp_catalog_panel_send_vsc_sdp()

Changes in v4:
- Use dp_utils_pack_sdp_header() to pack the SDP header and
  parity bytes into a buffer
- Use this buffer when writing the VSC SDP data in
  dp_catalog_panel_send_vsc_sdp() and write to all the
  MMSS_DP_GENERIC0 registers
- Clear up that DP_MAINLINK_CTRL_FLUSH_MODE register requires
  the use of bits [24:23]
- Modify certain macros to explicitly set their values in the
  bits of DP_MAINLINK_CTRL_FLUSH_MODE_MASK
- Remove hw_cdm check in dpu_encoder_needs_periph_flush() and
  dpu_encoder_phys_vid_enable()

Changes in v3:
- Change ordering of the header byte macros in dp_utils.h
- Create a new struct, msm_dp_sdp_with_parity
- Utilize drm_dp_vsc_sdp_pack() from a new added dependency of
  series [3] to pack the VSC SDP data into the new
  msm_dp_sdp_with_parity struct instead of packing only for
  YUV420
- Modify dp_catalog_panel_send_vsc_sdp() so that it sends the VSC SDP 
data
  using the new msm_dp_sdp_with_parity struct
- Clear up that the DP_MAINLINK_FLUSH_MODE_SDE_PERIPH_UPDATE macro is 
setting
  multiple bits and not just one
- Move the connector's ycbcr_420_allowed parameter so it is no longer
  dependent on if the dp_display is not eDP

Changes in v2:
- Minor formatting changes throughout
- Move 'fixes' patch to the top
- Move VSC SDP support check API from dp_panel.c to drm_dp_helper.c
- Create a separate patch for modifying the dimensions for CDM setup to 
be
  non-WB specific
- Remove a patch that modified the INTF_CONFIG2 register in favor of 
having
  this series be dependent on [2]
- Separate configuration ctrl programming from clock related 
programming into
  two patches
- Add a VSC SDP check in dp_bridge_mode_valid()
- Move parity calculation functions to new files dp_utils.c and 
dp_utils.h
- Remove dp_catalog_hw_revision() changes and utilize the original 
version of
  the function when checking the DP hardware version
- Create separate packing and programming functions for the VSC SDP
- Make the packing header bytes function generic so it can be used with
  dp_audio.c
- Create two separate enable/disable VSC SDP functions instead of 
having one
  with the ability to do both
- Move timing engine programming to a separate patch from original 
encoder
  programming patch
- Move update_pending_flush_periph() code to be in the same patch as the
  encoder programming
- Create new API's to check if the dpu encoder needs a peripheral flush
- Allow YUV420 modes for the DP connector when there's a CDM block 
available
  instead of checking if VSC SDP is supported

Kuogee Hsieh (1):
  drm/msm/dpu: add support of new peripheral flush mechanism

Paloma Arellano (18):
  drm/msm/dpu: allow certain formats for CDM for DP
  drm/msm/dpu: add division of drm_display_mode's hskew parameter
  drm/msm/dpu: pass mode dimensions instead of fb size in CDM setup
  drm/msm/dpu: allow dpu_encoder_helper_phys_setup_cdm to work for DP
  drm/msm/dpu: move dpu_encoder_helper_phys_setup_cdm to dpu_encoder
  drm/msm/dp: rename wide_bus_en to wide_bus_supported
  drm/msm/dp: store mode YUV420 information to be used by rest of DP
  drm/msm/dp: check if VSC SDP is supported in DP programming
  drm/msm/dpu: move widebus logic to its own API
  drm/msm/dp: program config ctrl for 

Re: [PATCH] drm/i915: Add missing ; to __assign_str() macros in tracepoint code

2024-02-22 Thread Steven Rostedt
On Thu, 22 Feb 2024 14:04:20 -0500
Rodrigo Vivi  wrote:

> > Note, I have patches that depend on this fix, so if one of the maintainers
> > would like to just give me an "Acked-by", I'll take it through my tree. I
> > doubt it will have any conflicts, unless you are planning on changing the
> > given effected events.  
> 
> since it is not breaking builds on our side and the conflicts, if any, would
> be minimal, feel free to take this trough your tree
> 
> Acked-by: Rodrigo Vivi 

Thanks, much appreciated!

-- Steve


Re: [PATCH 2/3] drm/sun4i: Add more parameters to sunxi_engine commit callback

2024-02-22 Thread Jernej Škrabec
Dne petek, 16. februar 2024 ob 20:04:25 CET je Ondřej Jirman napisal(a):
> From: Ondrej Jirman 
> 
> These will be needed later on when we move layer configuration to
> crtc update.
> 
> Signed-off-by: Ondrej Jirman 

Reviewed-by: Jernej Skrabec 

Best regards,
Jernej

> ---
>  drivers/gpu/drm/sun4i/sun4i_backend.c |  4 +++-
>  drivers/gpu/drm/sun4i/sun4i_crtc.c|  2 +-
>  drivers/gpu/drm/sun4i/sun8i_mixer.c   |  5 -
>  drivers/gpu/drm/sun4i/sunxi_engine.h  | 13 ++---
>  4 files changed, 18 insertions(+), 6 deletions(-)
> 
> diff --git a/drivers/gpu/drm/sun4i/sun4i_backend.c 
> b/drivers/gpu/drm/sun4i/sun4i_backend.c
> index 335fd0edb904..e89eb96d3131 100644
> --- a/drivers/gpu/drm/sun4i/sun4i_backend.c
> +++ b/drivers/gpu/drm/sun4i/sun4i_backend.c
> @@ -69,7 +69,9 @@ static void sun4i_backend_disable_color_correction(struct 
> sunxi_engine *engine)
>  SUN4I_BACKEND_OCCTL_ENABLE, 0);
>  }
>  
> -static void sun4i_backend_commit(struct sunxi_engine *engine)
> +static void sun4i_backend_commit(struct sunxi_engine *engine,
> +  struct drm_crtc *crtc,
> +  struct drm_atomic_state *state)
>  {
>   DRM_DEBUG_DRIVER("Committing changes\n");
>  
> diff --git a/drivers/gpu/drm/sun4i/sun4i_crtc.c 
> b/drivers/gpu/drm/sun4i/sun4i_crtc.c
> index c06d7cd45388..18e74047b0f5 100644
> --- a/drivers/gpu/drm/sun4i/sun4i_crtc.c
> +++ b/drivers/gpu/drm/sun4i/sun4i_crtc.c
> @@ -91,7 +91,7 @@ static void sun4i_crtc_atomic_flush(struct drm_crtc *crtc,
>  
>   DRM_DEBUG_DRIVER("Committing plane changes\n");
>  
> - sunxi_engine_commit(scrtc->engine);
> + sunxi_engine_commit(scrtc->engine, crtc, state);
>  
>   if (event) {
>   crtc->state->event = NULL;
> diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.c 
> b/drivers/gpu/drm/sun4i/sun8i_mixer.c
> index 1e681314e379..bdeb9b80e038 100644
> --- a/drivers/gpu/drm/sun4i/sun8i_mixer.c
> +++ b/drivers/gpu/drm/sun4i/sun8i_mixer.c
> @@ -16,6 +16,7 @@
>  #include 
>  #include 
>  
> +#include 
>  #include 
>  #include 
>  #include 
> @@ -249,7 +250,9 @@ int sun8i_mixer_drm_format_to_hw(u32 format, u32 
> *hw_format)
>   return -EINVAL;
>  }
>  
> -static void sun8i_mixer_commit(struct sunxi_engine *engine)
> +static void sun8i_mixer_commit(struct sunxi_engine *engine,
> +struct drm_crtc *crtc,
> +struct drm_atomic_state *state)
>  {
>   DRM_DEBUG_DRIVER("Committing changes\n");
>  
> diff --git a/drivers/gpu/drm/sun4i/sunxi_engine.h 
> b/drivers/gpu/drm/sun4i/sunxi_engine.h
> index ec8cf9b2bda4..ec0c4932f15c 100644
> --- a/drivers/gpu/drm/sun4i/sunxi_engine.h
> +++ b/drivers/gpu/drm/sun4i/sunxi_engine.h
> @@ -7,6 +7,7 @@
>  #define _SUNXI_ENGINE_H_
>  
>  struct drm_plane;
> +struct drm_crtc;
>  struct drm_device;
>  struct drm_crtc_state;
>  struct drm_display_mode;
> @@ -59,7 +60,9 @@ struct sunxi_engine_ops {
>*
>* This function is optional.
>*/
> - void (*commit)(struct sunxi_engine *engine);
> + void (*commit)(struct sunxi_engine *engine,
> +struct drm_crtc *crtc,
> +struct drm_atomic_state *state);
>  
>   /**
>* @layers_init:
> @@ -144,12 +147,16 @@ struct sunxi_engine {
>  /**
>   * sunxi_engine_commit() - commit all changes of the engine
>   * @engine:  pointer to the engine
> + * @crtc:pointer to crtc the engine is associated with
> + * @state:   atomic state
>   */
>  static inline void
> -sunxi_engine_commit(struct sunxi_engine *engine)
> +sunxi_engine_commit(struct sunxi_engine *engine,
> + struct drm_crtc *crtc,
> + struct drm_atomic_state *state)
>  {
>   if (engine->ops && engine->ops->commit)
> - engine->ops->commit(engine);
> + engine->ops->commit(engine, crtc, state);
>  }
>  
>  /**
> 






Re: [PATCH 1/3] drm/sun4i: Unify sun8i_*_layer structs

2024-02-22 Thread Jernej Škrabec
Dne petek, 16. februar 2024 ob 20:04:24 CET je Ondřej Jirman napisal(a):
> From: Ondrej Jirman 
> 
> These structs are identical, use a single struct to represent private
> data for the DRM plane. This is a preparation for configuring layer
> routing from the CRTC (mixer) instead of current approach of setting
> up routing from individual layer's atomic_update callback.
> 
> Signed-off-by: Ondrej Jirman 

Reviewed-by: Jernej Skrabec 

Best regards,
Jernej

> ---
>  drivers/gpu/drm/sun4i/sun8i_mixer.c|  4 ++--
>  drivers/gpu/drm/sun4i/sun8i_mixer.h| 14 ++
>  drivers/gpu/drm/sun4i/sun8i_ui_layer.c | 14 +++---
>  drivers/gpu/drm/sun4i/sun8i_ui_layer.h | 20 
>  drivers/gpu/drm/sun4i/sun8i_vi_layer.c | 14 +++---
>  drivers/gpu/drm/sun4i/sun8i_vi_layer.h | 20 
>  6 files changed, 38 insertions(+), 48 deletions(-)
> 
> diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.c 
> b/drivers/gpu/drm/sun4i/sun8i_mixer.c
> index 01382860aaee..1e681314e379 100644
> --- a/drivers/gpu/drm/sun4i/sun8i_mixer.c
> +++ b/drivers/gpu/drm/sun4i/sun8i_mixer.c
> @@ -271,7 +271,7 @@ static struct drm_plane **sun8i_layers_init(struct 
> drm_device *drm,
>   return ERR_PTR(-ENOMEM);
>  
>   for (i = 0; i < mixer->cfg->vi_num; i++) {
> - struct sun8i_vi_layer *layer;
> + struct sun8i_layer *layer;
>  
>   layer = sun8i_vi_layer_init_one(drm, mixer, i);
>   if (IS_ERR(layer)) {
> @@ -284,7 +284,7 @@ static struct drm_plane **sun8i_layers_init(struct 
> drm_device *drm,
>   }
>  
>   for (i = 0; i < mixer->cfg->ui_num; i++) {
> - struct sun8i_ui_layer *layer;
> + struct sun8i_layer *layer;
>  
>   layer = sun8i_ui_layer_init_one(drm, mixer, i);
>   if (IS_ERR(layer)) {
> diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.h 
> b/drivers/gpu/drm/sun4i/sun8i_mixer.h
> index 85c94884fb9a..5a610ee30301 100644
> --- a/drivers/gpu/drm/sun4i/sun8i_mixer.h
> +++ b/drivers/gpu/drm/sun4i/sun8i_mixer.h
> @@ -9,6 +9,7 @@
>  #include 
>  #include 
>  #include 
> +#include 
>  
>  #include "sunxi_engine.h"
>  
> @@ -185,6 +186,19 @@ struct sun8i_mixer {
>   struct clk  *mod_clk;
>  };
>  
> +struct sun8i_layer {
> + struct drm_planeplane;
> + struct sun8i_mixer  *mixer;
> + int channel;
> + int overlay;
> +};
> +
> +static inline struct sun8i_layer *
> +plane_to_sun8i_layer(struct drm_plane *plane)
> +{
> + return container_of(plane, struct sun8i_layer, plane);
> +}
> +
>  static inline struct sun8i_mixer *
>  engine_to_sun8i_mixer(struct sunxi_engine *engine)
>  {
> diff --git a/drivers/gpu/drm/sun4i/sun8i_ui_layer.c 
> b/drivers/gpu/drm/sun4i/sun8i_ui_layer.c
> index ca75ca0835a6..248fbb606ede 100644
> --- a/drivers/gpu/drm/sun4i/sun8i_ui_layer.c
> +++ b/drivers/gpu/drm/sun4i/sun8i_ui_layer.c
> @@ -232,7 +232,7 @@ static int sun8i_ui_layer_atomic_check(struct drm_plane 
> *plane,
>  {
>   struct drm_plane_state *new_plane_state = 
> drm_atomic_get_new_plane_state(state,
>   
>  plane);
> - struct sun8i_ui_layer *layer = plane_to_sun8i_ui_layer(plane);
> + struct sun8i_layer *layer = plane_to_sun8i_layer(plane);
>   struct drm_crtc *crtc = new_plane_state->crtc;
>   struct drm_crtc_state *crtc_state;
>   int min_scale, max_scale;
> @@ -264,7 +264,7 @@ static void sun8i_ui_layer_atomic_disable(struct 
> drm_plane *plane,
>  {
>   struct drm_plane_state *old_state = 
> drm_atomic_get_old_plane_state(state,
>  
> plane);
> - struct sun8i_ui_layer *layer = plane_to_sun8i_ui_layer(plane);
> + struct sun8i_layer *layer = plane_to_sun8i_layer(plane);
>   unsigned int old_zpos = old_state->normalized_zpos;
>   struct sun8i_mixer *mixer = layer->mixer;
>  
> @@ -279,7 +279,7 @@ static void sun8i_ui_layer_atomic_update(struct drm_plane 
> *plane,
>  
> plane);
>   struct drm_plane_state *new_state = 
> drm_atomic_get_new_plane_state(state,
>  
> plane);
> - struct sun8i_ui_layer *layer = plane_to_sun8i_ui_layer(plane);
> + struct sun8i_layer *layer = plane_to_sun8i_layer(plane);
>   unsigned int zpos = new_state->normalized_zpos;
>   unsigned int old_zpos = old_state->normalized_zpos;
>   struct sun8i_mixer *mixer = layer->mixer;
> @@ -345,13 +345,13 @@ static const uint64_t sun8i_layer_modifiers[] = {
>   DRM_FORMAT_MOD_INVALID
>  };
>  
> -struct sun8i_ui_layer *sun8i_ui_layer_init_one(struct drm_device *drm,
> -struct sun8i_mixer *mixer,
> -  

Re: [PATCH v7 36/36] drm/sun4i: hdmi: Switch to HDMI connector

2024-02-22 Thread Jernej Škrabec
Dne četrtek, 22. februar 2024 ob 19:14:22 CET je Maxime Ripard napisal(a):
> The new HDMI connector infrastructure allows to remove some boilerplate,
> especially to generate infoframes. Let's switch to it.
> 
> Signed-off-by: Maxime Ripard 

Reviewed-by: Jernej Skrabec 

Best regards,
Jernej

> ---
>  drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c | 80 
> ++
>  1 file changed, 51 insertions(+), 29 deletions(-)
> 
> diff --git a/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c 
> b/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c
> index b7cf369b1906..8a9106a39f23 100644
> --- a/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c
> +++ b/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c
> @@ -36,30 +36,24 @@
>  #define drm_connector_to_sun4i_hdmi(c)   \
>   container_of_const(c, struct sun4i_hdmi, connector)
>  
> -static int sun4i_hdmi_setup_avi_infoframes(struct sun4i_hdmi *hdmi,
> -struct drm_display_mode *mode)
> +static int sun4i_hdmi_write_infoframe(struct drm_connector *connector,
> +   enum hdmi_infoframe_type type,
> +   const u8 *buffer, size_t len)
>  {
> - struct hdmi_avi_infoframe frame;
> - u8 buffer[17];
> - int i, ret;
> + struct sun4i_hdmi *hdmi = drm_connector_to_sun4i_hdmi(connector);
> + int i;
>  
> - ret = drm_hdmi_avi_infoframe_from_display_mode(,
> ->connector, mode);
> - if (ret < 0) {
> - DRM_ERROR("Failed to get infoframes from mode\n");
> - return ret;
> + if (type != HDMI_INFOFRAME_TYPE_AVI) {
> + drm_err(connector->dev,
> + "Unsupported infoframe type: %u\n", type);
> + return 0;
>   }
>  
> - ret = hdmi_avi_infoframe_pack(, buffer, sizeof(buffer));
> - if (ret < 0) {
> - DRM_ERROR("Failed to pack infoframes\n");
> - return ret;
> - }
> -
> - for (i = 0; i < sizeof(buffer); i++)
> + for (i = 0; i < len; i++)
>   writeb(buffer[i], hdmi->base + SUN4I_HDMI_AVI_INFOFRAME_REG(i));
>  
>   return 0;
> +
>  }
>  
>  static void sun4i_hdmi_disable(struct drm_encoder *encoder,
> @@ -82,14 +76,18 @@ static void sun4i_hdmi_enable(struct drm_encoder *encoder,
>  {
>   struct drm_display_mode *mode = >crtc->state->adjusted_mode;
>   struct sun4i_hdmi *hdmi = drm_encoder_to_sun4i_hdmi(encoder);
> - struct drm_display_info *display = >connector.display_info;
> + struct drm_connector *connector = >connector;
> + struct drm_display_info *display = >display_info;
> + struct drm_connector_state *conn_state =
> + drm_atomic_get_new_connector_state(state, connector);
> + unsigned long long tmds_rate = conn_state->hdmi.tmds_char_rate;
>   unsigned int x, y;
>   u32 val = 0;
>  
>   DRM_DEBUG_DRIVER("Enabling the HDMI Output\n");
>  
> - clk_set_rate(hdmi->mod_clk, mode->crtc_clock * 1000);
> - clk_set_rate(hdmi->tmds_clk, mode->crtc_clock * 1000);
> + clk_set_rate(hdmi->mod_clk, tmds_rate);
> + clk_set_rate(hdmi->tmds_clk, tmds_rate);
>  
>   /* Set input sync enable */
>   writel(SUN4I_HDMI_UNKNOWN_INPUT_SYNC,
> @@ -142,7 +140,8 @@ static void sun4i_hdmi_enable(struct drm_encoder *encoder,
>  
>   clk_prepare_enable(hdmi->tmds_clk);
>  
> - sun4i_hdmi_setup_avi_infoframes(hdmi, mode);
> + drm_atomic_helper_connector_hdmi_update_infoframes(connector, state);
> +
>   val |= SUN4I_HDMI_PKT_CTRL_TYPE(0, SUN4I_HDMI_PKT_AVI);
>   val |= SUN4I_HDMI_PKT_CTRL_TYPE(1, SUN4I_HDMI_PKT_END);
>   writel(val, hdmi->base + SUN4I_HDMI_PKT_CTRL_REG(0));
> @@ -195,7 +194,7 @@ static int sun4i_hdmi_connector_atomic_check(struct 
> drm_connector *connector,
>   enum drm_mode_status status;
>  
>   status = sun4i_hdmi_connector_clock_valid(connector, mode,
> -   mode->clock * 1000);
> +   
> conn_state->hdmi.tmds_char_rate);
>   if (status != MODE_OK)
>   return -EINVAL;
>  
> @@ -206,8 +205,11 @@ static enum drm_mode_status
>  sun4i_hdmi_connector_mode_valid(struct drm_connector *connector,
>   struct drm_display_mode *mode)
>  {
> - return sun4i_hdmi_connector_clock_valid(connector, mode,
> - mode->clock * 1000);
> + unsigned long long rate =
> + drm_connector_hdmi_compute_mode_clock(mode, 8,
> +   HDMI_COLORSPACE_RGB);
> +
> + return sun4i_hdmi_connector_clock_valid(connector, mode, rate);
>  }
>  
>  static int sun4i_hdmi_get_modes(struct drm_connector *connector)
> @@ -253,6 +255,11 @@ static struct i2c_adapter *sun4i_hdmi_get_ddc(struct 
> device *dev)
>   return ddc;
>  }
>  
> +static const struct drm_connector_hdmi_funcs 

Re: [PATCH v7 35/36] drm/sun4i: hdmi: Consolidate atomic_check and mode_valid

2024-02-22 Thread Jernej Škrabec
Dne četrtek, 22. februar 2024 ob 19:14:21 CET je Maxime Ripard napisal(a):
> atomic_check and mode_valid do not check for the same things which can
> lead to surprising result if the userspace commits a mode that didn't go
> through mode_valid. Let's merge the two implementations into a function
> called by both.
> 
> Acked-by: Sui Jingfeng 
> Signed-off-by: Maxime Ripard 

Reviewed-by: Jernej Skrabec 

Best regards,
Jernej

> ---
>  drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c | 74 
> +-
>  1 file changed, 47 insertions(+), 27 deletions(-)
> 
> diff --git a/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c 
> b/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c
> index c276d984da6b..b7cf369b1906 100644
> --- a/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c
> +++ b/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c
> @@ -62,18 +62,6 @@ static int sun4i_hdmi_setup_avi_infoframes(struct 
> sun4i_hdmi *hdmi,
>   return 0;
>  }
>  
> -static int sun4i_hdmi_atomic_check(struct drm_encoder *encoder,
> -struct drm_crtc_state *crtc_state,
> -struct drm_connector_state *conn_state)
> -{
> - struct drm_display_mode *mode = _state->mode;
> -
> - if (mode->flags & DRM_MODE_FLAG_DBLCLK)
> - return -EINVAL;
> -
> - return 0;
> -}
> -
>  static void sun4i_hdmi_disable(struct drm_encoder *encoder,
>  struct drm_atomic_state *state)
>  {
> @@ -166,31 +154,61 @@ static void sun4i_hdmi_enable(struct drm_encoder 
> *encoder,
>   writel(val, hdmi->base + SUN4I_HDMI_VID_CTRL_REG);
>  }
>  
> -static enum drm_mode_status sun4i_hdmi_mode_valid(struct drm_encoder 
> *encoder,
> - const struct drm_display_mode *mode)
> +static const struct drm_encoder_helper_funcs sun4i_hdmi_helper_funcs = {
> + .atomic_disable = sun4i_hdmi_disable,
> + .atomic_enable  = sun4i_hdmi_enable,
> +};
> +
> +static enum drm_mode_status
> +sun4i_hdmi_connector_clock_valid(const struct drm_connector *connector,
> +  const struct drm_display_mode *mode,
> +  unsigned long long clock)
>  {
> - struct sun4i_hdmi *hdmi = drm_encoder_to_sun4i_hdmi(encoder);
> - unsigned long rate = mode->clock * 1000;
> - unsigned long diff = rate / 200; /* +-0.5% allowed by HDMI spec */
> + const struct sun4i_hdmi *hdmi = drm_connector_to_sun4i_hdmi(connector);
> + unsigned long diff = clock / 200; /* +-0.5% allowed by HDMI spec */
>   long rounded_rate;
>  
> + if (mode->flags & DRM_MODE_FLAG_DBLCLK)
> + return MODE_BAD;
> +
>   /* 165 MHz is the typical max pixelclock frequency for HDMI <= 1.2 */
> - if (rate > 16500)
> + if (clock > 16500)
>   return MODE_CLOCK_HIGH;
> - rounded_rate = clk_round_rate(hdmi->tmds_clk, rate);
> +
> + rounded_rate = clk_round_rate(hdmi->tmds_clk, clock);
>   if (rounded_rate > 0 &&
> - max_t(unsigned long, rounded_rate, rate) -
> - min_t(unsigned long, rounded_rate, rate) < diff)
> + max_t(unsigned long, rounded_rate, clock) -
> + min_t(unsigned long, rounded_rate, clock) < diff)
>   return MODE_OK;
> +
>   return MODE_NOCLOCK;
>  }
>  
> -static const struct drm_encoder_helper_funcs sun4i_hdmi_helper_funcs = {
> - .atomic_check   = sun4i_hdmi_atomic_check,
> - .atomic_disable = sun4i_hdmi_disable,
> - .atomic_enable  = sun4i_hdmi_enable,
> - .mode_valid = sun4i_hdmi_mode_valid,
> -};
> +static int sun4i_hdmi_connector_atomic_check(struct drm_connector *connector,
> +  struct drm_atomic_state *state)
> +{
> + struct drm_connector_state *conn_state =
> + drm_atomic_get_new_connector_state(state, connector);
> + struct drm_crtc *crtc = conn_state->crtc;
> + struct drm_crtc_state *crtc_state = crtc->state;
> + struct drm_display_mode *mode = _state->adjusted_mode;
> + enum drm_mode_status status;
> +
> + status = sun4i_hdmi_connector_clock_valid(connector, mode,
> +   mode->clock * 1000);
> + if (status != MODE_OK)
> + return -EINVAL;
> +
> + return 0;
> +}
> +
> +static enum drm_mode_status
> +sun4i_hdmi_connector_mode_valid(struct drm_connector *connector,
> + struct drm_display_mode *mode)
> +{
> + return sun4i_hdmi_connector_clock_valid(connector, mode,
> + mode->clock * 1000);
> +}
>  
>  static int sun4i_hdmi_get_modes(struct drm_connector *connector)
>  {
> @@ -236,6 +254,8 @@ static struct i2c_adapter *sun4i_hdmi_get_ddc(struct 
> device *dev)
>  }
>  
>  static const struct drm_connector_helper_funcs 
> sun4i_hdmi_connector_helper_funcs = {
> + .atomic_check   = sun4i_hdmi_connector_atomic_check,
> + .mode_valid = sun4i_hdmi_connector_mode_valid,
>   

Re: [PATCH v3 2/2] drm/dp: drop the size parameter from drm_dp_vsc_sdp_pack()

2024-02-22 Thread Rodrigo Vivi
On Tue, Feb 20, 2024 at 11:53:47AM -0800, Abhinav Kumar wrote:
> Currently the size parameter of drm_dp_vsc_sdp_pack() is always
> the size of struct dp_sdp. Hence lets drop this parameter and
> use sizeof() directly.
> 
> Suggested-by: Dmitry Baryshkov 
> Signed-off-by: Abhinav Kumar 

it looks indeed an unecessary check.
you can convert my ack to a

Reviewed-by: Rodrigo Vivi 

and the ack to take this through drm-misc if needed

> ---
>  drivers/gpu/drm/display/drm_dp_helper.c | 8 ++--
>  drivers/gpu/drm/i915/display/intel_dp.c | 3 +--
>  include/drm/display/drm_dp_helper.h | 3 +--
>  3 files changed, 4 insertions(+), 10 deletions(-)
> 
> diff --git a/drivers/gpu/drm/display/drm_dp_helper.c 
> b/drivers/gpu/drm/display/drm_dp_helper.c
> index 6c91f400ecb1..10ee82e34de7 100644
> --- a/drivers/gpu/drm/display/drm_dp_helper.c
> +++ b/drivers/gpu/drm/display/drm_dp_helper.c
> @@ -2918,19 +2918,15 @@ EXPORT_SYMBOL(drm_dp_vsc_sdp_log);
>   * @vsc: vsc sdp initialized according to its purpose as defined in
>   *   table 2-118 - table 2-120 in DP 1.4a specification
>   * @sdp: valid handle to the generic dp_sdp which will be packed
> - * @size: valid size of the passed sdp handle
>   *
>   * Returns length of sdp on success and error code on failure
>   */
>  ssize_t drm_dp_vsc_sdp_pack(const struct drm_dp_vsc_sdp *vsc,
> - struct dp_sdp *sdp, size_t size)
> + struct dp_sdp *sdp)
>  {
>   size_t length = sizeof(struct dp_sdp);
>  
> - if (size < length)
> - return -ENOSPC;
> -
> - memset(sdp, 0, size);
> + memset(sdp, 0, sizeof(struct dp_sdp));
>  
>   /*
>* Prepare VSC Header for SU as per DP 1.4a spec, Table 2-119
> diff --git a/drivers/gpu/drm/i915/display/intel_dp.c 
> b/drivers/gpu/drm/i915/display/intel_dp.c
> index a9458df475e2..e13121dc3a03 100644
> --- a/drivers/gpu/drm/i915/display/intel_dp.c
> +++ b/drivers/gpu/drm/i915/display/intel_dp.c
> @@ -4181,8 +4181,7 @@ static void intel_write_dp_sdp(struct intel_encoder 
> *encoder,
>  
>   switch (type) {
>   case DP_SDP_VSC:
> - len = drm_dp_vsc_sdp_pack(_state->infoframes.vsc, ,
> -   sizeof(sdp));
> + len = drm_dp_vsc_sdp_pack(_state->infoframes.vsc, );
>   break;
>   case HDMI_PACKET_TYPE_GAMUT_METADATA:
>   len = intel_dp_hdr_metadata_infoframe_sdp_pack(dev_priv,
> diff --git a/include/drm/display/drm_dp_helper.h 
> b/include/drm/display/drm_dp_helper.h
> index 8474504d4c88..1f41994796d3 100644
> --- a/include/drm/display/drm_dp_helper.h
> +++ b/include/drm/display/drm_dp_helper.h
> @@ -812,7 +812,6 @@ int drm_dp_bw_overhead(int lane_count, int hactive,
>  int bpp_x16, unsigned long flags);
>  int drm_dp_bw_channel_coding_efficiency(bool is_uhbr);
>  
> -ssize_t drm_dp_vsc_sdp_pack(const struct drm_dp_vsc_sdp *vsc,
> - struct dp_sdp *sdp, size_t size);
> +ssize_t drm_dp_vsc_sdp_pack(const struct drm_dp_vsc_sdp *vsc, struct dp_sdp 
> *sdp);
>  
>  #endif /* _DRM_DP_HELPER_H_ */
> -- 
> 2.34.1
> 


Re: [PATCH v7 34/36] drm/sun4i: hdmi: Switch to container_of_const

2024-02-22 Thread Jernej Škrabec
Dne četrtek, 22. februar 2024 ob 19:14:20 CET je Maxime Ripard napisal(a):
> container_of_const() allows to preserve the pointer constness and is
> thus more flexible than inline functions.
> 
> Let's switch all our instances of container_of() to container_of_const().
> 
> Reviewed-by: Sui Jingfeng 
> Signed-off-by: Maxime Ripard 

Reviewed-by: Jernej Skrabec 

Best regards,
Jernej

> ---
>  drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c | 16 
>  1 file changed, 4 insertions(+), 12 deletions(-)
> 
> diff --git a/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c 
> b/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c
> index bae69d696765..c276d984da6b 100644
> --- a/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c
> +++ b/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c
> @@ -30,19 +30,11 @@
>  #include "sun4i_drv.h"
>  #include "sun4i_hdmi.h"
>  
> -static inline struct sun4i_hdmi *
> -drm_encoder_to_sun4i_hdmi(struct drm_encoder *encoder)
> -{
> - return container_of(encoder, struct sun4i_hdmi,
> - encoder);
> -}
> +#define drm_encoder_to_sun4i_hdmi(e) \
> + container_of_const(e, struct sun4i_hdmi, encoder)
>  
> -static inline struct sun4i_hdmi *
> -drm_connector_to_sun4i_hdmi(struct drm_connector *connector)
> -{
> - return container_of(connector, struct sun4i_hdmi,
> - connector);
> -}
> +#define drm_connector_to_sun4i_hdmi(c)   \
> + container_of_const(c, struct sun4i_hdmi, connector)
>  
>  static int sun4i_hdmi_setup_avi_infoframes(struct sun4i_hdmi *hdmi,
>  struct drm_display_mode *mode)
> 
> 






Re: [PATCH v7 33/36] drm/sun4i: hdmi: Move mode_set into enable

2024-02-22 Thread Jernej Škrabec
Dne četrtek, 22. februar 2024 ob 19:14:19 CET je Maxime Ripard napisal(a):
> We're not doing anything special in atomic_mode_set so we can simply
> merge it into atomic_enable.
> 
> Acked-by: Sui Jingfeng 
> Signed-off-by: Maxime Ripard 

Reviewed-by: Jernej Skrabec 

Best regards,
Jernej

> ---
>  drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c | 38 
> +-
>  1 file changed, 14 insertions(+), 24 deletions(-)
> 
> diff --git a/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c 
> b/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c
> index 799a26215cc2..bae69d696765 100644
> --- a/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c
> +++ b/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c
> @@ -103,33 +103,11 @@ static void sun4i_hdmi_enable(struct drm_encoder 
> *encoder,
>   struct drm_display_mode *mode = >crtc->state->adjusted_mode;
>   struct sun4i_hdmi *hdmi = drm_encoder_to_sun4i_hdmi(encoder);
>   struct drm_display_info *display = >connector.display_info;
> + unsigned int x, y;
>   u32 val = 0;
>  
>   DRM_DEBUG_DRIVER("Enabling the HDMI Output\n");
>  
> - clk_prepare_enable(hdmi->tmds_clk);
> -
> - sun4i_hdmi_setup_avi_infoframes(hdmi, mode);
> - val |= SUN4I_HDMI_PKT_CTRL_TYPE(0, SUN4I_HDMI_PKT_AVI);
> - val |= SUN4I_HDMI_PKT_CTRL_TYPE(1, SUN4I_HDMI_PKT_END);
> - writel(val, hdmi->base + SUN4I_HDMI_PKT_CTRL_REG(0));
> -
> - val = SUN4I_HDMI_VID_CTRL_ENABLE;
> - if (display->is_hdmi)
> - val |= SUN4I_HDMI_VID_CTRL_HDMI_MODE;
> -
> - writel(val, hdmi->base + SUN4I_HDMI_VID_CTRL_REG);
> -}
> -
> -static void sun4i_hdmi_mode_set(struct drm_encoder *encoder,
> - struct drm_crtc_state *crtc_state,
> - struct drm_connector_state *conn_state)
> -{
> - const struct drm_display_mode *mode = _state->mode;
> - struct sun4i_hdmi *hdmi = drm_encoder_to_sun4i_hdmi(encoder);
> - unsigned int x, y;
> - u32 val;
> -
>   clk_set_rate(hdmi->mod_clk, mode->crtc_clock * 1000);
>   clk_set_rate(hdmi->tmds_clk, mode->crtc_clock * 1000);
>  
> @@ -181,6 +159,19 @@ static void sun4i_hdmi_mode_set(struct drm_encoder 
> *encoder,
>   val |= SUN4I_HDMI_VID_TIMING_POL_VSYNC;
>  
>   writel(val, hdmi->base + SUN4I_HDMI_VID_TIMING_POL_REG);
> +
> + clk_prepare_enable(hdmi->tmds_clk);
> +
> + sun4i_hdmi_setup_avi_infoframes(hdmi, mode);
> + val |= SUN4I_HDMI_PKT_CTRL_TYPE(0, SUN4I_HDMI_PKT_AVI);
> + val |= SUN4I_HDMI_PKT_CTRL_TYPE(1, SUN4I_HDMI_PKT_END);
> + writel(val, hdmi->base + SUN4I_HDMI_PKT_CTRL_REG(0));
> +
> + val = SUN4I_HDMI_VID_CTRL_ENABLE;
> + if (display->is_hdmi)
> + val |= SUN4I_HDMI_VID_CTRL_HDMI_MODE;
> +
> + writel(val, hdmi->base + SUN4I_HDMI_VID_CTRL_REG);
>  }
>  
>  static enum drm_mode_status sun4i_hdmi_mode_valid(struct drm_encoder 
> *encoder,
> @@ -206,7 +197,6 @@ static const struct drm_encoder_helper_funcs 
> sun4i_hdmi_helper_funcs = {
>   .atomic_check   = sun4i_hdmi_atomic_check,
>   .atomic_disable = sun4i_hdmi_disable,
>   .atomic_enable  = sun4i_hdmi_enable,
> - .atomic_mode_set= sun4i_hdmi_mode_set,
>   .mode_valid = sun4i_hdmi_mode_valid,
>  };
>  
> 
> 






Re: [PATCH v7 32/36] drm/sun4i: hdmi: Convert encoder to atomic

2024-02-22 Thread Jernej Škrabec
Dne četrtek, 22. februar 2024 ob 19:14:18 CET je Maxime Ripard napisal(a):
> The sun4i_hdmi driver still uses the non-atomic variants of the encoder
> hooks, so let's convert to their atomic equivalents.
> 
> Acked-by: Sui Jingfeng 
> Signed-off-by: Maxime Ripard 

Reviewed-by: Jernej Skrabec 

Best regards,
Jernej

> ---
>  drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c | 17 ++---
>  1 file changed, 10 insertions(+), 7 deletions(-)
> 
> diff --git a/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c 
> b/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c
> index 152375f3de2e..799a26215cc2 100644
> --- a/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c
> +++ b/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c
> @@ -82,7 +82,8 @@ static int sun4i_hdmi_atomic_check(struct drm_encoder 
> *encoder,
>   return 0;
>  }
>  
> -static void sun4i_hdmi_disable(struct drm_encoder *encoder)
> +static void sun4i_hdmi_disable(struct drm_encoder *encoder,
> +struct drm_atomic_state *state)
>  {
>   struct sun4i_hdmi *hdmi = drm_encoder_to_sun4i_hdmi(encoder);
>   u32 val;
> @@ -96,7 +97,8 @@ static void sun4i_hdmi_disable(struct drm_encoder *encoder)
>   clk_disable_unprepare(hdmi->tmds_clk);
>  }
>  
> -static void sun4i_hdmi_enable(struct drm_encoder *encoder)
> +static void sun4i_hdmi_enable(struct drm_encoder *encoder,
> +   struct drm_atomic_state *state)
>  {
>   struct drm_display_mode *mode = >crtc->state->adjusted_mode;
>   struct sun4i_hdmi *hdmi = drm_encoder_to_sun4i_hdmi(encoder);
> @@ -120,9 +122,10 @@ static void sun4i_hdmi_enable(struct drm_encoder 
> *encoder)
>  }
>  
>  static void sun4i_hdmi_mode_set(struct drm_encoder *encoder,
> - struct drm_display_mode *mode,
> - struct drm_display_mode *adjusted_mode)
> + struct drm_crtc_state *crtc_state,
> + struct drm_connector_state *conn_state)
>  {
> + const struct drm_display_mode *mode = _state->mode;
>   struct sun4i_hdmi *hdmi = drm_encoder_to_sun4i_hdmi(encoder);
>   unsigned int x, y;
>   u32 val;
> @@ -201,9 +204,9 @@ static enum drm_mode_status sun4i_hdmi_mode_valid(struct 
> drm_encoder *encoder,
>  
>  static const struct drm_encoder_helper_funcs sun4i_hdmi_helper_funcs = {
>   .atomic_check   = sun4i_hdmi_atomic_check,
> - .disable= sun4i_hdmi_disable,
> - .enable = sun4i_hdmi_enable,
> - .mode_set   = sun4i_hdmi_mode_set,
> + .atomic_disable = sun4i_hdmi_disable,
> + .atomic_enable  = sun4i_hdmi_enable,
> + .atomic_mode_set= sun4i_hdmi_mode_set,
>   .mode_valid = sun4i_hdmi_mode_valid,
>  };
>  
> 
> 






Re: [PATCH v3 2/2] drm/dp: drop the size parameter from drm_dp_vsc_sdp_pack()

2024-02-22 Thread Rodrigo Vivi
On Tue, Feb 20, 2024 at 11:53:47AM -0800, Abhinav Kumar wrote:
> Currently the size parameter of drm_dp_vsc_sdp_pack() is always
> the size of struct dp_sdp. Hence lets drop this parameter and
> use sizeof() directly.
> 
> Suggested-by: Dmitry Baryshkov 
> Signed-off-by: Abhinav Kumar 
> ---
>  drivers/gpu/drm/display/drm_dp_helper.c | 8 ++--
>  drivers/gpu/drm/i915/display/intel_dp.c | 3 +--

Acked-by: Rodrigo Vivi 

>  include/drm/display/drm_dp_helper.h | 3 +--
>  3 files changed, 4 insertions(+), 10 deletions(-)
> 
> diff --git a/drivers/gpu/drm/display/drm_dp_helper.c 
> b/drivers/gpu/drm/display/drm_dp_helper.c
> index 6c91f400ecb1..10ee82e34de7 100644
> --- a/drivers/gpu/drm/display/drm_dp_helper.c
> +++ b/drivers/gpu/drm/display/drm_dp_helper.c
> @@ -2918,19 +2918,15 @@ EXPORT_SYMBOL(drm_dp_vsc_sdp_log);
>   * @vsc: vsc sdp initialized according to its purpose as defined in
>   *   table 2-118 - table 2-120 in DP 1.4a specification
>   * @sdp: valid handle to the generic dp_sdp which will be packed
> - * @size: valid size of the passed sdp handle
>   *
>   * Returns length of sdp on success and error code on failure
>   */
>  ssize_t drm_dp_vsc_sdp_pack(const struct drm_dp_vsc_sdp *vsc,
> - struct dp_sdp *sdp, size_t size)
> + struct dp_sdp *sdp)
>  {
>   size_t length = sizeof(struct dp_sdp);
>  
> - if (size < length)
> - return -ENOSPC;
> -
> - memset(sdp, 0, size);
> + memset(sdp, 0, sizeof(struct dp_sdp));
>  
>   /*
>* Prepare VSC Header for SU as per DP 1.4a spec, Table 2-119
> diff --git a/drivers/gpu/drm/i915/display/intel_dp.c 
> b/drivers/gpu/drm/i915/display/intel_dp.c
> index a9458df475e2..e13121dc3a03 100644
> --- a/drivers/gpu/drm/i915/display/intel_dp.c
> +++ b/drivers/gpu/drm/i915/display/intel_dp.c
> @@ -4181,8 +4181,7 @@ static void intel_write_dp_sdp(struct intel_encoder 
> *encoder,
>  
>   switch (type) {
>   case DP_SDP_VSC:
> - len = drm_dp_vsc_sdp_pack(_state->infoframes.vsc, ,
> -   sizeof(sdp));
> + len = drm_dp_vsc_sdp_pack(_state->infoframes.vsc, );
>   break;
>   case HDMI_PACKET_TYPE_GAMUT_METADATA:
>   len = intel_dp_hdr_metadata_infoframe_sdp_pack(dev_priv,
> diff --git a/include/drm/display/drm_dp_helper.h 
> b/include/drm/display/drm_dp_helper.h
> index 8474504d4c88..1f41994796d3 100644
> --- a/include/drm/display/drm_dp_helper.h
> +++ b/include/drm/display/drm_dp_helper.h
> @@ -812,7 +812,6 @@ int drm_dp_bw_overhead(int lane_count, int hactive,
>  int bpp_x16, unsigned long flags);
>  int drm_dp_bw_channel_coding_efficiency(bool is_uhbr);
>  
> -ssize_t drm_dp_vsc_sdp_pack(const struct drm_dp_vsc_sdp *vsc,
> - struct dp_sdp *sdp, size_t size);
> +ssize_t drm_dp_vsc_sdp_pack(const struct drm_dp_vsc_sdp *vsc, struct dp_sdp 
> *sdp);
>  
>  #endif /* _DRM_DP_HELPER_H_ */
> -- 
> 2.34.1
> 


Re: [PATCH] drm/i915: Add missing ; to __assign_str() macros in tracepoint code

2024-02-22 Thread Rodrigo Vivi
On Thu, Feb 22, 2024 at 01:43:49PM -0500, Steven Rostedt wrote:
> On Thu, 22 Feb 2024 13:30:57 -0500
> Steven Rostedt  wrote:
> 
> > From: "Steven Rostedt (Google)" 
> > 
> > I'm working on improving the __assign_str() and __string() macros to be
> > more efficient, and removed some unneeded semicolons. This triggered a bug
> > in the build as some of the __assign_str() macros in intel_display_trace
> > was missing a terminating semicolon.
> > 
> > Fixes: 2ceea5d88048b ("drm/i915: Print plane name in fbc tracepoints")
> > Signed-off-by: Steven Rostedt (Google) 
> > ---
> 
> Note, I have patches that depend on this fix, so if one of the maintainers
> would like to just give me an "Acked-by", I'll take it through my tree. I
> doubt it will have any conflicts, unless you are planning on changing the
> given effected events.

since it is not breaking builds on our side and the conflicts, if any, would
be minimal, feel free to take this trough your tree

Acked-by: Rodrigo Vivi 

> 
> -- Steve


Re: [PATCH] drm/i915: Add missing ; to __assign_str() macros in tracepoint code

2024-02-22 Thread Steven Rostedt
On Thu, 22 Feb 2024 20:42:59 +0200
Ville Syrjälä  wrote:

> On Thu, Feb 22, 2024 at 01:30:57PM -0500, Steven Rostedt wrote:
> > From: "Steven Rostedt (Google)" 
> > 
> > I'm working on improving the __assign_str() and __string() macros to be
> > more efficient, and removed some unneeded semicolons. This triggered a bug
> > in the build as some of the __assign_str() macros in intel_display_trace
> > was missing a terminating semicolon.
> > 
> > Fixes: 2ceea5d88048b ("drm/i915: Print plane name in fbc tracepoints")
> > Signed-off-by: Steven Rostedt (Google)   
> 
> Reviewed-by: Ville Syrjälä 
> 
> Do you want me to apply this to drm-intel or do you want to take
> it through some other tree? Either way seems fine for this stuff.

Thanks. I would like to add it to my tree as my changes rely on it.

But I think to do that, I still need an Acked-by from one of the
maintainers listed in the MAINTAINERS file.

-- Steve


Re: [PATCH] drm/i915: Add missing ; to __assign_str() macros in tracepoint code

2024-02-22 Thread Ville Syrjälä
On Thu, Feb 22, 2024 at 01:30:57PM -0500, Steven Rostedt wrote:
> From: "Steven Rostedt (Google)" 
> 
> I'm working on improving the __assign_str() and __string() macros to be
> more efficient, and removed some unneeded semicolons. This triggered a bug
> in the build as some of the __assign_str() macros in intel_display_trace
> was missing a terminating semicolon.
> 
> Fixes: 2ceea5d88048b ("drm/i915: Print plane name in fbc tracepoints")
> Signed-off-by: Steven Rostedt (Google) 

Reviewed-by: Ville Syrjälä 

Do you want me to apply this to drm-intel or do you want to take
it through some other tree? Either way seems fine for this stuff.

> ---
>  drivers/gpu/drm/i915/display/intel_display_trace.h | 6 +++---
>  1 file changed, 3 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/display/intel_display_trace.h 
> b/drivers/gpu/drm/i915/display/intel_display_trace.h
> index 99bdb833591c..7862e7cefe02 100644
> --- a/drivers/gpu/drm/i915/display/intel_display_trace.h
> +++ b/drivers/gpu/drm/i915/display/intel_display_trace.h
> @@ -411,7 +411,7 @@ TRACE_EVENT(intel_fbc_activate,
>  struct intel_crtc *crtc = 
> intel_crtc_for_pipe(to_i915(plane->base.dev),
>
> plane->pipe);
>  __assign_str(dev, __dev_name_kms(plane));
> -__assign_str(name, plane->base.name)
> +__assign_str(name, plane->base.name);
>  __entry->pipe = crtc->pipe;
>  __entry->frame = intel_crtc_get_vblank_counter(crtc);
>  __entry->scanline = intel_get_crtc_scanline(crtc);
> @@ -438,7 +438,7 @@ TRACE_EVENT(intel_fbc_deactivate,
>  struct intel_crtc *crtc = 
> intel_crtc_for_pipe(to_i915(plane->base.dev),
>
> plane->pipe);
>  __assign_str(dev, __dev_name_kms(plane));
> -__assign_str(name, plane->base.name)
> +__assign_str(name, plane->base.name);
>  __entry->pipe = crtc->pipe;
>  __entry->frame = intel_crtc_get_vblank_counter(crtc);
>  __entry->scanline = intel_get_crtc_scanline(crtc);
> @@ -465,7 +465,7 @@ TRACE_EVENT(intel_fbc_nuke,
>  struct intel_crtc *crtc = 
> intel_crtc_for_pipe(to_i915(plane->base.dev),
>
> plane->pipe);
>  __assign_str(dev, __dev_name_kms(plane));
> -__assign_str(name, plane->base.name)
> +__assign_str(name, plane->base.name);
>  __entry->pipe = crtc->pipe;
>  __entry->frame = intel_crtc_get_vblank_counter(crtc);
>  __entry->scanline = intel_get_crtc_scanline(crtc);
> -- 
> 2.43.0

-- 
Ville Syrjälä
Intel


Re: [PATCH] drm/i915: Add missing ; to __assign_str() macros in tracepoint code

2024-02-22 Thread Steven Rostedt
On Thu, 22 Feb 2024 13:30:57 -0500
Steven Rostedt  wrote:

> From: "Steven Rostedt (Google)" 
> 
> I'm working on improving the __assign_str() and __string() macros to be
> more efficient, and removed some unneeded semicolons. This triggered a bug
> in the build as some of the __assign_str() macros in intel_display_trace
> was missing a terminating semicolon.
> 
> Fixes: 2ceea5d88048b ("drm/i915: Print plane name in fbc tracepoints")
> Signed-off-by: Steven Rostedt (Google) 
> ---

Note, I have patches that depend on this fix, so if one of the maintainers
would like to just give me an "Acked-by", I'll take it through my tree. I
doubt it will have any conflicts, unless you are planning on changing the
given effected events.

-- Steve


Re: [PATCH 1/2] devm-helpers: Add resource managed version of mutex init

2024-02-22 Thread Hans de Goede
Hi,

On 2/22/24 17:44, Matthew Auld wrote:
> On 22/02/2024 14:58, Marek Behún wrote:
>> A few drivers are doing resource-managed mutex initialization by
>> implementing ad-hoc one-liner mutex dropping functions and using them
>> with devm_add_action_or_reset(). Help drivers avoid these repeated
>> one-liners by adding managed version of mutex initialization.



>> index 74891802200d..70640fb96117 100644
>> --- a/include/linux/devm-helpers.h
>> +++ b/include/linux/devm-helpers.h
>> @@ -24,6 +24,8 @@
>>    */
>>     #include 
>> +#include 
>> +#include 
>>   #include 
>>     static inline void devm_delayed_work_drop(void *res)
>> @@ -76,4 +78,34 @@ static inline int devm_work_autocancel(struct device *dev,
>>   return devm_add_action(dev, devm_work_drop, w);
>>   }
>>   +static inline void devm_mutex_drop(void *res)
>> +{
>> +    mutex_destroy(res);
>> +}
>> +
>> +/**
>> + * devm_mutex_init - Resource managed mutex initialization
>> + * @dev:    Device which lifetime mutex is bound to
>> + * @lock:    Mutex to be initialized (and automatically destroyed)
>> + *
>> + * Initialize mutex which is automatically destroyed when driver is 
>> detached.
>> + * A few drivers initialize mutexes which they want destroyed before driver 
>> is
>> + * detached, for debugging purposes.
>> + * devm_mutex_init() can be used to omit the explicit mutex_destroy() call 
>> when
>> + * driver is detached.
>> + */
>> +static inline int devm_mutex_init(struct device *dev, struct mutex *lock)
>> +{
>> +    mutex_init(lock);
> 
> Do you know if this this needs __always_inline? The static lockdep key in 
> mutex_init() should be
> different for each caller class. See c21f11d182c2 ("drm: fix 
> drmm_mutex_init()").

That is a very good point. I believe that this should mirror mutex_init() and
the actual static inline function should be __devm_mutex_init() which takes
the key as extra argument (and calls __mutex_init()) and then make
devm_mutex_init() itself a macro mirroring the mutex_init() macro.

Regards,

Hans






> 
>> +
>> +    /*
>> + * mutex_destroy() is an empty function if CONFIG_DEBUG_MUTEXES is
>> + * disabled. No need to allocate an action in that case.
>> + */
>> +    if (IS_ENABLED(CONFIG_DEBUG_MUTEXES))
>> +    return devm_add_action_or_reset(dev, devm_mutex_drop, lock);
>> +    else
>> +    return 0;
>> +}
>> +
>>   #endif
> 



Re: [PATCH 3/9] arm64: dts: qcom: sc7280: Enable MDP turbo mode

2024-02-22 Thread Abhinav Kumar




On 2/22/2024 1:46 AM, Dmitry Baryshkov wrote:

On Thu, 22 Feb 2024 at 11:28, Konrad Dybcio  wrote:




On 2/22/24 10:04, Dmitry Baryshkov wrote:

On Thu, 22 Feb 2024 at 10:56, Konrad Dybcio  wrote:




On 2/22/24 00:41, Dmitry Baryshkov wrote:

On Thu, 22 Feb 2024 at 01:19, Bjorn Andersson  wrote:


The max frequency listed in the DPU opp-table is 506MHz, this is not
sufficient to drive a 4k@60 display, resulting in constant underrun.

Add the missing MDP_CLK turbo frequency of 608MHz to the opp-table to
fix this.


I think we might want to keep this disabled for ChromeOS devices. Doug?


ChromeOS devices don't get a special SoC


But they have the sc7280-chrome-common.dtsi, which might contain a
corresponding /delete-node/ .


What does that change? The clock rates are bound to the
SoC and the effective values are limited by link-frequencies
or the panel driver.


Preventing the DPU from overheating? Or spending too much power?



Running DPU clock in turbo is a requirement to support 4k@60 otherwise 
the pixel rate that high cannot be supported.


sc7280 chrome devices already limit to HBR2

https://lore.kernel.org/all/20230329233416.27152-1-quic_abhin...@quicinc.com/

So the DPU will not vote more than nominal.

And like others wrote, limiting SOC frequencies is not the way and we 
should filter out required frequencies using link-frequencies.


Hence fwiw, I am fine with this change.


Reviewed-by: Abhinav Kumar 



[PATCH] drm/i915: Add missing ; to __assign_str() macros in tracepoint code

2024-02-22 Thread Steven Rostedt
From: "Steven Rostedt (Google)" 

I'm working on improving the __assign_str() and __string() macros to be
more efficient, and removed some unneeded semicolons. This triggered a bug
in the build as some of the __assign_str() macros in intel_display_trace
was missing a terminating semicolon.

Fixes: 2ceea5d88048b ("drm/i915: Print plane name in fbc tracepoints")
Signed-off-by: Steven Rostedt (Google) 
---
 drivers/gpu/drm/i915/display/intel_display_trace.h | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_display_trace.h 
b/drivers/gpu/drm/i915/display/intel_display_trace.h
index 99bdb833591c..7862e7cefe02 100644
--- a/drivers/gpu/drm/i915/display/intel_display_trace.h
+++ b/drivers/gpu/drm/i915/display/intel_display_trace.h
@@ -411,7 +411,7 @@ TRACE_EVENT(intel_fbc_activate,
   struct intel_crtc *crtc = 
intel_crtc_for_pipe(to_i915(plane->base.dev),
 
plane->pipe);
   __assign_str(dev, __dev_name_kms(plane));
-  __assign_str(name, plane->base.name)
+  __assign_str(name, plane->base.name);
   __entry->pipe = crtc->pipe;
   __entry->frame = intel_crtc_get_vblank_counter(crtc);
   __entry->scanline = intel_get_crtc_scanline(crtc);
@@ -438,7 +438,7 @@ TRACE_EVENT(intel_fbc_deactivate,
   struct intel_crtc *crtc = 
intel_crtc_for_pipe(to_i915(plane->base.dev),
 
plane->pipe);
   __assign_str(dev, __dev_name_kms(plane));
-  __assign_str(name, plane->base.name)
+  __assign_str(name, plane->base.name);
   __entry->pipe = crtc->pipe;
   __entry->frame = intel_crtc_get_vblank_counter(crtc);
   __entry->scanline = intel_get_crtc_scanline(crtc);
@@ -465,7 +465,7 @@ TRACE_EVENT(intel_fbc_nuke,
   struct intel_crtc *crtc = 
intel_crtc_for_pipe(to_i915(plane->base.dev),
 
plane->pipe);
   __assign_str(dev, __dev_name_kms(plane));
-  __assign_str(name, plane->base.name)
+  __assign_str(name, plane->base.name);
   __entry->pipe = crtc->pipe;
   __entry->frame = intel_crtc_get_vblank_counter(crtc);
   __entry->scanline = intel_get_crtc_scanline(crtc);
-- 
2.43.0



Re: [PATCH 2/2] devm-helpers: Add resource managed version of debugfs directory create function

2024-02-22 Thread Dan Williams
Dan Williams wrote:
> Dave Jiang wrote:
> > 
> > 
> > On 2/22/24 7:58 AM, Marek Behún wrote:
> > > A few drivers register a devm action to remove a debugfs directory,
> > > implementing a one-liner function that calls debufs_remove_recursive().
> > > Help drivers avoid this repeated implementations by adding managed
> > > version of debugfs directory create function.
> > > 
> > > Use the new function devm_debugfs_create_dir() in the following
> > > drivers:
> > >   drivers/crypto/caam/ctrl.c
> > >   drivers/gpu/drm/bridge/ti-sn65dsi86.c
> > >   drivers/hwmon/hp-wmi-sensors.c
> > >   drivers/hwmon/mr75203.c
> > >   drivers/hwmon/pmbus/pmbus_core.c
> > > 
> > > Also use the action function devm_debugfs_dir_recursive_drop() in
> > > drivers
> > >   drivers/cxl/mem.c
> > >   drivers/gpio/gpio-mockup.c
> > > 
> > > Signed-off-by: Marek Behún 
> > > ---
> > >  drivers/crypto/caam/ctrl.c| 16 +++--
> > >  drivers/cxl/mem.c |  9 ++---
> > >  drivers/gpio/gpio-mockup.c| 11 ++
> > >  drivers/gpu/drm/bridge/ti-sn65dsi86.c | 13 ++--
> > >  drivers/hwmon/hp-wmi-sensors.c| 15 ++---
> > >  drivers/hwmon/mr75203.c   | 15 +++--
> > >  drivers/hwmon/pmbus/pmbus_core.c  | 16 +++--
> > >  include/linux/devm-helpers.h  | 48 +++
> > >  8 files changed, 72 insertions(+), 71 deletions(-)
> > > 
[..]
> > diff --git a/drivers/cxl/cxlmem.h b/drivers/cxl/cxlmem.h
> > index 5303d6942b88..b6f13ba87927 100644
> > --- a/drivers/cxl/cxlmem.h
> > +++ b/drivers/cxl/cxlmem.h
> > @@ -859,6 +859,5 @@ struct cxl_hdm {
> >  };
> >  
> >  struct seq_file;
> > -struct dentry *cxl_debugfs_create_dir(const char *dir);
> >  void cxl_dpa_debug(struct seq_file *file, struct cxl_dev_state *cxlds);
> >  #endif /* __CXL_MEM_H__ */
> > diff --git a/drivers/cxl/mem.c b/drivers/cxl/mem.c
> > index c5c9d8e0d88d..494abe7a54c5 100644
> > --- a/drivers/cxl/mem.c
> > +++ b/drivers/cxl/mem.c
> > @@ -4,6 +4,7 @@
> >  #include 
> >  #include 
> >  #include 
> > +#include 
> >  
> >  #include "cxlmem.h"
> >  #include "cxlpci.h"
> > @@ -30,11 +31,6 @@ static void enable_suspend(void *data)
> > cxl_mem_active_dec();
> >  }
> >  
> > -static void remove_debugfs(void *dentry)
> > -{
> > -   debugfs_remove_recursive(dentry);
> > -}
> > -
> >  static int cxl_mem_dpa_show(struct seq_file *file, void *data)
> >  {
> > struct device *dev = file->private;
> > @@ -128,7 +124,10 @@ static int cxl_mem_probe(struct device *dev)
> > if (work_pending(>detach_work))
> > return -EBUSY;
> >  
> > -   dentry = cxl_debugfs_create_dir(dev_name(dev));
> > +   dentry = devm_debugfs_create_dir(dev, dev_name(dev), NULL);
> > +   if (IS_ERR(dentry))
> > +   return PTR_ERR(dentry);
> > +
> 
> No that loses the "cxl" prefix.

So, to be clear, I do see the benefit of removing the
devm_add_action_or_reset() call altogether, but that work is a bit
deeper and should not be tied with all these other cleanups. So I think
from the CXL perspective, please drop these CXL changes out of this
patch. Follow up with a standalone patch, or leave it to drivers/cxl/
folks to create that deeper cleanup.


Re: [PATCH v5] drm/test: add a test suite for GEM objects backed by shmem

2024-02-22 Thread Guenter Roeck
On Thu, Feb 22, 2024 at 05:33:48PM +0100, Marco Pagani wrote:
> > 
> > In this context, the TTM unit tests fail as well in qemu, with worse result:
> > It seems there is some bad cleanup after a failed test case, causing list
> > corruptions in the drm core and ultimately a crash. I don't know if this
> > is also caused by the missing dma_mask initialization.
> > 
> 
> That's interesting. Which --arch argument are you using to run the
> tests with QEMU?

Example (I am not sure if any of those parameters matters; it is just one
of my tests):

qemu-system-x86_64 -kernel arch/x86/boot/bzImage -M q35 -cpu IvyBridge \
-no-reboot -snapshot -smp 2 \
-device e1000,netdev=net0 -netdev user,id=net0 -m 512 \
-drive file=rootfs.ext2,format=raw,if=ide \
--append "earlycon=uart8250,io,0x3f8,9600n8 root=/dev/sda1 
console=ttyS0" \
-d unimp,guest_errors -nographic -monitor none

This results in:

[ ... ]
[5.989496] KTAP version 1
[5.989639] # Subtest: ttm_device
[5.989711] # module: ttm_device_test
[5.989760] 1..5
[6.002044] ok 1 ttm_device_init_basic
[6.013557] ok 2 ttm_device_init_multiple
ILLOPC: b8ac9350: 0f 0b
[6.022481] ok 3 ttm_device_fini_basic
[6.026172] [ cut here ]
[6.026315] WARNING: CPU: 1 PID: 1575 at 
drivers/gpu/drm/ttm/ttm_device.c:206 ttm_device_init+0x170/0x190
...
[6.135016] ok 3 Above the allocation limit
[6.138759] [ cut here ]
[6.138925] WARNING: CPU: 1 PID: 1595 at kernel/dma/mapping.c:503 
dma_alloc_attrs+0xf6/0x100
...
[6.143850] # ttm_pool_alloc_basic: ASSERTION FAILED at 
drivers/gpu/drm/ttm/tests/ttm_pool_test.c:162
[6.143850] Expected err == 0, but
[6.143850] err == -12 (0xfff4)
[6.148824] not ok 4 One page, with coherent DMA mappings enabled

>From there things go downhill.

[6.152821] list_add corruption. prev->next should be next 
(bbd53950), but was . (prev=8af1c38f9e20).

and so on until the emulation crashes.

Guenter


[PATCH v7 35/36] drm/sun4i: hdmi: Consolidate atomic_check and mode_valid

2024-02-22 Thread Maxime Ripard
atomic_check and mode_valid do not check for the same things which can
lead to surprising result if the userspace commits a mode that didn't go
through mode_valid. Let's merge the two implementations into a function
called by both.

Acked-by: Sui Jingfeng 
Signed-off-by: Maxime Ripard 
---
 drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c | 74 +-
 1 file changed, 47 insertions(+), 27 deletions(-)

diff --git a/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c 
b/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c
index c276d984da6b..b7cf369b1906 100644
--- a/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c
+++ b/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c
@@ -62,18 +62,6 @@ static int sun4i_hdmi_setup_avi_infoframes(struct sun4i_hdmi 
*hdmi,
return 0;
 }
 
-static int sun4i_hdmi_atomic_check(struct drm_encoder *encoder,
-  struct drm_crtc_state *crtc_state,
-  struct drm_connector_state *conn_state)
-{
-   struct drm_display_mode *mode = _state->mode;
-
-   if (mode->flags & DRM_MODE_FLAG_DBLCLK)
-   return -EINVAL;
-
-   return 0;
-}
-
 static void sun4i_hdmi_disable(struct drm_encoder *encoder,
   struct drm_atomic_state *state)
 {
@@ -166,31 +154,61 @@ static void sun4i_hdmi_enable(struct drm_encoder *encoder,
writel(val, hdmi->base + SUN4I_HDMI_VID_CTRL_REG);
 }
 
-static enum drm_mode_status sun4i_hdmi_mode_valid(struct drm_encoder *encoder,
-   const struct drm_display_mode *mode)
+static const struct drm_encoder_helper_funcs sun4i_hdmi_helper_funcs = {
+   .atomic_disable = sun4i_hdmi_disable,
+   .atomic_enable  = sun4i_hdmi_enable,
+};
+
+static enum drm_mode_status
+sun4i_hdmi_connector_clock_valid(const struct drm_connector *connector,
+const struct drm_display_mode *mode,
+unsigned long long clock)
 {
-   struct sun4i_hdmi *hdmi = drm_encoder_to_sun4i_hdmi(encoder);
-   unsigned long rate = mode->clock * 1000;
-   unsigned long diff = rate / 200; /* +-0.5% allowed by HDMI spec */
+   const struct sun4i_hdmi *hdmi = drm_connector_to_sun4i_hdmi(connector);
+   unsigned long diff = clock / 200; /* +-0.5% allowed by HDMI spec */
long rounded_rate;
 
+   if (mode->flags & DRM_MODE_FLAG_DBLCLK)
+   return MODE_BAD;
+
/* 165 MHz is the typical max pixelclock frequency for HDMI <= 1.2 */
-   if (rate > 16500)
+   if (clock > 16500)
return MODE_CLOCK_HIGH;
-   rounded_rate = clk_round_rate(hdmi->tmds_clk, rate);
+
+   rounded_rate = clk_round_rate(hdmi->tmds_clk, clock);
if (rounded_rate > 0 &&
-   max_t(unsigned long, rounded_rate, rate) -
-   min_t(unsigned long, rounded_rate, rate) < diff)
+   max_t(unsigned long, rounded_rate, clock) -
+   min_t(unsigned long, rounded_rate, clock) < diff)
return MODE_OK;
+
return MODE_NOCLOCK;
 }
 
-static const struct drm_encoder_helper_funcs sun4i_hdmi_helper_funcs = {
-   .atomic_check   = sun4i_hdmi_atomic_check,
-   .atomic_disable = sun4i_hdmi_disable,
-   .atomic_enable  = sun4i_hdmi_enable,
-   .mode_valid = sun4i_hdmi_mode_valid,
-};
+static int sun4i_hdmi_connector_atomic_check(struct drm_connector *connector,
+struct drm_atomic_state *state)
+{
+   struct drm_connector_state *conn_state =
+   drm_atomic_get_new_connector_state(state, connector);
+   struct drm_crtc *crtc = conn_state->crtc;
+   struct drm_crtc_state *crtc_state = crtc->state;
+   struct drm_display_mode *mode = _state->adjusted_mode;
+   enum drm_mode_status status;
+
+   status = sun4i_hdmi_connector_clock_valid(connector, mode,
+ mode->clock * 1000);
+   if (status != MODE_OK)
+   return -EINVAL;
+
+   return 0;
+}
+
+static enum drm_mode_status
+sun4i_hdmi_connector_mode_valid(struct drm_connector *connector,
+   struct drm_display_mode *mode)
+{
+   return sun4i_hdmi_connector_clock_valid(connector, mode,
+   mode->clock * 1000);
+}
 
 static int sun4i_hdmi_get_modes(struct drm_connector *connector)
 {
@@ -236,6 +254,8 @@ static struct i2c_adapter *sun4i_hdmi_get_ddc(struct device 
*dev)
 }
 
 static const struct drm_connector_helper_funcs 
sun4i_hdmi_connector_helper_funcs = {
+   .atomic_check   = sun4i_hdmi_connector_atomic_check,
+   .mode_valid = sun4i_hdmi_connector_mode_valid,
.get_modes  = sun4i_hdmi_get_modes,
 };
 

-- 
2.43.2



[PATCH v7 33/36] drm/sun4i: hdmi: Move mode_set into enable

2024-02-22 Thread Maxime Ripard
We're not doing anything special in atomic_mode_set so we can simply
merge it into atomic_enable.

Acked-by: Sui Jingfeng 
Signed-off-by: Maxime Ripard 
---
 drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c | 38 +-
 1 file changed, 14 insertions(+), 24 deletions(-)

diff --git a/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c 
b/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c
index 799a26215cc2..bae69d696765 100644
--- a/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c
+++ b/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c
@@ -103,33 +103,11 @@ static void sun4i_hdmi_enable(struct drm_encoder *encoder,
struct drm_display_mode *mode = >crtc->state->adjusted_mode;
struct sun4i_hdmi *hdmi = drm_encoder_to_sun4i_hdmi(encoder);
struct drm_display_info *display = >connector.display_info;
+   unsigned int x, y;
u32 val = 0;
 
DRM_DEBUG_DRIVER("Enabling the HDMI Output\n");
 
-   clk_prepare_enable(hdmi->tmds_clk);
-
-   sun4i_hdmi_setup_avi_infoframes(hdmi, mode);
-   val |= SUN4I_HDMI_PKT_CTRL_TYPE(0, SUN4I_HDMI_PKT_AVI);
-   val |= SUN4I_HDMI_PKT_CTRL_TYPE(1, SUN4I_HDMI_PKT_END);
-   writel(val, hdmi->base + SUN4I_HDMI_PKT_CTRL_REG(0));
-
-   val = SUN4I_HDMI_VID_CTRL_ENABLE;
-   if (display->is_hdmi)
-   val |= SUN4I_HDMI_VID_CTRL_HDMI_MODE;
-
-   writel(val, hdmi->base + SUN4I_HDMI_VID_CTRL_REG);
-}
-
-static void sun4i_hdmi_mode_set(struct drm_encoder *encoder,
-   struct drm_crtc_state *crtc_state,
-   struct drm_connector_state *conn_state)
-{
-   const struct drm_display_mode *mode = _state->mode;
-   struct sun4i_hdmi *hdmi = drm_encoder_to_sun4i_hdmi(encoder);
-   unsigned int x, y;
-   u32 val;
-
clk_set_rate(hdmi->mod_clk, mode->crtc_clock * 1000);
clk_set_rate(hdmi->tmds_clk, mode->crtc_clock * 1000);
 
@@ -181,6 +159,19 @@ static void sun4i_hdmi_mode_set(struct drm_encoder 
*encoder,
val |= SUN4I_HDMI_VID_TIMING_POL_VSYNC;
 
writel(val, hdmi->base + SUN4I_HDMI_VID_TIMING_POL_REG);
+
+   clk_prepare_enable(hdmi->tmds_clk);
+
+   sun4i_hdmi_setup_avi_infoframes(hdmi, mode);
+   val |= SUN4I_HDMI_PKT_CTRL_TYPE(0, SUN4I_HDMI_PKT_AVI);
+   val |= SUN4I_HDMI_PKT_CTRL_TYPE(1, SUN4I_HDMI_PKT_END);
+   writel(val, hdmi->base + SUN4I_HDMI_PKT_CTRL_REG(0));
+
+   val = SUN4I_HDMI_VID_CTRL_ENABLE;
+   if (display->is_hdmi)
+   val |= SUN4I_HDMI_VID_CTRL_HDMI_MODE;
+
+   writel(val, hdmi->base + SUN4I_HDMI_VID_CTRL_REG);
 }
 
 static enum drm_mode_status sun4i_hdmi_mode_valid(struct drm_encoder *encoder,
@@ -206,7 +197,6 @@ static const struct drm_encoder_helper_funcs 
sun4i_hdmi_helper_funcs = {
.atomic_check   = sun4i_hdmi_atomic_check,
.atomic_disable = sun4i_hdmi_disable,
.atomic_enable  = sun4i_hdmi_enable,
-   .atomic_mode_set= sun4i_hdmi_mode_set,
.mode_valid = sun4i_hdmi_mode_valid,
 };
 

-- 
2.43.2



[PATCH v7 34/36] drm/sun4i: hdmi: Switch to container_of_const

2024-02-22 Thread Maxime Ripard
container_of_const() allows to preserve the pointer constness and is
thus more flexible than inline functions.

Let's switch all our instances of container_of() to container_of_const().

Reviewed-by: Sui Jingfeng 
Signed-off-by: Maxime Ripard 
---
 drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c | 16 
 1 file changed, 4 insertions(+), 12 deletions(-)

diff --git a/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c 
b/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c
index bae69d696765..c276d984da6b 100644
--- a/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c
+++ b/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c
@@ -30,19 +30,11 @@
 #include "sun4i_drv.h"
 #include "sun4i_hdmi.h"
 
-static inline struct sun4i_hdmi *
-drm_encoder_to_sun4i_hdmi(struct drm_encoder *encoder)
-{
-   return container_of(encoder, struct sun4i_hdmi,
-   encoder);
-}
+#define drm_encoder_to_sun4i_hdmi(e)   \
+   container_of_const(e, struct sun4i_hdmi, encoder)
 
-static inline struct sun4i_hdmi *
-drm_connector_to_sun4i_hdmi(struct drm_connector *connector)
-{
-   return container_of(connector, struct sun4i_hdmi,
-   connector);
-}
+#define drm_connector_to_sun4i_hdmi(c) \
+   container_of_const(c, struct sun4i_hdmi, connector)
 
 static int sun4i_hdmi_setup_avi_infoframes(struct sun4i_hdmi *hdmi,
   struct drm_display_mode *mode)

-- 
2.43.2



[PATCH v7 36/36] drm/sun4i: hdmi: Switch to HDMI connector

2024-02-22 Thread Maxime Ripard
The new HDMI connector infrastructure allows to remove some boilerplate,
especially to generate infoframes. Let's switch to it.

Signed-off-by: Maxime Ripard 
---
 drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c | 80 ++
 1 file changed, 51 insertions(+), 29 deletions(-)

diff --git a/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c 
b/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c
index b7cf369b1906..8a9106a39f23 100644
--- a/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c
+++ b/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c
@@ -36,30 +36,24 @@
 #define drm_connector_to_sun4i_hdmi(c) \
container_of_const(c, struct sun4i_hdmi, connector)
 
-static int sun4i_hdmi_setup_avi_infoframes(struct sun4i_hdmi *hdmi,
-  struct drm_display_mode *mode)
+static int sun4i_hdmi_write_infoframe(struct drm_connector *connector,
+ enum hdmi_infoframe_type type,
+ const u8 *buffer, size_t len)
 {
-   struct hdmi_avi_infoframe frame;
-   u8 buffer[17];
-   int i, ret;
+   struct sun4i_hdmi *hdmi = drm_connector_to_sun4i_hdmi(connector);
+   int i;
 
-   ret = drm_hdmi_avi_infoframe_from_display_mode(,
-  >connector, mode);
-   if (ret < 0) {
-   DRM_ERROR("Failed to get infoframes from mode\n");
-   return ret;
+   if (type != HDMI_INFOFRAME_TYPE_AVI) {
+   drm_err(connector->dev,
+   "Unsupported infoframe type: %u\n", type);
+   return 0;
}
 
-   ret = hdmi_avi_infoframe_pack(, buffer, sizeof(buffer));
-   if (ret < 0) {
-   DRM_ERROR("Failed to pack infoframes\n");
-   return ret;
-   }
-
-   for (i = 0; i < sizeof(buffer); i++)
+   for (i = 0; i < len; i++)
writeb(buffer[i], hdmi->base + SUN4I_HDMI_AVI_INFOFRAME_REG(i));
 
return 0;
+
 }
 
 static void sun4i_hdmi_disable(struct drm_encoder *encoder,
@@ -82,14 +76,18 @@ static void sun4i_hdmi_enable(struct drm_encoder *encoder,
 {
struct drm_display_mode *mode = >crtc->state->adjusted_mode;
struct sun4i_hdmi *hdmi = drm_encoder_to_sun4i_hdmi(encoder);
-   struct drm_display_info *display = >connector.display_info;
+   struct drm_connector *connector = >connector;
+   struct drm_display_info *display = >display_info;
+   struct drm_connector_state *conn_state =
+   drm_atomic_get_new_connector_state(state, connector);
+   unsigned long long tmds_rate = conn_state->hdmi.tmds_char_rate;
unsigned int x, y;
u32 val = 0;
 
DRM_DEBUG_DRIVER("Enabling the HDMI Output\n");
 
-   clk_set_rate(hdmi->mod_clk, mode->crtc_clock * 1000);
-   clk_set_rate(hdmi->tmds_clk, mode->crtc_clock * 1000);
+   clk_set_rate(hdmi->mod_clk, tmds_rate);
+   clk_set_rate(hdmi->tmds_clk, tmds_rate);
 
/* Set input sync enable */
writel(SUN4I_HDMI_UNKNOWN_INPUT_SYNC,
@@ -142,7 +140,8 @@ static void sun4i_hdmi_enable(struct drm_encoder *encoder,
 
clk_prepare_enable(hdmi->tmds_clk);
 
-   sun4i_hdmi_setup_avi_infoframes(hdmi, mode);
+   drm_atomic_helper_connector_hdmi_update_infoframes(connector, state);
+
val |= SUN4I_HDMI_PKT_CTRL_TYPE(0, SUN4I_HDMI_PKT_AVI);
val |= SUN4I_HDMI_PKT_CTRL_TYPE(1, SUN4I_HDMI_PKT_END);
writel(val, hdmi->base + SUN4I_HDMI_PKT_CTRL_REG(0));
@@ -195,7 +194,7 @@ static int sun4i_hdmi_connector_atomic_check(struct 
drm_connector *connector,
enum drm_mode_status status;
 
status = sun4i_hdmi_connector_clock_valid(connector, mode,
- mode->clock * 1000);
+ 
conn_state->hdmi.tmds_char_rate);
if (status != MODE_OK)
return -EINVAL;
 
@@ -206,8 +205,11 @@ static enum drm_mode_status
 sun4i_hdmi_connector_mode_valid(struct drm_connector *connector,
struct drm_display_mode *mode)
 {
-   return sun4i_hdmi_connector_clock_valid(connector, mode,
-   mode->clock * 1000);
+   unsigned long long rate =
+   drm_connector_hdmi_compute_mode_clock(mode, 8,
+ HDMI_COLORSPACE_RGB);
+
+   return sun4i_hdmi_connector_clock_valid(connector, mode, rate);
 }
 
 static int sun4i_hdmi_get_modes(struct drm_connector *connector)
@@ -253,6 +255,11 @@ static struct i2c_adapter *sun4i_hdmi_get_ddc(struct 
device *dev)
return ddc;
 }
 
+static const struct drm_connector_hdmi_funcs sun4i_hdmi_hdmi_connector_funcs = 
{
+   .tmds_char_rate_valid   = sun4i_hdmi_connector_clock_valid,
+   .write_infoframe= sun4i_hdmi_write_infoframe,
+};
+
 static const struct drm_connector_helper_funcs 
sun4i_hdmi_connector_helper_funcs = {

[PATCH v7 31/36] drm/rockchip: inno_hdmi: Switch to HDMI connector

2024-02-22 Thread Maxime Ripard
The new HDMI connector infrastructure allows to remove some boilerplate,
especially to generate infoframes. Let's switch to it.

Signed-off-by: Maxime Ripard 
---
 drivers/gpu/drm/rockchip/inno_hdmi.c | 123 ---
 1 file changed, 42 insertions(+), 81 deletions(-)

diff --git a/drivers/gpu/drm/rockchip/inno_hdmi.c 
b/drivers/gpu/drm/rockchip/inno_hdmi.c
index 1d2261643743..d59947679042 100644
--- a/drivers/gpu/drm/rockchip/inno_hdmi.c
+++ b/drivers/gpu/drm/rockchip/inno_hdmi.c
@@ -67,9 +67,7 @@ struct inno_hdmi {
 
 struct inno_hdmi_connector_state {
struct drm_connector_state  base;
-   unsigned intenc_out_format;
unsigned intcolorimetry;
-   boolrgb_limited_range;
 };
 
 static struct inno_hdmi *encoder_to_inno_hdmi(struct drm_encoder *encoder)
@@ -257,26 +255,29 @@ static void inno_hdmi_reset(struct inno_hdmi *hdmi)
inno_hdmi_standby(hdmi);
 }
 
-static void inno_hdmi_disable_frame(struct inno_hdmi *hdmi,
-   enum hdmi_infoframe_type type)
+static int inno_hdmi_disable_frame(struct drm_connector *connector,
+  enum hdmi_infoframe_type type)
 {
-   struct drm_connector *connector = >connector;
+   struct inno_hdmi *hdmi = connector_to_inno_hdmi(connector);
 
if (type != HDMI_INFOFRAME_TYPE_AVI) {
drm_err(connector->dev,
"Unsupported infoframe type: %u\n", type);
-   return;
+   return 0;
}
 
hdmi_writeb(hdmi, HDMI_CONTROL_PACKET_BUF_INDEX, INFOFRAME_AVI);
+
+   return 0;
 }
 
-static int inno_hdmi_upload_frame(struct inno_hdmi *hdmi,
- union hdmi_infoframe *frame, enum 
hdmi_infoframe_type type)
+static int inno_hdmi_upload_frame(struct drm_connector *connector,
+ enum hdmi_infoframe_type type,
+ const u8 *buffer, size_t len)
 {
-   struct drm_connector *connector = >connector;
+   struct inno_hdmi *hdmi = connector_to_inno_hdmi(connector);
u8 packed_frame[HDMI_MAXIMUM_INFO_FRAME_SIZE];
-   ssize_t rc, i;
+   ssize_t i;
 
if (type != HDMI_INFOFRAME_TYPE_AVI) {
drm_err(connector->dev,
@@ -284,59 +285,19 @@ static int inno_hdmi_upload_frame(struct inno_hdmi *hdmi,
return 0;
}
 
-   inno_hdmi_disable_frame(hdmi, type);
+   inno_hdmi_disable_frame(connector, type);
 
-   rc = hdmi_infoframe_pack(frame, packed_frame,
-sizeof(packed_frame));
-   if (rc < 0)
-   return rc;
-
-   for (i = 0; i < rc; i++)
+   for (i = 0; i < len; i++)
hdmi_writeb(hdmi, HDMI_CONTROL_PACKET_ADDR + i,
packed_frame[i]);
 
return 0;
 }
 
-static int inno_hdmi_config_video_avi(struct inno_hdmi *hdmi,
- struct drm_display_mode *mode)
-{
-   struct drm_connector *connector = >connector;
-   struct drm_connector_state *conn_state = connector->state;
-   struct inno_hdmi_connector_state *inno_conn_state =
-   to_inno_hdmi_conn_state(conn_state);
-   union hdmi_infoframe frame;
-   int rc;
-
-   rc = drm_hdmi_avi_infoframe_from_display_mode(,
- >connector,
- mode);
-   if (rc) {
-   inno_hdmi_disable_frame(hdmi, HDMI_INFOFRAME_TYPE_AVI);
-   return rc;
-   }
-
-   if (inno_conn_state->enc_out_format == HDMI_COLORSPACE_YUV444)
-   frame.avi.colorspace = HDMI_COLORSPACE_YUV444;
-   else if (inno_conn_state->enc_out_format == HDMI_COLORSPACE_YUV422)
-   frame.avi.colorspace = HDMI_COLORSPACE_YUV422;
-   else
-   frame.avi.colorspace = HDMI_COLORSPACE_RGB;
-
-   if (inno_conn_state->enc_out_format == HDMI_COLORSPACE_RGB) {
-   drm_hdmi_avi_infoframe_quant_range(,
-  connector, mode,
-  
inno_conn_state->rgb_limited_range ?
-  
HDMI_QUANTIZATION_RANGE_LIMITED :
-  
HDMI_QUANTIZATION_RANGE_FULL);
-   } else {
-   frame.avi.quantization_range = HDMI_QUANTIZATION_RANGE_DEFAULT;
-   frame.avi.ycc_quantization_range =
-   HDMI_YCC_QUANTIZATION_RANGE_LIMITED;
-   }
-
-   return inno_hdmi_upload_frame(hdmi, , HDMI_INFOFRAME_TYPE_AVI);
-}
+static const struct drm_connector_hdmi_funcs inno_hdmi_hdmi_connector_funcs = {
+   .clear_infoframe= inno_hdmi_disable_frame,
+   .write_infoframe= inno_hdmi_upload_frame,
+};
 
 

[PATCH v7 25/36] drm/connector: hdmi: Add Infoframes generation

2024-02-22 Thread Maxime Ripard
Infoframes in KMS is usually handled by a bunch of low-level helpers
that require quite some boilerplate for drivers. This leads to
discrepancies with how drivers generate them, and which are actually
sent.

Now that we have everything needed to generate them in the HDMI
connector state, we can generate them in our common logic so that
drivers can simply reuse what we precomputed.

Signed-off-by: Maxime Ripard 
---
 drivers/gpu/drm/Kconfig|   1 +
 drivers/gpu/drm/drm_atomic_state_helper.c  | 327 +
 drivers/gpu/drm/drm_connector.c|  16 +
 .../gpu/drm/tests/drm_atomic_state_helper_test.c   |   1 +
 drivers/gpu/drm/tests/drm_connector_test.c |  12 +
 include/drm/drm_atomic_state_helper.h  |   8 +
 include/drm/drm_connector.h| 133 +
 7 files changed, 498 insertions(+)

diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
index 872edb47bb53..ad9c467e20ce 100644
--- a/drivers/gpu/drm/Kconfig
+++ b/drivers/gpu/drm/Kconfig
@@ -99,6 +99,7 @@ config DRM_KUNIT_TEST
 config DRM_KMS_HELPER
tristate
depends on DRM
+   select DRM_DISPLAY_HDMI_HELPER
help
  CRTC helpers for KMS drivers.
 
diff --git a/drivers/gpu/drm/drm_atomic_state_helper.c 
b/drivers/gpu/drm/drm_atomic_state_helper.c
index e66272c0d006..46d9fd2ea8fa 100644
--- a/drivers/gpu/drm/drm_atomic_state_helper.c
+++ b/drivers/gpu/drm/drm_atomic_state_helper.c
@@ -38,6 +38,8 @@
 #include 
 #include 
 
+#include 
+
 #include 
 #include 
 
@@ -914,6 +916,142 @@ hdmi_compute_config(const struct drm_connector *connector,
return -EINVAL;
 }
 
+static int hdmi_generate_avi_infoframe(const struct drm_connector *connector,
+  struct drm_connector_state *state)
+{
+   const struct drm_display_mode *mode =
+   connector_state_get_mode(state);
+   struct drm_connector_hdmi_infoframe *infoframe =
+   >hdmi.infoframes.avi;
+   struct hdmi_avi_infoframe *frame =
+   >data.avi;
+   bool is_full_range = state->hdmi.is_full_range;
+   enum hdmi_quantization_range rgb_quant_range =
+   is_full_range ? HDMI_QUANTIZATION_RANGE_FULL : 
HDMI_QUANTIZATION_RANGE_LIMITED;
+   int ret;
+
+   ret = drm_hdmi_avi_infoframe_from_display_mode(frame, connector, mode);
+   if (ret)
+   return ret;
+
+   frame->colorspace = state->hdmi.output_format;
+
+   drm_hdmi_avi_infoframe_quant_range(frame, connector, mode, 
rgb_quant_range);
+   drm_hdmi_avi_infoframe_colorimetry(frame, state);
+   drm_hdmi_avi_infoframe_bars(frame, state);
+
+   infoframe->set = true;
+
+   return 0;
+}
+
+static int hdmi_generate_spd_infoframe(const struct drm_connector *connector,
+  struct drm_connector_state *state)
+{
+   struct drm_connector_hdmi_infoframe *infoframe =
+   >hdmi.infoframes.spd;
+   struct hdmi_spd_infoframe *frame =
+   >data.spd;
+   int ret;
+
+   ret = hdmi_spd_infoframe_init(frame,
+ connector->hdmi.vendor,
+ connector->hdmi.product);
+   if (ret)
+   return ret;
+
+   frame->sdi = HDMI_SPD_SDI_PC;
+
+   infoframe->set = true;
+
+   return 0;
+}
+
+static int hdmi_generate_hdr_infoframe(const struct drm_connector *connector,
+  struct drm_connector_state *state)
+{
+   struct drm_connector_hdmi_infoframe *infoframe =
+   >hdmi.infoframes.hdr_drm;
+   struct hdmi_drm_infoframe *frame =
+   >data.drm;
+   int ret;
+
+   if (connector->max_bpc < 10)
+   return 0;
+
+   if (!state->hdr_output_metadata)
+   return 0;
+
+   ret = drm_hdmi_infoframe_set_hdr_metadata(frame, state);
+   if (ret)
+   return ret;
+
+   infoframe->set = true;
+
+   return 0;
+}
+
+static int hdmi_generate_hdmi_vendor_infoframe(const struct drm_connector 
*connector,
+  struct drm_connector_state 
*state)
+{
+   const struct drm_display_mode *mode =
+   connector_state_get_mode(state);
+   struct drm_connector_hdmi_infoframe *infoframe =
+   >hdmi.infoframes.hdmi;
+   struct hdmi_vendor_infoframe *frame =
+   >data.vendor.hdmi;
+   int ret;
+
+   ret = drm_hdmi_vendor_infoframe_from_display_mode(frame, connector, 
mode);
+   if (ret) {
+   if (ret == -EINVAL)
+   return 0;
+
+   return ret;
+   }
+
+   infoframe->set = true;
+
+   return 0;
+}
+
+static int
+hdmi_generate_infoframes(const struct drm_connector *connector,
+struct drm_connector_state *state)
+{
+   const struct drm_display_info *info = 

[PATCH v7 28/36] drm/vc4: hdmi: Switch to HDMI connector

2024-02-22 Thread Maxime Ripard
The new HDMI connector infrastructure allows us to remove a lot of
boilerplate, so let's switch to it.

Signed-off-by: Maxime Ripard 
---
 drivers/gpu/drm/vc4/vc4_hdmi.c | 638 +
 drivers/gpu/drm/vc4/vc4_hdmi.h |  44 +--
 drivers/gpu/drm/vc4/vc4_hdmi_phy.c |   6 +-
 3 files changed, 86 insertions(+), 602 deletions(-)

diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
index 34f807ed1c31..1f489cbe0c90 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
@@ -110,25 +110,6 @@
 
 #define HDMI_14_MAX_TMDS_CLK   (340 * 1000 * 1000)
 
-static const char * const output_format_str[] = {
-   [VC4_HDMI_OUTPUT_RGB]   = "RGB",
-   [VC4_HDMI_OUTPUT_YUV420]= "YUV 4:2:0",
-   [VC4_HDMI_OUTPUT_YUV422]= "YUV 4:2:2",
-   [VC4_HDMI_OUTPUT_YUV444]= "YUV 4:4:4",
-};
-
-static const char *vc4_hdmi_output_fmt_str(enum vc4_hdmi_output_format fmt)
-{
-   if (fmt >= ARRAY_SIZE(output_format_str))
-   return "invalid";
-
-   return output_format_str[fmt];
-}
-
-static unsigned long long
-vc4_hdmi_encoder_compute_mode_clock(const struct drm_display_mode *mode,
-   unsigned int bpc, enum 
vc4_hdmi_output_format fmt);
-
 static bool vc4_hdmi_supports_scrambling(struct vc4_hdmi *vc4_hdmi)
 {
struct drm_display_info *display = _hdmi->connector.display_info;
@@ -147,28 +128,13 @@ static bool vc4_hdmi_supports_scrambling(struct vc4_hdmi 
*vc4_hdmi)
 
 static bool vc4_hdmi_mode_needs_scrambling(const struct drm_display_mode *mode,
   unsigned int bpc,
-  enum vc4_hdmi_output_format fmt)
+  enum hdmi_colorspace fmt)
 {
-   unsigned long long clock = vc4_hdmi_encoder_compute_mode_clock(mode, 
bpc, fmt);
+   unsigned long long clock = drm_connector_hdmi_compute_mode_clock(mode, 
bpc, fmt);
 
return clock > HDMI_14_MAX_TMDS_CLK;
 }
 
-static bool vc4_hdmi_is_full_range(struct vc4_hdmi *vc4_hdmi,
-  struct vc4_hdmi_connector_state *vc4_state)
-{
-   const struct drm_display_mode *mode = _hdmi->saved_adjusted_mode;
-   struct drm_display_info *display = _hdmi->connector.display_info;
-
-   if (vc4_state->broadcast_rgb == VC4_HDMI_BROADCAST_RGB_LIMITED)
-   return false;
-   else if (vc4_state->broadcast_rgb == VC4_HDMI_BROADCAST_RGB_FULL)
-   return true;
-
-   return !display->is_hdmi ||
-   drm_default_rgb_quant_range(mode) == 
HDMI_QUANTIZATION_RANGE_FULL;
-}
-
 static int vc4_hdmi_debugfs_regs(struct seq_file *m, void *unused)
 {
struct drm_debugfs_entry *entry = m->private;
@@ -520,7 +486,7 @@ static int vc4_hdmi_connector_get_modes(struct 
drm_connector *connector)
const struct drm_display_mode *mode;
 
list_for_each_entry(mode, >probed_modes, head) {
-   if (vc4_hdmi_mode_needs_scrambling(mode, 8, 
VC4_HDMI_OUTPUT_RGB)) {
+   if (vc4_hdmi_mode_needs_scrambling(mode, 8, 
HDMI_COLORSPACE_RGB)) {
drm_warn_once(drm, "The core clock cannot reach 
frequencies high enough to support 4k @ 60Hz.");
drm_warn_once(drm, "Please change your 
config.txt file to add hdmi_enable_4kp60.");
}
@@ -535,12 +501,8 @@ static int vc4_hdmi_connector_atomic_check(struct 
drm_connector *connector,
 {
struct drm_connector_state *old_state =
drm_atomic_get_old_connector_state(state, connector);
-   struct vc4_hdmi_connector_state *old_vc4_state =
-   conn_state_to_vc4_hdmi_conn_state(old_state);
struct drm_connector_state *new_state =
drm_atomic_get_new_connector_state(state, connector);
-   struct vc4_hdmi_connector_state *new_vc4_state =
-   conn_state_to_vc4_hdmi_conn_state(new_state);
struct drm_crtc *crtc = new_state->crtc;
 
if (!crtc)
@@ -572,9 +534,7 @@ static int vc4_hdmi_connector_atomic_check(struct 
drm_connector *connector,
return ret;
}
 
-   if (old_state->colorspace != new_state->colorspace ||
-   old_vc4_state->broadcast_rgb != new_vc4_state->broadcast_rgb ||
-   !drm_connector_atomic_hdr_metadata_equal(old_state, new_state)) {
+   if (old_state->colorspace != new_state->colorspace) {
struct drm_crtc_state *crtc_state;
 
crtc_state = drm_atomic_get_crtc_state(state, crtc);
@@ -584,112 +544,21 @@ static int vc4_hdmi_connector_atomic_check(struct 
drm_connector *connector,
crtc_state->mode_changed = true;
}
 
-   return 0;
-}
-
-static int vc4_hdmi_connector_get_property(struct drm_connector *connector,
-  const struct 

[PATCH v7 32/36] drm/sun4i: hdmi: Convert encoder to atomic

2024-02-22 Thread Maxime Ripard
The sun4i_hdmi driver still uses the non-atomic variants of the encoder
hooks, so let's convert to their atomic equivalents.

Acked-by: Sui Jingfeng 
Signed-off-by: Maxime Ripard 
---
 drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c | 17 ++---
 1 file changed, 10 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c 
b/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c
index 152375f3de2e..799a26215cc2 100644
--- a/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c
+++ b/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c
@@ -82,7 +82,8 @@ static int sun4i_hdmi_atomic_check(struct drm_encoder 
*encoder,
return 0;
 }
 
-static void sun4i_hdmi_disable(struct drm_encoder *encoder)
+static void sun4i_hdmi_disable(struct drm_encoder *encoder,
+  struct drm_atomic_state *state)
 {
struct sun4i_hdmi *hdmi = drm_encoder_to_sun4i_hdmi(encoder);
u32 val;
@@ -96,7 +97,8 @@ static void sun4i_hdmi_disable(struct drm_encoder *encoder)
clk_disable_unprepare(hdmi->tmds_clk);
 }
 
-static void sun4i_hdmi_enable(struct drm_encoder *encoder)
+static void sun4i_hdmi_enable(struct drm_encoder *encoder,
+ struct drm_atomic_state *state)
 {
struct drm_display_mode *mode = >crtc->state->adjusted_mode;
struct sun4i_hdmi *hdmi = drm_encoder_to_sun4i_hdmi(encoder);
@@ -120,9 +122,10 @@ static void sun4i_hdmi_enable(struct drm_encoder *encoder)
 }
 
 static void sun4i_hdmi_mode_set(struct drm_encoder *encoder,
-   struct drm_display_mode *mode,
-   struct drm_display_mode *adjusted_mode)
+   struct drm_crtc_state *crtc_state,
+   struct drm_connector_state *conn_state)
 {
+   const struct drm_display_mode *mode = _state->mode;
struct sun4i_hdmi *hdmi = drm_encoder_to_sun4i_hdmi(encoder);
unsigned int x, y;
u32 val;
@@ -201,9 +204,9 @@ static enum drm_mode_status sun4i_hdmi_mode_valid(struct 
drm_encoder *encoder,
 
 static const struct drm_encoder_helper_funcs sun4i_hdmi_helper_funcs = {
.atomic_check   = sun4i_hdmi_atomic_check,
-   .disable= sun4i_hdmi_disable,
-   .enable = sun4i_hdmi_enable,
-   .mode_set   = sun4i_hdmi_mode_set,
+   .atomic_disable = sun4i_hdmi_disable,
+   .atomic_enable  = sun4i_hdmi_enable,
+   .atomic_mode_set= sun4i_hdmi_mode_set,
.mode_valid = sun4i_hdmi_mode_valid,
 };
 

-- 
2.43.2



[PATCH v7 30/36] drm/vc4: tests: Convert to plane creation helper

2024-02-22 Thread Maxime Ripard
Now that we have a plane create helper for kunit mocked drivers, let's
convert to it in vc4.

Signed-off-by: Maxime Ripard 
---
 drivers/gpu/drm/vc4/tests/vc4_mock_plane.c | 34 +++---
 1 file changed, 8 insertions(+), 26 deletions(-)

diff --git a/drivers/gpu/drm/vc4/tests/vc4_mock_plane.c 
b/drivers/gpu/drm/vc4/tests/vc4_mock_plane.c
index 973f5f929097..14357db82238 100644
--- a/drivers/gpu/drm/vc4/tests/vc4_mock_plane.c
+++ b/drivers/gpu/drm/vc4/tests/vc4_mock_plane.c
@@ -1,43 +1,25 @@
 // SPDX-License-Identifier: GPL-2.0
 
-#include 
-#include 
-#include 
+#include 
 #include 
 
 #include 
 
 #include "vc4_mock.h"
 
-static const struct drm_plane_helper_funcs vc4_dummy_plane_helper_funcs = {
-};
-
-static const struct drm_plane_funcs vc4_dummy_plane_funcs = {
-   .atomic_destroy_state   = drm_atomic_helper_plane_destroy_state,
-   .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
-   .reset  = drm_atomic_helper_plane_reset,
-};
-
-static const uint32_t vc4_dummy_plane_formats[] = {
-   DRM_FORMAT_XRGB,
-};
-
 struct drm_plane *vc4_dummy_plane(struct kunit *test, struct drm_device *drm,
  enum drm_plane_type type)
 {
struct drm_plane *plane;
 
-   plane = __drmm_universal_plane_alloc(drm, sizeof(struct drm_plane), 0,
-0,
-_dummy_plane_funcs,
-vc4_dummy_plane_formats,
-
ARRAY_SIZE(vc4_dummy_plane_formats),
-NULL,
-DRM_PLANE_TYPE_PRIMARY,
-NULL);
+   KUNIT_ASSERT_EQ(test, type, DRM_PLANE_TYPE_PRIMARY);
+
+   plane = drm_kunit_helper_create_primary_plane(test, drm,
+ NULL,
+ NULL,
+ NULL, 0,
+ NULL);
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, plane);
 
-   drm_plane_helper_add(plane, _dummy_plane_helper_funcs);
-
return plane;
 }

-- 
2.43.2



[PATCH v7 26/36] drm/tests: Add infoframes test

2024-02-22 Thread Maxime Ripard
The previous patch added the generation of the infoframes matching an
HDMI connector state. Let's add a few tests to make sure it works as
expected.

Signed-off-by: Maxime Ripard 
---
 drivers/gpu/drm/tests/drm_connector_test.c | 219 +
 1 file changed, 219 insertions(+)

diff --git a/drivers/gpu/drm/tests/drm_connector_test.c 
b/drivers/gpu/drm/tests/drm_connector_test.c
index b9c80d282380..07066b704b36 100644
--- a/drivers/gpu/drm/tests/drm_connector_test.c
+++ b/drivers/gpu/drm/tests/drm_connector_test.c
@@ -219,6 +219,217 @@ static void drm_test_connector_hdmi_init_null_ddc(struct 
kunit *test)
KUNIT_EXPECT_EQ(test, ret, 0);
 }
 
+/*
+ * Test that the registration of an HDMI connector with a NULL vendor
+ * fails.
+ */
+static void drm_test_connector_hdmi_init_null_vendor(struct kunit *test)
+{
+   struct drm_connector_init_priv *priv = test->priv;
+   int ret;
+
+   ret = drmm_connector_hdmi_init(>drm, >connector,
+  NULL, "Product",
+  _funcs,
+  _hdmi_funcs,
+  DRM_MODE_CONNECTOR_HDMIA,
+  >ddc,
+  BIT(HDMI_COLORSPACE_RGB),
+  8);
+   KUNIT_EXPECT_LT(test, ret, 0);
+}
+
+/*
+ * Test that the registration of an HDMI connector with a NULL product
+ * fails.
+ */
+static void drm_test_connector_hdmi_init_null_product(struct kunit *test)
+{
+   struct drm_connector_init_priv *priv = test->priv;
+   int ret;
+
+   ret = drmm_connector_hdmi_init(>drm, >connector,
+  "Vendor", NULL,
+  _funcs,
+  _hdmi_funcs,
+  DRM_MODE_CONNECTOR_HDMIA,
+  >ddc,
+  BIT(HDMI_COLORSPACE_RGB),
+  8);
+   KUNIT_EXPECT_LT(test, ret, 0);
+}
+
+/*
+ * Test that the registration of a connector with a valid, shorter than
+ * the max length, product name succeeds, and is stored padded with 0.
+ */
+static void drm_test_connector_hdmi_init_product_valid(struct kunit *test)
+{
+   struct drm_connector_init_priv *priv = test->priv;
+   const unsigned char expected_product[DRM_CONNECTOR_HDMI_PRODUCT_LEN] = {
+   'P', 'r', 'o', 'd',
+   };
+   const char *product_name = "Prod";
+   int ret;
+
+   KUNIT_ASSERT_LT(test, strlen(product_name), 
DRM_CONNECTOR_HDMI_PRODUCT_LEN);
+
+   ret = drmm_connector_hdmi_init(>drm, >connector,
+  "Vendor", product_name,
+  _funcs,
+  _hdmi_funcs,
+  DRM_MODE_CONNECTOR_HDMIA,
+  >ddc,
+  BIT(HDMI_COLORSPACE_RGB),
+  8);
+   KUNIT_EXPECT_EQ(test, ret, 0);
+   KUNIT_EXPECT_MEMEQ(test,
+  priv->connector.hdmi.product,
+  expected_product,
+  sizeof(priv->connector.hdmi.product));
+}
+
+/*
+ * Test that the registration of a connector with a valid, at max
+ * length, product name succeeds, and is stored padded without any
+ * trailing \0.
+ */
+static void drm_test_connector_hdmi_init_product_length_exact(struct kunit 
*test)
+{
+   struct drm_connector_init_priv *priv = test->priv;
+   const unsigned char expected_product[DRM_CONNECTOR_HDMI_PRODUCT_LEN] = {
+   'P', 'r', 'o', 'd', 'u', 'c', 't',
+   'P', 'r', 'o', 'd', 'u', 'c', 't',
+   'P', 'r',
+   };
+   const char *product_name = "ProductProductPr";
+   int ret;
+
+   KUNIT_ASSERT_EQ(test, strlen(product_name), 
DRM_CONNECTOR_HDMI_PRODUCT_LEN);
+
+   ret = drmm_connector_hdmi_init(>drm, >connector,
+  "Vendor", product_name,
+  _funcs,
+  _hdmi_funcs,
+  DRM_MODE_CONNECTOR_HDMIA,
+  >ddc,
+  BIT(HDMI_COLORSPACE_RGB),
+  8);
+   KUNIT_EXPECT_EQ(test, ret, 0);
+   KUNIT_EXPECT_MEMEQ(test,
+  priv->connector.hdmi.product,
+  expected_product,
+  sizeof(priv->connector.hdmi.product));
+}
+
+/*
+ * Test that the registration of a connector with a product name larger
+ * than the maximum length fails.
+ */
+static void drm_test_connector_hdmi_init_product_length_too_long(struct kunit 
*test)
+{
+   struct drm_connector_init_priv *priv = 

[PATCH v7 24/36] drm/tests: Add RGB Quantization tests

2024-02-22 Thread Maxime Ripard
The previous commit added the infrastructure to the connector state to
track what RGB Quantization should be used in a given state for an HDMI
connector.

Let's add some kunit tests to make sure it works as expected.

Reviewed-by: Dave Stevenson 
Signed-off-by: Maxime Ripard 
---
 .../gpu/drm/tests/drm_atomic_state_helper_test.c   | 563 +
 1 file changed, 563 insertions(+)

diff --git a/drivers/gpu/drm/tests/drm_atomic_state_helper_test.c 
b/drivers/gpu/drm/tests/drm_atomic_state_helper_test.c
index 3de15cec2f5f..dcc0f7486f49 100644
--- a/drivers/gpu/drm/tests/drm_atomic_state_helper_test.c
+++ b/drivers/gpu/drm/tests/drm_atomic_state_helper_test.c
@@ -352,6 +352,560 @@ static void 
drm_test_check_broadcast_rgb_crtc_mode_not_changed(struct kunit *tes
KUNIT_EXPECT_FALSE(test, crtc_state->mode_changed);
 }
 
+/*
+ * Test that for an HDMI connector, with an HDMI monitor, if the
+ * Broadcast RGB property is set to auto with a mode that isn't the
+ * VIC-1 mode, we will get a limited RGB Quantization Range.
+ */
+static void drm_test_check_broadcast_rgb_auto_cea_mode(struct kunit *test)
+{
+   struct drm_atomic_helper_connector_hdmi_priv *priv;
+   struct drm_modeset_acquire_ctx *ctx;
+   struct drm_connector_state *conn_state;
+   struct drm_atomic_state *state;
+   struct drm_display_mode *preferred;
+   struct drm_connector *conn;
+   struct drm_device *drm;
+   struct drm_crtc *crtc;
+   int ret;
+
+   priv = drm_atomic_helper_connector_hdmi_init(test,
+BIT(HDMI_COLORSPACE_RGB),
+8);
+   KUNIT_ASSERT_NOT_NULL(test, priv);
+
+   conn = >connector;
+   KUNIT_ASSERT_TRUE(test, conn->display_info.is_hdmi);
+
+   ctx = drm_kunit_helper_acquire_ctx_alloc(test);
+   KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx);
+
+   preferred = find_preferred_mode(conn);
+   KUNIT_ASSERT_NOT_NULL(test, preferred);
+   KUNIT_ASSERT_NE(test, drm_match_cea_mode(preferred), 1);
+
+   drm = >drm;
+   crtc = priv->crtc;
+   ret = light_up_connector(test, drm, crtc, conn, preferred, ctx);
+   KUNIT_ASSERT_EQ(test, ret, 0);
+
+   state = drm_kunit_helper_atomic_state_alloc(test, drm, ctx);
+   KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state);
+
+   conn_state = drm_atomic_get_connector_state(state, conn);
+   KUNIT_ASSERT_NOT_ERR_OR_NULL(test, conn_state);
+
+   KUNIT_ASSERT_EQ(test,
+   conn_state->hdmi.broadcast_rgb,
+   DRM_HDMI_BROADCAST_RGB_AUTO);
+
+   ret = drm_atomic_check_only(state);
+   KUNIT_ASSERT_EQ(test, ret, 0);
+
+   conn_state = drm_atomic_get_connector_state(state, conn);
+   KUNIT_ASSERT_NOT_ERR_OR_NULL(test, conn_state);
+
+   KUNIT_EXPECT_FALSE(test, conn_state->hdmi.is_full_range);
+}
+
+/*
+ * Test that for an HDMI connector, with an HDMI monitor, if the
+ * Broadcast RGB property is set to auto with a VIC-1 mode, we will get
+ * a full RGB Quantization Range.
+ */
+static void drm_test_check_broadcast_rgb_auto_cea_mode_vic_1(struct kunit 
*test)
+{
+   struct drm_atomic_helper_connector_hdmi_priv *priv;
+   struct drm_modeset_acquire_ctx *ctx;
+   struct drm_connector_state *conn_state;
+   struct drm_atomic_state *state;
+   struct drm_display_mode *mode;
+   struct drm_connector *conn;
+   struct drm_device *drm;
+   struct drm_crtc *crtc;
+   int ret;
+
+   priv = drm_atomic_helper_connector_hdmi_init(test,
+BIT(HDMI_COLORSPACE_RGB),
+8);
+   KUNIT_ASSERT_NOT_NULL(test, priv);
+
+   conn = >connector;
+   KUNIT_ASSERT_TRUE(test, conn->display_info.is_hdmi);
+
+   ctx = drm_kunit_helper_acquire_ctx_alloc(test);
+   KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx);
+
+   mode = drm_display_mode_from_cea_vic(drm, 1);
+   KUNIT_ASSERT_NOT_NULL(test, mode);
+
+   drm = >drm;
+   crtc = priv->crtc;
+   ret = light_up_connector(test, drm, crtc, conn, mode, ctx);
+   KUNIT_ASSERT_EQ(test, ret, 0);
+
+   state = drm_kunit_helper_atomic_state_alloc(test, drm, ctx);
+   KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state);
+
+   conn_state = drm_atomic_get_connector_state(state, conn);
+   KUNIT_ASSERT_NOT_ERR_OR_NULL(test, conn_state);
+
+   KUNIT_ASSERT_EQ(test,
+   conn_state->hdmi.broadcast_rgb,
+   DRM_HDMI_BROADCAST_RGB_AUTO);
+
+   ret = drm_atomic_check_only(state);
+   KUNIT_ASSERT_EQ(test, ret, 0);
+
+   conn_state = drm_atomic_get_connector_state(state, conn);
+   KUNIT_ASSERT_NOT_ERR_OR_NULL(test, conn_state);
+
+   KUNIT_EXPECT_TRUE(test, conn_state->hdmi.is_full_range);
+}
+
+/*
+ * Test that for an HDMI connector, with an HDMI monitor, if the
+ * Broadcast RGB property is set to 

[PATCH v7 29/36] drm/vc4: tests: Remove vc4_dummy_plane structure

2024-02-22 Thread Maxime Ripard
The vc4_dummy_plane structure is an exact equivalent to vc4_plane, so we
don't need it.

Signed-off-by: Maxime Ripard 
---
 drivers/gpu/drm/vc4/tests/vc4_mock.c   |  6 ++
 drivers/gpu/drm/vc4/tests/vc4_mock.h   |  9 ++---
 drivers/gpu/drm/vc4/tests/vc4_mock_plane.c | 14 +-
 3 files changed, 9 insertions(+), 20 deletions(-)

diff --git a/drivers/gpu/drm/vc4/tests/vc4_mock.c 
b/drivers/gpu/drm/vc4/tests/vc4_mock.c
index becb3dbaa548..0731a7d85d7a 100644
--- a/drivers/gpu/drm/vc4/tests/vc4_mock.c
+++ b/drivers/gpu/drm/vc4/tests/vc4_mock.c
@@ -109,16 +109,14 @@ static const struct vc4_mock_desc vc5_mock =
 static int __build_one_pipe(struct kunit *test, struct drm_device *drm,
const struct vc4_mock_pipe_desc *pipe)
 {
-   struct vc4_dummy_plane *dummy_plane;
struct drm_plane *plane;
struct vc4_dummy_crtc *dummy_crtc;
struct drm_crtc *crtc;
unsigned int i;
 
-   dummy_plane = vc4_dummy_plane(test, drm, DRM_PLANE_TYPE_PRIMARY);
-   KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dummy_plane);
+   plane = vc4_dummy_plane(test, drm, DRM_PLANE_TYPE_PRIMARY);
+   KUNIT_ASSERT_NOT_ERR_OR_NULL(test, plane);
 
-   plane = _plane->plane.base;
dummy_crtc = vc4_mock_pv(test, drm, plane, pipe->data);
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dummy_crtc);
 
diff --git a/drivers/gpu/drm/vc4/tests/vc4_mock.h 
b/drivers/gpu/drm/vc4/tests/vc4_mock.h
index 2d0b339bd9f3..002b6218960c 100644
--- a/drivers/gpu/drm/vc4/tests/vc4_mock.h
+++ b/drivers/gpu/drm/vc4/tests/vc4_mock.h
@@ -21,13 +21,8 @@ struct drm_crtc *vc4_find_crtc_for_encoder(struct kunit 
*test,
return NULL;
 }
 
-struct vc4_dummy_plane {
-   struct vc4_plane plane;
-};
-
-struct vc4_dummy_plane *vc4_dummy_plane(struct kunit *test,
-   struct drm_device *drm,
-   enum drm_plane_type type);
+struct drm_plane *vc4_dummy_plane(struct kunit *test, struct drm_device *drm,
+ enum drm_plane_type type);
 
 struct vc4_dummy_crtc {
struct vc4_crtc crtc;
diff --git a/drivers/gpu/drm/vc4/tests/vc4_mock_plane.c 
b/drivers/gpu/drm/vc4/tests/vc4_mock_plane.c
index 62b18f5f41db..973f5f929097 100644
--- a/drivers/gpu/drm/vc4/tests/vc4_mock_plane.c
+++ b/drivers/gpu/drm/vc4/tests/vc4_mock_plane.c
@@ -22,15 +22,12 @@ static const uint32_t vc4_dummy_plane_formats[] = {
DRM_FORMAT_XRGB,
 };
 
-struct vc4_dummy_plane *vc4_dummy_plane(struct kunit *test,
-   struct drm_device *drm,
-   enum drm_plane_type type)
+struct drm_plane *vc4_dummy_plane(struct kunit *test, struct drm_device *drm,
+ enum drm_plane_type type)
 {
-   struct vc4_dummy_plane *dummy_plane;
struct drm_plane *plane;
 
-   dummy_plane = drmm_universal_plane_alloc(drm,
-struct vc4_dummy_plane, 
plane.base,
+   plane = __drmm_universal_plane_alloc(drm, sizeof(struct drm_plane), 0,
 0,
 _dummy_plane_funcs,
 vc4_dummy_plane_formats,
@@ -38,10 +35,9 @@ struct vc4_dummy_plane *vc4_dummy_plane(struct kunit *test,
 NULL,
 DRM_PLANE_TYPE_PRIMARY,
 NULL);
-   KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dummy_plane);
+   KUNIT_ASSERT_NOT_ERR_OR_NULL(test, plane);
 
-   plane = _plane->plane.base;
drm_plane_helper_add(plane, _dummy_plane_helper_funcs);
 
-   return dummy_plane;
+   return plane;
 }

-- 
2.43.2



[PATCH v7 27/36] drm/connector: hdmi: Create Infoframe DebugFS entries

2024-02-22 Thread Maxime Ripard
There has been some discussions recently about the infoframes sent by
drivers and if they were properly generated.

In parallel, there's been some interest in creating an infoframe-decode
tool similar to edid-decode.

Both would be much easier if we were to expose the infoframes programmed
in the hardware. It won't be perfect since we have no guarantee that
it's actually what goes through the wire, but it's the best we can do.

Signed-off-by: Maxime Ripard 
---
 drivers/gpu/drm/drm_debugfs.c | 110 ++
 1 file changed, 110 insertions(+)

diff --git a/drivers/gpu/drm/drm_debugfs.c b/drivers/gpu/drm/drm_debugfs.c
index 08fcefd804bc..160389f3d84b 100644
--- a/drivers/gpu/drm/drm_debugfs.c
+++ b/drivers/gpu/drm/drm_debugfs.c
@@ -520,6 +520,114 @@ static const struct file_operations drm_connector_fops = {
.write = connector_write
 };
 
+struct debugfs_wrapper {
+   struct drm_connector *connector;
+   struct drm_connector_hdmi_infoframe *frame;
+};
+
+#define HDMI_MAX_INFOFRAME_SIZE29
+
+static ssize_t
+infoframe_read(struct file *filp, char __user *ubuf, size_t count, loff_t 
*ppos)
+{
+   const struct debugfs_wrapper *wrapper = filp->private_data;
+   struct drm_connector *connector = wrapper->connector;
+   struct drm_connector_hdmi_infoframe *infoframe = wrapper->frame;
+   union hdmi_infoframe *frame = >data;
+   u8 buf[HDMI_MAX_INFOFRAME_SIZE];
+   ssize_t len = 0;
+
+   mutex_lock(>hdmi.infoframes.lock);
+
+   if (!infoframe->set)
+   goto out;
+
+   len = hdmi_infoframe_pack(frame, buf, sizeof(buf));
+   if (len < 0)
+   goto out;
+
+   len = simple_read_from_buffer(ubuf, count, ppos, buf, len);
+
+out:
+   mutex_unlock(>hdmi.infoframes.lock);
+   return len;
+}
+
+static const struct file_operations infoframe_fops = {
+   .owner   = THIS_MODULE,
+   .open= simple_open,
+   .read= infoframe_read,
+};
+
+static int create_hdmi_infoframe_file(struct drm_connector *connector,
+ struct dentry *parent,
+ const char *filename,
+ struct drm_connector_hdmi_infoframe 
*frame)
+{
+   struct drm_device *dev = connector->dev;
+   struct debugfs_wrapper *wrapper;
+   struct dentry *file;
+
+   wrapper = drmm_kzalloc(dev, sizeof(*wrapper), GFP_KERNEL);
+   if (!wrapper)
+   return -ENOMEM;
+
+   wrapper->connector = connector;
+   wrapper->frame = frame;
+
+   file = debugfs_create_file(filename, 0400, parent, wrapper, 
_fops);
+   if (IS_ERR(file))
+   return PTR_ERR(file);
+
+   return 0;
+}
+
+#define CREATE_HDMI_INFOFRAME_FILE(c, p, i)\
+   create_hdmi_infoframe_file(c, p, #i, &(c)->hdmi.infoframes.i)
+
+static int create_hdmi_infoframe_files(struct drm_connector *connector,
+  struct dentry *parent)
+{
+   int ret;
+
+   ret = CREATE_HDMI_INFOFRAME_FILE(connector, parent, audio);
+   if (ret)
+   return ret;
+
+   ret = CREATE_HDMI_INFOFRAME_FILE(connector, parent, avi);
+   if (ret)
+   return ret;
+
+   ret = CREATE_HDMI_INFOFRAME_FILE(connector, parent, hdr_drm);
+   if (ret)
+   return ret;
+
+   ret = CREATE_HDMI_INFOFRAME_FILE(connector, parent, spd);
+   if (ret)
+   return ret;
+
+   ret = CREATE_HDMI_INFOFRAME_FILE(connector, parent, hdmi);
+   if (ret)
+   return ret;
+
+   return 0;
+}
+
+static void hdmi_debugfs_add(struct drm_connector *connector)
+{
+   struct dentry *dir;
+
+   if (!(connector->connector_type == DRM_MODE_CONNECTOR_HDMIA ||
+ connector->connector_type == DRM_MODE_CONNECTOR_HDMIB))
+   return;
+
+   dir = debugfs_create_dir("infoframes", connector->debugfs_entry);
+   if (IS_ERR(dir))
+   return;
+
+   create_hdmi_infoframe_files(connector, dir);
+}
+
 void drm_debugfs_connector_add(struct drm_connector *connector)
 {
struct drm_device *dev = connector->dev;
@@ -547,6 +655,8 @@ void drm_debugfs_connector_add(struct drm_connector 
*connector)
debugfs_create_file("output_bpc", 0444, root, connector,
_bpc_fops);
 
+   hdmi_debugfs_add(connector);
+
if (connector->funcs->debugfs_init)
connector->funcs->debugfs_init(connector, root);
 }

-- 
2.43.2



[PATCH v7 20/36] drm/tests: Add HDMI connector bpc and format tests

2024-02-22 Thread Maxime Ripard
The previous patch added the bpc and format an HDMI connector needs to
be set up with for a given connector state.

Let's add a few tests to make sure it works as expected.

Signed-off-by: Maxime Ripard 
---
 .../gpu/drm/tests/drm_atomic_state_helper_test.c   | 504 +
 drivers/gpu/drm/tests/drm_kunit_edid.h | 160 +++
 2 files changed, 664 insertions(+)

diff --git a/drivers/gpu/drm/tests/drm_atomic_state_helper_test.c 
b/drivers/gpu/drm/tests/drm_atomic_state_helper_test.c
index f010fde0eb69..c0f26422e925 100644
--- a/drivers/gpu/drm/tests/drm_atomic_state_helper_test.c
+++ b/drivers/gpu/drm/tests/drm_atomic_state_helper_test.c
@@ -370,6 +370,56 @@ static void 
drm_test_check_output_bpc_crtc_mode_not_changed(struct kunit *test)
KUNIT_EXPECT_FALSE(test, crtc_state->mode_changed);
 }
 
+/*
+ * Test that if we have an HDMI connector but a !HDMI display, we always
+ * output RGB with 8 bpc.
+ */
+static void drm_test_check_output_bpc_dvi(struct kunit *test)
+{
+   struct drm_atomic_helper_connector_hdmi_priv *priv;
+   struct drm_modeset_acquire_ctx *ctx;
+   struct drm_connector_state *conn_state;
+   struct drm_display_info *info;
+   struct drm_display_mode *preferred;
+   struct drm_connector *conn;
+   struct drm_device *drm;
+   struct drm_crtc *crtc;
+   int ret;
+
+   priv = drm_atomic_helper_connector_hdmi_init(test,
+BIT(HDMI_COLORSPACE_RGB) |
+
BIT(HDMI_COLORSPACE_YUV422) |
+
BIT(HDMI_COLORSPACE_YUV444),
+12);
+   KUNIT_ASSERT_NOT_NULL(test, priv);
+
+   conn = >connector;
+   ret = set_connector_edid(test, conn,
+test_edid_dvi_1080p,
+ARRAY_SIZE(test_edid_dvi_1080p));
+   KUNIT_ASSERT_EQ(test, ret, 0);
+
+   info = >display_info;
+   KUNIT_ASSERT_FALSE(test, info->is_hdmi);
+
+   ctx = drm_kunit_helper_acquire_ctx_alloc(test);
+   KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx);
+
+   preferred = find_preferred_mode(conn);
+   KUNIT_ASSERT_NOT_NULL(test, preferred);
+
+   drm = >drm;
+   crtc = priv->crtc;
+   ret = light_up_connector(test, drm, crtc, conn, preferred, ctx);
+   KUNIT_ASSERT_EQ(test, ret, 0);
+
+   conn_state = conn->state;
+   KUNIT_ASSERT_NOT_NULL(test, conn_state);
+
+   KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_bpc, 8);
+   KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_format, 
HDMI_COLORSPACE_RGB);
+}
+
 /*
  * Test that when doing a commit which would use RGB 8bpc, the TMDS
  * clock rate stored in the connector state is equal to the mode clock
@@ -562,10 +612,464 @@ static void drm_test_check_hdmi_funcs_reject_rate(struct 
kunit *test)
KUNIT_EXPECT_LT(test, ret, 0);
 }
 
+/*
+ * Test that if:
+ * - We have an HDMI connector supporting RGB only
+ * - The chosen mode has a TMDS character rate higher than the display
+ *   supports in RGB/12bpc
+ * - The chosen mode has a TMDS character rate lower than the display
+ *   supports in RGB/10bpc.
+ *
+ * Then we will pick the latter, and the computed TMDS character rate
+ * will be equal to 1.25 times the mode pixel clock.
+ */
+static void drm_test_check_max_tmds_rate_bpc_fallback(struct kunit *test)
+{
+   struct drm_atomic_helper_connector_hdmi_priv *priv;
+   struct drm_modeset_acquire_ctx *ctx;
+   struct drm_connector_state *conn_state;
+   struct drm_display_info *info;
+   struct drm_display_mode *preferred;
+   unsigned long long rate;
+   struct drm_connector *conn;
+   struct drm_device *drm;
+   struct drm_crtc *crtc;
+   int ret;
+
+   priv = drm_atomic_helper_connector_hdmi_init(test,
+BIT(HDMI_COLORSPACE_RGB),
+12);
+   KUNIT_ASSERT_NOT_NULL(test, priv);
+
+   conn = >connector;
+   ret = set_connector_edid(test, conn,
+test_edid_hdmi_1080p_rgb_yuv_dc_max_200mhz,
+
ARRAY_SIZE(test_edid_hdmi_1080p_rgb_yuv_dc_max_200mhz));
+   KUNIT_ASSERT_EQ(test, ret, 0);
+
+   info = >display_info;
+   KUNIT_ASSERT_TRUE(test, info->is_hdmi);
+   KUNIT_ASSERT_GT(test, info->max_tmds_clock, 0);
+
+   ctx = drm_kunit_helper_acquire_ctx_alloc(test);
+   KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx);
+
+   preferred = find_preferred_mode(conn);
+   KUNIT_ASSERT_NOT_NULL(test, preferred);
+   KUNIT_ASSERT_FALSE(test, preferred->flags & DRM_MODE_FLAG_DBLCLK);
+
+   rate = drm_connector_hdmi_compute_mode_clock(preferred, 12, 
HDMI_COLORSPACE_RGB);
+   KUNIT_ASSERT_GT(test, rate, info->max_tmds_clock * 1000);
+
+   rate = 

[PATCH v7 23/36] drm/connector: hdmi: Add RGB Quantization Range to the connector state

2024-02-22 Thread Maxime Ripard
HDMI controller drivers will need to figure out the RGB range they need
to configure based on a mode and property values. Let's expose that in
the HDMI connector state so drivers can just use that value.

Reviewed-by: Dave Stevenson 
Signed-off-by: Maxime Ripard 
---
 drivers/gpu/drm/drm_atomic.c  |  1 +
 drivers/gpu/drm/drm_atomic_state_helper.c | 29 +
 include/drm/drm_connector.h   |  6 ++
 3 files changed, 36 insertions(+)

diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c
index 3e57d98d8418..ec6c6beda5c9 100644
--- a/drivers/gpu/drm/drm_atomic.c
+++ b/drivers/gpu/drm/drm_atomic.c
@@ -1147,6 +1147,7 @@ static void drm_atomic_connector_print_state(struct 
drm_printer *p,
connector->connector_type == DRM_MODE_CONNECTOR_HDMIB) {
drm_printf(p, "\tbroadcast_rgb=%s\n",
   
drm_hdmi_connector_get_broadcast_rgb_name(state->hdmi.broadcast_rgb));
+   drm_printf(p, "\tis_full_range=%c\n", state->hdmi.is_full_range 
? 'y' : 'n');
drm_printf(p, "\toutput_bpc=%u\n", state->hdmi.output_bpc);
drm_printf(p, "\toutput_format=%s\n",
   
drm_hdmi_connector_get_output_format_name(state->hdmi.output_format));
diff --git a/drivers/gpu/drm/drm_atomic_state_helper.c 
b/drivers/gpu/drm/drm_atomic_state_helper.c
index 0e8fb653965a..e66272c0d006 100644
--- a/drivers/gpu/drm/drm_atomic_state_helper.c
+++ b/drivers/gpu/drm/drm_atomic_state_helper.c
@@ -664,6 +664,33 @@ connector_state_get_mode(const struct drm_connector_state 
*conn_state)
return _state->mode;
 }
 
+static bool hdmi_is_full_range(const struct drm_connector *connector,
+  const struct drm_connector_state *state)
+{
+   const struct drm_display_info *display = >display_info;
+   const struct drm_display_mode *mode =
+   connector_state_get_mode(state);
+
+   /*
+* The Broadcast RGB property only applies to RGB format, and
+* i915 just assumes limited range for YCbCr output, so let's
+* just do the same.
+*/
+   if (state->hdmi.output_format != HDMI_COLORSPACE_RGB)
+   return false;
+
+   if (state->hdmi.broadcast_rgb == DRM_HDMI_BROADCAST_RGB_FULL)
+   return true;
+
+   if (state->hdmi.broadcast_rgb == DRM_HDMI_BROADCAST_RGB_LIMITED)
+   return false;
+
+   if (!display->is_hdmi)
+   return true;
+
+   return drm_default_rgb_quant_range(mode) == 
HDMI_QUANTIZATION_RANGE_FULL ? true : false;
+}
+
 static bool
 sink_supports_format_bpc(const struct drm_connector *connector,
 const struct drm_display_info *info,
@@ -910,6 +937,8 @@ int drm_atomic_helper_connector_hdmi_check(struct 
drm_connector *connector,
connector_state_get_mode(new_state);
int ret;
 
+   new_state->hdmi.is_full_range = hdmi_is_full_range(connector, 
new_state);
+
ret = hdmi_compute_config(connector, new_state, mode);
if (ret)
return ret;
diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h
index bb6b6a36ade3..3eaf4d54364d 100644
--- a/include/drm/drm_connector.h
+++ b/include/drm/drm_connector.h
@@ -1070,6 +1070,12 @@ struct drm_connector_state {
 */
enum drm_hdmi_broadcast_rgb broadcast_rgb;
 
+   /**
+* @is_full_range: Is the output supposed to use a full
+* RGB Quantization Range or not?
+*/
+   bool is_full_range;
+
/**
 * @output_bpc: Bits per color channel to output.
 */

-- 
2.43.2



[PATCH v7 18/36] drm/tests: Add HDMI connector rate filter hook tests

2024-02-22 Thread Maxime Ripard
The previous patch adds a new hook for HDMI connectors to filter out
configurations based on the TMDS character rate. Let's add some tests to
make sure it works as expected.

Reviewed-by: Dave Stevenson 
Signed-off-by: Maxime Ripard 
---
 .../gpu/drm/tests/drm_atomic_state_helper_test.c   | 65 ++
 1 file changed, 65 insertions(+)

diff --git a/drivers/gpu/drm/tests/drm_atomic_state_helper_test.c 
b/drivers/gpu/drm/tests/drm_atomic_state_helper_test.c
index 989661ad3aee..5a8750153510 100644
--- a/drivers/gpu/drm/tests/drm_atomic_state_helper_test.c
+++ b/drivers/gpu/drm/tests/drm_atomic_state_helper_test.c
@@ -113,6 +113,18 @@ static int set_connector_edid(struct kunit *test, struct 
drm_connector *connecto
 static const struct drm_connector_hdmi_funcs dummy_connector_hdmi_funcs = {
 };
 
+static enum drm_mode_status
+reject_connector_tmds_char_rate_valid(const struct drm_connector *connector,
+  const struct drm_display_mode *mode,
+  unsigned long long tmds_rate)
+{
+   return MODE_BAD;
+}
+
+static const struct drm_connector_hdmi_funcs reject_connector_hdmi_funcs = {
+   .tmds_char_rate_valid   = reject_connector_tmds_char_rate_valid,
+};
+
 static int dummy_connector_get_modes(struct drm_connector *connector)
 {
struct drm_atomic_helper_connector_hdmi_priv *priv =
@@ -491,7 +503,60 @@ static void drm_test_check_tmds_char_rate_rgb_12bpc(struct 
kunit *test)
KUNIT_EXPECT_EQ(test, conn_state->hdmi.tmds_char_rate, preferred->clock 
* 1500);
 }
 
+/*
+ * Test that if we filter a rate through our hook, it's indeed rejected
+ * by the whole atomic_check logic.
+ *
+ * We do so by first doing a commit on the pipeline to make sure that it
+ * works, change the HDMI helpers pointer, and then try the same commit
+ * again to see if it fails as it should.
+ */
+static void drm_test_check_hdmi_funcs_reject_rate(struct kunit *test)
+{
+   struct drm_atomic_helper_connector_hdmi_priv *priv;
+   struct drm_modeset_acquire_ctx *ctx;
+   struct drm_atomic_state *state;
+   struct drm_display_mode *preferred;
+   struct drm_crtc_state *crtc_state;
+   struct drm_connector *conn;
+   struct drm_device *drm;
+   struct drm_crtc *crtc;
+   int ret;
+
+   priv = drm_atomic_helper_connector_hdmi_init(test,
+BIT(HDMI_COLORSPACE_RGB),
+8);
+   KUNIT_ASSERT_NOT_NULL(test, priv);
+
+   ctx = drm_kunit_helper_acquire_ctx_alloc(test);
+   KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx);
+
+   conn = >connector;
+   preferred = find_preferred_mode(conn);
+   KUNIT_ASSERT_NOT_NULL(test, preferred);
+
+   drm = >drm;
+   crtc = priv->crtc;
+   ret = light_up_connector(test, drm, crtc, conn, preferred, ctx);
+   KUNIT_ASSERT_EQ(test, ret, 0);
+
+   /* You shouldn't be doing that at home. */
+   conn->hdmi.funcs = _connector_hdmi_funcs;
+
+   state = drm_kunit_helper_atomic_state_alloc(test, drm, ctx);
+   KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state);
+
+   crtc_state = drm_atomic_get_crtc_state(state, crtc);
+   KUNIT_ASSERT_NOT_ERR_OR_NULL(test, crtc_state);
+
+   crtc_state->connectors_changed = true;
+
+   ret = drm_atomic_check_only(state);
+   KUNIT_EXPECT_LT(test, ret, 0);
+}
+
 static struct kunit_case drm_atomic_helper_connector_hdmi_check_tests[] = {
+   KUNIT_CASE(drm_test_check_hdmi_funcs_reject_rate),
KUNIT_CASE(drm_test_check_output_bpc_crtc_mode_changed),
KUNIT_CASE(drm_test_check_output_bpc_crtc_mode_not_changed),
KUNIT_CASE(drm_test_check_tmds_char_rate_rgb_8bpc),

-- 
2.43.2



[PATCH v7 21/36] drm/connector: hdmi: Add Broadcast RGB property

2024-02-22 Thread Maxime Ripard
The i915 driver has a property to force the RGB range of an HDMI output.
The vc4 driver then implemented the same property with the same
semantics. KWin has support for it, and a PR for mutter is also there to
support it.

Both drivers implementing the same property with the same semantics,
plus the userspace having support for it, is proof enough that it's
pretty much a de-facto standard now and we can provide helpers for it.

Let's plumb it into the newly created HDMI connector.

Reviewed-by: Dave Stevenson 
Signed-off-by: Maxime Ripard 
---
 Documentation/gpu/kms-properties.csv  |  1 -
 drivers/gpu/drm/drm_atomic.c  |  2 +
 drivers/gpu/drm/drm_atomic_state_helper.c |  4 +-
 drivers/gpu/drm/drm_atomic_uapi.c |  4 ++
 drivers/gpu/drm/drm_connector.c   | 89 +++
 include/drm/drm_connector.h   | 36 +
 6 files changed, 134 insertions(+), 2 deletions(-)

diff --git a/Documentation/gpu/kms-properties.csv 
b/Documentation/gpu/kms-properties.csv
index 0f9590834829..caef14c532d4 100644
--- a/Documentation/gpu/kms-properties.csv
+++ b/Documentation/gpu/kms-properties.csv
@@ -17,7 +17,6 @@ Owner Module/Drivers,Group,Property Name,Type,Property 
Values,Object attached,De
 ,Virtual GPU,“suggested X”,RANGE,"Min=0, Max=0x",Connector,property to 
suggest an X offset for a connector
 ,,“suggested Y”,RANGE,"Min=0, Max=0x",Connector,property to suggest an 
Y offset for a connector
 ,Optional,"""aspect ratio""",ENUM,"{ ""None"", ""4:3"", ""16:9"" 
}",Connector,TDB
-i915,Generic,"""Broadcast RGB""",ENUM,"{ ""Automatic"", ""Full"", ""Limited 
16:235"" }",Connector,"When this property is set to Limited 16:235 and CTM is 
set, the hardware will be programmed with the result of the multiplication of 
CTM by the limited range matrix to ensure the pixels normally in the range 
0..1.0 are remapped to the range 16/255..235/255."
 ,,“audio”,ENUM,"{ ""force-dvi"", ""off"", ""auto"", ""on"" }",Connector,TBD
 ,SDVO-TV,“mode”,ENUM,"{ ""NTSC_M"", ""NTSC_J"", ""NTSC_443"", ""PAL_B"" } 
etc.",Connector,TBD
 ,,"""left_margin""",RANGE,"Min=0, Max= SDVO dependent",Connector,TBD
diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c
index 26f9e525c0a0..3e57d98d8418 100644
--- a/drivers/gpu/drm/drm_atomic.c
+++ b/drivers/gpu/drm/drm_atomic.c
@@ -1145,6 +1145,8 @@ static void drm_atomic_connector_print_state(struct 
drm_printer *p,
 
if (connector->connector_type == DRM_MODE_CONNECTOR_HDMIA ||
connector->connector_type == DRM_MODE_CONNECTOR_HDMIB) {
+   drm_printf(p, "\tbroadcast_rgb=%s\n",
+  
drm_hdmi_connector_get_broadcast_rgb_name(state->hdmi.broadcast_rgb));
drm_printf(p, "\toutput_bpc=%u\n", state->hdmi.output_bpc);
drm_printf(p, "\toutput_format=%s\n",
   
drm_hdmi_connector_get_output_format_name(state->hdmi.output_format));
diff --git a/drivers/gpu/drm/drm_atomic_state_helper.c 
b/drivers/gpu/drm/drm_atomic_state_helper.c
index 9f517599f117..0e8fb653965a 100644
--- a/drivers/gpu/drm/drm_atomic_state_helper.c
+++ b/drivers/gpu/drm/drm_atomic_state_helper.c
@@ -589,6 +589,7 @@ void __drm_atomic_helper_connector_hdmi_reset(struct 
drm_connector *connector,
 
new_state->max_bpc = max_bpc;
new_state->max_requested_bpc = max_bpc;
+   new_state->hdmi.broadcast_rgb = DRM_HDMI_BROADCAST_RGB_AUTO;
 }
 EXPORT_SYMBOL(__drm_atomic_helper_connector_hdmi_reset);
 
@@ -913,7 +914,8 @@ int drm_atomic_helper_connector_hdmi_check(struct 
drm_connector *connector,
if (ret)
return ret;
 
-   if (old_state->hdmi.output_bpc != new_state->hdmi.output_bpc ||
+   if (old_state->hdmi.broadcast_rgb != new_state->hdmi.broadcast_rgb ||
+   old_state->hdmi.output_bpc != new_state->hdmi.output_bpc ||
old_state->hdmi.output_format != new_state->hdmi.output_format) {
struct drm_crtc *crtc = new_state->crtc;
struct drm_crtc_state *crtc_state;
diff --git a/drivers/gpu/drm/drm_atomic_uapi.c 
b/drivers/gpu/drm/drm_atomic_uapi.c
index 29d4940188d4..2b415b4ed506 100644
--- a/drivers/gpu/drm/drm_atomic_uapi.c
+++ b/drivers/gpu/drm/drm_atomic_uapi.c
@@ -776,6 +776,8 @@ static int drm_atomic_connector_set_property(struct 
drm_connector *connector,
state->max_requested_bpc = val;
} else if (property == connector->privacy_screen_sw_state_property) {
state->privacy_screen_sw_state = val;
+   } else if (property == connector->broadcast_rgb_property) {
+   state->hdmi.broadcast_rgb = val;
} else if (connector->funcs->atomic_set_property) {
return connector->funcs->atomic_set_property(connector,
state, property, val);
@@ -859,6 +861,8 @@ drm_atomic_connector_get_property(struct drm_connector 
*connector,
*val = 

[PATCH v7 22/36] drm/tests: Add tests for Broadcast RGB property

2024-02-22 Thread Maxime Ripard
This had a bunch of kunit tests to make sure our code to handle the
Broadcast RGB property behaves properly.

This requires bringing a bit of infrastructure to create mock HDMI
connectors, with custom EDIDs.

Reviewed-by: Dave Stevenson 
Signed-off-by: Maxime Ripard 
---
 .../gpu/drm/tests/drm_atomic_state_helper_test.c   | 151 +
 drivers/gpu/drm/tests/drm_connector_test.c | 116 
 2 files changed, 267 insertions(+)

diff --git a/drivers/gpu/drm/tests/drm_atomic_state_helper_test.c 
b/drivers/gpu/drm/tests/drm_atomic_state_helper_test.c
index c0f26422e925..3de15cec2f5f 100644
--- a/drivers/gpu/drm/tests/drm_atomic_state_helper_test.c
+++ b/drivers/gpu/drm/tests/drm_atomic_state_helper_test.c
@@ -224,6 +224,134 @@ drm_atomic_helper_connector_hdmi_init(struct kunit *test,
return priv;
 }
 
+/*
+ * Test that if we change the RGB quantization property to a different
+ * value, we trigger a mode change on the connector's CRTC, which will
+ * in turn disable/enable the connector.
+ */
+static void drm_test_check_broadcast_rgb_crtc_mode_changed(struct kunit *test)
+{
+   struct drm_atomic_helper_connector_hdmi_priv *priv;
+   struct drm_modeset_acquire_ctx *ctx;
+   struct drm_connector_state *old_conn_state;
+   struct drm_connector_state *new_conn_state;
+   struct drm_crtc_state *crtc_state;
+   struct drm_atomic_state *state;
+   struct drm_display_mode *preferred;
+   struct drm_connector *conn;
+   struct drm_device *drm;
+   struct drm_crtc *crtc;
+   int ret;
+
+   priv = drm_atomic_helper_connector_hdmi_init(test,
+BIT(HDMI_COLORSPACE_RGB),
+8);
+   KUNIT_ASSERT_NOT_NULL(test, priv);
+
+   ctx = drm_kunit_helper_acquire_ctx_alloc(test);
+   KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx);
+
+   conn = >connector;
+   preferred = find_preferred_mode(conn);
+   KUNIT_ASSERT_NOT_NULL(test, preferred);
+
+   drm = >drm;
+   crtc = priv->crtc;
+   ret = light_up_connector(test, drm, crtc, conn, preferred, ctx);
+   KUNIT_ASSERT_EQ(test, ret, 0);
+
+   state = drm_kunit_helper_atomic_state_alloc(test, drm, ctx);
+   KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state);
+
+   new_conn_state = drm_atomic_get_connector_state(state, conn);
+   KUNIT_ASSERT_NOT_ERR_OR_NULL(test, new_conn_state);
+
+   old_conn_state = drm_atomic_get_old_connector_state(state, conn);
+   KUNIT_ASSERT_NOT_ERR_OR_NULL(test, old_conn_state);
+
+   new_conn_state->hdmi.broadcast_rgb = DRM_HDMI_BROADCAST_RGB_FULL;
+
+   KUNIT_ASSERT_NE(test,
+   old_conn_state->hdmi.broadcast_rgb,
+   new_conn_state->hdmi.broadcast_rgb);
+
+   ret = drm_atomic_check_only(state);
+   KUNIT_ASSERT_EQ(test, ret, 0);
+
+   new_conn_state = drm_atomic_get_new_connector_state(state, conn);
+   KUNIT_ASSERT_NOT_ERR_OR_NULL(test, new_conn_state);
+   KUNIT_EXPECT_EQ(test, new_conn_state->hdmi.broadcast_rgb, 
DRM_HDMI_BROADCAST_RGB_FULL);
+
+   crtc_state = drm_atomic_get_new_crtc_state(state, crtc);
+   KUNIT_ASSERT_NOT_ERR_OR_NULL(test, crtc_state);
+   KUNIT_EXPECT_TRUE(test, crtc_state->mode_changed);
+}
+
+/*
+ * Test that if we set the RGB quantization property to the same value,
+ * we don't trigger a mode change on the connector's CRTC and leave the
+ * connector unaffected.
+ */
+static void drm_test_check_broadcast_rgb_crtc_mode_not_changed(struct kunit 
*test)
+{
+   struct drm_atomic_helper_connector_hdmi_priv *priv;
+   struct drm_modeset_acquire_ctx *ctx;
+   struct drm_connector_state *old_conn_state;
+   struct drm_connector_state *new_conn_state;
+   struct drm_crtc_state *crtc_state;
+   struct drm_atomic_state *state;
+   struct drm_display_mode *preferred;
+   struct drm_connector *conn;
+   struct drm_device *drm;
+   struct drm_crtc *crtc;
+   int ret;
+
+   priv = drm_atomic_helper_connector_hdmi_init(test,
+BIT(HDMI_COLORSPACE_RGB),
+8);
+   KUNIT_ASSERT_NOT_NULL(test, priv);
+
+   ctx = drm_kunit_helper_acquire_ctx_alloc(test);
+   KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx);
+
+   conn = >connector;
+   preferred = find_preferred_mode(conn);
+   KUNIT_ASSERT_NOT_NULL(test, preferred);
+
+   drm = >drm;
+   crtc = priv->crtc;
+   ret = light_up_connector(test, drm, crtc, conn, preferred, ctx);
+   KUNIT_ASSERT_EQ(test, ret, 0);
+
+   state = drm_kunit_helper_atomic_state_alloc(test, drm, ctx);
+   KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state);
+
+   new_conn_state = drm_atomic_get_connector_state(state, conn);
+   KUNIT_ASSERT_NOT_ERR_OR_NULL(test, new_conn_state);
+
+   old_conn_state = 

[PATCH v7 14/36] drm/tests: Add HDMI TDMS character rate tests

2024-02-22 Thread Maxime Ripard
The previous patch added an helper to compute the TMDS character rate on
an HDMI connector. Let's add a few tests to make sure it works as
expected.

Reviewed-by: Dave Stevenson 
Signed-off-by: Maxime Ripard 
---
 drivers/gpu/drm/tests/drm_connector_test.c | 323 +
 1 file changed, 323 insertions(+)

diff --git a/drivers/gpu/drm/tests/drm_connector_test.c 
b/drivers/gpu/drm/tests/drm_connector_test.c
index 5bff67fbed87..882b9269148e 100644
--- a/drivers/gpu/drm/tests/drm_connector_test.c
+++ b/drivers/gpu/drm/tests/drm_connector_test.c
@@ -8,7 +8,9 @@
 #include 
 #include 
 #include 
+#include 
 #include 
+#include 
 
 #include 
 
@@ -606,9 +608,330 @@ static struct kunit_suite 
drm_hdmi_connector_get_output_format_name_test_suite =
.test_cases = drm_hdmi_connector_get_output_format_name_tests,
 };
 
+/*
+ * Test that for a given mode, with 8bpc and an RGB output the TMDS
+ * character rate is equal to the mode pixel clock.
+ */
+static void drm_test_drm_connector_hdmi_compute_mode_clock_rgb(struct kunit 
*test)
+{
+   struct drm_connector_init_priv *priv = test->priv;
+   const struct drm_display_mode *mode;
+   unsigned long long rate;
+   struct drm_device *drm = >drm;
+
+   mode = drm_display_mode_from_cea_vic(drm, 16);
+   KUNIT_ASSERT_NOT_NULL(test, mode);
+
+   KUNIT_ASSERT_FALSE(test, mode->flags & DRM_MODE_FLAG_DBLCLK);
+
+   rate = drm_connector_hdmi_compute_mode_clock(mode, 8, 
HDMI_COLORSPACE_RGB);
+   KUNIT_ASSERT_GT(test, rate, 0);
+   KUNIT_EXPECT_EQ(test, mode->clock * 1000ULL, rate);
+}
+
+/*
+ * Test that for a given mode, with 10bpc and an RGB output the TMDS
+ * character rate is equal to 1.25 times the mode pixel clock.
+ */
+static void drm_test_drm_connector_hdmi_compute_mode_clock_rgb_10bpc(struct 
kunit *test)
+{
+   struct drm_connector_init_priv *priv = test->priv;
+   const struct drm_display_mode *mode;
+   unsigned long long rate;
+   struct drm_device *drm = >drm;
+
+   mode = drm_display_mode_from_cea_vic(drm, 16);
+   KUNIT_ASSERT_NOT_NULL(test, mode);
+
+   KUNIT_ASSERT_FALSE(test, mode->flags & DRM_MODE_FLAG_DBLCLK);
+
+   rate = drm_connector_hdmi_compute_mode_clock(mode, 10, 
HDMI_COLORSPACE_RGB);
+   KUNIT_ASSERT_GT(test, rate, 0);
+   KUNIT_EXPECT_EQ(test, mode->clock * 1250, rate);
+}
+
+/*
+ * Test that for the VIC-1 mode, with 10bpc and an RGB output the TMDS
+ * character rate computation fails.
+ */
+static void 
drm_test_drm_connector_hdmi_compute_mode_clock_rgb_10bpc_vic_1(struct kunit 
*test)
+{
+   struct drm_connector_init_priv *priv = test->priv;
+   const struct drm_display_mode *mode;
+   unsigned long long rate;
+   struct drm_device *drm = >drm;
+
+   mode = drm_display_mode_from_cea_vic(drm, 1);
+   KUNIT_ASSERT_NOT_NULL(test, mode);
+
+   rate = drm_connector_hdmi_compute_mode_clock(mode, 10, 
HDMI_COLORSPACE_RGB);
+   KUNIT_EXPECT_EQ(test, rate, 0);
+}
+
+/*
+ * Test that for a given mode, with 12bpc and an RGB output the TMDS
+ * character rate is equal to 1.5 times the mode pixel clock.
+ */
+static void drm_test_drm_connector_hdmi_compute_mode_clock_rgb_12bpc(struct 
kunit *test)
+{
+   struct drm_connector_init_priv *priv = test->priv;
+   const struct drm_display_mode *mode;
+   unsigned long long rate;
+   struct drm_device *drm = >drm;
+
+   mode = drm_display_mode_from_cea_vic(drm, 16);
+   KUNIT_ASSERT_NOT_NULL(test, mode);
+
+   KUNIT_ASSERT_FALSE(test, mode->flags & DRM_MODE_FLAG_DBLCLK);
+
+   rate = drm_connector_hdmi_compute_mode_clock(mode, 12, 
HDMI_COLORSPACE_RGB);
+   KUNIT_ASSERT_GT(test, rate, 0);
+   KUNIT_EXPECT_EQ(test, mode->clock * 1500, rate);
+}
+
+/*
+ * Test that for the VIC-1 mode, with 12bpc and an RGB output the TMDS
+ * character rate computation fails.
+ */
+static void 
drm_test_drm_connector_hdmi_compute_mode_clock_rgb_12bpc_vic_1(struct kunit 
*test)
+{
+   struct drm_connector_init_priv *priv = test->priv;
+   const struct drm_display_mode *mode;
+   unsigned long long rate;
+   struct drm_device *drm = >drm;
+
+   mode = drm_display_mode_from_cea_vic(drm, 1);
+   KUNIT_ASSERT_NOT_NULL(test, mode);
+
+   rate = drm_connector_hdmi_compute_mode_clock(mode, 12, 
HDMI_COLORSPACE_RGB);
+   KUNIT_EXPECT_EQ(test, rate, 0);
+}
+
+/*
+ * Test that for a mode with the pixel repetition flag, the TMDS
+ * character rate is indeed double the mode pixel clock.
+ */
+static void drm_test_drm_connector_hdmi_compute_mode_clock_rgb_double(struct 
kunit *test)
+{
+   struct drm_connector_init_priv *priv = test->priv;
+   const struct drm_display_mode *mode;
+   unsigned long long rate;
+   struct drm_device *drm = >drm;
+
+   mode = drm_display_mode_from_cea_vic(drm, 6);
+   KUNIT_ASSERT_NOT_NULL(test, mode);
+
+   KUNIT_ASSERT_TRUE(test, mode->flags & DRM_MODE_FLAG_DBLCLK);
+
+   

[PATCH v7 19/36] drm/connector: hdmi: Compute bpc and format automatically

2024-02-22 Thread Maxime Ripard
Now that we have all the infrastructure needed, we can add some code
that will, for a given connector state and mode, compute the best output
format and bpc.

The algorithm is equivalent to the one already found in i915 and vc4.

Signed-off-by: Maxime Ripard 
---
 drivers/gpu/drm/drm_atomic_state_helper.c  | 184 -
 .../gpu/drm/tests/drm_atomic_state_helper_test.c   |  25 ++-
 2 files changed, 197 insertions(+), 12 deletions(-)

diff --git a/drivers/gpu/drm/drm_atomic_state_helper.c 
b/drivers/gpu/drm/drm_atomic_state_helper.c
index 448b4a73d1c8..9f517599f117 100644
--- a/drivers/gpu/drm/drm_atomic_state_helper.c
+++ b/drivers/gpu/drm/drm_atomic_state_helper.c
@@ -31,6 +31,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -662,6 +663,96 @@ connector_state_get_mode(const struct drm_connector_state 
*conn_state)
return _state->mode;
 }
 
+static bool
+sink_supports_format_bpc(const struct drm_connector *connector,
+const struct drm_display_info *info,
+const struct drm_display_mode *mode,
+unsigned int format, unsigned int bpc)
+{
+   struct drm_device *dev = connector->dev;
+   u8 vic = drm_match_cea_mode(mode);
+
+   if (vic == 1 && bpc != 8) {
+   drm_dbg(dev, "VIC1 requires a bpc of 8, got %u\n", bpc);
+   return false;
+   }
+
+   if (!info->is_hdmi &&
+   (format != HDMI_COLORSPACE_RGB || bpc != 8)) {
+   drm_dbg(dev, "DVI Monitors require an RGB output at 8 bpc\n");
+   return false;
+   }
+
+   if (!(connector->hdmi.supported_formats & BIT(format))) {
+   drm_dbg(dev, "%s format unsupported by the connector.\n",
+   drm_hdmi_connector_get_output_format_name(format));
+   return false;
+   }
+
+   switch (format) {
+   case HDMI_COLORSPACE_RGB:
+   drm_dbg(dev, "RGB Format, checking the constraints.\n");
+
+   if (!(info->color_formats & DRM_COLOR_FORMAT_RGB444))
+   return false;
+
+   if (bpc == 10 && !(info->edid_hdmi_rgb444_dc_modes & 
DRM_EDID_HDMI_DC_30)) {
+   drm_dbg(dev, "10 BPC but sink doesn't support Deep 
Color 30.\n");
+   return false;
+   }
+
+   if (bpc == 12 && !(info->edid_hdmi_rgb444_dc_modes & 
DRM_EDID_HDMI_DC_36)) {
+   drm_dbg(dev, "12 BPC but sink doesn't support Deep 
Color 36.\n");
+   return false;
+   }
+
+   drm_dbg(dev, "RGB format supported in that configuration.\n");
+
+   return true;
+
+   case HDMI_COLORSPACE_YUV422:
+   drm_dbg(dev, "YUV422 format, checking the constraints.\n");
+
+   if (!(info->color_formats & DRM_COLOR_FORMAT_YCBCR422)) {
+   drm_dbg(dev, "Sink doesn't support YUV422.\n");
+   return false;
+   }
+
+   if (bpc != 12) {
+   drm_dbg(dev, "YUV422 only supports 12 bpc.\n");
+   return false;
+   }
+
+   drm_dbg(dev, "YUV422 format supported in that 
configuration.\n");
+
+   return true;
+
+   case HDMI_COLORSPACE_YUV444:
+   drm_dbg(dev, "YUV444 format, checking the constraints.\n");
+
+   if (!(info->color_formats & DRM_COLOR_FORMAT_YCBCR444)) {
+   drm_dbg(dev, "Sink doesn't support YUV444.\n");
+   return false;
+   }
+
+   if (bpc == 10 && !(info->edid_hdmi_ycbcr444_dc_modes & 
DRM_EDID_HDMI_DC_30)) {
+   drm_dbg(dev, "10 BPC but sink doesn't support Deep 
Color 30.\n");
+   return false;
+   }
+
+   if (bpc == 12 && !(info->edid_hdmi_ycbcr444_dc_modes & 
DRM_EDID_HDMI_DC_36)) {
+   drm_dbg(dev, "12 BPC but sink doesn't support Deep 
Color 36.\n");
+   return false;
+   }
+
+   drm_dbg(dev, "YUV444 format supported in that 
configuration.\n");
+
+   return true;
+   }
+
+   return false;
+}
+
 static enum drm_mode_status
 hdmi_clock_valid(const struct drm_connector *connector,
 const struct drm_display_mode *mode,
@@ -706,6 +797,95 @@ hdmi_compute_clock(const struct drm_connector *connector,
return 0;
 }
 
+static bool
+hdmi_try_format_bpc(const struct drm_connector *connector,
+   struct drm_connector_state *state,
+   const struct drm_display_mode *mode,
+   unsigned int bpc, enum hdmi_colorspace fmt)
+{
+   const struct drm_display_info *info = >display_info;
+   struct drm_device *dev = connector->dev;
+   int ret;
+
+   drm_dbg(dev, "Trying %s output format\n",
+   

[PATCH v7 16/36] drm/tests: Add TDMS character rate connector state tests

2024-02-22 Thread Maxime Ripard
The previous patch stores in the connector state the expected TMDS
character rate matching the configuration of the HDMI connector. Let's
add a few tests to make sure it works as expected.

Reviewed-by: Dave Stevenson 
Signed-off-by: Maxime Ripard 
---
 .../gpu/drm/tests/drm_atomic_state_helper_test.c   | 166 
 drivers/gpu/drm/tests/drm_kunit_edid.h | 216 +
 2 files changed, 382 insertions(+)

diff --git a/drivers/gpu/drm/tests/drm_atomic_state_helper_test.c 
b/drivers/gpu/drm/tests/drm_atomic_state_helper_test.c
index f2acbd4c216c..dfed45b250a5 100644
--- a/drivers/gpu/drm/tests/drm_atomic_state_helper_test.c
+++ b/drivers/gpu/drm/tests/drm_atomic_state_helper_test.c
@@ -347,9 +347,152 @@ static void 
drm_test_check_output_bpc_crtc_mode_not_changed(struct kunit *test)
KUNIT_EXPECT_FALSE(test, crtc_state->mode_changed);
 }
 
+/*
+ * Test that when doing a commit which would use RGB 8bpc, the TMDS
+ * clock rate stored in the connector state is equal to the mode clock
+ */
+static void drm_test_check_tmds_char_rate_rgb_8bpc(struct kunit *test)
+{
+   struct drm_atomic_helper_connector_hdmi_priv *priv;
+   struct drm_modeset_acquire_ctx *ctx;
+   struct drm_connector_state *conn_state;
+   struct drm_display_mode *preferred;
+   struct drm_connector *conn;
+   struct drm_device *drm;
+   struct drm_crtc *crtc;
+   int ret;
+
+   priv = drm_atomic_helper_connector_hdmi_init(test,
+BIT(HDMI_COLORSPACE_RGB),
+8);
+   KUNIT_ASSERT_NOT_NULL(test, priv);
+
+   conn = >connector;
+   ret = set_connector_edid(test, conn,
+test_edid_hdmi_1080p_rgb_max_200mhz,
+
ARRAY_SIZE(test_edid_hdmi_1080p_rgb_max_200mhz));
+   KUNIT_ASSERT_EQ(test, ret, 0);
+
+   ctx = drm_kunit_helper_acquire_ctx_alloc(test);
+   KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx);
+
+   preferred = find_preferred_mode(conn);
+   KUNIT_ASSERT_NOT_NULL(test, preferred);
+   KUNIT_ASSERT_FALSE(test, preferred->flags & DRM_MODE_FLAG_DBLCLK);
+
+   drm = >drm;
+   crtc = priv->crtc;
+   ret = light_up_connector(test, drm, crtc, conn, preferred, ctx);
+   KUNIT_ASSERT_EQ(test, ret, 0);
+
+   conn_state = conn->state;
+   KUNIT_ASSERT_NOT_NULL(test, conn_state);
+
+   KUNIT_ASSERT_EQ(test, conn_state->hdmi.output_bpc, 8);
+   KUNIT_ASSERT_EQ(test, conn_state->hdmi.output_format, 
HDMI_COLORSPACE_RGB);
+   KUNIT_EXPECT_EQ(test, conn_state->hdmi.tmds_char_rate, preferred->clock 
* 1000);
+}
+
+/*
+ * Test that when doing a commit which would use RGB 10bpc, the TMDS
+ * clock rate stored in the connector state is equal to 1.25 times the
+ * mode pixel clock
+ */
+static void drm_test_check_tmds_char_rate_rgb_10bpc(struct kunit *test)
+{
+   struct drm_atomic_helper_connector_hdmi_priv *priv;
+   struct drm_modeset_acquire_ctx *ctx;
+   struct drm_connector_state *conn_state;
+   struct drm_display_mode *preferred;
+   struct drm_connector *conn;
+   struct drm_device *drm;
+   struct drm_crtc *crtc;
+   int ret;
+
+   priv = drm_atomic_helper_connector_hdmi_init(test,
+BIT(HDMI_COLORSPACE_RGB),
+10);
+   KUNIT_ASSERT_NOT_NULL(test, priv);
+
+   conn = >connector;
+   ret = set_connector_edid(test, conn,
+test_edid_hdmi_1080p_rgb_yuv_dc_max_340mhz,
+
ARRAY_SIZE(test_edid_hdmi_1080p_rgb_yuv_dc_max_340mhz));
+   KUNIT_ASSERT_EQ(test, ret, 0);
+
+   ctx = drm_kunit_helper_acquire_ctx_alloc(test);
+   KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx);
+
+   preferred = find_preferred_mode(conn);
+   KUNIT_ASSERT_NOT_NULL(test, preferred);
+   KUNIT_ASSERT_FALSE(test, preferred->flags & DRM_MODE_FLAG_DBLCLK);
+
+   drm = >drm;
+   crtc = priv->crtc;
+   ret = light_up_connector(test, drm, crtc, conn, preferred, ctx);
+   KUNIT_ASSERT_EQ(test, ret, 0);
+
+   conn_state = conn->state;
+   KUNIT_ASSERT_NOT_NULL(test, conn_state);
+
+   KUNIT_ASSERT_EQ(test, conn_state->hdmi.output_bpc, 10);
+   KUNIT_ASSERT_EQ(test, conn_state->hdmi.output_format, 
HDMI_COLORSPACE_RGB);
+   KUNIT_EXPECT_EQ(test, conn_state->hdmi.tmds_char_rate, preferred->clock 
* 1250);
+}
+
+/*
+ * Test that when doing a commit which would use RGB 12bpc, the TMDS
+ * clock rate stored in the connector state is equal to 1.5 times the
+ * mode pixel clock
+ */
+static void drm_test_check_tmds_char_rate_rgb_12bpc(struct kunit *test)
+{
+   struct drm_atomic_helper_connector_hdmi_priv *priv;
+   struct drm_modeset_acquire_ctx *ctx;
+   struct drm_connector_state *conn_state;
+   struct drm_display_mode 

  1   2   3   >