Re: [PATCH v3 1/4] drm: add devm release action

2024-04-24 Thread Maxime Ripard
On Mon, Apr 22, 2024 at 12:27:53PM +0530, Aravind Iddamsetty wrote:
> In scenarios where drm_dev_put is directly called by driver we want to
> release devm_drm_dev_init_release action associated with struct
> drm_device.
> 
> v2: Directly expose the original function, instead of introducing a
> helper (Rodrigo)
> 
> v3: add kernel-doc (Maxime Ripard)
> 
> Cc: Maxime Ripard 
> Cc: Thomas Hellstr_m 
> Cc: Rodrigo Vivi 
> 
> Reviewed-by: Rodrigo Vivi 
> Signed-off-by: Aravind Iddamsetty 
> ---
>  drivers/gpu/drm/drm_drv.c | 13 +
>  include/drm/drm_drv.h |  2 ++
>  2 files changed, 15 insertions(+)
> 
> diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c
> index 243cacb3575c..9d0409165f1e 100644
> --- a/drivers/gpu/drm/drm_drv.c
> +++ b/drivers/gpu/drm/drm_drv.c
> @@ -714,6 +714,19 @@ static int devm_drm_dev_init(struct device *parent,
>   devm_drm_dev_init_release, dev);
>  }
>  
> +/**
> + * devm_drm_dev_release_action - Call the final release action of the device
> + * @dev: DRM device
> + *
> + * In scenarios where drm_dev_put is directly called by driver we want to 
> release
> + * devm_drm_dev_init_release action associated with struct drm_device.
> + */

I'm not entirely sure what you mean by that documentation. "In scenarios
where drm_dev_put is directly called by the driver", we wouldn't need to
consider that function at all, right?

Also, we should reference it in drm_dev_put and devm_drm_dev_alloc too.

Maxime


signature.asc
Description: PGP signature


Re: [PATCH v3 1/4] drm: add devm release action

2024-04-24 Thread Maxime Ripard
On Tue, Apr 23, 2024 at 01:42:22PM -0400, Rodrigo Vivi wrote:
> On Tue, Apr 23, 2024 at 02:25:06PM +0530, Aravind Iddamsetty wrote:
> > 
> > On 23/04/24 02:24, Rodrigo Vivi wrote:
> > > On Mon, Apr 22, 2024 at 12:27:53PM +0530, Aravind Iddamsetty wrote:
> > >> In scenarios where drm_dev_put is directly called by driver we want to
> > >> release devm_drm_dev_init_release action associated with struct
> > >> drm_device.
> > >>
> > >> v2: Directly expose the original function, instead of introducing a
> > >> helper (Rodrigo)
> > >>
> > >> v3: add kernel-doc (Maxime Ripard)
> > >>
> > >> Cc: Maxime Ripard 
> > >> Cc: Thomas Hellstr_m 
> > >> Cc: Rodrigo Vivi 
> > >>
> > > please avoid these empty lines here cc, rv-b, sign-offs, links,
> > > etc are all in the same block.
> > ok.
> > >
> > >> Reviewed-by: Rodrigo Vivi 
> > >> Signed-off-by: Aravind Iddamsetty 
> > >> ---
> > >>  drivers/gpu/drm/drm_drv.c | 13 +
> > >>  include/drm/drm_drv.h |  2 ++
> > >>  2 files changed, 15 insertions(+)
> > >>
> > >> diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c
> > >> index 243cacb3575c..9d0409165f1e 100644
> > >> --- a/drivers/gpu/drm/drm_drv.c
> > >> +++ b/drivers/gpu/drm/drm_drv.c
> > >> @@ -714,6 +714,19 @@ static int devm_drm_dev_init(struct device *parent,
> > >>  devm_drm_dev_init_release, dev);
> > >>  }
> > >>  
> > >> +/**
> > >> + * devm_drm_dev_release_action - Call the final release action of the 
> > >> device
> > > Seeing the doc here gave me a second thought
> > >
> > > the original release should be renamed to _devm_drm_dev_release
> > > and this should be called devm_drm_dev_release without the 'action' word.
> > i believe, was suggested earlier to directly expose the main function, is 
> > there any reason to have a __ version ?
> 
> No no, just ignore me. Just remove the '_action' and don't change the other.
> 
> I don't like exposing the a function with '__'. what would '__' that mean?
> This is what I meant on the first comment.
> 
> Now, I believe that we don't need the '_action'. What does the 'action' mean?
> 
> the devm_drm_dev_release should be enough. But then I got confused and
> I thought it would conflict with the original released function name.
> But I misread it.

I don't think devm_drm_dev_release is a good name either. Just like any
other devm_* function that cancels what a previous one has been doing
(devm_kfree, devm_backlight_device_unregister, devm_nvmem_device_put,
etc.) it should be called devm_drm_dev_put or something similar.

Maxime


signature.asc
Description: PGP signature


Re: [PATCH 1/2] drm/panel/lg-sw43408: depends on CONFIG_DRM_DISPLAY_DP_HELPER

2024-04-24 Thread Maxime Ripard
Hi,

On Wed, Apr 24, 2024 at 10:43:32AM +0300, Dmitry Baryshkov wrote:
> On Wed, 24 Apr 2024 at 09:54, Neil Armstrong  
> wrote:
> >
> > On 20/04/2024 04:41, Dmitry Baryshkov wrote:
> > > This panel driver uses DSC PPS functions and as such depends on the
> > > DRM_DISPLAY_DP_HELPER. Add missing dependency
> > >
> > > Reported-by: kernel test robot 
> > > Closes: 
> > > https://lore.kernel.org/oe-kbuild-all/202404200800.kysryyli-...@intel.com/
> >
> > No Fixes ?
> 
> I'll add Fixes for v2. I'm waiting for the discussion on Kconfig to settle.
> 
> >
> > > Signed-off-by: Dmitry Baryshkov 
> > > ---
> > >   drivers/gpu/drm/panel/Kconfig | 1 +
> > >   1 file changed, 1 insertion(+)
> > >
> > > diff --git a/drivers/gpu/drm/panel/Kconfig b/drivers/gpu/drm/panel/Kconfig
> > > index ab67789e59a2..5e6692207beb 100644
> > > --- a/drivers/gpu/drm/panel/Kconfig
> > > +++ b/drivers/gpu/drm/panel/Kconfig
> > > @@ -340,6 +340,7 @@ config DRM_PANEL_LG_SW43408
> > >   depends on OF
> > >   depends on DRM_MIPI_DSI
> > >   depends on BACKLIGHT_CLASS_DEVICE
> > > + depends on DRM_DISPLAY_DP_HELPER
> > >   help
> > > Say Y here if you want to enable support for LG sw43408 panel.
> > > The panel has a 1080x2160@60Hz resolution and uses 24 bit RGB per
> > >
> >
> > Reviewed-by: Neil Armstrong 

There's an ongoing discussion about reverting the whole Kconfig rework
thing here and the dust hasn't settled yet:

https://lore.kernel.org/r/cover.1713780345.git.geert+rene...@glider.be

I don't think there's anything you need to do now, but it's probably
good to keep it in mind.

Maxime


signature.asc
Description: PGP signature


Re: [PATCH] drm/stm: dsi: relax mode_valid clock tolerance

2024-04-24 Thread Maxime Ripard
Hi,

Sorry, my previous review didn't go through.

On Fri, Mar 22, 2024 at 11:47:31AM +0100, Sean Nyekjaer wrote:
> When using the DSI interface via DSI2LVDS bridge, it seems a bit harsh
> to reguire the requested and the actual px clock to be within
> 50Hz. A typical LVDS display requires the px clock to be within +-10%.
> 
> In case for HDMI .5% tolerance is required.
> 
> Fixes: e01356d18273 ("drm/stm: dsi: provide the implementation of 
> mode_valid()")
> Signed-off-by: Sean Nyekjaer 
> ---
>  drivers/gpu/drm/stm/dw_mipi_dsi-stm.c | 7 +++
>  1 file changed, 3 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/gpu/drm/stm/dw_mipi_dsi-stm.c 
> b/drivers/gpu/drm/stm/dw_mipi_dsi-stm.c
> index d5f8c923d7bc..97936b0ef702 100644
> --- a/drivers/gpu/drm/stm/dw_mipi_dsi-stm.c
> +++ b/drivers/gpu/drm/stm/dw_mipi_dsi-stm.c
> @@ -322,8 +322,6 @@ dw_mipi_dsi_phy_get_timing(void *priv_data, unsigned int 
> lane_mbps,
>   return 0;
>  }
>  
> -#define CLK_TOLERANCE_HZ 50
> -
>  static enum drm_mode_status
>  dw_mipi_dsi_stm_mode_valid(void *priv_data,
>  const struct drm_display_mode *mode,
> @@ -375,9 +373,10 @@ dw_mipi_dsi_stm_mode_valid(void *priv_data,
>   /*
>* Filter modes according to the clock value, particularly 
> useful for
>* hdmi modes that require precise pixel clocks.
> +  * Check that px_clock is within .5% tolerance.
>*/
> - if (px_clock_hz < target_px_clock_hz - CLK_TOLERANCE_HZ ||
> - px_clock_hz > target_px_clock_hz + CLK_TOLERANCE_HZ)
> + if (px_clock_hz < mult_frac(target_px_clock_hz, 995, 1000) ||
> + px_clock_hz > mult_frac(target_px_clock_hz, 1005, 1000))
>   return MODE_CLOCK_RANGE;

I wonder if it's not something that should be made into a helper. We
have a couple of drivers doing it already, so it might be worth creating
a function that checks for a given struct clk pointer and pixel clock if
it's within parameters.

Maxime


signature.asc
Description: PGP signature


[PATCH v12 23/28] drm/connector: hdmi: Create Infoframe DebugFS entries

2024-04-23 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 | 152 ++
 1 file changed, 152 insertions(+)

diff --git a/drivers/gpu/drm/drm_debugfs.c b/drivers/gpu/drm/drm_debugfs.c
index 08fcefd804bc..dd39a5b7a711 100644
--- a/drivers/gpu/drm/drm_debugfs.c
+++ b/drivers/gpu/drm/drm_debugfs.c
@@ -518,10 +518,160 @@ static const struct file_operations drm_connector_fops = 
{
.llseek = seq_lseek,
.release = single_release,
.write = connector_write
 };
 
+#define HDMI_MAX_INFOFRAME_SIZE29
+
+static ssize_t
+audio_infoframe_read(struct file *filp, char __user *ubuf, size_t count, 
loff_t *ppos)
+{
+   struct drm_connector_hdmi_infoframe *infoframe;
+   struct drm_connector *connector;
+   union hdmi_infoframe *frame;
+   u8 buf[HDMI_INFOFRAME_SIZE(AUDIO)];
+   ssize_t len = 0;
+
+   connector = filp->private_data;
+   mutex_lock(>hdmi.infoframes.lock);
+
+   infoframe = >hdmi.infoframes.audio;
+   if (!infoframe->set)
+   goto out;
+
+   frame = >data;
+   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 audio_infoframe_fops = {
+   .owner   = THIS_MODULE,
+   .open= simple_open,
+   .read= audio_infoframe_read,
+};
+
+static int create_hdmi_audio_infoframe_file(struct drm_connector *connector,
+   struct dentry *parent)
+{
+   struct dentry *file;
+
+   file = debugfs_create_file("audio", 0400, parent, connector, 
_infoframe_fops);
+   if (IS_ERR(file))
+   return PTR_ERR(file);
+
+   return 0;
+}
+
+#define DEFINE_INFOFRAME_FILE(_f) \
+static ssize_t _f##_read_infoframe(struct file *filp, \
+  char __user *ubuf, \
+  size_t count,  \
+  loff_t *ppos)  \
+{ \
+   struct drm_connector_hdmi_infoframe *infoframe; \
+   struct drm_connector_state *conn_state; \
+   struct drm_connector *connector; \
+   union hdmi_infoframe *frame; \
+   struct drm_device *dev; \
+   u8 buf[HDMI_MAX_INFOFRAME_SIZE]; \
+   ssize_t len = 0; \
+   \
+   connector = filp->private_data; \
+   dev = connector->dev; \
+   \
+   drm_modeset_lock(>mode_config.connection_mutex, NULL); \
+   \
+   conn_state = connector->state; \
+   infoframe = _state->hdmi.infoframes._f; \
+   if (!infoframe->set) \
+   goto out; \
+   \
+   frame = >data; \
+   len = hdmi_infoframe_pack(frame, buf, sizeof(buf)); \
+   if (len < 0) \
+   goto out; \
+   \
+   len = simple_read_from_buffer(ubuf, count, ppos, buf, len); \
+   \
+out: \
+   drm_modeset_unlock(>mode_config.connection_mutex); \
+   return len; \
+} \
+\
+static const struct file_operations _f##_infoframe_fops = { \
+   .owner = THIS_MODULE, \
+   .open = simple_open, \
+   .read = _f##_read_infoframe, \
+}; \
+\
+static int create_hdmi_## _f ## _infoframe_file (struct drm_connector 
*connector, \
+struct dentry *parent) \
+{ \
+   struct dentry *file; \
+   \
+   file = debugfs_create_file(#_f, 0400, parent, connector, & _f ## 
_infoframe_fops); \
+   if (IS_ERR(file)) \
+   return PTR_ERR(file); \
+   \
+   return 0; \
+}
+
+DEFINE_INFOFRAME_FILE(avi);
+DEFINE_INFOFRAME_FILE(hdmi);
+DEFINE_INFOFRAME_FILE(hdr_drm);
+DEFINE_INFOFRAME_FILE(spd);
+
+static int create_hdmi_infoframe_files(struct drm_connector *connector,
+  struct dentry *parent)
+{
+   int ret;
+
+   ret = create_hdmi_audio_infoframe_file(connector, parent);
+   if (ret)
+   return ret;
+
+   ret = create_hdmi_avi_infoframe_file(connector, parent);
+   if (ret)
+   return ret;
+
+   ret = create_hdmi_hdmi_infoframe_file(connector, parent);
+   if (ret)
+   return ret;
+
+   ret = create_hdmi_hdr_drm_infoframe_file(connector, parent);
+   if (ret)
+   return ret;
+
+   ret = create_hdmi_spd_infoframe_file(connector, parent);
+   if (ret)
+  

[PATCH v12 22/28] drm/tests: Add infoframes test

2024-04-23 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 4e3c2c7dfaf2..9ea228266de2 100644
--- a/drivers/gpu/drm/tests/drm_connector_test.c
+++ b/drivers/gpu/drm/tests/drm_connector_test.c
@@ -219,10 +219,221 @@ static void drm_test_connector_hdmi_init_null_ddc(struct 
kunit *test)
   BIT(HDMI_COLORSPACE_RGB),
   8);
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));
+}
+
+/*
+ * T

[PATCH v12 28/28] drm/sun4i: hdmi: Switch to HDMI connector

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

Reviewed-by: Jernej Skrabec 
Acked-by: Sui Jingfeng 
Signed-off-by: Maxime Ripard 
---
 drivers/gpu/drm/sun4i/Kconfig  |  1 +
 drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c | 80 ++
 2 files changed, 52 insertions(+), 29 deletions(-)

diff --git a/drivers/gpu/drm/sun4i/Kconfig b/drivers/gpu/drm/sun4i/Kconfig
index 5b19c7cb7b7e..80b607903331 100644
--- a/drivers/gpu/drm/sun4i/Kconfig
+++ b/drivers/gpu/drm/sun4i/Kconfig
@@ -16,10 +16,11 @@ config DRM_SUN4I
 if DRM_SUN4I
 
 config DRM_SUN4I_HDMI
tristate "Allwinner A10/A10s/A20/A31 HDMI Controller Support"
depends on ARM || COMPILE_TEST
+   depends on DRM_HDMI_STATE_HELPER
default DRM_SUN4I
help
  Choose this option if you have an Allwinner A10/A10s/A20/A31
  SoC with an HDMI controller.
 
diff --git a/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c 
b/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c
index 2d1880c61b50..7ac085aa0a35 100644
--- a/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c
+++ b/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c
@@ -35,34 +35,28 @@
container_of_const(e, struct sun4i_hdmi, encoder)
 
 #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,
   struct drm_atomic_state *state)
 {
@@ -81,18 +75,22 @@ static void sun4i_hdmi_disable(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);
-   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,
   hdmi->base + SUN4I_HDMI_UNKNOWN_REG);
 
@@ -141,11 +139,12 @@ static void sun4i_hdmi_enable(struct drm_encoder *encoder,
 
writel(val, hdmi->base + SUN4I_HDMI_VID_TIMING_POL_REG);
 
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));
 
val = SUN4I_HDMI_VID_CTRL_ENABLE;
@@ -194,23 +193,26 @@ static int sun4i_hdmi_connector_atomic_check(struct 
drm_connector *connector,
struct drm_crtc_state *crtc_state = crtc->state;
struct drm_display_mode *mode = _state->adjusted_mode;
enum drm_mode_status status;
 
   

[PATCH v12 25/28] drm/vc4: tests: Remove vc4_dummy_plane structure

2024-04-23 Thread Maxime Ripard
The vc4_dummy_plane structure was introduced as a mean to add
mock-specific fields.

However, we never really used it and it's still strictly equivalent to
vc4_plane (which is in the same situation vs drm_plane), so we can
simply remove the vc4_dummy_plane structure and make the mock code
cleaner.

Reviewed-by: Maíra Canal 
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
@@ -107,20 +107,18 @@ 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);
 
crtc = _crtc->crtc.base;
for (i = 0; i < pipe->noutputs; i++) {
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
@@ -19,17 +19,12 @@ struct drm_crtc *vc4_find_crtc_for_encoder(struct kunit 
*test,
return crtc;
 
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
@@ -20,28 +20,24 @@ static const struct drm_plane_funcs vc4_dummy_plane_funcs = 
{
 
 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,
 
ARRAY_SIZE(vc4_dummy_plane_formats),
 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.44.0



[PATCH v12 24/28] drm/vc4: hdmi: Switch to HDMI connector

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

Acked-by: Sui Jingfeng 
Signed-off-by: Maxime Ripard 
---
 drivers/gpu/drm/vc4/Kconfig|   1 +
 drivers/gpu/drm/vc4/vc4_hdmi.c | 644 +
 drivers/gpu/drm/vc4/vc4_hdmi.h |  44 +--
 drivers/gpu/drm/vc4/vc4_hdmi_phy.c |   6 +-
 4 files changed, 92 insertions(+), 603 deletions(-)

diff --git a/drivers/gpu/drm/vc4/Kconfig b/drivers/gpu/drm/vc4/Kconfig
index 4801f8b64d3d..0d3629291a1f 100644
--- a/drivers/gpu/drm/vc4/Kconfig
+++ b/drivers/gpu/drm/vc4/Kconfig
@@ -3,10 +3,11 @@ config DRM_VC4
tristate "Broadcom VC4 Graphics"
depends on ARCH_BCM || ARCH_BCM2835 || COMPILE_TEST
depends on COMMON_CLK
depends on DRM
depends on DRM_DISPLAY_HDMI_HELPER
+   depends on DRM_DISPLAY_HDMI_STATE_HELPER
depends on DRM_DISPLAY_HELPER
depends on PM
# Make sure not 'y' when RASPBERRYPI_FIRMWARE is 'm'. This can only
# happen when COMPILE_TEST=y, hence the added !RASPBERRYPI_FIRMWARE.
depends on RASPBERRYPI_FIRMWARE || (COMPILE_TEST && 
!RASPBERRYPI_FIRMWARE)
diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
index 5f8d51b29370..d3212171b2d4 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
@@ -30,10 +30,11 @@
  * The driver does not yet support CEC control, though the HDMI
  * encoder block has CEC support.
  */
 
 #include 
+#include 
 #include 
 #include 
 #include 
 #include 
 #include 
@@ -108,29 +109,10 @@
 #define HSM_MIN_CLOCK_FREQ 12000
 #define CEC_CLOCK_FREQ 4
 
 #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;
 
lockdep_assert_held(_hdmi->mutex);
@@ -145,32 +127,17 @@ static bool vc4_hdmi_supports_scrambling(struct vc4_hdmi 
*vc4_hdmi)
return true;
 }
 
 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_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;
struct vc4_hdmi *vc4_hdmi = entry->file.data;
struct drm_device *drm = vc4_hdmi->connector.dev;
@@ -518,11 +485,11 @@ static int vc4_hdmi_connector_get_modes(struct 
drm_connector *connector)
if (!vc4->hvs->vc5_hdmi_enable_hdmi_20) {
struct drm_device *drm = connector->dev;
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.");

[PATCH v12 17/28] drm/connector: hdmi: Add Broadcast RGB property

2024-04-23 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 
Acked-by: Pekka Paalanen 
Reviewed-by: Sebastian Wick 
Signed-off-by: Maxime Ripard 
---
 Documentation/gpu/kms-properties.csv|  1 -
 drivers/gpu/drm/display/drm_hdmi_state_helper.c |  4 +-
 drivers/gpu/drm/drm_atomic.c|  2 +
 drivers/gpu/drm/drm_atomic_uapi.c   |  4 ++
 drivers/gpu/drm/drm_connector.c | 88 +
 include/drm/drm_connector.h | 36 ++
 6 files changed, 133 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
@@ -15,11 +15,10 @@ Owner Module/Drivers,Group,Property Name,Type,Property 
Values,Object attached,De
 ,,“saturation”,RANGE,"Min=0, Max=100",Connector,TBD
 ,,“hue”,RANGE,"Min=0, Max=100",Connector,TBD
 ,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
 ,,"""right_margin""",RANGE,"Min=0, Max= SDVO dependent",Connector,TBD
 ,,"""top_margin""",RANGE,"Min=0, Max= SDVO dependent",Connector,TBD
diff --git a/drivers/gpu/drm/display/drm_hdmi_state_helper.c 
b/drivers/gpu/drm/display/drm_hdmi_state_helper.c
index b9bc0fb027ea..c844cbeb675b 100644
--- a/drivers/gpu/drm/display/drm_hdmi_state_helper.c
+++ b/drivers/gpu/drm/display/drm_hdmi_state_helper.c
@@ -23,10 +23,11 @@ void __drm_atomic_helper_connector_hdmi_reset(struct 
drm_connector *connector,
 {
unsigned int max_bpc = connector->max_bpc;
 
new_conn_state->max_bpc = max_bpc;
new_conn_state->max_requested_bpc = max_bpc;
+   new_conn_state->hdmi.broadcast_rgb = DRM_HDMI_BROADCAST_RGB_AUTO;
 }
 EXPORT_SYMBOL(__drm_atomic_helper_connector_hdmi_reset);
 
 static const struct drm_display_mode *
 connector_state_get_mode(const struct drm_connector_state *conn_state)
@@ -310,11 +311,12 @@ int drm_atomic_helper_connector_hdmi_check(struct 
drm_connector *connector,
 
ret = hdmi_compute_config(connector, new_conn_state, mode);
if (ret)
return ret;
 
-   if (old_conn_state->hdmi.output_bpc != new_conn_state->hdmi.output_bpc 
||
+   if (old_conn_state->hdmi.broadcast_rgb != 
new_conn_state->hdmi.broadcast_rgb ||
+   old_conn_state->hdmi.output_bpc != new_conn_state->hdmi.output_bpc 
||
old_conn_state->hdmi.output_format != 
new_conn_state->hdmi.output_format) {
struct drm_crtc *crtc = new_conn_state->crtc;
struct drm_crtc_state *crtc_state;
 
crtc_state = drm_atomic_get_crtc_state(state, crtc);
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
@@ -1143,10 +1143,12 @@ static void drm_atomic_connector_print_state(struct 
drm_printer *p,
drm_printf(p, "\tmax_requested_bpc=%d\n", state->max_requested_bpc);
drm_printf(p, "\tcolorsp

[PATCH v12 27/28] drm/rockchip: inno_hdmi: Switch to HDMI connector

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

Reviewed-by: Heiko Stuebner 
Acked-by: Heiko Stuebner 
Signed-off-by: Maxime Ripard 
---
 drivers/gpu/drm/rockchip/Kconfig |   1 +
 drivers/gpu/drm/rockchip/inno_hdmi.c | 143 +--
 2 files changed, 53 insertions(+), 91 deletions(-)

diff --git a/drivers/gpu/drm/rockchip/Kconfig b/drivers/gpu/drm/rockchip/Kconfig
index 4c7072e6e34e..e2ec20c2e2eb 100644
--- a/drivers/gpu/drm/rockchip/Kconfig
+++ b/drivers/gpu/drm/rockchip/Kconfig
@@ -72,10 +72,11 @@ config ROCKCHIP_DW_MIPI_DSI
  enable MIPI DSI on RK3288 or RK3399 based SoC, you should
  select this option.
 
 config ROCKCHIP_INNO_HDMI
bool "Rockchip specific extensions for Innosilicon HDMI"
+   depends on DRM_HDMI_STATE_HELPER
help
  This selects support for Rockchip SoC specific extensions
  for the Innosilicon HDMI driver. If you want to enable
  HDMI on RK3036 based SoC, you should select this option.
 
diff --git a/drivers/gpu/drm/rockchip/inno_hdmi.c 
b/drivers/gpu/drm/rockchip/inno_hdmi.c
index 1d2261643743..3756259bfb10 100644
--- a/drivers/gpu/drm/rockchip/inno_hdmi.c
+++ b/drivers/gpu/drm/rockchip/inno_hdmi.c
@@ -65,13 +65,11 @@ struct inno_hdmi {
const struct inno_hdmi_variant *variant;
 };
 
 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)
 {
struct rockchip_encoder *rkencoder = to_rockchip_encoder(encoder);
@@ -255,90 +253,53 @@ static void inno_hdmi_reset(struct inno_hdmi *hdmi)
hdmi_modb(hdmi, HDMI_SYS_CTRL, msk, val);
 
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;
-
-   if (type != HDMI_INFOFRAME_TYPE_AVI) {
-   drm_err(connector->dev,
-   "Unsupported infoframe type: %u\n", type);
-   return;
-   }
-
-   hdmi_writeb(hdmi, HDMI_CONTROL_PACKET_BUF_INDEX, INFOFRAME_AVI);
-}
-
-static int inno_hdmi_upload_frame(struct inno_hdmi *hdmi,
- union hdmi_infoframe *frame, enum 
hdmi_infoframe_type type)
-{
-   struct drm_connector *connector = >connector;
-   u8 packed_frame[HDMI_MAXIMUM_INFO_FRAME_SIZE];
-   ssize_t rc, i;
+   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 0;
}
 
-   inno_hdmi_disable_frame(hdmi, type);
+   hdmi_writeb(hdmi, HDMI_CONTROL_PACKET_BUF_INDEX, INFOFRAME_AVI);
 
-   rc = hdmi_infoframe_pack(frame, packed_frame,
-sizeof(packed_frame));
-   if (rc < 0)
-   return rc;
+   return 0;
+}
 
-   for (i = 0; i < rc; i++)
+static int inno_hdmi_upload_frame(struct drm_connector *connector,
+ enum hdmi_infoframe_type type,
+ const u8 *buffer, size_t len)
+{
+   struct inno_hdmi *hdmi = connector_to_inno_hdmi(connector);
+   u8 packed_frame[HDMI_MAXIMUM_INFO_FRAME_SIZE];
+   ssize_t i;
+
+   if (type != HDMI_INFOFRAME_TYPE_AVI) {
+   drm_err(connector->dev,
+   "Unsupported infoframe type: %u\n", type);
+   return 0;
+   }
+
+   inno_hdmi_disable_frame(connector, type);
+
+   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

[PATCH v12 21/28] drm/connector: hdmi: Add Infoframes generation

2024-04-23 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.

Cc: Ville Syrjälä 
Signed-off-by: Maxime Ripard 
---
 drivers/gpu/drm/display/drm_hdmi_state_helper.c| 336 +
 drivers/gpu/drm/drm_connector.c|  14 +
 drivers/gpu/drm/tests/drm_connector_test.c |  12 +
 drivers/gpu/drm/tests/drm_hdmi_state_helper_test.c |   1 +
 include/drm/display/drm_hdmi_state_helper.h|   7 +
 include/drm/drm_connector.h| 111 ++-
 6 files changed, 480 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/display/drm_hdmi_state_helper.c 
b/drivers/gpu/drm/display/drm_hdmi_state_helper.c
index 6be3a7d9e0cc..20a6c6a567d5 100644
--- a/drivers/gpu/drm/display/drm_hdmi_state_helper.c
+++ b/drivers/gpu/drm/display/drm_hdmi_state_helper.c
@@ -311,10 +311,148 @@ 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 *conn_state)
+{
+   const struct drm_display_mode *mode =
+   connector_state_get_mode(conn_state);
+   struct drm_connector_hdmi_infoframe *infoframe =
+   _state->hdmi.infoframes.avi;
+   struct hdmi_avi_infoframe *frame =
+   >data.avi;
+   bool is_limited_range = conn_state->hdmi.is_limited_range;
+   enum hdmi_quantization_range rgb_quant_range =
+   is_limited_range ? HDMI_QUANTIZATION_RANGE_LIMITED : 
HDMI_QUANTIZATION_RANGE_FULL;
+   int ret;
+
+   ret = drm_hdmi_avi_infoframe_from_display_mode(frame, connector, mode);
+   if (ret)
+   return ret;
+
+   frame->colorspace = conn_state->hdmi.output_format;
+
+   /*
+* FIXME: drm_hdmi_avi_infoframe_quant_range() doesn't handle
+* YUV formats at all at the moment, so if we ever support YUV
+* formats this needs to be revised.
+*/
+   drm_hdmi_avi_infoframe_quant_range(frame, connector, mode, 
rgb_quant_range);
+   drm_hdmi_avi_infoframe_colorimetry(frame, conn_state);
+   drm_hdmi_avi_infoframe_bars(frame, conn_state);
+
+   infoframe->set = true;
+
+   return 0;
+}
+
+static int hdmi_generate_spd_infoframe(const struct drm_connector *connector,
+  struct drm_connector_state *conn_state)
+{
+   struct drm_connector_hdmi_infoframe *infoframe =
+   _state->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 *conn_state)
+{
+   struct drm_connector_hdmi_infoframe *infoframe =
+   _state->hdmi.infoframes.hdr_drm;
+   struct hdmi_drm_infoframe *frame =
+   >data.drm;
+   int ret;
+
+   if (connector->max_bpc < 10)
+   return 0;
+
+   if (!conn_state->hdr_output_metadata)
+   return 0;
+
+   ret = drm_hdmi_infoframe_set_hdr_metadata(frame, conn_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 
*conn_state)
+{
+   const struct drm_display_info *info = >display_info;
+   const struct drm_display_mode *mode =
+   connector_state_get_mode(conn_state);
+   struct drm_connector_hdmi_infoframe *infoframe =
+   _state->hdmi.infoframes.hdmi;
+   struct hdmi_vendor_infoframe *frame =
+   >data.vendor.hdmi;
+   int ret;
+
+   if (!info->has_hdmi_infoframe)
+   return 0;
+
+   ret = drm_hdmi_vendor_infoframe_from_display_mode(frame, connector, 
mode);
+   if (ret)
+   return ret;
+
+   infoframe->set = true;
+
+   return 0;
+}
+
+static int
+hdmi_generate_infoframes(const struct drm_connector *connector,
+struct drm_connector_state *conn_state)
+{
+   const struct drm_display_info

[PATCH v12 26/28] drm/vc4: tests: Convert to plane creation helper

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

Reviewed-by: Maíra Canal 
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_NOT_ERR_OR_NULL(test, plane);
+   KUNIT_ASSERT_EQ(test, type, DRM_PLANE_TYPE_PRIMARY);
 
-   drm_plane_helper_add(plane, _dummy_plane_helper_funcs);
+   plane = drm_kunit_helper_create_primary_plane(test, drm,
+ NULL,
+ NULL,
+ NULL, 0,
+ NULL);
+   KUNIT_ASSERT_NOT_ERR_OR_NULL(test, plane);
 
return plane;
 }

-- 
2.44.0



[PATCH v12 16/28] drm/tests: Add HDMI connector bpc and format tests

2024-04-23 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 
---
 drivers/gpu/drm/tests/drm_hdmi_state_helper_test.c | 509 +
 drivers/gpu/drm/tests/drm_kunit_edid.h | 160 +++
 2 files changed, 669 insertions(+)

diff --git a/drivers/gpu/drm/tests/drm_hdmi_state_helper_test.c 
b/drivers/gpu/drm/tests/drm_hdmi_state_helper_test.c
index a49a544d7b49..968204781928 100644
--- a/drivers/gpu/drm/tests/drm_hdmi_state_helper_test.c
+++ b/drivers/gpu/drm/tests/drm_hdmi_state_helper_test.c
@@ -15,10 +15,11 @@
 #include 
 #include 
 #include 
 #include 
 
+#include 
 #include 
 
 #include "../drm_crtc_internal.h"
 
 #include 
@@ -370,10 +371,60 @@ static void 
drm_test_check_output_bpc_crtc_mode_not_changed(struct kunit *test)
crtc_state = drm_atomic_get_new_crtc_state(state, crtc);
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, crtc_state);
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
  */
 static void drm_test_check_tmds_char_rate_rgb_8bpc(struct kunit *test)
@@ -562,14 +613,472 @@ static void drm_test_check_hdmi_funcs_reject_rate(struct 
kunit *test)
 
ret = drm_atomic_check_only(state);
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

[PATCH v12 19/28] drm/connector: hdmi: Add RGB Quantization Range to the connector state

2024-04-23 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/display/drm_hdmi_state_helper.c | 29 +
 drivers/gpu/drm/drm_atomic.c|  1 +
 include/drm/drm_connector.h |  6 +
 3 files changed, 36 insertions(+)

diff --git a/drivers/gpu/drm/display/drm_hdmi_state_helper.c 
b/drivers/gpu/drm/display/drm_hdmi_state_helper.c
index c844cbeb675b..6be3a7d9e0cc 100644
--- a/drivers/gpu/drm/display/drm_hdmi_state_helper.c
+++ b/drivers/gpu/drm/display/drm_hdmi_state_helper.c
@@ -49,10 +49,37 @@ connector_state_get_mode(const struct drm_connector_state 
*conn_state)
return NULL;
 
return _state->mode;
 }
 
+static bool hdmi_is_limited_range(const struct drm_connector *connector,
+ const struct drm_connector_state *conn_state)
+{
+   const struct drm_display_info *info = >display_info;
+   const struct drm_display_mode *mode =
+   connector_state_get_mode(conn_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 (conn_state->hdmi.output_format != HDMI_COLORSPACE_RGB)
+   return true;
+
+   if (conn_state->hdmi.broadcast_rgb == DRM_HDMI_BROADCAST_RGB_FULL)
+   return false;
+
+   if (conn_state->hdmi.broadcast_rgb == DRM_HDMI_BROADCAST_RGB_LIMITED)
+   return true;
+
+   if (!info->is_hdmi)
+   return false;
+
+   return drm_default_rgb_quant_range(mode) == 
HDMI_QUANTIZATION_RANGE_LIMITED;
+}
+
 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)
@@ -307,10 +334,12 @@ int drm_atomic_helper_connector_hdmi_check(struct 
drm_connector *connector,
drm_atomic_get_new_connector_state(state, connector);
const struct drm_display_mode *mode =
connector_state_get_mode(new_conn_state);
int ret;
 
+   new_conn_state->hdmi.is_limited_range = 
hdmi_is_limited_range(connector, new_conn_state);
+
ret = hdmi_compute_config(connector, new_conn_state, mode);
if (ret)
return ret;
 
if (old_conn_state->hdmi.broadcast_rgb != 
new_conn_state->hdmi.broadcast_rgb ||
diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c
index 3e57d98d8418..07b4b394e3bf 100644
--- a/drivers/gpu/drm/drm_atomic.c
+++ b/drivers/gpu/drm/drm_atomic.c
@@ -1145,10 +1145,11 @@ 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, "\tis_limited_range=%c\n", 
state->hdmi.is_limited_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));
drm_printf(p, "\ttmds_char_rate=%llu\n", 
state->hdmi.tmds_char_rate);
}
diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h
index a40eaf3a8ce4..1fca26d51218 100644
--- a/include/drm/drm_connector.h
+++ b/include/drm/drm_connector.h
@@ -1068,10 +1068,16 @@ struct drm_connector_state {
 * @broadcast_rgb: Connector property to pass the
 * Broadcast RGB selection value.
 */
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_limited_range;
+
/**
 * @output_bpc: Bits per color channel to output.
 */
unsigned int output_bpc;
 

-- 
2.44.0



[PATCH v12 14/28] drm/tests: Add HDMI connector rate filter hook tests

2024-04-23 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 
---
 drivers/gpu/drm/tests/drm_hdmi_state_helper_test.c | 65 ++
 1 file changed, 65 insertions(+)

diff --git a/drivers/gpu/drm/tests/drm_hdmi_state_helper_test.c 
b/drivers/gpu/drm/tests/drm_hdmi_state_helper_test.c
index 7f9a48902db4..ead998a691e7 100644
--- a/drivers/gpu/drm/tests/drm_hdmi_state_helper_test.c
+++ b/drivers/gpu/drm/tests/drm_hdmi_state_helper_test.c
@@ -113,10 +113,22 @@ 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 =
connector_to_priv(connector);
const struct drm_edid *edid;
@@ -491,11 +503,64 @@ static void 
drm_test_check_tmds_char_rate_rgb_12bpc(struct kunit *test)
KUNIT_ASSERT_EQ(test, conn_state->hdmi.output_bpc, 12);
KUNIT_ASSERT_EQ(test, conn_state->hdmi.output_format, 
HDMI_COLORSPACE_RGB);
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),
KUNIT_CASE(drm_test_check_tmds_char_rate_rgb_10bpc),
KUNIT_CASE(drm_test_check_tmds_char_rate_rgb_12bpc),

-- 
2.44.0



[PATCH v12 18/28] drm/tests: Add tests for Broadcast RGB property

2024-04-23 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 
---
 drivers/gpu/drm/tests/drm_connector_test.c | 116 
 drivers/gpu/drm/tests/drm_hdmi_state_helper_test.c | 151 +
 2 files changed, 267 insertions(+)

diff --git a/drivers/gpu/drm/tests/drm_connector_test.c 
b/drivers/gpu/drm/tests/drm_connector_test.c
index 34d96f7fbb25..672b74bc9e23 100644
--- a/drivers/gpu/drm/tests/drm_connector_test.c
+++ b/drivers/gpu/drm/tests/drm_connector_test.c
@@ -564,10 +564,67 @@ static struct kunit_case 
drm_get_tv_mode_from_name_tests[] = {
 static struct kunit_suite drm_get_tv_mode_from_name_test_suite = {
.name = "drm_get_tv_mode_from_name",
.test_cases = drm_get_tv_mode_from_name_tests,
 };
 
+struct drm_hdmi_connector_get_broadcast_rgb_name_test {
+   unsigned int kind;
+   const char *expected_name;
+};
+
+#define BROADCAST_RGB_TEST(_kind, _name)   \
+   {   \
+   .kind = _kind,  \
+   .expected_name = _name, \
+   }
+
+static void drm_test_drm_hdmi_connector_get_broadcast_rgb_name(struct kunit 
*test)
+{
+   const struct drm_hdmi_connector_get_broadcast_rgb_name_test *params =
+   test->param_value;
+
+   KUNIT_EXPECT_STREQ(test,
+  
drm_hdmi_connector_get_broadcast_rgb_name(params->kind),
+  params->expected_name);
+}
+
+static const
+struct drm_hdmi_connector_get_broadcast_rgb_name_test
+drm_hdmi_connector_get_broadcast_rgb_name_valid_tests[] = {
+   BROADCAST_RGB_TEST(DRM_HDMI_BROADCAST_RGB_AUTO, "Automatic"),
+   BROADCAST_RGB_TEST(DRM_HDMI_BROADCAST_RGB_FULL, "Full"),
+   BROADCAST_RGB_TEST(DRM_HDMI_BROADCAST_RGB_LIMITED, "Limited 16:235"),
+};
+
+static void
+drm_hdmi_connector_get_broadcast_rgb_name_valid_desc(const struct 
drm_hdmi_connector_get_broadcast_rgb_name_test *t,
+char *desc)
+{
+   sprintf(desc, "%s", t->expected_name);
+}
+
+KUNIT_ARRAY_PARAM(drm_hdmi_connector_get_broadcast_rgb_name_valid,
+ drm_hdmi_connector_get_broadcast_rgb_name_valid_tests,
+ drm_hdmi_connector_get_broadcast_rgb_name_valid_desc);
+
+static void drm_test_drm_hdmi_connector_get_broadcast_rgb_name_invalid(struct 
kunit *test)
+{
+   KUNIT_EXPECT_NULL(test, drm_hdmi_connector_get_broadcast_rgb_name(3));
+};
+
+static struct kunit_case drm_hdmi_connector_get_broadcast_rgb_name_tests[] = {
+   KUNIT_CASE_PARAM(drm_test_drm_hdmi_connector_get_broadcast_rgb_name,
+
drm_hdmi_connector_get_broadcast_rgb_name_valid_gen_params),
+   KUNIT_CASE(drm_test_drm_hdmi_connector_get_broadcast_rgb_name_invalid),
+   { }
+};
+
+static struct kunit_suite drm_hdmi_connector_get_broadcast_rgb_name_test_suite 
= {
+   .name = "drm_hdmi_connector_get_broadcast_rgb_name",
+   .test_cases = drm_hdmi_connector_get_broadcast_rgb_name_tests,
+};
+
 struct drm_hdmi_connector_get_output_format_name_test {
unsigned int kind;
const char *expected_name;
 };
 
@@ -622,10 +679,67 @@ static struct kunit_case 
drm_hdmi_connector_get_output_format_name_tests[] = {
 static struct kunit_suite drm_hdmi_connector_get_output_format_name_test_suite 
= {
.name = "drm_hdmi_connector_get_output_format_name",
.test_cases = drm_hdmi_connector_get_output_format_name_tests,
 };
 
+static void drm_test_drm_connector_attach_broadcast_rgb_property(struct kunit 
*test)
+{
+   struct drm_connector_init_priv *priv = test->priv;
+   struct drm_connector *connector = >connector;
+   struct drm_property *prop;
+   int ret;
+
+   ret = drmm_connector_init(>drm, connector,
+ _funcs,
+ DRM_MODE_CONNECTOR_HDMIA,
+ >ddc);
+   KUNIT_ASSERT_EQ(test, ret, 0);
+
+   ret = drm_connector_attach_broadcast_rgb_property(connector);
+   KUNIT_ASSERT_EQ(test, ret, 0);
+
+   prop = connector->broadcast_rgb_property;
+   KUNIT_ASSERT_NOT_NULL(test, prop);
+   KUNIT_EXPECT_NOT_NULL(test, drm_mode_obj_find_prop_id(>base, 
prop->base.id));
+}
+
+static void 
drm_test_drm_connector_attach_broadcast_rgb_property_hdmi_connector(struct 
kunit *test)
+{
+   struct drm_connector_init_priv *priv = test->priv;
+   struct drm_connector *connector = >connector;
+   struct drm_property *prop;
+   int ret;
+
+   ret = drmm_connector_hdmi_init(>drm, connector,
+  _funcs,
+  

[PATCH v12 20/28] drm/tests: Add RGB Quantization tests

2024-04-23 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 
---
 drivers/gpu/drm/tests/drm_hdmi_state_helper_test.c | 355 +
 1 file changed, 355 insertions(+)

diff --git a/drivers/gpu/drm/tests/drm_hdmi_state_helper_test.c 
b/drivers/gpu/drm/tests/drm_hdmi_state_helper_test.c
index ff9a882201eb..da5c3d9a80bb 100644
--- a/drivers/gpu/drm/tests/drm_hdmi_state_helper_test.c
+++ b/drivers/gpu/drm/tests/drm_hdmi_state_helper_test.c
@@ -353,10 +353,354 @@ static void 
drm_test_check_broadcast_rgb_crtc_mode_not_changed(struct kunit *tes
crtc_state = drm_atomic_get_new_crtc_state(state, crtc);
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, crtc_state);
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_TRUE(test, conn_state->hdmi.is_limited_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);
+
+   drm = >drm;
+   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_st

[PATCH v12 15/28] drm/connector: hdmi: Compute bpc and format automatically

2024-04-23 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.

Cc: Ville Syrjälä 
Signed-off-by: Maxime Ripard 
---
 drivers/gpu/drm/display/drm_hdmi_state_helper.c| 197 -
 drivers/gpu/drm/tests/drm_hdmi_state_helper_test.c |  25 ++-
 2 files changed, 210 insertions(+), 12 deletions(-)

diff --git a/drivers/gpu/drm/display/drm_hdmi_state_helper.c 
b/drivers/gpu/drm/display/drm_hdmi_state_helper.c
index 063421835dba..b9bc0fb027ea 100644
--- a/drivers/gpu/drm/display/drm_hdmi_state_helper.c
+++ b/drivers/gpu/drm/display/drm_hdmi_state_helper.c
@@ -1,9 +1,11 @@
 // SPDX-License-Identifier: MIT
 
 #include 
 #include 
+#include 
+#include 
 
 #include 
 #include 
 
 /**
@@ -46,10 +48,110 @@ connector_state_get_mode(const struct drm_connector_state 
*conn_state)
return NULL;
 
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);
+
+   /*
+* CTA-861-F, section 5.4 - Color Coding & Quantization states
+* that the bpc must be 8, 10, 12 or 16 except for the default
+* 640x480 VIC1 where the value must be 8.
+*
+* The definition of default here is ambiguous but the spec
+* refers to VIC1 being the default timing in several occasions
+* so our understanding is that for the default timing (ie,
+* VIC1), the bpc must be 8.
+*/
+   if (vic == 1 && bpc != 8) {
+   drm_dbg_kms(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_kms(dev, "DVI Monitors require an RGB output at 8 
bpc\n");
+   return false;
+   }
+
+   if (!(connector->hdmi.supported_formats & BIT(format))) {
+   drm_dbg_kms(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_kms(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_kms(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_kms(dev, "12 BPC but sink doesn't support Deep 
Color 36.\n");
+   return false;
+   }
+
+   drm_dbg_kms(dev, "RGB format supported in that 
configuration.\n");
+
+   return true;
+
+   case HDMI_COLORSPACE_YUV422:
+   drm_dbg_kms(dev, "YUV422 format, checking the constraints.\n");
+
+   if (!(info->color_formats & DRM_COLOR_FORMAT_YCBCR422)) {
+   drm_dbg_kms(dev, "Sink doesn't support YUV422.\n");
+   return false;
+   }
+
+   if (bpc != 12) {
+   drm_dbg_kms(dev, "YUV422 only supports 12 bpc.\n");
+   return false;
+   }
+
+   drm_dbg_kms(dev, "YUV422 format supported in that 
configuration.\n");
+
+   return true;
+
+   case HDMI_COLORSPACE_YUV444:
+   drm_dbg_kms(dev, "YUV444 format, checking the constraints.\n");
+
+   if (!(info->color_formats & DRM_COLOR_FORMAT_YCBCR444)) {
+   drm_dbg_kms(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_kms(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_kms(dev, "12 BPC but sink doesn't support Deep 
Color 36.\n&qu

[PATCH v12 12/28] drm/tests: Add TDMS character rate connector state tests

2024-04-23 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 
---
 drivers/gpu/drm/tests/drm_hdmi_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_hdmi_state_helper_test.c 
b/drivers/gpu/drm/tests/drm_hdmi_state_helper_test.c
index 4f46a70a5017..8ff53ee54e97 100644
--- a/drivers/gpu/drm/tests/drm_hdmi_state_helper_test.c
+++ b/drivers/gpu/drm/tests/drm_hdmi_state_helper_test.c
@@ -347,13 +347,156 @@ static void 
drm_test_check_output_bpc_crtc_mode_not_changed(struct kunit *test)
crtc_state = drm_atomic_get_new_crtc_state(state, crtc);
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, crtc_state);
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)
+{
+   s

[PATCH v12 09/28] drm/display: hdmi: Add HDMI compute clock helper

2024-04-23 Thread Maxime Ripard
A lot of HDMI drivers have some variation of the formula to calculate
the TMDS character rate from a mode, but few of them actually take all
parameters into account.

Let's create a helper to provide that rate taking all parameters into
account.

Reviewed-by: Dave Stevenson 
Signed-off-by: Maxime Ripard 
---
 drivers/gpu/drm/display/drm_hdmi_helper.c | 57 +++
 include/drm/display/drm_hdmi_helper.h |  4 +++
 2 files changed, 61 insertions(+)

diff --git a/drivers/gpu/drm/display/drm_hdmi_helper.c 
b/drivers/gpu/drm/display/drm_hdmi_helper.c
index faf5e9efa7d3..679eb3e81393 100644
--- a/drivers/gpu/drm/display/drm_hdmi_helper.c
+++ b/drivers/gpu/drm/display/drm_hdmi_helper.c
@@ -193,5 +193,62 @@ void drm_hdmi_avi_infoframe_content_type(struct 
hdmi_avi_infoframe *frame,
}
 
frame->itc = conn_state->content_type != DRM_MODE_CONTENT_TYPE_NO_DATA;
 }
 EXPORT_SYMBOL(drm_hdmi_avi_infoframe_content_type);
+
+/**
+ * drm_hdmi_compute_mode_clock() - Computes the TMDS Character Rate
+ * @mode: Display mode to compute the clock for
+ * @bpc: Bits per character
+ * @fmt: Output Pixel Format used
+ *
+ * Returns the TMDS Character Rate for a given mode, bpc count and output 
format.
+ *
+ * RETURNS:
+ * The TMDS Character Rate, in Hertz, or 0 on error.
+ */
+unsigned long long
+drm_hdmi_compute_mode_clock(const struct drm_display_mode *mode,
+   unsigned int bpc, enum hdmi_colorspace fmt)
+{
+   unsigned long long clock = mode->clock * 1000ULL;
+   unsigned int vic = drm_match_cea_mode(mode);
+
+   /*
+* CTA-861-G Spec, section 5.4 - Color Coding and Quantization
+* mandates that VIC 1 always uses 8 bpc.
+*/
+   if (vic == 1 && bpc != 8)
+   return 0;
+
+   if (fmt == HDMI_COLORSPACE_YUV422) {
+   /*
+* HDMI 1.4b Spec, section 6.2.3 - Pixel Encoding Requirements
+* specifies that YUV422 is 36-bit only.
+*/
+   if (bpc != 12)
+   return 0;
+
+   /*
+* HDMI 1.0 Spec, section 6.5 - Pixel Encoding
+* specifies that YUV422 requires two 12-bits components per
+* pixel clock, which is equivalent in our calculation to three
+* 8-bits components
+*/
+   bpc = 8;
+   }
+
+   /*
+* HDMI 2.0 Spec, Section 7.1 - YCbCr 4:2:0 Pixel Encoding
+* specifies that YUV420 encoding is carried at a TMDS Character Rate
+* equal to half the pixel clock rate.
+*/
+   if (fmt == HDMI_COLORSPACE_YUV420)
+   clock = clock / 2;
+
+   if (mode->flags & DRM_MODE_FLAG_DBLCLK)
+   clock = clock * 2;
+
+   return DIV_ROUND_CLOSEST_ULL(clock * bpc, 8);
+}
+EXPORT_SYMBOL(drm_hdmi_compute_mode_clock);
diff --git a/include/drm/display/drm_hdmi_helper.h 
b/include/drm/display/drm_hdmi_helper.h
index 76d234826e22..57e3b18c15ec 100644
--- a/include/drm/display/drm_hdmi_helper.h
+++ b/include/drm/display/drm_hdmi_helper.h
@@ -22,6 +22,10 @@ drm_hdmi_infoframe_set_hdr_metadata(struct 
hdmi_drm_infoframe *frame,
const struct drm_connector_state 
*conn_state);
 
 void drm_hdmi_avi_infoframe_content_type(struct hdmi_avi_infoframe *frame,
 const struct drm_connector_state 
*conn_state);
 
+unsigned long long
+drm_hdmi_compute_mode_clock(const struct drm_display_mode *mode,
+   unsigned int bpc, enum hdmi_colorspace fmt);
+
 #endif

-- 
2.44.0



[PATCH v12 08/28] drm/tests: Add output formats tests

2024-04-23 Thread Maxime Ripard
Now that we track the HDMI output format as part of the connector state,
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 | 99 +-
 drivers/gpu/drm/tests/drm_hdmi_state_helper_test.c | 32 +++
 2 files changed, 130 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/tests/drm_connector_test.c 
b/drivers/gpu/drm/tests/drm_connector_test.c
index 9589867bdf7c..72f22ec951d6 100644
--- a/drivers/gpu/drm/tests/drm_connector_test.c
+++ b/drivers/gpu/drm/tests/drm_connector_test.c
@@ -346,10 +346,46 @@ static void drm_test_connector_hdmi_init_bpc_12(struct 
kunit *test)
prop = priv->drm.mode_config.hdr_output_metadata_property;
KUNIT_ASSERT_NOT_NULL(test, prop);
KUNIT_EXPECT_NOT_NULL(test, drm_mode_obj_find_prop_id(>base, 
prop->base.id));
 }
 
+/*
+ * Test that the registration of an HDMI connector with no supported
+ * format fails.
+ */
+static void drm_test_connector_hdmi_init_formats_empty(struct kunit *test)
+{
+   struct drm_connector_init_priv *priv = test->priv;
+   int ret;
+
+   ret = drmm_connector_hdmi_init(>drm, >connector,
+  _funcs,
+  DRM_MODE_CONNECTOR_HDMIA,
+  >ddc,
+  0,
+  8);
+   KUNIT_EXPECT_LT(test, ret, 0);
+}
+
+/*
+ * Test that the registration of an HDMI connector not listing RGB as a
+ * supported format fails.
+ */
+static void drm_test_connector_hdmi_init_formats_no_rgb(struct kunit *test)
+{
+   struct drm_connector_init_priv *priv = test->priv;
+   int ret;
+
+   ret = drmm_connector_hdmi_init(>drm, >connector,
+  _funcs,
+  DRM_MODE_CONNECTOR_HDMIA,
+  >ddc,
+  BIT(HDMI_COLORSPACE_YUV422),
+  8);
+   KUNIT_EXPECT_LT(test, ret, 0);
+}
+
 /*
  * Test that the registration of an HDMI connector with an HDMI
  * connector type succeeds.
  */
 static void drm_test_connector_hdmi_init_type_valid(struct kunit *test)
@@ -431,10 +467,12 @@ static struct kunit_case drmm_connector_hdmi_init_tests[] 
= {
KUNIT_CASE(drm_test_connector_hdmi_init_bpc_8),
KUNIT_CASE(drm_test_connector_hdmi_init_bpc_10),
KUNIT_CASE(drm_test_connector_hdmi_init_bpc_12),
KUNIT_CASE(drm_test_connector_hdmi_init_bpc_invalid),
KUNIT_CASE(drm_test_connector_hdmi_init_bpc_null),
+   KUNIT_CASE(drm_test_connector_hdmi_init_formats_empty),
+   KUNIT_CASE(drm_test_connector_hdmi_init_formats_no_rgb),
KUNIT_CASE(drm_test_connector_hdmi_init_null_ddc),
KUNIT_CASE_PARAM(drm_test_connector_hdmi_init_type_valid,
 drm_connector_hdmi_init_type_valid_gen_params),
KUNIT_CASE_PARAM(drm_test_connector_hdmi_init_type_invalid,
 drm_connector_hdmi_init_type_invalid_gen_params),
@@ -508,13 +546,72 @@ static struct kunit_case 
drm_get_tv_mode_from_name_tests[] = {
 static struct kunit_suite drm_get_tv_mode_from_name_test_suite = {
.name = "drm_get_tv_mode_from_name",
.test_cases = drm_get_tv_mode_from_name_tests,
 };
 
+struct drm_hdmi_connector_get_output_format_name_test {
+   unsigned int kind;
+   const char *expected_name;
+};
+
+#define OUTPUT_FORMAT_TEST(_kind, _name)   \
+   {   \
+   .kind = _kind,  \
+   .expected_name = _name, \
+   }
+
+static void drm_test_drm_hdmi_connector_get_output_format_name(struct kunit 
*test)
+{
+   const struct drm_hdmi_connector_get_output_format_name_test *params =
+   test->param_value;
+
+   KUNIT_EXPECT_STREQ(test,
+  
drm_hdmi_connector_get_output_format_name(params->kind),
+  params->expected_name);
+}
+
+static const
+struct drm_hdmi_connector_get_output_format_name_test
+drm_hdmi_connector_get_output_format_name_valid_tests[] = {
+   OUTPUT_FORMAT_TEST(HDMI_COLORSPACE_RGB, "RGB"),
+   OUTPUT_FORMAT_TEST(HDMI_COLORSPACE_YUV420, "YUV 4:2:0"),
+   OUTPUT_FORMAT_TEST(HDMI_COLORSPACE_YUV422, "YUV 4:2:2"),
+   OUTPUT_FORMAT_TEST(HDMI_COLORSPACE_YUV444, "YUV 4:4:4"),
+};
+
+static void
+drm_hdmi_connector_get_output_format_name_valid_desc(const struct 
drm_hdmi_connector_get_output_format_name_test *t,
+char *desc)
+{
+   sprintf(desc, "%s", t->expected_name);
+}
+
+KUNIT_ARRAY_PARAM(drm_hdmi_connec

[PATCH v12 13/28] drm/connector: hdmi: Add custom hook to filter TMDS character rate

2024-04-23 Thread Maxime Ripard
Most of the HDMI controllers have an upper TMDS character rate limit
they can't exceed. On "embedded"-grade display controllers, it will
typically be lower than what high-grade monitors can provide these days,
so drivers will filter the TMDS character rate based on the controller
capabilities.

To make that easier to handle for drivers, let's provide an optional
hook to be implemented by drivers so they can tell the HDMI controller
helpers if a given TMDS character rate is reachable for them or not.

This will then be useful to figure out the best format and bpc count for
a given mode.

Reviewed-by: Dave Stevenson 
Signed-off-by: Maxime Ripard 
---
 drivers/gpu/drm/display/drm_hdmi_state_helper.c|  9 +++
 drivers/gpu/drm/drm_connector.c|  4 +++
 drivers/gpu/drm/tests/drm_connector_test.c | 14 ++
 drivers/gpu/drm/tests/drm_hdmi_state_helper_test.c |  4 +++
 include/drm/drm_connector.h| 31 ++
 5 files changed, 62 insertions(+)

diff --git a/drivers/gpu/drm/display/drm_hdmi_state_helper.c 
b/drivers/gpu/drm/display/drm_hdmi_state_helper.c
index 08630561d864..063421835dba 100644
--- a/drivers/gpu/drm/display/drm_hdmi_state_helper.c
+++ b/drivers/gpu/drm/display/drm_hdmi_state_helper.c
@@ -51,15 +51,24 @@ connector_state_get_mode(const struct drm_connector_state 
*conn_state)
 static enum drm_mode_status
 hdmi_clock_valid(const struct drm_connector *connector,
 const struct drm_display_mode *mode,
 unsigned long long clock)
 {
+   const struct drm_connector_hdmi_funcs *funcs = connector->hdmi.funcs;
const struct drm_display_info *info = >display_info;
 
if (info->max_tmds_clock && clock > info->max_tmds_clock * 1000)
return MODE_CLOCK_HIGH;
 
+   if (funcs && funcs->tmds_char_rate_valid) {
+   enum drm_mode_status status;
+
+   status = funcs->tmds_char_rate_valid(connector, mode, clock);
+   if (status != MODE_OK)
+   return status;
+   }
+
return MODE_OK;
 }
 
 static int
 hdmi_compute_clock(const struct drm_connector *connector,
diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c
index b629c8e990f4..555eac20e5a4 100644
--- a/drivers/gpu/drm/drm_connector.c
+++ b/drivers/gpu/drm/drm_connector.c
@@ -455,10 +455,11 @@ EXPORT_SYMBOL(drmm_connector_init);
 /**
  * drmm_connector_hdmi_init - Init a preallocated HDMI connector
  * @dev: DRM device
  * @connector: A pointer to the HDMI connector to init
  * @funcs: callbacks for this connector
+ * @hdmi_funcs: HDMI-related callbacks for this connector
  * @connector_type: user visible type of the connector
  * @ddc: optional pointer to the associated ddc adapter
  * @supported_formats: Bitmask of @hdmi_colorspace listing supported output 
formats
  * @max_bpc: Maximum bits per char the HDMI connector supports
  *
@@ -474,10 +475,11 @@ EXPORT_SYMBOL(drmm_connector_init);
  * Zero on success, error code on failure.
  */
 int drmm_connector_hdmi_init(struct drm_device *dev,
 struct drm_connector *connector,
 const struct drm_connector_funcs *funcs,
+const struct drm_connector_hdmi_funcs *hdmi_funcs,
 int connector_type,
 struct i2c_adapter *ddc,
 unsigned long supported_formats,
 unsigned int max_bpc)
 {
@@ -510,10 +512,12 @@ int drmm_connector_hdmi_init(struct drm_device *dev,
connector->max_bpc = max_bpc;
 
if (max_bpc > 8)
drm_connector_attach_hdr_output_metadata_property(connector);
 
+   connector->hdmi.funcs = hdmi_funcs;
+
return 0;
 }
 EXPORT_SYMBOL(drmm_connector_hdmi_init);
 
 /**
diff --git a/drivers/gpu/drm/tests/drm_connector_test.c 
b/drivers/gpu/drm/tests/drm_connector_test.c
index 426d974d8d74..34d96f7fbb25 100644
--- a/drivers/gpu/drm/tests/drm_connector_test.c
+++ b/drivers/gpu/drm/tests/drm_connector_test.c
@@ -22,10 +22,13 @@ struct drm_connector_init_priv {
struct drm_device drm;
struct drm_connector connector;
struct i2c_adapter ddc;
 };
 
+static const struct drm_connector_hdmi_funcs dummy_hdmi_funcs = {
+};
+
 static const struct drm_connector_funcs dummy_funcs = {
.atomic_destroy_state   = drm_atomic_helper_connector_destroy_state,
.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
.reset  = drm_atomic_helper_connector_reset,
 };
@@ -187,10 +190,11 @@ static void drm_test_connector_hdmi_init_valid(struct 
kunit *test)
struct drm_connector_init_priv *priv = test->priv;
int ret;
 
ret = drmm_connector_hdmi_init(>drm, >connector,

[PATCH v12 10/28] drm/tests: Add HDMI TDMS character rate tests

2024-04-23 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 | 296 +
 1 file changed, 296 insertions(+)

diff --git a/drivers/gpu/drm/tests/drm_connector_test.c 
b/drivers/gpu/drm/tests/drm_connector_test.c
index 72f22ec951d6..426d974d8d74 100644
--- a/drivers/gpu/drm/tests/drm_connector_test.c
+++ b/drivers/gpu/drm/tests/drm_connector_test.c
@@ -6,11 +6,15 @@
 #include 
 
 #include 
 #include 
 #include 
+#include 
 #include 
+#include 
+
+#include 
 
 #include 
 
 #include "../drm_crtc_internal.h"
 
@@ -604,14 +608,306 @@ static struct kunit_case 
drm_hdmi_connector_get_output_format_name_tests[] = {
 static struct kunit_suite drm_hdmi_connector_get_output_format_name_test_suite 
= {
.name = "drm_hdmi_connector_get_output_format_name",
.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_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_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_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_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_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_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_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_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_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_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_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;
+
+ 

[PATCH v12 11/28] drm/connector: hdmi: Calculate TMDS character rate

2024-04-23 Thread Maxime Ripard
Most HDMI drivers have some code to calculate the TMDS character rate,
usually to adjust an internal clock to match what the mode requires.

Since the TMDS character rates mostly depends on the resolution, whether
we need to repeat pixels or not, the bpc count and the format, we can
now derive it from the HDMI connector state that stores all those infos
and remove the duplication from drivers.

Reviewed-by: Dave Stevenson 
Signed-off-by: Maxime Ripard 
---
 drivers/gpu/drm/display/drm_hdmi_state_helper.c| 67 ++
 drivers/gpu/drm/drm_atomic.c   |  1 +
 drivers/gpu/drm/tests/drm_hdmi_state_helper_test.c |  3 +
 include/drm/drm_connector.h|  5 ++
 4 files changed, 76 insertions(+)

diff --git a/drivers/gpu/drm/display/drm_hdmi_state_helper.c 
b/drivers/gpu/drm/display/drm_hdmi_state_helper.c
index f6cd0612ea2c..08630561d864 100644
--- a/drivers/gpu/drm/display/drm_hdmi_state_helper.c
+++ b/drivers/gpu/drm/display/drm_hdmi_state_helper.c
@@ -1,10 +1,11 @@
 // SPDX-License-Identifier: MIT
 
 #include 
 #include 
 
+#include 
 #include 
 
 /**
  * __drm_atomic_helper_connector_hdmi_reset() - Initializes all HDMI 
@drm_connector_state resources
  * @connector: DRM connector
@@ -23,10 +24,67 @@ void __drm_atomic_helper_connector_hdmi_reset(struct 
drm_connector *connector,
new_conn_state->max_bpc = max_bpc;
new_conn_state->max_requested_bpc = max_bpc;
 }
 EXPORT_SYMBOL(__drm_atomic_helper_connector_hdmi_reset);
 
+static const struct drm_display_mode *
+connector_state_get_mode(const struct drm_connector_state *conn_state)
+{
+   struct drm_atomic_state *state;
+   struct drm_crtc_state *crtc_state;
+   struct drm_crtc *crtc;
+
+   state = conn_state->state;
+   if (!state)
+   return NULL;
+
+   crtc = conn_state->crtc;
+   if (!crtc)
+   return NULL;
+
+   crtc_state = drm_atomic_get_new_crtc_state(state, crtc);
+   if (!crtc_state)
+   return NULL;
+
+   return _state->mode;
+}
+
+static enum drm_mode_status
+hdmi_clock_valid(const struct drm_connector *connector,
+const struct drm_display_mode *mode,
+unsigned long long clock)
+{
+   const struct drm_display_info *info = >display_info;
+
+   if (info->max_tmds_clock && clock > info->max_tmds_clock * 1000)
+   return MODE_CLOCK_HIGH;
+
+   return MODE_OK;
+}
+
+static int
+hdmi_compute_clock(const struct drm_connector *connector,
+  struct drm_connector_state *conn_state,
+  const struct drm_display_mode *mode,
+  unsigned int bpc, enum hdmi_colorspace fmt)
+{
+   enum drm_mode_status status;
+   unsigned long long clock;
+
+   clock = drm_hdmi_compute_mode_clock(mode, bpc, fmt);
+   if (!clock)
+   return -EINVAL;
+
+   status = hdmi_clock_valid(connector, mode, clock);
+   if (status != MODE_OK)
+   return -EINVAL;
+
+   conn_state->hdmi.tmds_char_rate = clock;
+
+   return 0;
+}
+
 /**
  * drm_atomic_helper_connector_hdmi_check() - Helper to check HDMI connector 
atomic state
  * @connector: DRM Connector
  * @state: the DRM State object
  *
@@ -42,10 +100,19 @@ int drm_atomic_helper_connector_hdmi_check(struct 
drm_connector *connector,
 {
struct drm_connector_state *old_conn_state =
drm_atomic_get_old_connector_state(state, connector);
struct drm_connector_state *new_conn_state =
drm_atomic_get_new_connector_state(state, connector);
+   const struct drm_display_mode *mode =
+   connector_state_get_mode(new_conn_state);
+   int ret;
+
+   ret = hdmi_compute_clock(connector, new_conn_state, mode,
+new_conn_state->hdmi.output_bpc,
+new_conn_state->hdmi.output_format);
+   if (ret)
+   return ret;
 
if (old_conn_state->hdmi.output_bpc != new_conn_state->hdmi.output_bpc 
||
old_conn_state->hdmi.output_format != 
new_conn_state->hdmi.output_format) {
struct drm_crtc *crtc = new_conn_state->crtc;
struct drm_crtc_state *crtc_state;
diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c
index 8730137baa86..26f9e525c0a0 100644
--- a/drivers/gpu/drm/drm_atomic.c
+++ b/drivers/gpu/drm/drm_atomic.c
@@ -1146,10 +1146,11 @@ 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, "\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_for

[PATCH v12 04/28] drm/connector: hdmi: Create an HDMI sub-state

2024-04-23 Thread Maxime Ripard
The next features we will need to share across drivers will need to
store some parameters for drivers to use, such as the selected output
format.

Let's create a new connector sub-state dedicated to HDMI controllers,
that will eventually store everything we need.

Reviewed-by: Dave Stevenson 
Reviewed-by: Sui Jingfeng 
Signed-off-by: Maxime Ripard 
---
 drivers/gpu/drm/display/Kconfig |  8 +
 drivers/gpu/drm/display/Makefile|  2 ++
 drivers/gpu/drm/display/drm_hdmi_state_helper.c | 41 +
 include/drm/display/drm_hdmi_state_helper.h | 16 ++
 include/drm/drm_connector.h |  7 +
 5 files changed, 74 insertions(+)

diff --git a/drivers/gpu/drm/display/Kconfig b/drivers/gpu/drm/display/Kconfig
index a38962a556c2..78839f088462 100644
--- a/drivers/gpu/drm/display/Kconfig
+++ b/drivers/gpu/drm/display/Kconfig
@@ -76,5 +76,13 @@ config DRM_DISPLAY_HDMI_HELPER
bool "DRM HDMI Helpers"
depends on DRM_DISPLAY_HELPER
default y
help
  DRM display helpers for HDMI.
+
+config DRM_DISPLAY_HDMI_STATE_HELPER
+   bool "DRM HDMI Atomic State Helpers"
+   depends on DRM_DISPLAY_HELPER
+   depends on DRM_DISPLAY_HDMI_HELPER
+   default y
+   help
+ DRM KMS state helpers for HDMI.
diff --git a/drivers/gpu/drm/display/Makefile b/drivers/gpu/drm/display/Makefile
index 17d2cc73ff56..629df2f4d322 100644
--- a/drivers/gpu/drm/display/Makefile
+++ b/drivers/gpu/drm/display/Makefile
@@ -12,9 +12,11 @@ drm_display_helper-$(CONFIG_DRM_DISPLAY_DP_TUNNEL) += \
drm_dp_tunnel.o
 drm_display_helper-$(CONFIG_DRM_DISPLAY_HDCP_HELPER) += drm_hdcp_helper.o
 drm_display_helper-$(CONFIG_DRM_DISPLAY_HDMI_HELPER) += \
drm_hdmi_helper.o \
drm_scdc_helper.o
+drm_display_helper-$(CONFIG_DRM_DISPLAY_HDMI_STATE_HELPER) += \
+   drm_hdmi_state_helper.o
 drm_display_helper-$(CONFIG_DRM_DISPLAY_DP_AUX_CHARDEV) += drm_dp_aux_dev.o
 drm_display_helper-$(CONFIG_DRM_DISPLAY_DP_AUX_CEC) += drm_dp_cec.o
 
 obj-$(CONFIG_DRM_DISPLAY_HELPER) += drm_display_helper.o
diff --git a/drivers/gpu/drm/display/drm_hdmi_state_helper.c 
b/drivers/gpu/drm/display/drm_hdmi_state_helper.c
new file mode 100644
index ..1e92c1108d23
--- /dev/null
+++ b/drivers/gpu/drm/display/drm_hdmi_state_helper.c
@@ -0,0 +1,41 @@
+// SPDX-License-Identifier: MIT
+
+#include 
+#include 
+
+#include 
+
+/**
+ * __drm_atomic_helper_connector_hdmi_reset() - Initializes all HDMI 
@drm_connector_state resources
+ * @connector: DRM connector
+ * @new_conn_state: connector state to reset
+ *
+ * Initializes all HDMI resources from a @drm_connector_state without
+ * actually allocating it. This is useful for HDMI drivers, in
+ * combination with __drm_atomic_helper_connector_reset() or
+ * drm_atomic_helper_connector_reset().
+ */
+void __drm_atomic_helper_connector_hdmi_reset(struct drm_connector *connector,
+ struct drm_connector_state 
*new_conn_state)
+{
+}
+EXPORT_SYMBOL(__drm_atomic_helper_connector_hdmi_reset);
+
+/**
+ * drm_atomic_helper_connector_hdmi_check() - Helper to check HDMI connector 
atomic state
+ * @connector: DRM Connector
+ * @state: the DRM State object
+ *
+ * Provides a default connector state check handler for HDMI connectors.
+ * Checks that a desired connector update is valid, and updates various
+ * fields of derived state.
+ *
+ * RETURNS:
+ * Zero on success, or an errno code otherwise.
+ */
+int drm_atomic_helper_connector_hdmi_check(struct drm_connector *connector,
+  struct drm_atomic_state *state)
+{
+   return 0;
+}
+EXPORT_SYMBOL(drm_atomic_helper_connector_hdmi_check);
diff --git a/include/drm/display/drm_hdmi_state_helper.h 
b/include/drm/display/drm_hdmi_state_helper.h
new file mode 100644
index ..6021983e2602
--- /dev/null
+++ b/include/drm/display/drm_hdmi_state_helper.h
@@ -0,0 +1,16 @@
+#/* SPDX-License-Identifier: MIT */
+
+#ifndef DRM_HDMI_STATE_HELPER_H_
+#define DRM_HDMI_STATE_HELPER_H_
+
+struct drm_atomic_state;
+struct drm_connector;
+struct drm_connector_state;
+
+void __drm_atomic_helper_connector_hdmi_reset(struct drm_connector *connector,
+ struct drm_connector_state 
*new_conn_state);
+
+int drm_atomic_helper_connector_hdmi_check(struct drm_connector *connector,
+  struct drm_atomic_state *state);
+
+#endif // DRM_HDMI_STATE_HELPER_H_
diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h
index 4491c4c2fb6e..000a2a156619 100644
--- a/include/drm/drm_connector.h
+++ b/include/drm/drm_connector.h
@@ -1029,10 +1029,17 @@ struct drm_connector_state {
/**
 * @hdr_output_metadata:
 * DRM blob property for HDR output metadata
 */
struct drm_property_blob *hdr_output_metadata;
+
+   /**
+*

[PATCH v12 07/28] drm/connector: hdmi: Add support for output format

2024-04-23 Thread Maxime Ripard
Just like BPC, we'll add support for automatic selection of the output
format for HDMI connectors.

Let's add the needed defaults and fields for now.

Reviewed-by: Dave Stevenson 
Signed-off-by: Maxime Ripard 
---
 drivers/gpu/drm/display/drm_hdmi_state_helper.c|  3 ++-
 drivers/gpu/drm/drm_atomic.c   |  2 ++
 drivers/gpu/drm/drm_connector.c| 31 ++
 drivers/gpu/drm/tests/drm_connector_test.c |  9 +++
 drivers/gpu/drm/tests/drm_hdmi_state_helper_test.c | 22 +++
 include/drm/drm_connector.h| 20 ++
 6 files changed, 81 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/display/drm_hdmi_state_helper.c 
b/drivers/gpu/drm/display/drm_hdmi_state_helper.c
index 82293d93b5f8..f6cd0612ea2c 100644
--- a/drivers/gpu/drm/display/drm_hdmi_state_helper.c
+++ b/drivers/gpu/drm/display/drm_hdmi_state_helper.c
@@ -43,11 +43,12 @@ int drm_atomic_helper_connector_hdmi_check(struct 
drm_connector *connector,
struct drm_connector_state *old_conn_state =
drm_atomic_get_old_connector_state(state, connector);
struct drm_connector_state *new_conn_state =
drm_atomic_get_new_connector_state(state, connector);
 
-   if (old_conn_state->hdmi.output_bpc != new_conn_state->hdmi.output_bpc) 
{
+   if (old_conn_state->hdmi.output_bpc != new_conn_state->hdmi.output_bpc 
||
+   old_conn_state->hdmi.output_format != 
new_conn_state->hdmi.output_format) {
struct drm_crtc *crtc = new_conn_state->crtc;
struct drm_crtc_state *crtc_state;
 
crtc_state = drm_atomic_get_crtc_state(state, crtc);
if (IS_ERR(crtc_state))
diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c
index 4e11cfb4518b..8730137baa86 100644
--- a/drivers/gpu/drm/drm_atomic.c
+++ b/drivers/gpu/drm/drm_atomic.c
@@ -1144,10 +1144,12 @@ static void drm_atomic_connector_print_state(struct 
drm_printer *p,
drm_printf(p, "\tcolorspace=%s\n", 
drm_get_colorspace_name(state->colorspace));
 
if (connector->connector_type == DRM_MODE_CONNECTOR_HDMIA ||
connector->connector_type == DRM_MODE_CONNECTOR_HDMIB) {
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));
}
 
if (connector->connector_type == DRM_MODE_CONNECTOR_WRITEBACK)
if (state->writeback_job && state->writeback_job->fb)
drm_printf(p, "\tfb=%d\n", 
state->writeback_job->fb->base.id);
diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c
index da51a2bcb978..b629c8e990f4 100644
--- a/drivers/gpu/drm/drm_connector.c
+++ b/drivers/gpu/drm/drm_connector.c
@@ -457,10 +457,11 @@ EXPORT_SYMBOL(drmm_connector_init);
  * @dev: DRM device
  * @connector: A pointer to the HDMI connector to init
  * @funcs: callbacks for this connector
  * @connector_type: user visible type of the connector
  * @ddc: optional pointer to the associated ddc adapter
+ * @supported_formats: Bitmask of @hdmi_colorspace listing supported output 
formats
  * @max_bpc: Maximum bits per char the HDMI connector supports
  *
  * Initialises a preallocated HDMI connector. Connectors can be
  * subclassed as part of driver connector objects.
  *
@@ -475,25 +476,31 @@ EXPORT_SYMBOL(drmm_connector_init);
 int drmm_connector_hdmi_init(struct drm_device *dev,
 struct drm_connector *connector,
 const struct drm_connector_funcs *funcs,
 int connector_type,
 struct i2c_adapter *ddc,
+unsigned long supported_formats,
 unsigned int max_bpc)
 {
int ret;
 
if (!(connector_type == DRM_MODE_CONNECTOR_HDMIA ||
  connector_type == DRM_MODE_CONNECTOR_HDMIB))
return -EINVAL;
 
+   if (!supported_formats || !(supported_formats & 
BIT(HDMI_COLORSPACE_RGB)))
+   return -EINVAL;
+
if (!(max_bpc == 8 || max_bpc == 10 || max_bpc == 12))
return -EINVAL;
 
ret = drmm_connector_init(dev, connector, funcs, connector_type, ddc);
if (ret)
return ret;
 
+   connector->hdmi.supported_formats = supported_formats;
+
/*
 * drm_connector_attach_max_bpc_property() requires the
 * connector to have a state.
 */
if (connector->funcs->reset)
@@ -1199,10 +1206,34 @@ static const u32 dp_colorspaces =
BIT(DRM_MODE_COLORIMETRY_SYCC_601) |
BIT(DRM_MODE_COLORIMETRY_OPYCC_601) |
BIT(DRM_MODE_C

[PATCH v12 06/28] drm/tests: Add output bpc tests

2024-04-23 Thread Maxime Ripard
Now that we're tracking the output bpc count in the connector state,
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/Kconfig|   1 +
 drivers/gpu/drm/tests/Makefile |   1 +
 drivers/gpu/drm/tests/drm_connector_test.c | 140 +++
 drivers/gpu/drm/tests/drm_hdmi_state_helper_test.c | 438 +
 drivers/gpu/drm/tests/drm_kunit_edid.h | 106 +
 5 files changed, 686 insertions(+)

diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
index 959b19a04101..c51d023088d8 100644
--- a/drivers/gpu/drm/Kconfig
+++ b/drivers/gpu/drm/Kconfig
@@ -74,10 +74,11 @@ config DRM_KUNIT_TEST_HELPERS
 
 config DRM_KUNIT_TEST
tristate "KUnit tests for DRM" if !KUNIT_ALL_TESTS
depends on DRM
depends on DRM_DISPLAY_DP_HELPER
+   depends on DRM_DISPLAY_HDMI_STATE_HELPER
depends on DRM_DISPLAY_HELPER
depends on KUNIT
depends on MMU
select DRM_BUDDY
select DRM_EXEC
diff --git a/drivers/gpu/drm/tests/Makefile b/drivers/gpu/drm/tests/Makefile
index d6183b3d7688..56dab563abd7 100644
--- a/drivers/gpu/drm/tests/Makefile
+++ b/drivers/gpu/drm/tests/Makefile
@@ -12,10 +12,11 @@ obj-$(CONFIG_DRM_KUNIT_TEST) += \
drm_exec_test.o \
drm_format_helper_test.o \
drm_format_test.o \
drm_framebuffer_test.o \
drm_gem_shmem_test.o \
+   drm_hdmi_state_helper_test.o \
drm_managed_test.o \
drm_mm_test.o \
drm_modes_test.o \
drm_plane_helper_test.o \
drm_probe_helper_test.o \
diff --git a/drivers/gpu/drm/tests/drm_connector_test.c 
b/drivers/gpu/drm/tests/drm_connector_test.c
index 2661eb64a5cd..2519b91de95e 100644
--- a/drivers/gpu/drm/tests/drm_connector_test.c
+++ b/drivers/gpu/drm/tests/drm_connector_test.c
@@ -10,10 +10,12 @@
 #include 
 #include 
 
 #include 
 
+#include "../drm_crtc_internal.h"
+
 struct drm_connector_init_priv {
struct drm_device drm;
struct drm_connector connector;
struct i2c_adapter ddc;
 };
@@ -204,10 +206,143 @@ static void drm_test_connector_hdmi_init_null_ddc(struct 
kunit *test)
   NULL,
   8);
KUNIT_EXPECT_EQ(test, ret, 0);
 }
 
+/*
+ * Test that the registration of a connector with an invalid maximum bpc
+ * count fails.
+ */
+static void drm_test_connector_hdmi_init_bpc_invalid(struct kunit *test)
+{
+   struct drm_connector_init_priv *priv = test->priv;
+   int ret;
+
+   ret = drmm_connector_hdmi_init(>drm, >connector,
+  _funcs,
+  DRM_MODE_CONNECTOR_HDMIA,
+  >ddc,
+  9);
+   KUNIT_EXPECT_LT(test, ret, 0);
+}
+
+/*
+ * Test that the registration of a connector with a null maximum bpc
+ * count fails.
+ */
+static void drm_test_connector_hdmi_init_bpc_null(struct kunit *test)
+{
+   struct drm_connector_init_priv *priv = test->priv;
+   int ret;
+
+   ret = drmm_connector_hdmi_init(>drm, >connector,
+  _funcs,
+  DRM_MODE_CONNECTOR_HDMIA,
+  >ddc,
+  0);
+   KUNIT_EXPECT_LT(test, ret, 0);
+}
+
+/*
+ * Test that the registration of a connector with a maximum bpc count of
+ * 8 succeeds, registers the max bpc property, but doesn't register the
+ * HDR output metadata one.
+ */
+static void drm_test_connector_hdmi_init_bpc_8(struct kunit *test)
+{
+   struct drm_connector_init_priv *priv = test->priv;
+   struct drm_connector *connector = >connector;
+   struct drm_property *prop;
+   uint64_t val;
+   int ret;
+
+   ret = drmm_connector_hdmi_init(>drm, connector,
+  _funcs,
+  DRM_MODE_CONNECTOR_HDMIA,
+  >ddc,
+  8);
+   KUNIT_EXPECT_EQ(test, ret, 0);
+
+   prop = connector->max_bpc_property;
+   KUNIT_ASSERT_NOT_NULL(test, prop);
+   KUNIT_EXPECT_NOT_NULL(test, drm_mode_obj_find_prop_id(>base, 
prop->base.id));
+
+   ret = drm_object_property_get_value(>base, prop, );
+   KUNIT_EXPECT_EQ(test, ret, 0);
+   KUNIT_EXPECT_EQ(test, val, 8);
+
+   prop = priv->drm.mode_config.hdr_output_metadata_property;
+   KUNIT_ASSERT_NOT_NULL(test, prop);
+   KUNIT_EXPECT_NULL(test, drm_mode_obj_find_prop_id(>base, 
prop->base.id));
+}
+
+/*
+ * Test that the registration of a connector with a maximum bpc count of
+ * 10 succeeds and registers the max bpc and HDR output metadata
+ * propert

[PATCH v12 03/28] drm/tests: connector: Add tests for drmm_connector_hdmi_init

2024-04-23 Thread Maxime Ripard
We just introduced a new initialization function for our connectors, so
let's build a kunit test suite for it as well.

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

diff --git a/drivers/gpu/drm/tests/drm_connector_test.c 
b/drivers/gpu/drm/tests/drm_connector_test.c
index 44f82ed2a958..261d4109946d 100644
--- a/drivers/gpu/drm/tests/drm_connector_test.c
+++ b/drivers/gpu/drm/tests/drm_connector_test.c
@@ -170,10 +170,132 @@ static struct kunit_suite drmm_connector_init_test_suite 
= {
.name = "drmm_connector_init",
.init = drm_test_connector_init,
.test_cases = drmm_connector_init_tests,
 };
 
+/*
+ * Test that the registration of a bog standard connector works as
+ * expected and doesn't report any error.
+ */
+static void drm_test_connector_hdmi_init_valid(struct kunit *test)
+{
+   struct drm_connector_init_priv *priv = test->priv;
+   int ret;
+
+   ret = drmm_connector_hdmi_init(>drm, >connector,
+  _funcs,
+  DRM_MODE_CONNECTOR_HDMIA,
+  >ddc);
+   KUNIT_EXPECT_EQ(test, ret, 0);
+}
+
+/*
+ * Test that the registration of a connector without a DDC adapter
+ * doesn't report any error.
+ */
+static void drm_test_connector_hdmi_init_null_ddc(struct kunit *test)
+{
+   struct drm_connector_init_priv *priv = test->priv;
+   int ret;
+
+   ret = drmm_connector_hdmi_init(>drm, >connector,
+  _funcs,
+  DRM_MODE_CONNECTOR_HDMIA,
+  NULL);
+   KUNIT_EXPECT_EQ(test, ret, 0);
+}
+
+/*
+ * Test that the registration of an HDMI connector with an HDMI
+ * connector type succeeds.
+ */
+static void drm_test_connector_hdmi_init_type_valid(struct kunit *test)
+{
+   struct drm_connector_init_priv *priv = test->priv;
+   unsigned int connector_type = *(unsigned int *)test->param_value;
+   int ret;
+
+   ret = drmm_connector_hdmi_init(>drm, >connector,
+  _funcs,
+  connector_type,
+  >ddc);
+   KUNIT_EXPECT_EQ(test, ret, 0);
+}
+
+static const unsigned int drm_connector_hdmi_init_type_valid_tests[] = {
+   DRM_MODE_CONNECTOR_HDMIA,
+   DRM_MODE_CONNECTOR_HDMIB,
+};
+
+static void drm_connector_hdmi_init_type_desc(const unsigned int *type, char 
*desc)
+{
+   sprintf(desc, "%s", drm_get_connector_type_name(*type));
+}
+
+KUNIT_ARRAY_PARAM(drm_connector_hdmi_init_type_valid,
+ drm_connector_hdmi_init_type_valid_tests,
+ drm_connector_hdmi_init_type_desc);
+
+/*
+ * Test that the registration of an HDMI connector with an !HDMI
+ * connector type fails.
+ */
+static void drm_test_connector_hdmi_init_type_invalid(struct kunit *test)
+{
+   struct drm_connector_init_priv *priv = test->priv;
+   unsigned int connector_type = *(unsigned int *)test->param_value;
+   int ret;
+
+   ret = drmm_connector_hdmi_init(>drm, >connector,
+  _funcs,
+  connector_type,
+  >ddc);
+   KUNIT_EXPECT_LT(test, ret, 0);
+}
+
+static const unsigned int drm_connector_hdmi_init_type_invalid_tests[] = {
+   DRM_MODE_CONNECTOR_Unknown,
+   DRM_MODE_CONNECTOR_VGA,
+   DRM_MODE_CONNECTOR_DVII,
+   DRM_MODE_CONNECTOR_DVID,
+   DRM_MODE_CONNECTOR_DVIA,
+   DRM_MODE_CONNECTOR_Composite,
+   DRM_MODE_CONNECTOR_SVIDEO,
+   DRM_MODE_CONNECTOR_LVDS,
+   DRM_MODE_CONNECTOR_Component,
+   DRM_MODE_CONNECTOR_9PinDIN,
+   DRM_MODE_CONNECTOR_DisplayPort,
+   DRM_MODE_CONNECTOR_TV,
+   DRM_MODE_CONNECTOR_eDP,
+   DRM_MODE_CONNECTOR_VIRTUAL,
+   DRM_MODE_CONNECTOR_DSI,
+   DRM_MODE_CONNECTOR_DPI,
+   DRM_MODE_CONNECTOR_WRITEBACK,
+   DRM_MODE_CONNECTOR_SPI,
+   DRM_MODE_CONNECTOR_USB,
+};
+
+KUNIT_ARRAY_PARAM(drm_connector_hdmi_init_type_invalid,
+ drm_connector_hdmi_init_type_invalid_tests,
+ drm_connector_hdmi_init_type_desc);
+
+static struct kunit_case drmm_connector_hdmi_init_tests[] = {
+   KUNIT_CASE(drm_test_connector_hdmi_init_valid),
+   KUNIT_CASE(drm_test_connector_hdmi_init_null_ddc),
+   KUNIT_CASE_PARAM(drm_test_connector_hdmi_init_type_valid,
+drm_connector_hdmi_init_type_valid_gen_params),
+   KUNIT_CASE_PARAM(drm_test_connector_hdmi_init_type_invalid,
+drm_connector_hdmi_init_type_invalid_gen_params),
+   { }
+};
+
+static struct kunit_suite drmm_connector_hdmi_init_test_suite = {
+   .nam

[PATCH v12 05/28] drm/connector: hdmi: Add output BPC to the connector state

2024-04-23 Thread Maxime Ripard
We'll add automatic selection of the output BPC in a following patch,
but let's add it to the HDMI connector state already.

Reviewed-by: Dave Stevenson 
Signed-off-by: Maxime Ripard 
---
 drivers/gpu/drm/display/drm_hdmi_state_helper.c | 20 
 drivers/gpu/drm/drm_atomic.c|  5 +
 drivers/gpu/drm/drm_connector.c | 20 +++-
 drivers/gpu/drm/tests/drm_connector_test.c  | 12 
 include/drm/drm_connector.h | 12 +++-
 5 files changed, 63 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/display/drm_hdmi_state_helper.c 
b/drivers/gpu/drm/display/drm_hdmi_state_helper.c
index 1e92c1108d23..82293d93b5f8 100644
--- a/drivers/gpu/drm/display/drm_hdmi_state_helper.c
+++ b/drivers/gpu/drm/display/drm_hdmi_state_helper.c
@@ -16,10 +16,14 @@
  * drm_atomic_helper_connector_reset().
  */
 void __drm_atomic_helper_connector_hdmi_reset(struct drm_connector *connector,
  struct drm_connector_state 
*new_conn_state)
 {
+   unsigned int max_bpc = connector->max_bpc;
+
+   new_conn_state->max_bpc = max_bpc;
+   new_conn_state->max_requested_bpc = max_bpc;
 }
 EXPORT_SYMBOL(__drm_atomic_helper_connector_hdmi_reset);
 
 /**
  * drm_atomic_helper_connector_hdmi_check() - Helper to check HDMI connector 
atomic state
@@ -34,8 +38,24 @@ EXPORT_SYMBOL(__drm_atomic_helper_connector_hdmi_reset);
  * Zero on success, or an errno code otherwise.
  */
 int drm_atomic_helper_connector_hdmi_check(struct drm_connector *connector,
   struct drm_atomic_state *state)
 {
+   struct drm_connector_state *old_conn_state =
+   drm_atomic_get_old_connector_state(state, connector);
+   struct drm_connector_state *new_conn_state =
+   drm_atomic_get_new_connector_state(state, connector);
+
+   if (old_conn_state->hdmi.output_bpc != new_conn_state->hdmi.output_bpc) 
{
+   struct drm_crtc *crtc = new_conn_state->crtc;
+   struct drm_crtc_state *crtc_state;
+
+   crtc_state = drm_atomic_get_crtc_state(state, crtc);
+   if (IS_ERR(crtc_state))
+   return PTR_ERR(crtc_state);
+
+   crtc_state->mode_changed = true;
+   }
+
return 0;
 }
 EXPORT_SYMBOL(drm_atomic_helper_connector_hdmi_check);
diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c
index a91737adf8e7..4e11cfb4518b 100644
--- a/drivers/gpu/drm/drm_atomic.c
+++ b/drivers/gpu/drm/drm_atomic.c
@@ -1141,10 +1141,15 @@ static void drm_atomic_connector_print_state(struct 
drm_printer *p,
drm_printf(p, "\tcrtc=%s\n", state->crtc ? state->crtc->name : 
"(null)");
drm_printf(p, "\tself_refresh_aware=%d\n", state->self_refresh_aware);
drm_printf(p, "\tmax_requested_bpc=%d\n", state->max_requested_bpc);
drm_printf(p, "\tcolorspace=%s\n", 
drm_get_colorspace_name(state->colorspace));
 
+   if (connector->connector_type == DRM_MODE_CONNECTOR_HDMIA ||
+   connector->connector_type == DRM_MODE_CONNECTOR_HDMIB) {
+   drm_printf(p, "\toutput_bpc=%u\n", state->hdmi.output_bpc);
+   }
+
if (connector->connector_type == DRM_MODE_CONNECTOR_WRITEBACK)
if (state->writeback_job && state->writeback_job->fb)
drm_printf(p, "\tfb=%d\n", 
state->writeback_job->fb->base.id);
 
if (connector->funcs->atomic_print_state)
diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c
index d9961cce8245..da51a2bcb978 100644
--- a/drivers/gpu/drm/drm_connector.c
+++ b/drivers/gpu/drm/drm_connector.c
@@ -457,10 +457,11 @@ EXPORT_SYMBOL(drmm_connector_init);
  * @dev: DRM device
  * @connector: A pointer to the HDMI connector to init
  * @funcs: callbacks for this connector
  * @connector_type: user visible type of the connector
  * @ddc: optional pointer to the associated ddc adapter
+ * @max_bpc: Maximum bits per char the HDMI connector supports
  *
  * Initialises a preallocated HDMI connector. Connectors can be
  * subclassed as part of driver connector objects.
  *
  * Cleanup is automatically handled with a call to
@@ -473,22 +474,39 @@ EXPORT_SYMBOL(drmm_connector_init);
  */
 int drmm_connector_hdmi_init(struct drm_device *dev,
 struct drm_connector *connector,
 const struct drm_connector_funcs *funcs,
 int connector_type,
-struct i2c_adapter *ddc)
+struct i2c_adapter *ddc,
+unsigned int max_bpc)
 {
int ret;
 
if (!(connector_type == DRM_MODE_CONNECTOR_HDMIA ||
  connector_type == D

[PATCH v12 02/28] drm/mode_object: Export drm_mode_obj_find_prop_id for tests

2024-04-23 Thread Maxime Ripard
We'll need to use drm_mode_obj_find_prop_id() for kunit tests to make
sure a given property has been properly created. Let's export it for
tests only.

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

diff --git a/drivers/gpu/drm/drm_mode_object.c 
b/drivers/gpu/drm/drm_mode_object.c
index 0e8355063eee..df4cc0e8e263 100644
--- a/drivers/gpu/drm/drm_mode_object.c
+++ b/drivers/gpu/drm/drm_mode_object.c
@@ -476,10 +476,11 @@ struct drm_property *drm_mode_obj_find_prop_id(struct 
drm_mode_object *obj,
if (obj->properties->properties[i]->base.id == prop_id)
return obj->properties->properties[i];
 
return NULL;
 }
+EXPORT_SYMBOL_FOR_TESTS_ONLY(drm_mode_obj_find_prop_id);
 
 static int set_property_legacy(struct drm_mode_object *obj,
   struct drm_property *prop,
   uint64_t prop_value)
 {

-- 
2.44.0



[PATCH v12 01/28] drm/connector: Introduce an HDMI connector initialization function

2024-04-23 Thread Maxime Ripard
A lot of the various HDMI drivers duplicate some logic that depends on
the HDMI spec itself and not really a particular hardware
implementation.

Output BPC or format selection, infoframe generation are good examples
of such areas.

This creates a lot of boilerplate, with a lot of variations, which makes
it hard for userspace to rely on, and makes it difficult to get it right
for drivers.

In the next patches, we'll add a lot of infrastructure around the
drm_connector and drm_connector_state structures, which will allow to
abstract away the duplicated logic. This infrastructure comes with a few
requirements though, and thus we need a new initialization function.

Hopefully, this will make drivers simpler to handle, and their behaviour
more consistent.

Reviewed-by: Dave Stevenson 
Reviewed-by: Sui Jingfeng 
Signed-off-by: Maxime Ripard 
---
 drivers/gpu/drm/drm_connector.c | 39 +++
 include/drm/drm_connector.h |  5 +
 2 files changed, 44 insertions(+)

diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c
index b0516505f7ae..d9961cce8245 100644
--- a/drivers/gpu/drm/drm_connector.c
+++ b/drivers/gpu/drm/drm_connector.c
@@ -450,10 +450,49 @@ int drmm_connector_init(struct drm_device *dev,
 
return 0;
 }
 EXPORT_SYMBOL(drmm_connector_init);
 
+/**
+ * drmm_connector_hdmi_init - Init a preallocated HDMI connector
+ * @dev: DRM device
+ * @connector: A pointer to the HDMI connector to init
+ * @funcs: callbacks for this connector
+ * @connector_type: user visible type of the connector
+ * @ddc: optional pointer to the associated ddc adapter
+ *
+ * Initialises a preallocated HDMI connector. Connectors can be
+ * subclassed as part of driver connector objects.
+ *
+ * Cleanup is automatically handled with a call to
+ * drm_connector_cleanup() in a DRM-managed action.
+ *
+ * The connector structure should be allocated with drmm_kzalloc().
+ *
+ * Returns:
+ * Zero on success, error code on failure.
+ */
+int drmm_connector_hdmi_init(struct drm_device *dev,
+struct drm_connector *connector,
+const struct drm_connector_funcs *funcs,
+int connector_type,
+struct i2c_adapter *ddc)
+{
+   int ret;
+
+   if (!(connector_type == DRM_MODE_CONNECTOR_HDMIA ||
+ connector_type == DRM_MODE_CONNECTOR_HDMIB))
+   return -EINVAL;
+
+   ret = drmm_connector_init(dev, connector, funcs, connector_type, ddc);
+   if (ret)
+   return ret;
+
+   return 0;
+}
+EXPORT_SYMBOL(drmm_connector_hdmi_init);
+
 /**
  * drm_connector_attach_edid_property - attach edid property.
  * @connector: the connector
  *
  * Some connector types like DRM_MODE_CONNECTOR_VIRTUAL do not get a
diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h
index fe88d7fc6b8f..4491c4c2fb6e 100644
--- a/include/drm/drm_connector.h
+++ b/include/drm/drm_connector.h
@@ -1902,10 +1902,15 @@ int drm_connector_init_with_ddc(struct drm_device *dev,
 int drmm_connector_init(struct drm_device *dev,
struct drm_connector *connector,
const struct drm_connector_funcs *funcs,
int connector_type,
struct i2c_adapter *ddc);
+int drmm_connector_hdmi_init(struct drm_device *dev,
+struct drm_connector *connector,
+const struct drm_connector_funcs *funcs,
+int connector_type,
+struct i2c_adapter *ddc);
 void drm_connector_attach_edid_property(struct drm_connector *connector);
 int drm_connector_register(struct drm_connector *connector);
 void drm_connector_unregister(struct drm_connector *connector);
 int drm_connector_attach_encoder(struct drm_connector *connector,
  struct drm_encoder *encoder);

-- 
2.44.0



[PATCH v12 00/28] drm/connector: Create HDMI Connector infrastructure

2024-04-23 Thread Maxime Ripard
Hi,

Here's a series that creates some extra infrastructure specifically
targeted at HDMI controllers.

The idea behind this series came from a recent discussion on IRC during
which we discussed infoframes generation of i915 vs everything else.

Infoframes generation code still requires some decent boilerplate, with
each driver doing some variation of it.

In parallel, while working on vc4, we ended up converting a lot of i915
logic (mostly around format / bpc selection, and scrambler setup) to
apply on top of a driver that relies only on helpers.

While currently sitting in the vc4 driver, none of that logic actually
relies on any driver or hardware-specific behaviour.

The only missing piece to make it shareable are a bunch of extra
variables stored in a state (current bpc, format, RGB range selection,
etc.).

The initial implementation was relying on some generic subclass of
drm_connector to address HDMI connectors, with a bunch of helpers that
will take care of all the "HDMI Spec" related code. Scrambler setup is
missing at the moment but can easily be plugged in.

The feedback was that creating a connector subclass like was done for
writeback would prevent the adoption of those helpers since it couldn't
be used in all situations (like when the connector driver can implement
multiple output) and required more churn to cast between the
drm_connector and its subclass. The decision was thus to provide a set
of helper and to store the required variables in drm_connector and
drm_connector_state. This what has been implemented now.

Hans Verkuil also expressed interest in implementing a mechanism in v4l2
to retrieve infoframes from HDMI receiver and implementing a tool to
decode (and eventually check) infoframes. His current work on
edid-decode to enable that based on that series can be found here:
https://git.linuxtv.org/hverkuil/edid-decode.git/log/?h=hverkuil

And some more context here:
https://lore.kernel.org/dri-devel/50db7366-cd3d-4675-aaad-b85720223...@xs4all.nl/

This series thus leverages the infoframe generation code to expose it
through debugfs.

I also used the occasion to unit-test everything but the infoframe
generation, which can come later once I get a proper understanding of
what the infoframe are supposed to look like. This required to add some
extra kunit helpers and infrastructure to have multiple EDIDs and allow
each test to run with a particular set of capabilities.

This entire series has been tested on a Pi4, passes all its unittests
(125 new tests), and has only been build-tested for sunxi and rockchip.

Let me know what you think,
Maxime

To: Maarten Lankhorst 
To: Thomas Zimmermann 
To: David Airlie 
To: Daniel Vetter 
To: Jonathan Corbet 
To: Sandy Huang 
To: Heiko Stübner 
To: Chen-Yu Tsai 
To: Jernej Skrabec 
To: Samuel Holland 
To: Andy Yan 
Cc: Hans Verkuil 
Cc: Sebastian Wick 
Cc: Ville Syrjälä 
Cc: dri-devel@lists.freedesktop.org
Cc: linux-arm-ker...@lists.infradead.org
Cc: linux-...@vger.kernel.org
Cc: linux-ker...@vger.kernel.org
Cc: linux-me...@vger.kernel.org
Cc: linux-rockc...@lists.infradead.org
Cc: linux-su...@lists.linux.dev
Signed-off-by: Maxime Ripard 

Changes in v12:
- Rebase on current drm-misc-next
- Remove VIC check in clock rate computation function
- Invert RGB range logic to signal limited range instead of full like
  before
- Link to v11: 
https://lore.kernel.org/r/20240326-kms-hdmi-connector-state-v11-0-c5680ffcf...@kernel.org

Changes in v11:
- Turn the HDMI state helpers into a separate C file under
  drivers/gpu/drm/display
- Rework the Kconfig options too to prevent configuration breakages.
- Link to v10: 
https://lore.kernel.org/r/20240321-kms-hdmi-connector-state-v10-0-e6c178361...@kernel.org

Changes in v10:
- Drop the YUV422 fallback, and adjust the tests accordingly
- Fix HDMI infoframe handling
- Remove the infoframe copy in drm_connector
- Add a TODO that drm_hdmi_avi_infoframe_quant_range() only works for
  RGB
- Add a TODO for the YUV420 selection
- Fix a few bugs in vc4
- Change the logging from driver to KMS for the helpers
- Drop UPDATE_INFOFRAME macro
- Add infoframe code logging
- Document the selection of 8bpc for VIC1
- Rename state to conn_state where relevant
- Link to v9: 
https://lore.kernel.org/r/20240311-kms-hdmi-connector-state-v9-0-d45890323...@kernel.org

Changes in v9:
- Generate every infoframe but the HDMI vendor one if has_hdmi_infoframe
  isn't set
- Fix typos in the doc
- Removed undef for inexisting macro
- Improve the Broadcast RGB sanitation test
- Make EDID bytes array const
- Link to v8: 
https://lore.kernel.org/r/20240307-kms-hdmi-connector-state-v8-0-ef6a6f319...@kernel.org

Changes in v8:
- Drop applied patches
- Drop the YUV limited range mention in the Broadcast RGB documentation
- Rephrase the vc4_dummy_plane removal commit log
- Move infroframe mutex initialisation to the main drm_connector_init
  function to make sure it's always initialised
- Link to v7: 
https://lore.kernel.org/r/2024022

Re: [PATCH v3 0/5] drm/v3d: Fix GPU stats inconsistencies and race-condition

2024-04-23 Thread Maxime Ripard
Hi,

On Mon, Apr 22, 2024 at 01:08:44PM -0300, Maíra Canal wrote:
> @drm-misc maintainers, is there any chance you could backport commit
> 35f4f8c9fc97 ("drm/v3d: Don't increment `enabled_ns` twice") [1] to drm-
> misc-next?
> 
> I would like to apply this series to drm-misc-next because it fixes
> another issue with the GPU stats, but this series depends on commit
> 35f4f8c9fc97, as it has plenty of refactors on the GPU stats code.
> 
> Although I could theoretically apply this series in drm-misc-fixes, I
> don't believe it would be ideal, as discussed in #dri-devel earlier
> today.
> 
> [1] 
> https://gitlab.freedesktop.org/drm/misc/kernel/-/commit/35f4f8c9fc972248055096d63b782060e473311b

I just did the backmerge

Maxime


signature.asc
Description: PGP signature


Re: [PATCH v17 0/9] Enable Adaptive Sync SDP Support for DP

2024-04-19 Thread Maxime Ripard
On Fri, Apr 19, 2024 at 05:09:29PM +0300, Jani Nikula wrote:
> On Fri, 19 Apr 2024, Maxime Ripard  wrote:
> > On Fri, Apr 19, 2024 at 03:35:55PM +0300, Jani Nikula wrote:
> >> On Thu, 04 Apr 2024, "Nautiyal, Ankit K"  
> >> wrote:
> >> > On 3/19/2024 3:16 PM, Maxime Ripard wrote:
> >> >> On Mon, Mar 18, 2024 at 04:37:58PM +0200, Jani Nikula wrote:
> >> >>> On Mon, 11 Mar 2024, Mitul Golani 
> >> >>>  wrote:
> >> >>>>   An Adaptive-Sync-capable DP protocol converter indicates its
> >> >>>> support by setting the related bit in the DPCD register. This
> >> >>>> is valid for DP and edp as well.
> >> >>>>
> >> >>>> Computes AS SDP values based on the display configuration,
> >> >>>> ensuring proper handling of Variable Refresh Rate (VRR)
> >> >>>> in the context of Adaptive Sync.
> >> >>> [snip]
> >> >>>
> >> >>>> Mitul Golani (9):
> >> >>>>drm/dp: Add support to indicate if sink supports AS SDP
> >> >>>>drm: Add Adaptive Sync SDP logging
> >> >>> Maarten, Maxime, Thomas, ack for merging these two patches via
> >> >>> drm-intel-next?
> >> >> Ack
> >> >>
> >> >> Maxime
> >> >
> >> > Thanks for the patch, ack and reviews, pushed to drm-intel-next.
> >> 
> >> This came up again today [1]. The acks absolutely must be recorded in
> >> the commit messages when pushing the patches.
> >> 
> >> dim should complain about applying non-i915 patches without acks.
> >
> > It doesn't at the moment, this has bitten us a couple of times in
> > drm-misc too.
> 
> See check_maintainer() that gets called from apply_patch() and
> dim_b4_shazam_branch().

Oh, right, I missed it sorry.

> It's of limited value, but it should complain while applying non-i915
> patches.
> 
> > I did a MR to address that that hasn't been reviewed yet:
> > https://gitlab.freedesktop.org/drm/maintainer-tools/-/merge_requests/40
> 
> Yeah, a more generic solution is needed, but I think we should unify
> with the above.

Fully agreed, I'll rework it.

Thanks!
Maxime


signature.asc
Description: PGP signature


Re: [PATCH v11 15/28] drm/connector: hdmi: Compute bpc and format automatically

2024-04-19 Thread Maxime Ripard
On Tue, Apr 16, 2024 at 04:50:58PM +0300, Ville Syrjälä wrote:
> On Tue, Mar 26, 2024 at 04:40:19PM +0100, Maxime Ripard wrote:
> > 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/display/drm_hdmi_state_helper.c| 197 
> > -
> >  drivers/gpu/drm/tests/drm_hdmi_state_helper_test.c |  25 ++-
> >  2 files changed, 210 insertions(+), 12 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/display/drm_hdmi_state_helper.c 
> > b/drivers/gpu/drm/display/drm_hdmi_state_helper.c
> > index 063421835dba..b9bc0fb027ea 100644
> > --- a/drivers/gpu/drm/display/drm_hdmi_state_helper.c
> > +++ b/drivers/gpu/drm/display/drm_hdmi_state_helper.c
> > @@ -1,9 +1,11 @@
> >  // SPDX-License-Identifier: MIT
> >  
> >  #include 
> >  #include 
> > +#include 
> > +#include 
> >  
> >  #include 
> >  #include 
> >  
> >  /**
> > @@ -46,10 +48,110 @@ connector_state_get_mode(const struct 
> > drm_connector_state *conn_state)
> > return NULL;
> >  
> > 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);
> > +
> > +   /*
> > +* CTA-861-F, section 5.4 - Color Coding & Quantization states
> > +* that the bpc must be 8, 10, 12 or 16 except for the default
> > +* 640x480 VIC1 where the value must be 8.
> > +*
> > +* The definition of default here is ambiguous but the spec
> > +* refers to VIC1 being the default timing in several occasions
> > +* so our understanding is that for the default timing (ie,
> > +* VIC1), the bpc must be 8.
> > +*/
> > +   if (vic == 1 && bpc != 8) {
> > +   drm_dbg_kms(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_kms(dev, "DVI Monitors require an RGB output at 8 
> > bpc\n");
> > +   return false;
> > +   }
> > +
> > +   if (!(connector->hdmi.supported_formats & BIT(format))) {
> 
> These are the capabilities of the souce I take it?
>
> > +   drm_dbg_kms(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_kms(dev, "RGB Format, checking the constraints.\n");
> > +
> > +   if (!(info->color_formats & DRM_COLOR_FORMAT_RGB444))
> > +   return false;
> 
> and this is the sink.
>
> Maybe we should use the same bits for both? Anyways, that seems like
> material for a followup series.

Ack

> > +
> > +   if (bpc == 10 && !(info->edid_hdmi_rgb444_dc_modes & 
> > DRM_EDID_HDMI_DC_30)) {
> > +   drm_dbg_kms(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_kms(dev, "12 BPC but sink doesn't support Deep 
> > Color 36.\n");
> > +   return false;
> > +   }
> > +
> > +   drm_dbg_kms(dev, "RGB format supported in that 
> > configuration.\n");
> > +
> > +   return true;
> > +
> > +   case HDMI_COLORSPACE_YUV422:
> > +   drm_dbg_kms(dev, "YUV422 format, checking the constraints.\n");
> > +
> > +   if (!(info->color_formats & DRM_COLOR_FORMAT_YCBCR422)) {
> > +   drm_dbg_kms(dev, "Sink doesn't support YUV422.\n");
> > +   return false;
> > +   }
> > +
> > +   if (bpc != 12) {
> > +   drm_dbg_kms(dev, "YUV422 only supports 12 bpc.\n");
> > +   return false;
> > +   }
> 
> Did something change around here from the last time?

The format selection code now prefers to select a lower bpc rather than
another format, which is what you asked for in the previous version.



signature.asc
Description: PGP signature


Re: [PATCH v17 0/9] Enable Adaptive Sync SDP Support for DP

2024-04-19 Thread Maxime Ripard
On Fri, Apr 19, 2024 at 03:35:55PM +0300, Jani Nikula wrote:
> On Thu, 04 Apr 2024, "Nautiyal, Ankit K"  wrote:
> > On 3/19/2024 3:16 PM, Maxime Ripard wrote:
> >> On Mon, Mar 18, 2024 at 04:37:58PM +0200, Jani Nikula wrote:
> >>> On Mon, 11 Mar 2024, Mitul Golani  
> >>> wrote:
> >>>>   An Adaptive-Sync-capable DP protocol converter indicates its
> >>>> support by setting the related bit in the DPCD register. This
> >>>> is valid for DP and edp as well.
> >>>>
> >>>> Computes AS SDP values based on the display configuration,
> >>>> ensuring proper handling of Variable Refresh Rate (VRR)
> >>>> in the context of Adaptive Sync.
> >>> [snip]
> >>>
> >>>> Mitul Golani (9):
> >>>>drm/dp: Add support to indicate if sink supports AS SDP
> >>>>drm: Add Adaptive Sync SDP logging
> >>> Maarten, Maxime, Thomas, ack for merging these two patches via
> >>> drm-intel-next?
> >> Ack
> >>
> >> Maxime
> >
> > Thanks for the patch, ack and reviews, pushed to drm-intel-next.
> 
> This came up again today [1]. The acks absolutely must be recorded in
> the commit messages when pushing the patches.
> 
> dim should complain about applying non-i915 patches without acks.

It doesn't at the moment, this has bitten us a couple of times in
drm-misc too.

I did a MR to address that that hasn't been reviewed yet:
https://gitlab.freedesktop.org/drm/maintainer-tools/-/merge_requests/40

Maxime


signature.asc
Description: PGP signature


Re: [PULL] drm-intel-next

2024-04-19 Thread Maxime Ripard
Hi,

On Wed, Apr 17, 2024 at 09:38:55AM -0400, Rodrigo Vivi wrote:
> Another thing that it is important to highlight is that we have 3 drm level
> patches in this pull request where I didn't see any explicit recorded
> ack from you (drm maintainers) nor from drm-misc maintainers.
> The patches looks good to me and shouldn't cause conflict, so I hope it
> is okay to continue with them here instead of a big removal at this
> point.

Sigh...

I guess it's a good occasion to test
https://gitlab.freedesktop.org/drm/maintainer-tools/-/merge_requests/40

And merge it if it works.

Maxime


signature.asc
Description: PGP signature


Re: [PATCH v2 1/4] drm: add devm release action

2024-04-19 Thread Maxime Ripard
On Wed, Apr 17, 2024 at 09:55:55AM -0400, Rodrigo Vivi wrote:
> On Wed, Apr 17, 2024 at 02:11:42PM +0530, Aravind Iddamsetty wrote:
> > In scenarios where drm_dev_put is directly called by driver we want to
> > release devm_drm_dev_init_release action associated with struct
> > drm_device.
> > 
> > v2: Directly expose the original function, instead of introducing a
> > helper (Rodrigo)
> > 
> > Cc: Thomas Hellstr_m 
> > Cc: Rodrigo Vivi 
> > 
> > Reviewed-by: Rodrigo Vivi 
> 
> Sima, Dave, or drm-misc, ack to get this through drm-xe-next?

On principle, I'm fine with some later iteration of that patch going
through drm/xe, but the documentation needs to be improved in its
current state.

Maxime


signature.asc
Description: PGP signature


Re: [PATCH v11 17/28] drm/connector: hdmi: Add Broadcast RGB property

2024-04-19 Thread Maxime Ripard
On Tue, Apr 16, 2024 at 05:00:26PM +0300, Ville Syrjälä wrote:
> On Tue, Mar 26, 2024 at 04:40:21PM +0100, Maxime Ripard wrote:
> > 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.
> 
> Is there a i915 patch to switch over to hdmi.broadcast_rgb? Though
> the "hdmi" name is perhaps not the best idea given this is also a
> thing for DP.

No, there's none yet. I can try to cook one as a follow-up, but I have
no way to test it

Maxime


signature.asc
Description: PGP signature


Re: [PATCH v2 1/4] drm: add devm release action

2024-04-19 Thread Maxime Ripard
On Fri, Apr 19, 2024 at 02:28:23PM +0530, Aravind Iddamsetty wrote:
> In scenarios where drm_dev_put is directly called by driver we want to
> release devm_drm_dev_init_release action associated with struct
> drm_device.
> 
> v2: Directly expose the original function, instead of introducing a
> helper (Rodrigo)
> 
> Cc: Thomas Hellstr_m 
> Cc: Rodrigo Vivi 
> 
> Reviewed-by: Rodrigo Vivi 
> Signed-off-by: Aravind Iddamsetty 
> ---
>  drivers/gpu/drm/drm_drv.c | 6 ++
>  include/drm/drm_drv.h | 2 ++
>  2 files changed, 8 insertions(+)
> 
> diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c
> index 243cacb3575c..ba60cbb0725f 100644
> --- a/drivers/gpu/drm/drm_drv.c
> +++ b/drivers/gpu/drm/drm_drv.c
> @@ -714,6 +714,12 @@ static int devm_drm_dev_init(struct device *parent,
>   devm_drm_dev_init_release, dev);
>  }
>  
> +void devm_drm_dev_release_action(struct drm_device *dev)
> +{
> + devm_release_action(dev->dev, devm_drm_dev_init_release, dev);
> +}
> +EXPORT_SYMBOL(devm_drm_dev_release_action);

Again, this needs to be documented.

Maxime


signature.asc
Description: PGP signature


Re: [PATCH v11 09/28] drm/display: hdmi: Add HDMI compute clock helper

2024-04-18 Thread Maxime Ripard
On Tue, Apr 16, 2024 at 04:44:14PM +0300, Ville Syrjälä wrote:
> On Tue, Mar 26, 2024 at 04:40:13PM +0100, Maxime Ripard wrote:
> > A lot of HDMI drivers have some variation of the formula to calculate
> > the TMDS character rate from a mode, but few of them actually take all
> > parameters into account.
> > 
> > Let's create a helper to provide that rate taking all parameters into
> > account.
> > 
> > Reviewed-by: Dave Stevenson 
> > Signed-off-by: Maxime Ripard 
> > ---
> >  drivers/gpu/drm/display/drm_hdmi_helper.c | 70 
> > +++
> >  include/drm/display/drm_hdmi_helper.h |  4 ++
> >  2 files changed, 74 insertions(+)
> > 
> > diff --git a/drivers/gpu/drm/display/drm_hdmi_helper.c 
> > b/drivers/gpu/drm/display/drm_hdmi_helper.c
> > index faf5e9efa7d3..2518dd1a07e7 100644
> > --- a/drivers/gpu/drm/display/drm_hdmi_helper.c
> > +++ b/drivers/gpu/drm/display/drm_hdmi_helper.c
> > @@ -193,5 +193,75 @@ void drm_hdmi_avi_infoframe_content_type(struct 
> > hdmi_avi_infoframe *frame,
> > }
> >  
> > frame->itc = conn_state->content_type != DRM_MODE_CONTENT_TYPE_NO_DATA;
> >  }
> >  EXPORT_SYMBOL(drm_hdmi_avi_infoframe_content_type);
> > +
> > +/**
> > + * drm_hdmi_compute_mode_clock() - Computes the TMDS Character Rate
> > + * @mode: Display mode to compute the clock for
> > + * @bpc: Bits per character
> > + * @fmt: Output Pixel Format used
> > + *
> > + * Returns the TMDS Character Rate for a given mode, bpc count and output 
> > format.
> > + *
> > + * RETURNS:
> > + * The TMDS Character Rate, in Hertz, or 0 on error.
> 
> Everything generally uses kHz. Sticking to common units
> would be better.

Not everything, no. The clock framework is using Hz for example, and on
drm-misc drivers it's usually going to be the consumer of that field.

And there's almost 200 hits on mode->clock * 1000 in drivers/gpu/drm as
of today, including some in i915. This is a bit less than a third of all
the mode->clock usage, including the one that are unit-neutral (like
comparisons between two mode->clock fields).

Given how the rest of the DRM code is structured, yes, there's going to
be some impedance mismatch, but it's really not as clear cut as you make
it to be.

> > + */
> > +unsigned long long
> > +drm_hdmi_compute_mode_clock(const struct drm_display_mode *mode,
> > +   unsigned int bpc, enum hdmi_colorspace fmt)
> > +{
> > +   unsigned long long clock = mode->clock * 1000ULL;
> > +   unsigned int vic = drm_match_cea_mode(mode);
> > +
> > +   /*
> > +* CTA-861-G Spec, section 5.4 - Color Coding and Quantization
> > +* mandates that VIC 1 always uses 8 bpc.
> > +*/
> > +   if (vic == 1 && bpc != 8)
> > +   return 0;
> > +
> > +   /*
> > +* HDMI 2.0 Spec, section 7.1 - YCbCr 4:2:0 Pixel Encoding
> > +* specifies that YUV420 encoding is only available for those
> > +* VICs.
> > +*/
> > +   if (fmt == HDMI_COLORSPACE_YUV420 &&
> > +   !(vic == 96 || vic == 97 || vic == 101 ||
> > + vic == 102 || vic == 106 || vic == 107))
> > +   return 0;
> 
> I believe that is already outdated. I would just rip this out since the 
> sink is anyway required to declare for which timings it will support
> 4:2:0 via the Y420CMDB/VDB data blocks (see
> drm_mode_is_420_{only,also}().

Should we use drm_mode_is_420() then or rip it out entirely?

> > +
> > +   if (fmt == HDMI_COLORSPACE_YUV422) {
> > +   /*
> > +* HDMI 1.4b Spec, section 6.2.3 - Pixel Encoding Requirements
> > +* specifies that YUV422 is 36-bit only.
> > +*/
> > +   if (bpc != 12)
> > +   return 0;
> > +
> > +   /*
> > +* HDMI 1.0 Spec, section 6.5 - Pixel Encoding
> > +* specifies that YUV422 requires two 12-bits components per
> > +* pixel clock, which is equivalent in our calculation to three
> > +* 8-bits components
> > +*/
> > +   bpc = 8;
> > +   }
> > +
> > +   /*
> > +* HDMI 2.0 Spec, Section 7.1 - YCbCr 4:2:0 Pixel Encoding
> > +* specifies that YUV420 encoding is carried at a TMDS Character Rate
> > +* equal to half the pixel clock rate.
> > +*/
> > +   if (fmt == HDMI_COLORSPACE_YUV420)
> > +   clock = clock / 2;
> > +
> > +   if (mode->flags & DRM_MODE_FLAG_DBLCLK)
> > +   clock = clock * 2;
> > +
> > +   clock = clock * bpc;
> > +   do_div(clock, 8);
> 
> IMO one shouldn't use bare do_div(). There are
> more sensible wrappers for it.
> 
> In this case I would use DIV_ROUND_CLOSEST_ULL().

Ack.

Thanks!
Maxime



signature.asc
Description: PGP signature


Re: [PATCH 07/15] drm/vc4: hdmi: switch to struct drm_edid

2024-04-18 Thread Maxime Ripard
On Tue, 16 Apr 2024 16:22:21 +0300, Jani Nikula wrote:
> Prefer struct drm_edid based functions over struct edid.
> 
> Signed-off-by: Jani Nikula 
> 

Acked-by: Maxime Ripard 

Thanks!
Maxime


Re: [PATCH 06/15] drm/sun4i: hdmi: switch to struct drm_edid

2024-04-18 Thread Maxime Ripard
On Tue, 16 Apr 2024 16:22:20 +0300, Jani Nikula wrote:
> Prefer struct drm_edid based functions over struct edid.
> 
> Signed-off-by: Jani Nikula 
> 

Acked-by: Maxime Ripard 

Thanks!
Maxime


Re: Re: [PATCH 1/2] drm/print: drop include debugfs.h and include where needed

2024-04-15 Thread Maxime Ripard
On Mon, 15 Apr 2024 16:09:22 +0300, Jani Nikula wrote:
> On Wed, 10 Apr 2024, Jani Nikula  wrote:
> > Surprisingly many places depend on debugfs.h to be included via
> > drm_print.h. Fix them.
> 
> While all of this is trivial, merely adding some includes, please
> 
> [ ... ]

Acked-by: Maxime Ripard 

Thanks!
Maxime


Re: [PATCH 0/7] drm/display: Fix display helpers depends on fallouts

2024-04-15 Thread Maxime Ripard
Hi Mark

On Wed, Apr 10, 2024 at 07:06:39PM +0100, Mark Brown wrote:
> On Wed, Apr 03, 2024 at 12:56:18PM +0200, Maxime Ripard wrote:
> > Hi,
> > 
> > Here's a series addressing the various regressions that were reported
> > after the Kconfig rework for the DRM display helpers.
> > 
> > Let me know what you think,
> > Maxime
> 
> Is there any news on getting the rest of this merged?  It's been more
> than a week now and the Designware display controllers are all still
> broken in -next, causing widespread breakage in CI.  For bisection
> purposes it probably makes sense for the defconfig updates to go along
> with the changes to the Kconfig for the driver...

I was on holidays so I've admittedly hoped that it would be picked up /
reviewed by the relevant maintainers.

Aside from the changes on sunxi_defconfig, I haven't seen any review
from the relevant maintainers so I'm not sure how to merge this. Should
we get an Acked-by from Arnd, Olof, Catalin or Will and merge everything
through drm-misc?

Maxime



signature.asc
Description: PGP signature


Re: [PATCH v5 2/9] drm/mediatek: Add secure buffer control flow to mtk_drm_gem

2024-04-15 Thread Maxime Ripard
On Wed, Apr 03, 2024 at 06:26:54PM +0800, Shawn Sung wrote:
> From: "Jason-JH.Lin" 
> 
> Add secure buffer control flow to mtk_drm_gem.
> 
> When user space takes DRM_MTK_GEM_CREATE_ENCRYPTED flag and size
> to create a mtk_drm_gem object, mtk_drm_gem will find a matched size
> dma buffer from secure dma-heap and bind it to mtk_drm_gem object.
> 
> Signed-off-by: Jason-JH.Lin 
> Signed-off-by: Hsiao Chien Sung 
> ---
>  drivers/gpu/drm/mediatek/mtk_gem.c | 85 +-
>  drivers/gpu/drm/mediatek/mtk_gem.h |  4 ++
>  2 files changed, 88 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/gpu/drm/mediatek/mtk_gem.c 
> b/drivers/gpu/drm/mediatek/mtk_gem.c
> index e59e0727717b7..ec34d02c14377 100644
> --- a/drivers/gpu/drm/mediatek/mtk_gem.c
> +++ b/drivers/gpu/drm/mediatek/mtk_gem.c
> @@ -4,6 +4,8 @@
>   */
>  
>  #include 
> +#include 
> +#include 
>  #include 
>  
>  #include 
> @@ -102,6 +104,81 @@ struct mtk_gem_obj *mtk_gem_create(struct drm_device 
> *dev,
>   return ERR_PTR(ret);
>  }
>  
> +struct mtk_gem_obj *mtk_gem_create_from_heap(struct drm_device *dev,
> +  const char *heap, size_t size)
> +{
> + struct mtk_drm_private *priv = dev->dev_private;
> + struct mtk_gem_obj *mtk_gem;
> + struct drm_gem_object *obj;
> + struct dma_heap *dma_heap;
> + struct dma_buf *dma_buf;
> + struct dma_buf_attachment *attach;
> + struct sg_table *sgt;
> + struct iosys_map map = {};
> + int ret;
> +
> + mtk_gem = mtk_gem_init(dev, size);
> + if (IS_ERR(mtk_gem))
> + return ERR_CAST(mtk_gem);
> +
> + obj = _gem->base;
> +
> + dma_heap = dma_heap_find(heap);
> + if (!dma_heap) {
> + DRM_ERROR("heap find fail\n");
> + goto err_gem_free;
> + }
> + dma_buf = dma_heap_buffer_alloc(dma_heap, size,
> + O_RDWR | O_CLOEXEC, 
> DMA_HEAP_VALID_HEAP_FLAGS);
> + if (IS_ERR(dma_buf)) {
> + DRM_ERROR("buffer alloc fail\n");
> + dma_heap_put(dma_heap);
> + goto err_gem_free;
> + }
> + dma_heap_put(dma_heap);
> +
> + attach = dma_buf_attach(dma_buf, priv->dma_dev);
> + if (IS_ERR(attach)) {
> + DRM_ERROR("attach fail, return\n");
> + dma_buf_put(dma_buf);
> + goto err_gem_free;
> + }
> +
> + sgt = dma_buf_map_attachment(attach, DMA_BIDIRECTIONAL);
> + if (IS_ERR(sgt)) {
> + DRM_ERROR("map failed, detach and return\n");
> + dma_buf_detach(dma_buf, attach);
> + dma_buf_put(dma_buf);
> + goto err_gem_free;
> + }
> + obj->import_attach = attach;
> + mtk_gem->dma_addr = sg_dma_address(sgt->sgl);
> + mtk_gem->sg = sgt;
> + mtk_gem->size = dma_buf->size;
> +
> + if (!strcmp(heap, "mtk_svp") || !strcmp(heap, "mtk_svp_cma")) {
> + /* secure buffer can not be mapped */
> + mtk_gem->secure = true;
> + } else {
> + ret = dma_buf_vmap(dma_buf, );
> + mtk_gem->kvaddr = map.vaddr;
> + if (ret) {
> + DRM_ERROR("map failed, ret=%d\n", ret);
> + dma_buf_unmap_attachment(attach, sgt, 
> DMA_BIDIRECTIONAL);
> + dma_buf_detach(dma_buf, attach);
> + dma_buf_put(dma_buf);
> + mtk_gem->kvaddr = NULL;
> + }
> + }
> +
> + return mtk_gem;
> +
> +err_gem_free:
> + drm_gem_object_release(obj);
> + kfree(mtk_gem);
> + return ERR_PTR(-ENOMEM);
> +}
> +
>  void mtk_gem_free_object(struct drm_gem_object *obj)
>  {
>   struct mtk_gem_obj *mtk_gem = to_mtk_gem_obj(obj);
> @@ -229,7 +306,9 @@ struct drm_gem_object 
> *mtk_gem_prime_import_sg_table(struct drm_device *dev,
>   if (IS_ERR(mtk_gem))
>   return ERR_CAST(mtk_gem);
>  
> + mtk_gem->secure = !sg_page(sg->sgl);
>   mtk_gem->dma_addr = sg_dma_address(sg->sgl);
> + mtk_gem->size = attach->dmabuf->size;
>   mtk_gem->sg = sg;
>  
>   return _gem->base;
> @@ -304,7 +383,11 @@ int mtk_gem_create_ioctl(struct drm_device *dev, void 
> *data,
>   struct drm_mtk_gem_create *args = data;
>   int ret;
>  
> - mtk_gem = mtk_gem_create(dev, args->size, false);
> + if (args->flags & DRM_MTK_GEM_CREATE_ENCRYPTED)
> + mtk_gem = mtk_gem_create_from_heap(dev, "mtk_svp_cma", 
> args->size);

That heap doesn't exist upstream either. Also, I'm wondering if it's the
right solution there.

From what I can tell, you want to allow to create encrypted buffers from
the TEE. Why do we need this as a DRM ioctl at all? A heap seems like
the perfect solution to do so, and then you just have to import it into
DRM.

I'm also not entirely sure that not having a SG list is enough to
consider the buffer secure. Wouldn't a buffer allocated without a kernel
mapping also be in that situation?

Maxime


signature.asc

Re: [PATCH v5 1/9] drm/mediatek/uapi: Add DRM_MTK_GEM_CREATE_ENCRYPTED flag

2024-04-15 Thread Maxime Ripard
Hi,

On Wed, Apr 03, 2024 at 06:26:53PM +0800, Shawn Sung wrote:
> From: "Jason-JH.Lin" 
> 
> Add DRM_MTK_GEM_CREATE_ENCRYPTED flag to allow user to allocate
> a secure buffer to support secure video path feature.
> 
> Signed-off-by: Jason-JH.Lin 
> Signed-off-by: Hsiao Chien Sung 
> ---
>  include/uapi/drm/mediatek_drm.h | 1 +
>  1 file changed, 1 insertion(+)
> 
> diff --git a/include/uapi/drm/mediatek_drm.h b/include/uapi/drm/mediatek_drm.h
> index b0dea00bacbc4..e9125de3a24ad 100644
> --- a/include/uapi/drm/mediatek_drm.h
> +++ b/include/uapi/drm/mediatek_drm.h
> @@ -54,6 +54,7 @@ struct drm_mtk_gem_map_off {
>  
>  #define DRM_MTK_GEM_CREATE   0x00
>  #define DRM_MTK_GEM_MAP_OFFSET   0x01
> +#define DRM_MTK_GEM_CREATE_ENCRYPTED 0x02
>  
>  #define DRM_IOCTL_MTK_GEM_CREATE DRM_IOWR(DRM_COMMAND_BASE + \
>   DRM_MTK_GEM_CREATE, struct drm_mtk_gem_create)

That flag doesn't exist in drm-misc-next, which tree is this based on?

Maxime


signature.asc
Description: PGP signature


Re: (subset) [PATCH] drm: fix DRM_DISPLAY_DP_HELPER dependencies, part 2

2024-04-15 Thread Maxime Ripard
On Fri, 05 Apr 2024 16:35:10 +0200, Arnd Bergmann wrote:
> After my fix yesterday, I ran into another problem of the same kind:
> 
> aarch64-linux-ld: drivers/gpu/drm/bridge/analogix/analogix_dp_core.o: in 
> function `drm_dp_dpcd_readb':
> analogix_dp_core.c:(.text+0x194): undefined reference to `drm_dp_dpcd_read'
> aarch64-linux-ld: drivers/gpu/drm/bridge/analogix/analogix_dp_core.o: in 
> function `drm_dp_dpcd_writeb':
> analogix_dp_core.c:(.text+0x214): undefined reference to `drm_dp_dpcd_write'
> aarch64-linux-ld: drivers/gpu/drm/bridge/analogix/analogix_dp_core.o: in 
> function `analogix_dp_stop_crc':
> analogix_dp_core.c:(.text+0x4b0): undefined reference to `drm_dp_stop_crc'
> aarch64-linux-ld: drivers/gpu/drm/bridge/analogix/analogix_dp_core.o: in 
> function `analogix_dp_start_crc':
> analogix_dp_core.c:(.text+0xbe8): undefined reference to `drm_dp_start_crc'
> 
> [...]

Applied to misc/kernel.git (drm-misc-next).

Thanks!
Maxime



Re: (subset) [PATCH] drm: vc4: Fix possible null pointer dereference

2024-04-15 Thread Maxime Ripard
On Tue, 09 Apr 2024 10:56:22 +0300, Aleksandr Mishin wrote:
> In vc4_hdmi_audio_init() of_get_address() may return
> NULL which is later dereferenced. Fix this bug by adding NULL check.
> 
> Found by Linux Verification Center (linuxtesting.org) with SVACE.
> 
> 

Applied to misc/kernel.git (drm-misc-next).

Thanks!
Maxime



Re: (subset) [PATCH v2] drm: Document requirements for driver-specific KMS props in new drivers

2024-04-15 Thread Maxime Ripard
On Wed, 10 Apr 2024 14:20:06 +0200, Sebastian Wick wrote:
> When extending support for a driver-specific KMS property to additional
> drivers, we should apply all the requirements for new properties and
> make sure the semantics are the same and documented.
> 
> v2: devs of the driver which introduced property shall help and ack
> 
> 
> [...]

Applied to misc/kernel.git (drm-misc-next).

Thanks!
Maxime



Re: [PATCH] drm/bridge: sii902x: Fix mode_valid hook

2024-04-15 Thread Maxime Ripard
Hi,

On Mon, Apr 08, 2024 at 01:44:35PM +0530, Jayesh Choudhary wrote:
> Currently, mode_valid hook returns all mode as valid. Add the check
> for the maximum and minimum pixel clock that the bridge can support
> while validating a mode.
> 
> Signed-off-by: Jayesh Choudhary 
> ---
>  drivers/gpu/drm/bridge/sii902x.c | 16 +++-
>  1 file changed, 15 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/gpu/drm/bridge/sii902x.c 
> b/drivers/gpu/drm/bridge/sii902x.c
> index 8f84e98249c7..658819199c84 100644
> --- a/drivers/gpu/drm/bridge/sii902x.c
> +++ b/drivers/gpu/drm/bridge/sii902x.c
> @@ -163,6 +163,16 @@
>  
>  #define SII902X_AUDIO_PORT_INDEX 3
>  
> +/*
> + * The maximum resolution supported by the HDMI bridge is 1080p@60Hz
> + * and 1920x1200 requiring a pixel clock of 165MHz and the minimum
> + * resolution supported is 480p@60Hz requiring a pixel clock of 25MHz
> + *
> + * (drm_display_mode clock is in kHz)
> + */
> +#define SII902X_MIN_PIXEL_CLOCK  25000
> +#define SII902X_MAX_PIXEL_CLOCK  165000
> +

You should probably add a KHZ suffix or something to make it obvious.
The natural unit for a frequency is Hertz.

>  struct sii902x {
>   struct i2c_client *i2c;
>   struct regmap *regmap;
> @@ -313,7 +323,11 @@ static int sii902x_get_modes(struct drm_connector 
> *connector)
>  static enum drm_mode_status sii902x_mode_valid(struct drm_connector 
> *connector,
>  struct drm_display_mode *mode)
>  {
> - /* TODO: check mode */
> + if (mode->clock < SII902X_MIN_PIXEL_CLOCK)
> + return MODE_CLOCK_LOW;
> +
> + if (mode->clock > SII902X_MAX_PIXEL_CLOCK)
> + return MODE_CLOCK_HIGH;
>  
>   return MODE_OK;
>  }

It's something you should do in atomic_check too

Maxime


signature.asc
Description: PGP signature


Re: [PATCH v2 01/43] drm/fbdev-generic: Do not set physical framebuffer address

2024-04-15 Thread Maxime Ripard
On Wed, 10 Apr 2024 15:01:57 +0200, Thomas Zimmermann wrote:
> Framebuffer memory is allocated via vzalloc() from non-contiguous
> physical pages. The physical framebuffer start address is therefore
> meaningless. Do not set it.
> 
> The value is not used within the kernel and only exported to userspace
> 
> [ ... ]

Acked-by: Maxime Ripard 

Thanks!
Maxime


Re: (subset) [PATCH v2 1/1] Revert "drm/qxl: simplify qxl_fence_wait"

2024-04-05 Thread Maxime Ripard
On Thu, 04 Apr 2024 19:14:48 +0100, Alex Constantino wrote:
> This reverts commit 5a838e5d5825c85556011478abde708251cc0776.
> 
> Changes from commit 5a838e5d5825 ("drm/qxl: simplify qxl_fence_wait") would
> result in a '[TTM] Buffer eviction failed' exception whenever it reached a
> timeout.
> Due to a dependency to DMA_FENCE_WARN this also restores some code deleted
> by commit d72277b6c37d ("dma-buf: nuke DMA_FENCE_TRACE macros v2").
> 
> [...]

Applied to misc/kernel.git (drm-misc-fixes).

Thanks!
Maxime



Re: (subset) [PATCH 2/7] drm/bridge: dw-hdmi: Make DRM_DW_HDMI selectable

2024-04-05 Thread Maxime Ripard
On Wed, 03 Apr 2024 12:56:20 +0200, Maxime Ripard wrote:
> Commit c0e0f139354c ("drm: Make drivers depends on DRM_DW_HDMI") turned
> select dependencies into depends on ones. However, DRM_DW_HDMI was not
> manually selectable which resulted in no way to enable the drivers that
> were now depending on it.
> 
> 

Applied to misc/kernel.git (drm-misc-next).

Thanks!
Maxime



Re: (subset) [PATCH 1/7] drm/display: Select DRM_KMS_HELPER for DP helpers

2024-04-05 Thread Maxime Ripard
On Wed, 03 Apr 2024 12:56:19 +0200, Maxime Ripard wrote:
> The DisplayPort helpers rely on some
> (__drm_atomic_helper_private_obj_duplicate_state,
> drm_kms_helper_hotplug_event) helpers found in files compiled by
> DRM_KMS_HELPER.
> 
> Prior to commit d674858ff979 ("drm/display: Make all helpers visible and
> switch to depends on"), DRM_DISPLAY_DP_HELPER was only selectable so it
> wasn't really a big deal. However, since that commit, it's now something
> that can be enabled as is, and since there's no expressed dependency
> with DRM_KMS_HELPER, it can break too.
> 
> [...]

Applied to misc/kernel.git (drm-misc-next).

Thanks!
Maxime



Re: [PATCH] drm: fix DRM_DISPLAY_DP_HELPER dependencies

2024-04-04 Thread Maxime Ripard
On Thu, 04 Apr 2024 14:40:51 +0200, Arnd Bergmann wrote:
> Both the exynos and rockchip drivers ran into link failures after
> a Kconfig cleanup:
> 
> aarch64-linux-ld: drivers/gpu/drm/exynos/exynos_dp.o: in function 
> `exynos_dp_resume':
> exynos_dp.c:(.text+0xc0): undefined reference to `analogix_dp_resume'
> aarch64-linux-ld: drivers/gpu/drm/exynos/exynos_dp.o: in function 
> `exynos_dp_suspend':
> exynos_dp.c:(.text+0xf4): undefined reference to `analogix_dp_suspend'
> 
> [...]

Applied to misc/kernel.git (drm-misc-next).

Thanks!
Maxime



[PATCH 7/7] mips: configs: ci20: Enable DRM_DW_HDMI

2024-04-03 Thread Maxime Ripard
Commit 4fc8cb47fcfd ("drm/display: Move HDMI helpers into display-helper
module") turned the DRM_DW_HDMI dependency of DRM_INGENIC_DW_HDMI into a
depends on which ended up disabling the drivers in the defconfig. Make
sure it's still enabled.

Fixes: 4fc8cb47fcfd ("drm/display: Move HDMI helpers into display-helper 
module")
Reported-by: Mark Brown 
Reported-by: Alexander Stein 
Signed-off-by: Maxime Ripard 
---
 arch/mips/configs/ci20_defconfig | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/mips/configs/ci20_defconfig b/arch/mips/configs/ci20_defconfig
index cdf2a782dee1..0b1c17a650e4 100644
--- a/arch/mips/configs/ci20_defconfig
+++ b/arch/mips/configs/ci20_defconfig
@@ -120,10 +120,11 @@ CONFIG_RC_DEVICES=y
 CONFIG_IR_GPIO_CIR=m
 CONFIG_IR_GPIO_TX=m
 CONFIG_MEDIA_SUPPORT=m
 CONFIG_DRM=m
 CONFIG_DRM_DISPLAY_CONNECTOR=m
+CONFIG_DRM_DW_HDMI=m
 CONFIG_DRM_INGENIC=m
 CONFIG_DRM_INGENIC_DW_HDMI=m
 CONFIG_FB=y
 # CONFIG_VGA_CONSOLE is not set
 CONFIG_FRAMEBUFFER_CONSOLE=y

-- 
2.44.0



[PATCH 6/7] arm64: defconfig: Enable DRM_DW_HDMI

2024-04-03 Thread Maxime Ripard
Commit 4fc8cb47fcfd ("drm/display: Move HDMI helpers into display-helper
module") turned the DRM_DW_HDMI dependency of ROCKCHIP_DW_HDMI,
DRM_RCAR_DW_HDMI and DRM_IMX8MP_DW_HDMI_BRIDGE into a depends on which
ended up disabling the drivers in the defconfig. Make sure it's still
enabled.

Fixes: 4fc8cb47fcfd ("drm/display: Move HDMI helpers into display-helper 
module")
Reported-by: Mark Brown 
Reported-by: Alexander Stein 
Signed-off-by: Maxime Ripard 
---
 arch/arm64/configs/defconfig | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig
index 94e677800899..6c223541e4f0 100644
--- a/arch/arm64/configs/defconfig
+++ b/arch/arm64/configs/defconfig
@@ -894,10 +894,11 @@ CONFIG_DRM_TI_SN65DSI86=m
 CONFIG_DRM_ANALOGIX_ANX7625=m
 CONFIG_DRM_I2C_ADV7511=m
 CONFIG_DRM_I2C_ADV7511_AUDIO=y
 CONFIG_DRM_CDNS_MHDP8546=m
 CONFIG_DRM_IMX8MP_DW_HDMI_BRIDGE=m
+CONFIG_DRM_DW_HDMI=m
 CONFIG_DRM_DW_HDMI_AHB_AUDIO=m
 CONFIG_DRM_DW_HDMI_CEC=m
 CONFIG_DRM_IMX_DCSS=m
 CONFIG_DRM_V3D=m
 CONFIG_DRM_VC4=m

-- 
2.44.0



[PATCH 5/7] ARM: configs: sunxi: Enable DRM_DW_HDMI

2024-04-03 Thread Maxime Ripard
Commit 4fc8cb47fcfd ("drm/display: Move HDMI helpers into display-helper
module") turned the DRM_DW_HDMI dependency of DRM_SUN8I_DW_HDMI into a
depends on which ended up disabling the driver in the defconfig. Make
sure it's still enabled.

Fixes: 4fc8cb47fcfd ("drm/display: Move HDMI helpers into display-helper 
module")
Reported-by: Mark Brown 
Reported-by: Alexander Stein 
Signed-off-by: Maxime Ripard 
---
 arch/arm/configs/sunxi_defconfig | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm/configs/sunxi_defconfig b/arch/arm/configs/sunxi_defconfig
index bddc82f78942..a83d29fed175 100644
--- a/arch/arm/configs/sunxi_defconfig
+++ b/arch/arm/configs/sunxi_defconfig
@@ -108,10 +108,11 @@ CONFIG_DRM_SUN4I_HDMI_CEC=y
 CONFIG_DRM_SUN8I_DW_HDMI=y
 CONFIG_DRM_PANEL_LVDS=y
 CONFIG_DRM_PANEL_SIMPLE=y
 CONFIG_DRM_PANEL_EDP=y
 CONFIG_DRM_SIMPLE_BRIDGE=y
+CONFIG_DRM_DW_HDMI=y
 CONFIG_DRM_LIMA=y
 CONFIG_FB_SIMPLE=y
 CONFIG_BACKLIGHT_CLASS_DEVICE=y
 CONFIG_BACKLIGHT_PWM=y
 CONFIG_SOUND=y

-- 
2.44.0



[PATCH 4/7] ARM: configs: multi_v7: Enable DRM_DW_HDMI

2024-04-03 Thread Maxime Ripard
Commit 4fc8cb47fcfd ("drm/display: Move HDMI helpers into display-helper
module") turned the DRM_DW_HDMI dependency of DRM_IMX_HDMI,
and ROCKCHIP_DW_HDMI into a depends on which ended up disabling the
drivers in the defconfig. Make sure it's still enabled.

Fixes: 4fc8cb47fcfd ("drm/display: Move HDMI helpers into display-helper 
module")
Reported-by: Mark Brown 
Reported-by: Alexander Stein 
Signed-off-by: Maxime Ripard 
---
 arch/arm/configs/multi_v7_defconfig | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm/configs/multi_v7_defconfig 
b/arch/arm/configs/multi_v7_defconfig
index 86bf057ac366..9aac9610dd86 100644
--- a/arch/arm/configs/multi_v7_defconfig
+++ b/arch/arm/configs/multi_v7_defconfig
@@ -756,10 +756,11 @@ CONFIG_DRM_TOSHIBA_TC358764=m
 CONFIG_DRM_TOSHIBA_TC358768=m
 CONFIG_DRM_TI_TFP410=m
 CONFIG_DRM_TI_TPD12S015=m
 CONFIG_DRM_I2C_ADV7511=m
 CONFIG_DRM_I2C_ADV7511_AUDIO=y
+CONFIG_DRM_DW_HDMI=m
 CONFIG_DRM_STI=m
 CONFIG_DRM_IMX=m
 CONFIG_DRM_IMX_PARALLEL_DISPLAY=m
 CONFIG_DRM_IMX_TVE=m
 CONFIG_DRM_IMX_LDB=m

-- 
2.44.0



[PATCH 3/7] ARM: configs: imx_v6_v7: Enable DRM_DW_HDMI

2024-04-03 Thread Maxime Ripard
Commit 4fc8cb47fcfd ("drm/display: Move HDMI helpers into display-helper
module") turned the DRM_DW_HDMI dependency of DRM_IMX_HDMI into a
depends on which ended up disabling the driver in the defconfig. Make
sure it's still enabled.

Fixes: 4fc8cb47fcfd ("drm/display: Move HDMI helpers into display-helper 
module")
Reported-by: Mark Brown 
Reported-by: Alexander Stein 
Signed-off-by: Maxime Ripard 
---
 arch/arm/configs/imx_v6_v7_defconfig | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm/configs/imx_v6_v7_defconfig 
b/arch/arm/configs/imx_v6_v7_defconfig
index 7327fce87808..294c0c3df370 100644
--- a/arch/arm/configs/imx_v6_v7_defconfig
+++ b/arch/arm/configs/imx_v6_v7_defconfig
@@ -281,10 +281,11 @@ CONFIG_DRM_MSM=y
 CONFIG_DRM_PANEL_LVDS=y
 CONFIG_DRM_PANEL_SIMPLE=y
 CONFIG_DRM_PANEL_EDP=y
 CONFIG_DRM_PANEL_SEIKO_43WVF1G=y
 CONFIG_DRM_TI_TFP410=y
+CONFIG_DRM_DW_HDMI=y
 CONFIG_DRM_DW_HDMI_AHB_AUDIO=m
 CONFIG_DRM_DW_HDMI_CEC=y
 CONFIG_DRM_IMX=y
 CONFIG_DRM_IMX_PARALLEL_DISPLAY=y
 CONFIG_DRM_IMX_TVE=y

-- 
2.44.0



[PATCH 2/7] drm/bridge: dw-hdmi: Make DRM_DW_HDMI selectable

2024-04-03 Thread Maxime Ripard
Commit c0e0f139354c ("drm: Make drivers depends on DRM_DW_HDMI") turned
select dependencies into depends on ones. However, DRM_DW_HDMI was not
manually selectable which resulted in no way to enable the drivers that
were now depending on it.

Fixes: 4fc8cb47fcfd ("drm/display: Move HDMI helpers into display-helper 
module")
Reported-by: Mark Brown 
Reported-by: Alexander Stein 
Signed-off-by: Maxime Ripard 
---
 drivers/gpu/drm/bridge/synopsys/Kconfig | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/bridge/synopsys/Kconfig 
b/drivers/gpu/drm/bridge/synopsys/Kconfig
index 387f5bd86089..1252fd30d4a4 100644
--- a/drivers/gpu/drm/bridge/synopsys/Kconfig
+++ b/drivers/gpu/drm/bridge/synopsys/Kconfig
@@ -1,8 +1,8 @@
 # SPDX-License-Identifier: GPL-2.0-only
 config DRM_DW_HDMI
-   tristate
+   tristate "Synopsys Designware HDMI TX Controller"
depends on DRM_DISPLAY_HDMI_HELPER
depends on DRM_DISPLAY_HELPER
select DRM_KMS_HELPER
select REGMAP_MMIO
select CEC_CORE if CEC_NOTIFIER

-- 
2.44.0



[PATCH 1/7] drm/display: Select DRM_KMS_HELPER for DP helpers

2024-04-03 Thread Maxime Ripard
The DisplayPort helpers rely on some
(__drm_atomic_helper_private_obj_duplicate_state,
drm_kms_helper_hotplug_event) helpers found in files compiled by
DRM_KMS_HELPER.

Prior to commit d674858ff979 ("drm/display: Make all helpers visible and
switch to depends on"), DRM_DISPLAY_DP_HELPER was only selectable so it
wasn't really a big deal. However, since that commit, it's now something
that can be enabled as is, and since there's no expressed dependency
with DRM_KMS_HELPER, it can break too.

Since DRM_KMS_HELPER is a selectable option for now, let's select it for
DRM_DISPLAY_DP_HELPER.

Reported-by: kernel test robot 
Closes: 
https://lore.kernel.org/oe-kbuild-all/202404021556.0jvcnc13-...@intel.com/
Closes: 
https://lore.kernel.org/oe-kbuild-all/202404021700.lbyyzgfd-...@intel.com/
Fixes: d674858ff979 ("drm/display: Make all helpers visible and switch to 
depends on")
Signed-off-by: Maxime Ripard 
---
 drivers/gpu/drm/display/Kconfig | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/gpu/drm/display/Kconfig b/drivers/gpu/drm/display/Kconfig
index 01f2a231aa5f..a38962a556c2 100644
--- a/drivers/gpu/drm/display/Kconfig
+++ b/drivers/gpu/drm/display/Kconfig
@@ -37,10 +37,11 @@ config DRM_DISPLAY_DP_AUX_CHARDEV
  channel.
 
 config DRM_DISPLAY_DP_HELPER
bool "DRM DisplayPort Helpers"
depends on DRM_DISPLAY_HELPER
+   select DRM_KMS_HELPER
default y
help
  DRM display helpers for DisplayPort.
 
 config DRM_DISPLAY_DP_TUNNEL

-- 
2.44.0



[PATCH 0/7] drm/display: Fix display helpers depends on fallouts

2024-04-03 Thread Maxime Ripard
Hi,

Here's a series addressing the various regressions that were reported
after the Kconfig rework for the DRM display helpers.

Let me know what you think,
Maxime

Signed-off-by: Maxime Ripard 
---
Maxime Ripard (7):
  drm/display: Select DRM_KMS_HELPER for DP helpers
  drm/bridge: dw-hdmi: Make DRM_DW_HDMI selectable
  ARM: configs: imx_v6_v7: Enable DRM_DW_HDMI
  ARM: configs: multi_v7: Enable DRM_DW_HDMI
  ARM: configs: sunxi: Enable DRM_DW_HDMI
  arm64: defconfig: Enable DRM_DW_HDMI
  mips: configs: ci20: Enable DRM_DW_HDMI

 arch/arm/configs/imx_v6_v7_defconfig| 1 +
 arch/arm/configs/multi_v7_defconfig | 1 +
 arch/arm/configs/sunxi_defconfig| 1 +
 arch/arm64/configs/defconfig| 1 +
 arch/mips/configs/ci20_defconfig| 1 +
 drivers/gpu/drm/bridge/synopsys/Kconfig | 2 +-
 drivers/gpu/drm/display/Kconfig | 1 +
 7 files changed, 7 insertions(+), 1 deletion(-)
---
base-commit: 727900b675b749c40ba1f6669c7ae5eb7eb8e837
change-id: 20240403-fix-dw-hdmi-kconfig-068b121eeae7

Best regards,
-- 
Maxime Ripard 



Re: [PATCH v3 00/13] drm/display: Convert helpers Kconfig symbols to depends on

2024-03-28 Thread Maxime Ripard
On Wed, 27 Mar 2024 11:56:55 +0100, Maxime Ripard wrote:
> Jani recently pointed out that the Kconfig symbols are a bit difficult
> to work with at the moment when they depend on each other, and that
> using depends on would be a better idea, but no one really did the work
> so far.
> 
> So here it goes :)
> 
> [...]

Applied to misc/kernel.git (drm-misc-next).

Thanks!
Maxime



Re: [PATCH 1/2] drm/qxl: remove unused `count` variable from `qxl_surface_id_alloc()`

2024-03-28 Thread Maxime Ripard
On Wed, Mar 27, 2024 at 07:14:12PM +0100, Miguel Ojeda wrote:
> On Wed, Mar 27, 2024 at 6:56 PM Miguel Ojeda  wrote:
> >
> > Closes: 
> > https://lore.kernel.org/lkml/caniq72mjc5t4n25sqvysroehxxpxypz4ppznesjhenc3qap...@mail.gmail.com/
> 
> Should have a [1] at the end.

I added it while committing

> > Signed-off-by: Miguel Ojeda 
> > ---
> > Given there is a loop going on here, it would be good to double-check 
> > whether
> > this variable was supposed to be used for something useful or if it was 
> > just a
> > remnant of a version previous to v1.4.
> 
> Also, I see Nathan sent meanwhile a message about these two that were
> also mentioned/reported a while ago [1].

"a while ago" here being 2 hours before your message :)

I've added a Closes tag for that report too.

I've applied both patches to drm-misc-fixes, thanks!
Maxime


signature.asc
Description: PGP signature


Re: [PATCH 1/1] drm/qxl: fixes qxl_fence_wait

2024-03-27 Thread Maxime Ripard
Hi,

On Wed, Mar 20, 2024 at 04:25:48PM +0100, Linux regression tracking (Thorsten 
Leemhuis) wrote:
> On 08.03.24 02:08, Alex Constantino wrote:
> > Fix OOM scenario by doing multiple notifications to the OOM handler through
> > a busy wait logic.
> > Changes from commit 5a838e5d5825 ("drm/qxl: simplify qxl_fence_wait") would
> > result in a '[TTM] Buffer eviction failed' exception whenever it reached a
> > timeout.
> > 
> > Fixes: 5a838e5d5825 ("drm/qxl: simplify qxl_fence_wait")
> > Link: 
> > https://lore.kernel.org/regressions/fb0fda6a-3750-4e1b-893f-97a3e402b...@leemhuis.info
> > Reported-by: Timo Lindfors 
> > Closes: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1054514
> > Signed-off-by: Alex Constantino 
> > ---
> >  drivers/gpu/drm/qxl/qxl_release.c | 20 ++--
> >  1 file changed, 14 insertions(+), 6 deletions(-)
> 
> Hey Dave and Gerd as well as Thomas, Maarten and Maxime (the latter two
> I just added to the CC), it seems to me this regression fix did not
> maybe any progress since it was posted. Did I miss something, is it just
> "we are busy with the merge window", or is there some other a reason?
> Just wondering, I just saw someone on a Fedora IRC channel complaining
> about the regression, that's why I'm asking. Would be really good to
> finally get this resolved...

I've ping'd Gerd last week about it, but he couldn't remember the
details of why that patch was warranted in the first place.

If it works, I'd prefer to revert the original patch that we know used
to work instead of coming up with some less proven logic, which seems to
be quite different to what it used to be.

Alex, could you try reverting 5a838e5d5825c85556011478abde708251cc0776
and letting us know the result?

Thanks!
Maxime


signature.asc
Description: PGP signature


Re: [PATCH 4/4] drm/bridge: hotplug-bridge: add driver to support hot-pluggable DSI bridges

2024-03-27 Thread Maxime Ripard
On Tue, Mar 26, 2024 at 05:28:14PM +0100, Luca Ceresoli wrote:
> This driver implements the point of a DRM pipeline where a connector allows
> removal of all the following bridges up to the panel.
> 
> The DRM subsystem currently allows hotplug of the monitor but not preceding
> components. However there are embedded devices where the "tail" of the DRM
> pipeline, including one or more bridges, can be physically removed:
> 
>  ..
>  |   DISPLAY CONTROLLER   |
>  | .-.   .--. |
>  | | ENCODER |<--| CRTC | |
>  | '-'   '--' |
>  '--|-'
> |
> |   HOTPLUG
> V  CONNECTOR
>.-..--..-..-. .---.
>| 0 to N  || _|   _| || 1 to N  | |   |
>| BRIDGES |--DSI-->||_   |_  |--DSI-->| BRIDGES |--LVDS-->| PANEL |
>| ||  || || | |   |
>'-''--''-''-' '---'
> 
>  [--- fixed components --]  [--- removable add-on ---]
> 
> This driver supports such devices, where the final segment of a MIPI DSI
> bus, including one or more bridges, can be physically disconnected and
> reconnected at runtime, possibly with a different model.
> 
> This implementation supports a MIPI DSI bus only, but it is designed to be
> as far as possible generic and extendable to other busses that have no
> native hotplug and model ID discovery.
>
> This driver does not provide facilities to add and remove the hot-pluggable
> components from the kernel: this needs to be done by other means
> (e.g. device tree overlay runtime insertion and removal). The
> hotplug-bridge gets notified of hot-plugging by the DRM bridge notifier
> callbacks after they get added or before they get removed.
> 
> The hotplug-bridge role is to implement the "hot-pluggable connector" in
> the bridge chain. In this position, what the hotplug-bridge should ideally
> do is:
> 
>  * communicate with the previous component (bridge or encoder) so that it
>believes it always has a connected bridge following it and the DRM card
>is always present
>  * be notified of the addition and removal of the following bridge and
>attach/detach to/from it
>  * communicate with the following bridge so that it will attach and detach
>using the normal procedure (as if the entire pipeline were being created
>or destroyed, not only the tail)
>  * expose the "add-on connected/disconnected" status via the DRM connector
>connected/disconnected status, so that users of the DRM pipeline know
>when they can render output on the display
> 
> However some aspects make it a bit more complex than that. Most notably:
> 
>  * the next bridge can be probed and removed at any moment and all probing
>sequences need to be handled
>  * the DSI host/device registration process, which adds to the DRM bridge
>attach process, makes the initial card registration tricky
>  * the need to register and deregister the following bridges at runtime
>without tearing down the whole DRM card prevents using the functions
>that are normally recommended
>  * the automatic mechanism to call the appropriate .get_modes operation
>(typically provided by the panel bridge) cannot work as the panel can
>disappear and reappear as a different model, so an ad-hoc lookup is
>needed

There's several additional hurdles there:

 - You mentioned the connector in your ideal scenario. But as soon as
   you remove the last bridge, the connector will probably go away too.
   There's two scenarii here then:

   - The driver is ok, and it will stay there until the last user its to
 the main DRM device. Which means that if you create a new one,
 you'll have the old one and the new one together, but you can't
 tell which one you're supposed to use.

   - If the driver isn't ok, the connector will be freed immediately.
 There's plenty of lingering pointers in the framework, and
 especially the states though, leading to use-after-free errors.

 - So far, we told everyone that the graphics pipeline wasn't going to
   change. How do you expect applications to deal with a connector going
   away without any regression? I guess the natural thing here would be
   to emit a uevent just like we do when the connection status change,
   but the thing is: we're doing that for the connector, and the
   connector is gone.

Between the userspace expectations and the memory-safety issue plaguing
way too many drivers, I'm not sure this approach can work.

I guess one way to somewhat achieve what you're trying to do would be to
introduce the connection status at the bridge level, reflect the
aggregate connection status of all bridges on the connector, and make
each bridge driver probe its device in the connect hook through DCS or
I2C.

We wouldn't be able to change the bridge halfway through 

[PATCH v3 13/13] drm/bridge: it6505: Remove useless select

2024-03-27 Thread Maxime Ripard
The IT6505 bridge Kconfig symbol selects a Kconfig symbol that doesn't
exist. Remove it.

Reviewed-by: Jani Nikula 
Signed-off-by: Maxime Ripard 
---
 drivers/gpu/drm/bridge/Kconfig | 1 -
 1 file changed, 1 deletion(-)

diff --git a/drivers/gpu/drm/bridge/Kconfig b/drivers/gpu/drm/bridge/Kconfig
index 6e6ec300ab16..d1fbf8796fea 100644
--- a/drivers/gpu/drm/bridge/Kconfig
+++ b/drivers/gpu/drm/bridge/Kconfig
@@ -96,11 +96,10 @@ config DRM_ITE_IT6505
depends on DRM_DISPLAY_DP_HELPER
depends on DRM_DISPLAY_HDCP_HELPER
depends on DRM_DISPLAY_HELPER
depends on OF
select DRM_KMS_HELPER
-   select DRM_DP_HELPER
select EXTCON
select CRYPTO
select CRYPTO_HASH
help
  ITE IT6505 DisplayPort bridge chip driver.

-- 
2.44.0



[PATCH v3 07/13] drm: Make drivers depends on DRM_DW_HDMI

2024-03-27 Thread Maxime Ripard
DRM_DW_HDMI has a number of dependencies that might not be enabled.
However, drivers were used to selecting it while not enforcing the
DRM_DW_HDMI dependencies.

This could result in Kconfig warnings (and further build breakages) such
as:

  Kconfig warnings: (for reference only)
 WARNING: unmet direct dependencies detected for DRM_DW_HDMI
 Depends on [n]: HAS_IOMEM [=y] && DRM [=m] && DRM_BRIDGE [=y] && 
DRM_DISPLAY_HELPER [=n]
 Selected by [m]:
 - DRM_SUN8I_DW_HDMI [=m] && HAS_IOMEM [=y] && DRM_SUN4I [=m]

Reported-by: kernel test robot 
Closes: 
https://lore.kernel.org/oe-kbuild-all/202403262127.kzkttfnz-...@intel.com/
Signed-off-by: Maxime Ripard 
---
 drivers/gpu/drm/bridge/imx/Kconfig  | 4 ++--
 drivers/gpu/drm/imx/ipuv3/Kconfig   | 5 +++--
 drivers/gpu/drm/ingenic/Kconfig | 2 +-
 drivers/gpu/drm/meson/Kconfig   | 2 +-
 drivers/gpu/drm/renesas/rcar-du/Kconfig | 2 +-
 drivers/gpu/drm/rockchip/Kconfig| 2 +-
 drivers/gpu/drm/sun4i/Kconfig   | 2 +-
 7 files changed, 10 insertions(+), 9 deletions(-)

diff --git a/drivers/gpu/drm/bridge/imx/Kconfig 
b/drivers/gpu/drm/bridge/imx/Kconfig
index 5965e8027529..7687ed652df5 100644
--- a/drivers/gpu/drm/bridge/imx/Kconfig
+++ b/drivers/gpu/drm/bridge/imx/Kconfig
@@ -3,13 +3,13 @@ if ARCH_MXC || COMPILE_TEST
 config DRM_IMX_LDB_HELPER
tristate
 
 config DRM_IMX8MP_DW_HDMI_BRIDGE
tristate "Freescale i.MX8MP HDMI-TX bridge support"
-   depends on OF
depends on COMMON_CLK
-   select DRM_DW_HDMI
+   depends on DRM_DW_HDMI
+   depends on OF
select DRM_IMX8MP_HDMI_PVI
select PHY_FSL_SAMSUNG_HDMI_PHY
help
  Choose this to enable support for the internal HDMI encoder found
  on the i.MX8MP SoC.
diff --git a/drivers/gpu/drm/imx/ipuv3/Kconfig 
b/drivers/gpu/drm/imx/ipuv3/Kconfig
index bacf0655ebaf..5d810ac02171 100644
--- a/drivers/gpu/drm/imx/ipuv3/Kconfig
+++ b/drivers/gpu/drm/imx/ipuv3/Kconfig
@@ -33,9 +33,10 @@ config DRM_IMX_LDB
  Choose this to enable the internal LVDS Display Bridge (LDB)
  found on i.MX53 and i.MX6 processors.
 
 config DRM_IMX_HDMI
tristate "Freescale i.MX DRM HDMI"
-   select DRM_DW_HDMI
-   depends on DRM_IMX && OF
+   depends on DRM_DW_HDMI
+   depends on DRM_IMX
+   depends on OF
help
  Choose this if you want to use HDMI on i.MX6.
diff --git a/drivers/gpu/drm/ingenic/Kconfig b/drivers/gpu/drm/ingenic/Kconfig
index 3db117c5edd9..23effeb2ac72 100644
--- a/drivers/gpu/drm/ingenic/Kconfig
+++ b/drivers/gpu/drm/ingenic/Kconfig
@@ -25,12 +25,12 @@ config DRM_INGENIC_IPU
 
  The Image Processing Unit (IPU) will appear as a second primary plane.
 
 config DRM_INGENIC_DW_HDMI
tristate "Ingenic specific support for Synopsys DW HDMI"
+   depends on DRM_DW_HDMI
depends on MACH_JZ4780
-   select DRM_DW_HDMI
help
  Choose this option to enable Synopsys DesignWare HDMI based driver.
  If you want to enable HDMI on Ingenic JZ4780 based SoC, you should
  select this option.
 
diff --git a/drivers/gpu/drm/meson/Kconfig b/drivers/gpu/drm/meson/Kconfig
index 615fdd0ce41b..5520b9e3f010 100644
--- a/drivers/gpu/drm/meson/Kconfig
+++ b/drivers/gpu/drm/meson/Kconfig
@@ -11,13 +11,13 @@ config DRM_MESON
select MESON_CANVAS
select CEC_CORE if CEC_NOTIFIER
 
 config DRM_MESON_DW_HDMI
tristate "HDMI Synopsys Controller support for Amlogic Meson Display"
+   depends on DRM_DW_HDMI
depends on DRM_MESON
default y if DRM_MESON
-   select DRM_DW_HDMI
imply DRM_DW_HDMI_I2S_AUDIO
 
 config DRM_MESON_DW_MIPI_DSI
tristate "MIPI DSI Synopsys Controller support for Amlogic Meson 
Display"
depends on DRM_MESON
diff --git a/drivers/gpu/drm/renesas/rcar-du/Kconfig 
b/drivers/gpu/drm/renesas/rcar-du/Kconfig
index 53c356aed5d5..2dc739db2ba3 100644
--- a/drivers/gpu/drm/renesas/rcar-du/Kconfig
+++ b/drivers/gpu/drm/renesas/rcar-du/Kconfig
@@ -23,12 +23,12 @@ config DRM_RCAR_CMM
depends on DRM_RCAR_USE_CMM
 
 config DRM_RCAR_DW_HDMI
tristate "R-Car Gen3 and RZ/G2 DU HDMI Encoder Support"
depends on DRM && OF
+   depends on DRM_DW_HDMI
depends on DRM_RCAR_DU || COMPILE_TEST
-   select DRM_DW_HDMI
help
  Enable support for R-Car Gen3 or RZ/G2 internal HDMI encoder.
 
 config DRM_RCAR_USE_LVDS
bool "R-Car DU LVDS Encoder Support"
diff --git a/drivers/gpu/drm/rockchip/Kconfig b/drivers/gpu/drm/rockchip/Kconfig
index 1bf3e2829cd0..0d5260e10f27 100644
--- a/drivers/gpu/drm/rockchip/Kconfig
+++ b/drivers/gpu/drm/rockchip/Kconfig
@@ -5,11 +5,10 @@ config DRM_ROCKCHIP
select DRM_GEM_DMA_HELPER
select DRM_KMS_HELPER
select DRM_PANEL
select VIDEOMOD

[PATCH v3 12/13] drm: Switch DRM_DISPLAY_HDMI_HELPER to depends on

2024-03-27 Thread Maxime Ripard
Most of our helpers have relied on being selected so far through
Kconfig, but that creates issues when we have multiple layers of helpers
with some depending on others.

Indeed, select doesn't select a dependency's dependencies, and thus
isn't super intuitive. Depends on however doesn't have that limitation,
so we can just switch all the drivers that were selecting
DRM_DISPLAY_HDMI_HELPER to depend on it.

Reviewed-by: Jani Nikula 
Signed-off-by: Maxime Ripard 
---
 drivers/gpu/drm/amd/amdgpu/Kconfig  | 2 +-
 drivers/gpu/drm/bridge/synopsys/Kconfig | 2 +-
 drivers/gpu/drm/display/Kconfig | 1 +
 drivers/gpu/drm/i915/Kconfig| 2 +-
 drivers/gpu/drm/nouveau/Kconfig | 2 +-
 drivers/gpu/drm/tegra/Kconfig   | 2 +-
 drivers/gpu/drm/vc4/Kconfig | 2 +-
 drivers/gpu/drm/xe/Kconfig  | 2 +-
 8 files changed, 8 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/Kconfig 
b/drivers/gpu/drm/amd/amdgpu/Kconfig
index 1662dc49f18e..b0365cc1374e 100644
--- a/drivers/gpu/drm/amd/amdgpu/Kconfig
+++ b/drivers/gpu/drm/amd/amdgpu/Kconfig
@@ -3,16 +3,16 @@
 config DRM_AMDGPU
tristate "AMD GPU"
depends on DRM
depends on DRM_DISPLAY_DP_HELPER
depends on DRM_DISPLAY_HDCP_HELPER
+   depends on DRM_DISPLAY_HDMI_HELPER
depends on DRM_DISPLAY_HELPER
depends on MMU
depends on PCI
depends on !UML
select FW_LOADER
-   select DRM_DISPLAY_HDMI_HELPER
select DRM_KMS_HELPER
select DRM_SCHED
select DRM_TTM
select DRM_TTM_HELPER
select POWER_SUPPLY
diff --git a/drivers/gpu/drm/bridge/synopsys/Kconfig 
b/drivers/gpu/drm/bridge/synopsys/Kconfig
index f366ece47146..387f5bd86089 100644
--- a/drivers/gpu/drm/bridge/synopsys/Kconfig
+++ b/drivers/gpu/drm/bridge/synopsys/Kconfig
@@ -1,10 +1,10 @@
 # SPDX-License-Identifier: GPL-2.0-only
 config DRM_DW_HDMI
tristate
+   depends on DRM_DISPLAY_HDMI_HELPER
depends on DRM_DISPLAY_HELPER
-   select DRM_DISPLAY_HDMI_HELPER
select DRM_KMS_HELPER
select REGMAP_MMIO
select CEC_CORE if CEC_NOTIFIER
 
 config DRM_DW_HDMI_AHB_AUDIO
diff --git a/drivers/gpu/drm/display/Kconfig b/drivers/gpu/drm/display/Kconfig
index d65f1a37c08c..01f2a231aa5f 100644
--- a/drivers/gpu/drm/display/Kconfig
+++ b/drivers/gpu/drm/display/Kconfig
@@ -72,7 +72,8 @@ config DRM_DISPLAY_HDCP_HELPER
  DRM display helpers for HDCP.
 
 config DRM_DISPLAY_HDMI_HELPER
bool "DRM HDMI Helpers"
depends on DRM_DISPLAY_HELPER
+   default y
help
  DRM display helpers for HDMI.
diff --git a/drivers/gpu/drm/i915/Kconfig b/drivers/gpu/drm/i915/Kconfig
index 87ef8c4d72a5..4f0d18a16b0f 100644
--- a/drivers/gpu/drm/i915/Kconfig
+++ b/drivers/gpu/drm/i915/Kconfig
@@ -2,20 +2,20 @@
 config DRM_I915
tristate "Intel 8xx/9xx/G3x/G4x/HD Graphics"
depends on DRM
depends on DRM_DISPLAY_DP_HELPER
depends on DRM_DISPLAY_HDCP_HELPER
+   depends on DRM_DISPLAY_HDMI_HELPER
depends on DRM_DISPLAY_HELPER
depends on X86 && PCI
depends on !PREEMPT_RT
select INTEL_GTT if X86
select INTERVAL_TREE
# we need shmfs for the swappable backing store, and in particular
# the shmem_readpage() which depends upon tmpfs
select SHMEM
select TMPFS
-   select DRM_DISPLAY_HDMI_HELPER
select DRM_KMS_HELPER
select DRM_PANEL
select DRM_MIPI_DSI
select FB_IOMEM_HELPERS if DRM_FBDEV_EMULATION
select RELAY
diff --git a/drivers/gpu/drm/nouveau/Kconfig b/drivers/gpu/drm/nouveau/Kconfig
index 7cc305b2826d..4c10b400658c 100644
--- a/drivers/gpu/drm/nouveau/Kconfig
+++ b/drivers/gpu/drm/nouveau/Kconfig
@@ -1,16 +1,16 @@
 # SPDX-License-Identifier: GPL-2.0-only
 config DRM_NOUVEAU
tristate "Nouveau (NVIDIA) cards"
depends on DRM
depends on DRM_DISPLAY_DP_HELPER
+   depends on DRM_DISPLAY_HDMI_HELPER
depends on DRM_DISPLAY_HELPER
depends on PCI
depends on MMU
select IOMMU_API
select FW_LOADER
-   select DRM_DISPLAY_HDMI_HELPER
select DRM_KMS_HELPER
select DRM_TTM
select DRM_TTM_HELPER
select DRM_EXEC
select DRM_GPUVM
diff --git a/drivers/gpu/drm/tegra/Kconfig b/drivers/gpu/drm/tegra/Kconfig
index bb6e35261f11..6974caa99ece 100644
--- a/drivers/gpu/drm/tegra/Kconfig
+++ b/drivers/gpu/drm/tegra/Kconfig
@@ -4,13 +4,13 @@ config DRM_TEGRA
depends on ARCH_TEGRA || COMPILE_TEST
depends on COMMON_CLK
depends on DRM
depends on DRM_DISPLAY_DP_AUX_BUS
depends on DRM_DISPLAY_DP_HELPER
+   depends on DRM_DISPLAY_HDMI_HELPER
depends on DRM_DISPLAY_HELPER
depends on OF
-   select DRM_DISPLAY_HDMI_HELPER
select DRM_KMS_HELPER
select DRM_

[PATCH v3 06/13] drm/display: Make all helpers visible and switch to depends on

2024-03-27 Thread Maxime Ripard
All the helpers Kconfig symbols so far have relied on drivers selecting
them, and that's what most drivers did.

However, this creates an issue nowadays when helpers depend on each
other, and select doesn't transitively select a dependency dependencies.

Depends on doesn't have that limitation though, so let's convert those
symbols to be dependable and use depends on between them too.

Suggested-by: Jani Nikula 
Reviewed-by: Jani Nikula 
Signed-off-by: Maxime Ripard 
---
 drivers/gpu/drm/display/Kconfig | 26 ++
 1 file changed, 14 insertions(+), 12 deletions(-)

diff --git a/drivers/gpu/drm/display/Kconfig b/drivers/gpu/drm/display/Kconfig
index 864a6488bfdf..c77e7f85bd67 100644
--- a/drivers/gpu/drm/display/Kconfig
+++ b/drivers/gpu/drm/display/Kconfig
@@ -1,48 +1,50 @@
 # SPDX-License-Identifier: MIT
 
 config DRM_DISPLAY_HELPER
-   tristate
+   tristate "DRM Display Helpers"
depends on DRM
help
  DRM helpers for display adapters.
 
 config DRM_DISPLAY_DP_AUX_BUS
-   tristate
+   tristate "DRM DisplayPort AUX bus support"
depends on DRM
depends on OF || COMPILE_TEST
 
 config DRM_DISPLAY_DP_AUX_CEC
bool "Enable DisplayPort CEC-Tunneling-over-AUX HDMI support"
-   depends on DRM && DRM_DISPLAY_HELPER
-   select DRM_DISPLAY_DP_HELPER
+   depends on DRM
+   depends on DRM_DISPLAY_HELPER
+   depends on DRM_DISPLAY_DP_HELPER
select CEC_CORE
help
  Choose this option if you want to enable HDMI CEC support for
  DisplayPort/USB-C to HDMI adapters.
 
  Note: not all adapters support this feature, and even for those
  that do support this they often do not hook up the CEC pin.
 
 config DRM_DISPLAY_DP_AUX_CHARDEV
-   bool "DRM DP AUX Interface"
-   depends on DRM && DRM_DISPLAY_HELPER
-   select DRM_DISPLAY_DP_HELPER
+   bool "DRM DisplayPort AUX Interface"
+   depends on DRM
+   depends on DRM_DISPLAY_HELPER
+   depends on DRM_DISPLAY_DP_HELPER
help
  Choose this option to enable a /dev/drm_dp_auxN node that allows to
  read and write values to arbitrary DPCD registers on the DP aux
  channel.
 
 config DRM_DISPLAY_DP_HELPER
-   bool
+   bool "DRM DisplayPort Helpers"
depends on DRM_DISPLAY_HELPER
help
  DRM display helpers for DisplayPort.
 
 config DRM_DISPLAY_DP_TUNNEL
-   bool
-   select DRM_DISPLAY_DP_HELPER
+   bool "DRM DisplayPort tunnels support"
+   depends on 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.
 
@@ -58,15 +60,15 @@ config DRM_DISPLAY_DP_TUNNEL_STATE_DEBUG
  streams contained in tunnels.
 
  If in doubt, say "N".
 
 config DRM_DISPLAY_HDCP_HELPER
-   bool
+   bool "DRM HDCD Helpers"
depends on DRM_DISPLAY_HELPER
help
  DRM display helpers for HDCP.
 
 config DRM_DISPLAY_HDMI_HELPER
-   bool
+   bool "DRM HDMI Helpers"
depends on DRM_DISPLAY_HELPER
help
  DRM display helpers for HDMI.

-- 
2.44.0



[PATCH v3 11/13] drm: Switch DRM_DISPLAY_HDCP_HELPER to depends on

2024-03-27 Thread Maxime Ripard
Most of our helpers have relied on being selected so far through
Kconfig, but that creates issues when we have multiple layers of helpers
with some depending on others.

Indeed, select doesn't select a dependency's dependencies, and thus
isn't super intuitive. Depends on however doesn't have that limitation,
so we can just switch all the drivers that were selecting
DRM_DISPLAY_HDCP_HELPER to depend on it.

Reviewed-by: Jani Nikula 
Signed-off-by: Maxime Ripard 
---
 drivers/gpu/drm/amd/amdgpu/Kconfig  | 2 +-
 drivers/gpu/drm/bridge/Kconfig  | 2 +-
 drivers/gpu/drm/bridge/analogix/Kconfig | 2 +-
 drivers/gpu/drm/bridge/cadence/Kconfig  | 2 +-
 drivers/gpu/drm/display/Kconfig | 1 +
 drivers/gpu/drm/i915/Kconfig| 2 +-
 drivers/gpu/drm/xe/Kconfig  | 2 +-
 7 files changed, 7 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/Kconfig 
b/drivers/gpu/drm/amd/amdgpu/Kconfig
index ba09121e7deb..1662dc49f18e 100644
--- a/drivers/gpu/drm/amd/amdgpu/Kconfig
+++ b/drivers/gpu/drm/amd/amdgpu/Kconfig
@@ -2,17 +2,17 @@
 
 config DRM_AMDGPU
tristate "AMD GPU"
depends on DRM
depends on DRM_DISPLAY_DP_HELPER
+   depends on DRM_DISPLAY_HDCP_HELPER
depends on DRM_DISPLAY_HELPER
depends on MMU
depends on PCI
depends on !UML
select FW_LOADER
select DRM_DISPLAY_HDMI_HELPER
-   select DRM_DISPLAY_HDCP_HELPER
select DRM_KMS_HELPER
select DRM_SCHED
select DRM_TTM
select DRM_TTM_HELPER
select POWER_SUPPLY
diff --git a/drivers/gpu/drm/bridge/Kconfig b/drivers/gpu/drm/bridge/Kconfig
index 54d45dd31b7f..6e6ec300ab16 100644
--- a/drivers/gpu/drm/bridge/Kconfig
+++ b/drivers/gpu/drm/bridge/Kconfig
@@ -92,13 +92,13 @@ config DRM_FSL_LDB
 
 config DRM_ITE_IT6505
tristate "ITE IT6505 DisplayPort bridge"
depends on DRM_DISPLAY_DP_AUX_BUS
depends on DRM_DISPLAY_DP_HELPER
+   depends on DRM_DISPLAY_HDCP_HELPER
depends on DRM_DISPLAY_HELPER
depends on OF
-   select DRM_DISPLAY_HDCP_HELPER
select DRM_KMS_HELPER
select DRM_DP_HELPER
select EXTCON
select CRYPTO
select CRYPTO_HASH
diff --git a/drivers/gpu/drm/bridge/analogix/Kconfig 
b/drivers/gpu/drm/bridge/analogix/Kconfig
index 9659df6718de..12bfea53bf24 100644
--- a/drivers/gpu/drm/bridge/analogix/Kconfig
+++ b/drivers/gpu/drm/bridge/analogix/Kconfig
@@ -33,13 +33,13 @@ config DRM_ANALOGIX_DP
 config DRM_ANALOGIX_ANX7625
tristate "Analogix Anx7625 MIPI to DP interface support"
depends on DRM
depends on DRM_DISPLAY_DP_AUX_BUS
depends on DRM_DISPLAY_DP_HELPER
+   depends on DRM_DISPLAY_HDCP_HELPER
depends on DRM_DISPLAY_HELPER
depends on OF
-   select DRM_DISPLAY_HDCP_HELPER
select DRM_MIPI_DSI
help
  ANX7625 is an ultra-low power 4K mobile HD transmitter
  designed for portable devices. It converts MIPI/DPI to
  DisplayPort1.3 4K.
diff --git a/drivers/gpu/drm/bridge/cadence/Kconfig 
b/drivers/gpu/drm/bridge/cadence/Kconfig
index 3480fd4d0a5f..7817f6f56607 100644
--- a/drivers/gpu/drm/bridge/cadence/Kconfig
+++ b/drivers/gpu/drm/bridge/cadence/Kconfig
@@ -22,13 +22,13 @@ config DRM_CDNS_DSI_J721E
 endif
 
 config DRM_CDNS_MHDP8546
tristate "Cadence DPI/DP bridge"
depends on DRM_DISPLAY_DP_HELPER
+   depends on DRM_DISPLAY_HDCP_HELPER
depends on DRM_DISPLAY_HELPER
depends on OF
-   select DRM_DISPLAY_HDCP_HELPER
select DRM_KMS_HELPER
select DRM_PANEL_BRIDGE
help
  Support Cadence DPI to DP bridge. This is an internal
  bridge and is meant to be directly embedded in a SoC.
diff --git a/drivers/gpu/drm/display/Kconfig b/drivers/gpu/drm/display/Kconfig
index 9801f47a3704..d65f1a37c08c 100644
--- a/drivers/gpu/drm/display/Kconfig
+++ b/drivers/gpu/drm/display/Kconfig
@@ -65,10 +65,11 @@ config DRM_DISPLAY_DP_TUNNEL_STATE_DEBUG
  If in doubt, say "N".
 
 config DRM_DISPLAY_HDCP_HELPER
bool "DRM HDCD Helpers"
depends on DRM_DISPLAY_HELPER
+   default y
help
  DRM display helpers for HDCP.
 
 config DRM_DISPLAY_HDMI_HELPER
bool "DRM HDMI Helpers"
diff --git a/drivers/gpu/drm/i915/Kconfig b/drivers/gpu/drm/i915/Kconfig
index dbde4e29d93a..87ef8c4d72a5 100644
--- a/drivers/gpu/drm/i915/Kconfig
+++ b/drivers/gpu/drm/i915/Kconfig
@@ -1,20 +1,20 @@
 # SPDX-License-Identifier: GPL-2.0-only
 config DRM_I915
tristate "Intel 8xx/9xx/G3x/G4x/HD Graphics"
depends on DRM
depends on DRM_DISPLAY_DP_HELPER
+   depends on DRM_DISPLAY_HDCP_HELPER
depends on DRM_DISPLAY_HELPER
depends on X86 && PCI
depends on !PREEMPT_RT
select INTEL_GTT if X86
select 

[PATCH v3 08/13] drm: Switch DRM_DISPLAY_HELPER to depends on

2024-03-27 Thread Maxime Ripard
Most of our helpers have relied on being selected so far through
Kconfig, but that creates issues when we have multiple layers of helpers
with some depending on others.

Indeed, select doesn't select a dependency's dependencies, and thus
isn't super intuitive. Depends on however doesn't have that limitation,
so we can just switch all the drivers that were selecting
DRM_DISPLAY_HELPER to depend on it.

Reviewed-by: Jani Nikula 
Signed-off-by: Maxime Ripard 
---
 drivers/gpu/drm/Kconfig |  6 --
 drivers/gpu/drm/amd/amdgpu/Kconfig  |  6 --
 drivers/gpu/drm/bridge/Kconfig  | 10 +-
 drivers/gpu/drm/bridge/analogix/Kconfig |  6 +++---
 drivers/gpu/drm/bridge/cadence/Kconfig  |  4 ++--
 drivers/gpu/drm/bridge/synopsys/Kconfig |  2 +-
 drivers/gpu/drm/display/Kconfig |  1 +
 drivers/gpu/drm/exynos/Kconfig  |  2 +-
 drivers/gpu/drm/i915/Kconfig|  2 +-
 drivers/gpu/drm/mediatek/Kconfig|  2 +-
 drivers/gpu/drm/msm/Kconfig |  4 ++--
 drivers/gpu/drm/nouveau/Kconfig |  6 --
 drivers/gpu/drm/panel/Kconfig   | 20 ++--
 drivers/gpu/drm/radeon/Kconfig  |  6 --
 drivers/gpu/drm/rockchip/Kconfig|  4 ++--
 drivers/gpu/drm/tegra/Kconfig   |  2 +-
 drivers/gpu/drm/vc4/Kconfig |  8 
 drivers/gpu/drm/xe/Kconfig  |  7 +--
 drivers/gpu/drm/xlnx/Kconfig|  6 --
 19 files changed, 59 insertions(+), 45 deletions(-)

diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
index 16029435b750..1eb939463c35 100644
--- a/drivers/gpu/drm/Kconfig
+++ b/drivers/gpu/drm/Kconfig
@@ -71,14 +71,16 @@ config DRM_KUNIT_TEST_HELPERS
help
  KUnit Helpers for KMS drivers.
 
 config DRM_KUNIT_TEST
tristate "KUnit tests for DRM" if !KUNIT_ALL_TESTS
-   depends on DRM && KUNIT && MMU
+   depends on DRM
+   depends on DRM_DISPLAY_HELPER
+   depends on KUNIT
+   depends on MMU
select DRM_BUDDY
select DRM_DISPLAY_DP_HELPER
-   select DRM_DISPLAY_HELPER
select DRM_EXEC
select DRM_EXPORT_FOR_TESTS if m
select DRM_GEM_SHMEM_HELPER
select DRM_KMS_HELPER
select DRM_KUNIT_TEST_HELPERS
diff --git a/drivers/gpu/drm/amd/amdgpu/Kconfig 
b/drivers/gpu/drm/amd/amdgpu/Kconfig
index 22d88f8ef527..cf931b94a188 100644
--- a/drivers/gpu/drm/amd/amdgpu/Kconfig
+++ b/drivers/gpu/drm/amd/amdgpu/Kconfig
@@ -1,16 +1,18 @@
 # SPDX-License-Identifier: MIT
 
 config DRM_AMDGPU
tristate "AMD GPU"
-   depends on DRM && PCI && MMU
+   depends on DRM
+   depends on DRM_DISPLAY_HELPER
+   depends on MMU
+   depends on PCI
depends on !UML
select FW_LOADER
select DRM_DISPLAY_DP_HELPER
select DRM_DISPLAY_HDMI_HELPER
select DRM_DISPLAY_HDCP_HELPER
-   select DRM_DISPLAY_HELPER
select DRM_KMS_HELPER
select DRM_SCHED
select DRM_TTM
select DRM_TTM_HELPER
select POWER_SUPPLY
diff --git a/drivers/gpu/drm/bridge/Kconfig b/drivers/gpu/drm/bridge/Kconfig
index 703c3e30885b..aa870e68e165 100644
--- a/drivers/gpu/drm/bridge/Kconfig
+++ b/drivers/gpu/drm/bridge/Kconfig
@@ -90,14 +90,14 @@ config DRM_FSL_LDB
help
  Support for i.MX8MP DPI-to-LVDS on-SoC encoder.
 
 config DRM_ITE_IT6505
tristate "ITE IT6505 DisplayPort bridge"
+   depends on DRM_DISPLAY_HELPER
depends on OF
select DRM_DISPLAY_DP_HELPER
select DRM_DISPLAY_HDCP_HELPER
-   select DRM_DISPLAY_HELPER
select DRM_DISPLAY_DP_AUX_BUS
select DRM_KMS_HELPER
select DRM_DP_HELPER
select EXTCON
select CRYPTO
@@ -224,13 +224,13 @@ config DRM_PARADE_PS8622
help
  Parade eDP-LVDS bridge chip driver.
 
 config DRM_PARADE_PS8640
tristate "Parade PS8640 MIPI DSI to eDP Converter"
+   depends on DRM_DISPLAY_HELPER
depends on OF
select DRM_DISPLAY_DP_HELPER
-   select DRM_DISPLAY_HELPER
select DRM_DISPLAY_DP_AUX_BUS
select DRM_KMS_HELPER
select DRM_MIPI_DSI
select DRM_PANEL
help
@@ -311,13 +311,13 @@ config DRM_TOSHIBA_TC358764
help
  Toshiba TC358764 DSI/LVDS bridge driver.
 
 config DRM_TOSHIBA_TC358767
tristate "Toshiba TC358767 eDP bridge"
+   depends on DRM_DISPLAY_HELPER
depends on OF
select DRM_DISPLAY_DP_HELPER
-   select DRM_DISPLAY_HELPER
select DRM_KMS_HELPER
select REGMAP_I2C
select DRM_MIPI_DSI
select DRM_PANEL
help
@@ -334,13 +334,13 @@ config DRM_TOSHIBA_TC358768
help
  Toshiba TC358768AXBG/TC358778XBG DSI bridge chip driver.
 
 config DRM_TOSHIBA_TC358775
tristate "Toshiba TC358775 DSI/LVDS bridge"
+   depends on DRM_DISPLAY_HELPER

[PATCH v3 09/13] drm: Switch DRM_DISPLAY_DP_AUX_BUS to depends on

2024-03-27 Thread Maxime Ripard
Most of our helpers have relied on being selected so far through
Kconfig, but that creates issues when we have multiple layers of helpers
with some depending on others.

Indeed, select doesn't select a dependency's dependencies, and thus
isn't super intuitive. Depends on however doesn't have that limitation,
so we can just switch all the drivers that were selecting
DRM_DISPLAY_DP_AUX_BUS to depend on it.

Reviewed-by: Jani Nikula 
Signed-off-by: Maxime Ripard 
---
 drivers/gpu/drm/bridge/Kconfig  | 6 +++---
 drivers/gpu/drm/bridge/analogix/Kconfig | 2 +-
 drivers/gpu/drm/display/Kconfig | 1 +
 drivers/gpu/drm/mediatek/Kconfig| 2 +-
 drivers/gpu/drm/msm/Kconfig | 2 +-
 drivers/gpu/drm/panel/Kconfig   | 4 ++--
 drivers/gpu/drm/tegra/Kconfig   | 2 +-
 7 files changed, 10 insertions(+), 9 deletions(-)

diff --git a/drivers/gpu/drm/bridge/Kconfig b/drivers/gpu/drm/bridge/Kconfig
index aa870e68e165..5d0193a87314 100644
--- a/drivers/gpu/drm/bridge/Kconfig
+++ b/drivers/gpu/drm/bridge/Kconfig
@@ -90,15 +90,15 @@ config DRM_FSL_LDB
help
  Support for i.MX8MP DPI-to-LVDS on-SoC encoder.
 
 config DRM_ITE_IT6505
tristate "ITE IT6505 DisplayPort bridge"
+   depends on DRM_DISPLAY_DP_AUX_BUS
depends on DRM_DISPLAY_HELPER
depends on OF
select DRM_DISPLAY_DP_HELPER
select DRM_DISPLAY_HDCP_HELPER
-   select DRM_DISPLAY_DP_AUX_BUS
select DRM_KMS_HELPER
select DRM_DP_HELPER
select EXTCON
select CRYPTO
select CRYPTO_HASH
@@ -224,14 +224,14 @@ config DRM_PARADE_PS8622
help
  Parade eDP-LVDS bridge chip driver.
 
 config DRM_PARADE_PS8640
tristate "Parade PS8640 MIPI DSI to eDP Converter"
+   depends on DRM_DISPLAY_DP_AUX_BUS
depends on DRM_DISPLAY_HELPER
depends on OF
select DRM_DISPLAY_DP_HELPER
-   select DRM_DISPLAY_DP_AUX_BUS
select DRM_KMS_HELPER
select DRM_MIPI_DSI
select DRM_PANEL
help
  Choose this option if you have PS8640 for display
@@ -379,19 +379,19 @@ config DRM_TI_SN65DSI83
help
  Texas Instruments SN65DSI83 and SN65DSI84 DSI to LVDS Bridge driver
 
 config DRM_TI_SN65DSI86
tristate "TI SN65DSI86 DSI to eDP bridge"
+   depends on DRM_DISPLAY_DP_AUX_BUS
depends on DRM_DISPLAY_HELPER
depends on OF
select DRM_DISPLAY_DP_HELPER
select DRM_KMS_HELPER
select REGMAP_I2C
select DRM_PANEL
select DRM_MIPI_DSI
select AUXILIARY_BUS
-   select DRM_DISPLAY_DP_AUX_BUS
help
  Texas Instruments SN65DSI86 DSI to eDP Bridge driver
 
 config DRM_TI_TPD12S015
tristate "TI TPD12S015 HDMI level shifter and ESD protection"
diff --git a/drivers/gpu/drm/bridge/analogix/Kconfig 
b/drivers/gpu/drm/bridge/analogix/Kconfig
index 16d18dde483a..ec98c9453573 100644
--- a/drivers/gpu/drm/bridge/analogix/Kconfig
+++ b/drivers/gpu/drm/bridge/analogix/Kconfig
@@ -31,15 +31,15 @@ config DRM_ANALOGIX_DP
depends on DRM
 
 config DRM_ANALOGIX_ANX7625
tristate "Analogix Anx7625 MIPI to DP interface support"
depends on DRM
+   depends on DRM_DISPLAY_DP_AUX_BUS
depends on DRM_DISPLAY_HELPER
depends on OF
select DRM_DISPLAY_DP_HELPER
select DRM_DISPLAY_HDCP_HELPER
-   select DRM_DISPLAY_DP_AUX_BUS
select DRM_MIPI_DSI
help
  ANX7625 is an ultra-low power 4K mobile HD transmitter
  designed for portable devices. It converts MIPI/DPI to
  DisplayPort1.3 4K.
diff --git a/drivers/gpu/drm/display/Kconfig b/drivers/gpu/drm/display/Kconfig
index cffa2acdbc6c..0cd439691422 100644
--- a/drivers/gpu/drm/display/Kconfig
+++ b/drivers/gpu/drm/display/Kconfig
@@ -9,10 +9,11 @@ config DRM_DISPLAY_HELPER
 
 config DRM_DISPLAY_DP_AUX_BUS
tristate "DRM DisplayPort AUX bus support"
depends on DRM
depends on OF || COMPILE_TEST
+   default y
 
 config DRM_DISPLAY_DP_AUX_CEC
bool "Enable DisplayPort CEC-Tunneling-over-AUX HDMI support"
depends on DRM
depends on DRM_DISPLAY_HELPER
diff --git a/drivers/gpu/drm/mediatek/Kconfig b/drivers/gpu/drm/mediatek/Kconfig
index 50bb28327f65..2add54486ac4 100644
--- a/drivers/gpu/drm/mediatek/Kconfig
+++ b/drivers/gpu/drm/mediatek/Kconfig
@@ -20,15 +20,15 @@ config DRM_MEDIATEK
  This driver provides kernel mode setting and
  buffer management to userspace.
 
 config DRM_MEDIATEK_DP
tristate "DRM DPTX Support for MediaTek SoCs"
+   depends on DRM_DISPLAY_DP_AUX_BUS
depends on DRM_DISPLAY_HELPER
depends on DRM_MEDIATEK
select PHY_MTK_DP
select DRM_DISPLAY_DP_HELPER
-   select DRM_DISPLAY_DP_AUX_BUS
help
  DRM/KMS Display Port driver for MediaTek SoCs.
 
 config DR

[PATCH v3 10/13] drm: Switch DRM_DISPLAY_DP_HELPER to depends on

2024-03-27 Thread Maxime Ripard
Most of our helpers have relied on being selected so far through
Kconfig, but that creates issues when we have multiple layers of helpers
with some depending on others.

Indeed, select doesn't select a dependency's dependencies, and thus
isn't super intuitive. Depends on however doesn't have that limitation,
so we can just switch all the drivers that were selecting
DRM_DISPLAY_DP_HELPER to depend on it.

Reviewed-by: Jani Nikula 
Signed-off-by: Maxime Ripard 
---
 drivers/gpu/drm/Kconfig |  2 +-
 drivers/gpu/drm/amd/amdgpu/Kconfig  |  2 +-
 drivers/gpu/drm/bridge/Kconfig  | 10 +-
 drivers/gpu/drm/bridge/analogix/Kconfig |  6 +++---
 drivers/gpu/drm/bridge/cadence/Kconfig  |  2 +-
 drivers/gpu/drm/display/Kconfig |  1 +
 drivers/gpu/drm/exynos/Kconfig  |  2 +-
 drivers/gpu/drm/i915/Kconfig|  2 +-
 drivers/gpu/drm/mediatek/Kconfig|  2 +-
 drivers/gpu/drm/msm/Kconfig |  2 +-
 drivers/gpu/drm/nouveau/Kconfig |  2 +-
 drivers/gpu/drm/panel/Kconfig   |  8 
 drivers/gpu/drm/radeon/Kconfig  |  2 +-
 drivers/gpu/drm/rockchip/Kconfig|  4 ++--
 drivers/gpu/drm/tegra/Kconfig   |  2 +-
 drivers/gpu/drm/xe/Kconfig  |  2 +-
 drivers/gpu/drm/xlnx/Kconfig|  2 +-
 17 files changed, 27 insertions(+), 26 deletions(-)

diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
index 1eb939463c35..50b809346bf9 100644
--- a/drivers/gpu/drm/Kconfig
+++ b/drivers/gpu/drm/Kconfig
@@ -72,15 +72,15 @@ config DRM_KUNIT_TEST_HELPERS
  KUnit Helpers for KMS drivers.
 
 config DRM_KUNIT_TEST
tristate "KUnit tests for DRM" if !KUNIT_ALL_TESTS
depends on DRM
+   depends on DRM_DISPLAY_DP_HELPER
depends on DRM_DISPLAY_HELPER
depends on KUNIT
depends on MMU
select DRM_BUDDY
-   select DRM_DISPLAY_DP_HELPER
select DRM_EXEC
select DRM_EXPORT_FOR_TESTS if m
select DRM_GEM_SHMEM_HELPER
select DRM_KMS_HELPER
select DRM_KUNIT_TEST_HELPERS
diff --git a/drivers/gpu/drm/amd/amdgpu/Kconfig 
b/drivers/gpu/drm/amd/amdgpu/Kconfig
index cf931b94a188..ba09121e7deb 100644
--- a/drivers/gpu/drm/amd/amdgpu/Kconfig
+++ b/drivers/gpu/drm/amd/amdgpu/Kconfig
@@ -1,16 +1,16 @@
 # SPDX-License-Identifier: MIT
 
 config DRM_AMDGPU
tristate "AMD GPU"
depends on DRM
+   depends on DRM_DISPLAY_DP_HELPER
depends on DRM_DISPLAY_HELPER
depends on MMU
depends on PCI
depends on !UML
select FW_LOADER
-   select DRM_DISPLAY_DP_HELPER
select DRM_DISPLAY_HDMI_HELPER
select DRM_DISPLAY_HDCP_HELPER
select DRM_KMS_HELPER
select DRM_SCHED
select DRM_TTM
diff --git a/drivers/gpu/drm/bridge/Kconfig b/drivers/gpu/drm/bridge/Kconfig
index 5d0193a87314..54d45dd31b7f 100644
--- a/drivers/gpu/drm/bridge/Kconfig
+++ b/drivers/gpu/drm/bridge/Kconfig
@@ -91,13 +91,13 @@ config DRM_FSL_LDB
  Support for i.MX8MP DPI-to-LVDS on-SoC encoder.
 
 config DRM_ITE_IT6505
tristate "ITE IT6505 DisplayPort bridge"
depends on DRM_DISPLAY_DP_AUX_BUS
+   depends on DRM_DISPLAY_DP_HELPER
depends on DRM_DISPLAY_HELPER
depends on OF
-   select DRM_DISPLAY_DP_HELPER
select DRM_DISPLAY_HDCP_HELPER
select DRM_KMS_HELPER
select DRM_DP_HELPER
select EXTCON
select CRYPTO
@@ -225,13 +225,13 @@ config DRM_PARADE_PS8622
  Parade eDP-LVDS bridge chip driver.
 
 config DRM_PARADE_PS8640
tristate "Parade PS8640 MIPI DSI to eDP Converter"
depends on DRM_DISPLAY_DP_AUX_BUS
+   depends on DRM_DISPLAY_DP_HELPER
depends on DRM_DISPLAY_HELPER
depends on OF
-   select DRM_DISPLAY_DP_HELPER
select DRM_KMS_HELPER
select DRM_MIPI_DSI
select DRM_PANEL
help
  Choose this option if you have PS8640 for display
@@ -311,13 +311,13 @@ config DRM_TOSHIBA_TC358764
help
  Toshiba TC358764 DSI/LVDS bridge driver.
 
 config DRM_TOSHIBA_TC358767
tristate "Toshiba TC358767 eDP bridge"
+   depends on DRM_DISPLAY_DP_HELPER
depends on DRM_DISPLAY_HELPER
depends on OF
-   select DRM_DISPLAY_DP_HELPER
select DRM_KMS_HELPER
select REGMAP_I2C
select DRM_MIPI_DSI
select DRM_PANEL
help
@@ -334,13 +334,13 @@ config DRM_TOSHIBA_TC358768
help
  Toshiba TC358768AXBG/TC358778XBG DSI bridge chip driver.
 
 config DRM_TOSHIBA_TC358775
tristate "Toshiba TC358775 DSI/LVDS bridge"
+   depends on DRM_DISPLAY_DP_HELPER
depends on DRM_DISPLAY_HELPER
depends on OF
-   select DRM_DISPLAY_DP_HELPER
select DRM_KMS_HELPER
select REGMAP_I2C
select DRM_PANEL
select DRM_MIPI_DSI
help
@@ -380,13 +380,13 @@ c

[PATCH v3 05/13] drm/display: Reorder Kconfig symbols

2024-03-27 Thread Maxime Ripard
The display kconfig helpers are not organized in any particular order,
so let's move them around to create an alphabetical order.

Reviewed-by: Jani Nikula 
Reviewed-by: Lucas De Marchi 
Signed-off-by: Maxime Ripard 
---
 drivers/gpu/drm/display/Kconfig | 52 -
 1 file changed, 26 insertions(+), 26 deletions(-)

diff --git a/drivers/gpu/drm/display/Kconfig b/drivers/gpu/drm/display/Kconfig
index 35cb68db0bfd..864a6488bfdf 100644
--- a/drivers/gpu/drm/display/Kconfig
+++ b/drivers/gpu/drm/display/Kconfig
@@ -1,18 +1,39 @@
 # SPDX-License-Identifier: MIT
 
-config DRM_DISPLAY_DP_AUX_BUS
-   tristate
-   depends on DRM
-   depends on OF || COMPILE_TEST
-
 config DRM_DISPLAY_HELPER
tristate
depends on DRM
help
  DRM helpers for display adapters.
 
+config DRM_DISPLAY_DP_AUX_BUS
+   tristate
+   depends on DRM
+   depends on OF || COMPILE_TEST
+
+config DRM_DISPLAY_DP_AUX_CEC
+   bool "Enable DisplayPort CEC-Tunneling-over-AUX HDMI support"
+   depends on DRM && DRM_DISPLAY_HELPER
+   select DRM_DISPLAY_DP_HELPER
+   select CEC_CORE
+   help
+ Choose this option if you want to enable HDMI CEC support for
+ DisplayPort/USB-C to HDMI adapters.
+
+ Note: not all adapters support this feature, and even for those
+ that do support this they often do not hook up the CEC pin.
+
+config DRM_DISPLAY_DP_AUX_CHARDEV
+   bool "DRM DP AUX Interface"
+   depends on DRM && DRM_DISPLAY_HELPER
+   select DRM_DISPLAY_DP_HELPER
+   help
+ Choose this option to enable a /dev/drm_dp_auxN node that allows to
+ read and write values to arbitrary DPCD registers on the DP aux
+ channel.
+
 config DRM_DISPLAY_DP_HELPER
bool
depends on DRM_DISPLAY_HELPER
help
  DRM display helpers for DisplayPort.
@@ -47,26 +68,5 @@ config DRM_DISPLAY_HDCP_HELPER
 config DRM_DISPLAY_HDMI_HELPER
bool
depends on DRM_DISPLAY_HELPER
help
  DRM display helpers for HDMI.
-
-config DRM_DISPLAY_DP_AUX_CHARDEV
-   bool "DRM DP AUX Interface"
-   depends on DRM && DRM_DISPLAY_HELPER
-   select DRM_DISPLAY_DP_HELPER
-   help
- Choose this option to enable a /dev/drm_dp_auxN node that allows to
- read and write values to arbitrary DPCD registers on the DP aux
- channel.
-
-config DRM_DISPLAY_DP_AUX_CEC
-   bool "Enable DisplayPort CEC-Tunneling-over-AUX HDMI support"
-   depends on DRM && DRM_DISPLAY_HELPER
-   select DRM_DISPLAY_DP_HELPER
-   select CEC_CORE
-   help
- Choose this option if you want to enable HDMI CEC support for
- DisplayPort/USB-C to HDMI adapters.
-
- Note: not all adapters support this feature, and even for those
- that do support this they often do not hook up the CEC pin.

-- 
2.44.0



[PATCH v3 03/13] drm/display: Make DisplayPort AUX Chardev Kconfig name consistent

2024-03-27 Thread Maxime Ripard
While most display helpers Kconfig symbols have the DRM_DISPLAY prefix,
the DisplayPort-AUX chardev interface uses DRM_DP_AUX_CHARDEV.

Since the number of users is limited and it's a selected symbol, we can
easily rename it to make it consistent.

Reviewed-by: Jani Nikula 
Reviewed-by: Lucas De Marchi 
Signed-off-by: Maxime Ripard 
---
 drivers/gpu/drm/display/Kconfig  | 2 +-
 drivers/gpu/drm/display/Makefile | 2 +-
 drivers/gpu/drm/display/drm_dp_helper.c  | 2 +-
 drivers/gpu/drm/display/drm_dp_helper_internal.h | 2 +-
 drivers/gpu/drm/i915/Kconfig.debug   | 2 +-
 5 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/display/Kconfig b/drivers/gpu/drm/display/Kconfig
index 0d350e9db807..038be9795581 100644
--- a/drivers/gpu/drm/display/Kconfig
+++ b/drivers/gpu/drm/display/Kconfig
@@ -48,11 +48,11 @@ config DRM_DISPLAY_HDMI_HELPER
bool
depends on DRM_DISPLAY_HELPER
help
  DRM display helpers for HDMI.
 
-config DRM_DP_AUX_CHARDEV
+config DRM_DISPLAY_DP_AUX_CHARDEV
bool "DRM DP AUX Interface"
depends on DRM && DRM_DISPLAY_HELPER
select DRM_DISPLAY_DP_HELPER
help
  Choose this option to enable a /dev/drm_dp_auxN node that allows to
diff --git a/drivers/gpu/drm/display/Makefile b/drivers/gpu/drm/display/Makefile
index 3edf1ba2764e..44015aef1e8c 100644
--- a/drivers/gpu/drm/display/Makefile
+++ b/drivers/gpu/drm/display/Makefile
@@ -12,9 +12,9 @@ drm_display_helper-$(CONFIG_DRM_DISPLAY_DP_TUNNEL) += \
drm_dp_tunnel.o
 drm_display_helper-$(CONFIG_DRM_DISPLAY_HDCP_HELPER) += drm_hdcp_helper.o
 drm_display_helper-$(CONFIG_DRM_DISPLAY_HDMI_HELPER) += \
drm_hdmi_helper.o \
drm_scdc_helper.o
-drm_display_helper-$(CONFIG_DRM_DP_AUX_CHARDEV) += drm_dp_aux_dev.o
+drm_display_helper-$(CONFIG_DRM_DISPLAY_DP_AUX_CHARDEV) += drm_dp_aux_dev.o
 drm_display_helper-$(CONFIG_DRM_DP_CEC) += drm_dp_cec.o
 
 obj-$(CONFIG_DRM_DISPLAY_HELPER) += drm_display_helper.o
diff --git a/drivers/gpu/drm/display/drm_dp_helper.c 
b/drivers/gpu/drm/display/drm_dp_helper.c
index 266826eac4a7..66a1785447b8 100644
--- a/drivers/gpu/drm/display/drm_dp_helper.c
+++ b/drivers/gpu/drm/display/drm_dp_helper.c
@@ -2111,11 +2111,11 @@ EXPORT_SYMBOL(drm_dp_aux_init);
  * _dp_aux.dev will typically be the _connector  which
  * corresponds to @aux. For these devices, it's advised to call
  * drm_dp_aux_register() in _connector_funcs.late_register, and likewise to
  * call drm_dp_aux_unregister() in _connector_funcs.early_unregister.
  * Functions which don't follow this will likely Oops when
- * %CONFIG_DRM_DP_AUX_CHARDEV is enabled.
+ * %CONFIG_DRM_DISPLAY_DP_AUX_CHARDEV is enabled.
  *
  * For devices where the AUX channel is a device that exists independently of
  * the _device that uses it, such as SoCs and bridge devices, it is
  * recommended to call drm_dp_aux_register() after a _device has been
  * assigned to _dp_aux.drm_dev, and likewise to call
diff --git a/drivers/gpu/drm/display/drm_dp_helper_internal.h 
b/drivers/gpu/drm/display/drm_dp_helper_internal.h
index 8917fc3af9ec..737949a2820f 100644
--- a/drivers/gpu/drm/display/drm_dp_helper_internal.h
+++ b/drivers/gpu/drm/display/drm_dp_helper_internal.h
@@ -3,11 +3,11 @@
 #ifndef DRM_DP_HELPER_INTERNAL_H
 #define DRM_DP_HELPER_INTERNAL_H
 
 struct drm_dp_aux;
 
-#ifdef CONFIG_DRM_DP_AUX_CHARDEV
+#ifdef CONFIG_DRM_DISPLAY_DP_AUX_CHARDEV
 int drm_dp_aux_dev_init(void);
 void drm_dp_aux_dev_exit(void);
 int drm_dp_aux_register_devnode(struct drm_dp_aux *aux);
 void drm_dp_aux_unregister_devnode(struct drm_dp_aux *aux);
 #else
diff --git a/drivers/gpu/drm/i915/Kconfig.debug 
b/drivers/gpu/drm/i915/Kconfig.debug
index 5ae02c1cd25c..d8397065c3f0 100644
--- a/drivers/gpu/drm/i915/Kconfig.debug
+++ b/drivers/gpu/drm/i915/Kconfig.debug
@@ -25,11 +25,11 @@ config DRM_I915_DEBUG
select PREEMPT_COUNT
select I2C_CHARDEV
select REF_TRACKER
select STACKDEPOT
select STACKTRACE
-   select DRM_DP_AUX_CHARDEV
+   select DRM_DISPLAY_DP_AUX_CHARDEV
select DRM_DISPLAY_DP_TUNNEL_STATE_DEBUG if DRM_I915_DP_TUNNEL
select X86_MSR # used by igt/pm_rpm
select DRM_VGEM # used by igt/prime_vgem (dmabuf interop checks)
select DRM_DEBUG_MM if DRM=y
select DRM_EXPORT_FOR_TESTS if m

-- 
2.44.0



[PATCH v3 04/13] drm/display: Make DisplayPort CEC-over-AUX Kconfig name consistent

2024-03-27 Thread Maxime Ripard
While most display helpers Kconfig symbols have the DRM_DISPLAY prefix,
the DisplayPort CEC tunnelling implementation uses 
CONFIG_DRM_DISPLAY_DP_AUX_CEC.

Since the number of users is limited, we can easily rename it to make it
consistent.

Reviewed-by: Jani Nikula 
Reviewed-by: Lucas De Marchi 
Signed-off-by: Maxime Ripard 
---
 arch/parisc/configs/generic-32bit_defconfig | 2 +-
 drivers/gpu/drm/display/Kconfig | 2 +-
 drivers/gpu/drm/display/Makefile| 2 +-
 include/drm/display/drm_dp_helper.h | 2 +-
 4 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/arch/parisc/configs/generic-32bit_defconfig 
b/arch/parisc/configs/generic-32bit_defconfig
index ee4febb30386..5ce258f3fffa 100644
--- a/arch/parisc/configs/generic-32bit_defconfig
+++ b/arch/parisc/configs/generic-32bit_defconfig
@@ -129,11 +129,11 @@ CONFIG_PRINTER=m
 CONFIG_PPDEV=m
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=y
 CONFIG_HWMON=m
 CONFIG_DRM=m
-CONFIG_DRM_DP_CEC=y
+CONFIG_DRM_DISPLAY_DP_AUX_CEC=y
 # CONFIG_DRM_I2C_CH7006 is not set
 # CONFIG_DRM_I2C_SIL164 is not set
 CONFIG_DRM_RADEON=m
 CONFIG_DRM_NOUVEAU=m
 # CONFIG_DRM_NOUVEAU_BACKLIGHT is not set
diff --git a/drivers/gpu/drm/display/Kconfig b/drivers/gpu/drm/display/Kconfig
index 038be9795581..35cb68db0bfd 100644
--- a/drivers/gpu/drm/display/Kconfig
+++ b/drivers/gpu/drm/display/Kconfig
@@ -57,11 +57,11 @@ config DRM_DISPLAY_DP_AUX_CHARDEV
help
  Choose this option to enable a /dev/drm_dp_auxN node that allows to
  read and write values to arbitrary DPCD registers on the DP aux
  channel.
 
-config DRM_DP_CEC
+config DRM_DISPLAY_DP_AUX_CEC
bool "Enable DisplayPort CEC-Tunneling-over-AUX HDMI support"
depends on DRM && DRM_DISPLAY_HELPER
select DRM_DISPLAY_DP_HELPER
select CEC_CORE
help
diff --git a/drivers/gpu/drm/display/Makefile b/drivers/gpu/drm/display/Makefile
index 44015aef1e8c..17d2cc73ff56 100644
--- a/drivers/gpu/drm/display/Makefile
+++ b/drivers/gpu/drm/display/Makefile
@@ -13,8 +13,8 @@ drm_display_helper-$(CONFIG_DRM_DISPLAY_DP_TUNNEL) += \
 drm_display_helper-$(CONFIG_DRM_DISPLAY_HDCP_HELPER) += drm_hdcp_helper.o
 drm_display_helper-$(CONFIG_DRM_DISPLAY_HDMI_HELPER) += \
drm_hdmi_helper.o \
drm_scdc_helper.o
 drm_display_helper-$(CONFIG_DRM_DISPLAY_DP_AUX_CHARDEV) += drm_dp_aux_dev.o
-drm_display_helper-$(CONFIG_DRM_DP_CEC) += drm_dp_cec.o
+drm_display_helper-$(CONFIG_DRM_DISPLAY_DP_AUX_CEC) += drm_dp_cec.o
 
 obj-$(CONFIG_DRM_DISPLAY_HELPER) += drm_display_helper.o
diff --git a/include/drm/display/drm_dp_helper.h 
b/include/drm/display/drm_dp_helper.h
index a62fcd051d4d..46f4e0467d24 100644
--- a/include/drm/display/drm_dp_helper.h
+++ b/include/drm/display/drm_dp_helper.h
@@ -720,11 +720,11 @@ static inline int drm_panel_dp_aux_backlight(struct 
drm_panel *panel,
return 0;
 }
 
 #endif
 
-#ifdef CONFIG_DRM_DP_CEC
+#ifdef CONFIG_DRM_DISPLAY_DP_AUX_CEC
 void drm_dp_cec_irq(struct drm_dp_aux *aux);
 void drm_dp_cec_register_connector(struct drm_dp_aux *aux,
   struct drm_connector *connector);
 void drm_dp_cec_unregister_connector(struct drm_dp_aux *aux);
 void drm_dp_cec_attach(struct drm_dp_aux *aux, u16 source_physical_address);

-- 
2.44.0



[PATCH v3 02/13] drm/display: Make DisplayPort tunnel debug Kconfig name consistent

2024-03-27 Thread Maxime Ripard
While most display helpers Kconfig symbols have the DRM_DISPLAY prefix,
the DisplayPort Tunnel debugging uses DRM_DISPLAY_DEBUG_DP_TUNNEL_STATE.

Since the number of users is limited and it's a selected symbol, we can
easily rename it to make it consistent.

Reviewed-by: Jani Nikula 
Reviewed-by: Lucas De Marchi 
Signed-off-by: Maxime Ripard 
---
 drivers/gpu/drm/display/Kconfig |  2 +-
 drivers/gpu/drm/display/drm_dp_tunnel.c | 10 +-
 drivers/gpu/drm/i915/Kconfig.debug  |  2 +-
 3 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/display/Kconfig b/drivers/gpu/drm/display/Kconfig
index 843d74db1dce..0d350e9db807 100644
--- a/drivers/gpu/drm/display/Kconfig
+++ b/drivers/gpu/drm/display/Kconfig
@@ -23,11 +23,11 @@ config DRM_DISPLAY_DP_TUNNEL
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
+config DRM_DISPLAY_DP_TUNNEL_STATE_DEBUG
bool "Enable debugging the DP tunnel state"
depends on REF_TRACKER
depends on DRM_DISPLAY_DP_TUNNEL
depends on DEBUG_KERNEL
depends on EXPERT
diff --git a/drivers/gpu/drm/display/drm_dp_tunnel.c 
b/drivers/gpu/drm/display/drm_dp_tunnel.c
index 120e0de674c1..2a91e9b11d03 100644
--- a/drivers/gpu/drm/display/drm_dp_tunnel.c
+++ b/drivers/gpu/drm/display/drm_dp_tunnel.c
@@ -189,11 +189,11 @@ struct drm_dp_tunnel_mgr {
 
int group_count;
struct drm_dp_tunnel_group *groups;
wait_queue_head_t bw_req_queue;
 
-#ifdef CONFIG_DRM_DISPLAY_DEBUG_DP_TUNNEL_STATE
+#ifdef CONFIG_DRM_DISPLAY_DP_TUNNEL_STATE_DEBUG
struct ref_tracker_dir ref_tracker;
 #endif
 };
 
 /*
@@ -383,11 +383,11 @@ static void free_tunnel(struct kref *kref)
 static void tunnel_put(struct drm_dp_tunnel *tunnel)
 {
kref_put(>kref, free_tunnel);
 }
 
-#ifdef CONFIG_DRM_DISPLAY_DEBUG_DP_TUNNEL_STATE
+#ifdef CONFIG_DRM_DISPLAY_DP_TUNNEL_STATE_DEBUG
 static void track_tunnel_ref(struct drm_dp_tunnel *tunnel,
 struct ref_tracker **tracker)
 {
ref_tracker_alloc(>group->mgr->ref_tracker,
  tracker, GFP_KERNEL);
@@ -1601,11 +1601,11 @@ static bool init_group(struct drm_dp_tunnel_mgr *mgr, 
struct drm_dp_tunnel_group
 static void cleanup_group(struct drm_dp_tunnel_group *group)
 {
drm_atomic_private_obj_fini(>base);
 }
 
-#ifdef CONFIG_DRM_DISPLAY_DEBUG_DP_TUNNEL_STATE
+#ifdef CONFIG_DRM_DISPLAY_DP_TUNNEL_STATE_DEBUG
 static void check_unique_stream_ids(const struct drm_dp_tunnel_group_state 
*group_state)
 {
const struct drm_dp_tunnel_state *tunnel_state;
u32 stream_mask = 0;
 
@@ -1879,11 +1879,11 @@ static void destroy_mgr(struct drm_dp_tunnel_mgr *mgr)
for (i = 0; i < mgr->group_count; i++) {
cleanup_group(>groups[i]);
drm_WARN_ON(mgr->dev, !list_empty(>groups[i].tunnels));
}
 
-#ifdef CONFIG_DRM_DISPLAY_DEBUG_DP_TUNNEL_STATE
+#ifdef CONFIG_DRM_DISPLAY_DP_TUNNEL_STATE_DEBUG
ref_tracker_dir_exit(>ref_tracker);
 #endif
 
kfree(mgr->groups);
kfree(mgr);
@@ -1916,11 +1916,11 @@ drm_dp_tunnel_mgr_create(struct drm_device *dev, int 
max_group_count)
kfree(mgr);
 
return NULL;
}
 
-#ifdef CONFIG_DRM_DISPLAY_DEBUG_DP_TUNNEL_STATE
+#ifdef CONFIG_DRM_DISPLAY_DP_TUNNEL_STATE_DEBUG
ref_tracker_dir_init(>ref_tracker, 16, "dptun");
 #endif
 
for (i = 0; i < max_group_count; i++) {
if (!init_group(mgr, >groups[i])) {
diff --git a/drivers/gpu/drm/i915/Kconfig.debug 
b/drivers/gpu/drm/i915/Kconfig.debug
index bc18e2d9ea05..5ae02c1cd25c 100644
--- a/drivers/gpu/drm/i915/Kconfig.debug
+++ b/drivers/gpu/drm/i915/Kconfig.debug
@@ -26,11 +26,11 @@ config DRM_I915_DEBUG
select I2C_CHARDEV
select REF_TRACKER
select STACKDEPOT
select STACKTRACE
select DRM_DP_AUX_CHARDEV
-   select DRM_DISPLAY_DEBUG_DP_TUNNEL_STATE if DRM_I915_DP_TUNNEL
+   select DRM_DISPLAY_DP_TUNNEL_STATE_DEBUG if DRM_I915_DP_TUNNEL
select X86_MSR # used by igt/pm_rpm
select DRM_VGEM # used by igt/prime_vgem (dmabuf interop checks)
select DRM_DEBUG_MM if DRM=y
select DRM_EXPORT_FOR_TESTS if m
select DRM_DEBUG_SELFTEST

-- 
2.44.0



[PATCH v3 01/13] drm/display: Make DisplayPort AUX bus Kconfig name consistent

2024-03-27 Thread Maxime Ripard
While most display helpers Kconfig symbols have the DRM_DISPLAY prefix,
the DisplayPort AUX bus implementation uses DRM_DP_AUX_BUS.

Since the number of users is limited and it's a selected symbol, we can
easily rename it to make it consistent.

Reviewed-by: Jani Nikula 
Reviewed-by: Lucas De Marchi 
Signed-off-by: Maxime Ripard 
---
 drivers/gpu/drm/bridge/Kconfig  | 6 +++---
 drivers/gpu/drm/bridge/analogix/Kconfig | 2 +-
 drivers/gpu/drm/display/Kconfig | 2 +-
 drivers/gpu/drm/display/Makefile| 2 +-
 drivers/gpu/drm/mediatek/Kconfig| 2 +-
 drivers/gpu/drm/msm/Kconfig | 2 +-
 drivers/gpu/drm/panel/Kconfig   | 4 ++--
 drivers/gpu/drm/tegra/Kconfig   | 2 +-
 8 files changed, 11 insertions(+), 11 deletions(-)

diff --git a/drivers/gpu/drm/bridge/Kconfig b/drivers/gpu/drm/bridge/Kconfig
index efd996f6c138..703c3e30885b 100644
--- a/drivers/gpu/drm/bridge/Kconfig
+++ b/drivers/gpu/drm/bridge/Kconfig
@@ -94,11 +94,11 @@ config DRM_ITE_IT6505
tristate "ITE IT6505 DisplayPort bridge"
depends on OF
select DRM_DISPLAY_DP_HELPER
select DRM_DISPLAY_HDCP_HELPER
select DRM_DISPLAY_HELPER
-   select DRM_DP_AUX_BUS
+   select DRM_DISPLAY_DP_AUX_BUS
select DRM_KMS_HELPER
select DRM_DP_HELPER
select EXTCON
select CRYPTO
select CRYPTO_HASH
@@ -227,11 +227,11 @@ config DRM_PARADE_PS8622
 config DRM_PARADE_PS8640
tristate "Parade PS8640 MIPI DSI to eDP Converter"
depends on OF
select DRM_DISPLAY_DP_HELPER
select DRM_DISPLAY_HELPER
-   select DRM_DP_AUX_BUS
+   select DRM_DISPLAY_DP_AUX_BUS
select DRM_KMS_HELPER
select DRM_MIPI_DSI
select DRM_PANEL
help
  Choose this option if you have PS8640 for display
@@ -387,11 +387,11 @@ config DRM_TI_SN65DSI86
select DRM_KMS_HELPER
select REGMAP_I2C
select DRM_PANEL
select DRM_MIPI_DSI
select AUXILIARY_BUS
-   select DRM_DP_AUX_BUS
+   select DRM_DISPLAY_DP_AUX_BUS
help
  Texas Instruments SN65DSI86 DSI to eDP Bridge driver
 
 config DRM_TI_TPD12S015
tristate "TI TPD12S015 HDMI level shifter and ESD protection"
diff --git a/drivers/gpu/drm/bridge/analogix/Kconfig 
b/drivers/gpu/drm/bridge/analogix/Kconfig
index 173dada218ec..4846b2e9be7c 100644
--- a/drivers/gpu/drm/bridge/analogix/Kconfig
+++ b/drivers/gpu/drm/bridge/analogix/Kconfig
@@ -35,11 +35,11 @@ config DRM_ANALOGIX_ANX7625
depends on DRM
depends on OF
select DRM_DISPLAY_DP_HELPER
select DRM_DISPLAY_HDCP_HELPER
select DRM_DISPLAY_HELPER
-   select DRM_DP_AUX_BUS
+   select DRM_DISPLAY_DP_AUX_BUS
select DRM_MIPI_DSI
help
  ANX7625 is an ultra-low power 4K mobile HD transmitter
  designed for portable devices. It converts MIPI/DPI to
  DisplayPort1.3 4K.
diff --git a/drivers/gpu/drm/display/Kconfig b/drivers/gpu/drm/display/Kconfig
index c0f56888c328..843d74db1dce 100644
--- a/drivers/gpu/drm/display/Kconfig
+++ b/drivers/gpu/drm/display/Kconfig
@@ -1,8 +1,8 @@
 # SPDX-License-Identifier: MIT
 
-config DRM_DP_AUX_BUS
+config DRM_DISPLAY_DP_AUX_BUS
tristate
depends on DRM
depends on OF || COMPILE_TEST
 
 config DRM_DISPLAY_HELPER
diff --git a/drivers/gpu/drm/display/Makefile b/drivers/gpu/drm/display/Makefile
index 7ca61333c669..3edf1ba2764e 100644
--- a/drivers/gpu/drm/display/Makefile
+++ b/drivers/gpu/drm/display/Makefile
@@ -1,8 +1,8 @@
 # SPDX-License-Identifier: MIT
 
-obj-$(CONFIG_DRM_DP_AUX_BUS) += drm_dp_aux_bus.o
+obj-$(CONFIG_DRM_DISPLAY_DP_AUX_BUS) += drm_dp_aux_bus.o
 
 drm_display_helper-y := drm_display_helper_mod.o
 drm_display_helper-$(CONFIG_DRM_DISPLAY_DP_HELPER) += \
drm_dp_dual_mode_helper.o \
drm_dp_helper.o \
diff --git a/drivers/gpu/drm/mediatek/Kconfig b/drivers/gpu/drm/mediatek/Kconfig
index 76cab28e010c..96cbe020f493 100644
--- a/drivers/gpu/drm/mediatek/Kconfig
+++ b/drivers/gpu/drm/mediatek/Kconfig
@@ -24,11 +24,11 @@ config DRM_MEDIATEK_DP
tristate "DRM DPTX Support for MediaTek SoCs"
depends on DRM_MEDIATEK
select PHY_MTK_DP
select DRM_DISPLAY_HELPER
select DRM_DISPLAY_DP_HELPER
-   select DRM_DP_AUX_BUS
+   select DRM_DISPLAY_DP_AUX_BUS
help
  DRM/KMS Display Port driver for MediaTek SoCs.
 
 config DRM_MEDIATEK_HDMI
tristate "DRM HDMI Support for Mediatek SoCs"
diff --git a/drivers/gpu/drm/msm/Kconfig b/drivers/gpu/drm/msm/Kconfig
index f202f26adab2..27d72ed8b389 100644
--- a/drivers/gpu/drm/msm/Kconfig
+++ b/drivers/gpu/drm/msm/Kconfig
@@ -12,11 +12,11 @@ config DRM_MSM
depends on QCOM_COMMAND_DB || QCOM_COMMAND_DB=n
depends on PM
select IOMMU_IO_PGTABLE
select QCOM_MDT_LOADER if ARCH_QCOM
select REGU

[PATCH v3 00/13] drm/display: Convert helpers Kconfig symbols to depends on

2024-03-27 Thread Maxime Ripard
Hi,

Jani recently pointed out that the Kconfig symbols are a bit difficult
to work with at the moment when they depend on each other, and that
using depends on would be a better idea, but no one really did the work
so far.

So here it goes :)

It's been tested by comparing the riscv defconfig, arm
multi_v7_defconfig, arm64 defconfig, drm-misc-arm, drm-misc-arm64 and
drm-misc-x86 before and after this series and making sure they are
identical.

Let me know what you think,
Maxime

Signed-off-by: Maxime Ripard 
---
Changes in v3:
- Fix a build issue for DRM_DW_HDMI
- Link to v2: 
https://lore.kernel.org/r/20240326-kms-kconfig-helpers-v2-0-3b0aeee32...@kernel.org

Changes in v2:
- Make all the symbols that used to be selected enabled by default to
  prevent defconfig disruptions.
- Fix typo in commit log of patch 3
- Link to v1: 
https://lore.kernel.org/r/20240325-kms-kconfig-helpers-v1-0-bfec6949d...@kernel.org

---
Maxime Ripard (13):
  drm/display: Make DisplayPort AUX bus Kconfig name consistent
  drm/display: Make DisplayPort tunnel debug Kconfig name consistent
  drm/display: Make DisplayPort AUX Chardev Kconfig name consistent
  drm/display: Make DisplayPort CEC-over-AUX Kconfig name consistent
  drm/display: Reorder Kconfig symbols
  drm/display: Make all helpers visible and switch to depends on
  drm: Make drivers depends on DRM_DW_HDMI
  drm: Switch DRM_DISPLAY_HELPER to depends on
  drm: Switch DRM_DISPLAY_DP_AUX_BUS to depends on
  drm: Switch DRM_DISPLAY_DP_HELPER to depends on
  drm: Switch DRM_DISPLAY_HDCP_HELPER to depends on
  drm: Switch DRM_DISPLAY_HDMI_HELPER to depends on
  drm/bridge: it6505: Remove useless select

 arch/parisc/configs/generic-32bit_defconfig  |  2 +-
 drivers/gpu/drm/Kconfig  |  8 ++-
 drivers/gpu/drm/amd/amdgpu/Kconfig   | 12 ++--
 drivers/gpu/drm/bridge/Kconfig   | 29 +
 drivers/gpu/drm/bridge/analogix/Kconfig  | 16 ++---
 drivers/gpu/drm/bridge/cadence/Kconfig   |  8 +--
 drivers/gpu/drm/bridge/imx/Kconfig   |  4 +-
 drivers/gpu/drm/bridge/synopsys/Kconfig  |  4 +-
 drivers/gpu/drm/display/Kconfig  | 75 +---
 drivers/gpu/drm/display/Makefile |  6 +-
 drivers/gpu/drm/display/drm_dp_helper.c  |  2 +-
 drivers/gpu/drm/display/drm_dp_helper_internal.h |  2 +-
 drivers/gpu/drm/display/drm_dp_tunnel.c  | 10 ++--
 drivers/gpu/drm/exynos/Kconfig   |  4 +-
 drivers/gpu/drm/i915/Kconfig |  8 +--
 drivers/gpu/drm/i915/Kconfig.debug   |  4 +-
 drivers/gpu/drm/imx/ipuv3/Kconfig|  5 +-
 drivers/gpu/drm/ingenic/Kconfig  |  2 +-
 drivers/gpu/drm/mediatek/Kconfig |  6 +-
 drivers/gpu/drm/meson/Kconfig|  2 +-
 drivers/gpu/drm/msm/Kconfig  |  8 +--
 drivers/gpu/drm/nouveau/Kconfig  | 10 ++--
 drivers/gpu/drm/panel/Kconfig| 32 +-
 drivers/gpu/drm/radeon/Kconfig   |  8 ++-
 drivers/gpu/drm/renesas/rcar-du/Kconfig  |  2 +-
 drivers/gpu/drm/rockchip/Kconfig | 10 ++--
 drivers/gpu/drm/sun4i/Kconfig|  2 +-
 drivers/gpu/drm/tegra/Kconfig|  8 +--
 drivers/gpu/drm/vc4/Kconfig  | 10 ++--
 drivers/gpu/drm/xe/Kconfig   | 13 ++--
 drivers/gpu/drm/xlnx/Kconfig |  8 ++-
 include/drm/display/drm_dp_helper.h  |  2 +-
 32 files changed, 171 insertions(+), 151 deletions(-)
---
base-commit: 5e842d55bad7794823a50f24fd645b58f2ef93ab
change-id: 20240325-kms-kconfig-helpers-f94991bdd6fa

Best regards,
-- 
Maxime Ripard 



Re: drivers/gpu/drm/qxl/qxl_cmd.c:424:6: error: variable 'count' set but not used

2024-03-27 Thread Maxime Ripard
Hi Miguel,

On Tue, Mar 26, 2024 at 07:04:34PM +0100, Miguel Ojeda wrote:
> Hi,
> 
> In today's next, I got:
> 
> drivers/gpu/drm/qxl/qxl_cmd.c:424:6: error: variable 'count' set
> but not used [-Werror,-Wunused-but-set-variable]
> 
> `count` seems to be there since commit f64122c1f6ad ("drm: add new QXL
> driver. (v1.4)").
> 
> Untested diff below -- if you want a formal patch, please let me know.
> 
> Cheers,
> Miguel
> 
> diff --git a/drivers/gpu/drm/qxl/qxl_cmd.c b/drivers/gpu/drm/qxl/qxl_cmd.c
> index 281edab518cd..d6ea01f3797b 100644
> --- a/drivers/gpu/drm/qxl/qxl_cmd.c
> +++ b/drivers/gpu/drm/qxl/qxl_cmd.c
> @@ -421,7 +421,6 @@ int qxl_surface_id_alloc(struct qxl_device *qdev,
>  {
> uint32_t handle;
> int idr_ret;
> -   int count = 0;
>  again:
> idr_preload(GFP_ATOMIC);
> spin_lock(>surf_id_idr_lock);
> @@ -433,7 +432,6 @@ int qxl_surface_id_alloc(struct qxl_device *qdev,
> handle = idr_ret;
> 
> if (handle >= qdev->rom->n_surfaces) {
> -   count++;
> spin_lock(>surf_id_idr_lock);
> idr_remove(>surf_id_idr, handle);
> spin_unlock(>surf_id_idr_lock);
> 

It looks reasonable to me, can you send a formal patch?

Thanks!
Maxime


signature.asc
Description: PGP signature


Re: [RESEND v3 2/2] drm: Add CONFIG_DRM_WERROR

2024-03-27 Thread Maxime Ripard
Hi,

On Tue, Mar 26, 2024 at 03:56:50PM -0700, Nathan Chancellor wrote:
> On Tue, Mar 05, 2024 at 11:07:36AM +0200, Jani Nikula wrote:
> > Add kconfig to enable -Werror subsystem wide. This is useful for
> > development and CI to keep the subsystem warning free, while avoiding
> > issues outside of the subsystem that kernel wide CONFIG_WERROR=y might
> > hit.
> > 
> > v2: Don't depend on COMPILE_TEST
> > 
> > Reviewed-by: Hamza Mahfooz  # v1
> > Signed-off-by: Jani Nikula 
> > ---
> >  drivers/gpu/drm/Kconfig  | 13 +
> >  drivers/gpu/drm/Makefile |  3 +++
> >  2 files changed, 16 insertions(+)
> > 
> > diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
> > index 6e853acf15da..c08e18108c2a 100644
> > --- a/drivers/gpu/drm/Kconfig
> > +++ b/drivers/gpu/drm/Kconfig
> > @@ -416,3 +416,16 @@ config DRM_LIB_RANDOM
> >  config DRM_PRIVACY_SCREEN
> > bool
> > default n
> > +
> > +config DRM_WERROR
> > +   bool "Compile the drm subsystem with warnings as errors"
> > +   depends on EXPERT
> > +   default n
> > +   help
> > + A kernel build should not cause any compiler warnings, and this
> > + enables the '-Werror' flag to enforce that rule in the drm subsystem.
> > +
> > + The drm subsystem enables more warnings than the kernel default, so
> > + this config option is disabled by default.
> > +
> > + If in doubt, say N.
> 
> While I understand the desire for an easy switch that maintainers and
> developers can use to ensure that their changes are warning free for the
> drm subsystem specifically, I think subsystem specific configuration
> options like this are actively detrimental to developers and continuous
> integration systems that build test the entire kernel. For example, we
> turned off CONFIG_WERROR for our Hexagon builds because of warnings that
> appear with -Wextra that are legitimate but require treewide changes to
> resolve in a manner sufficient for Linus:
> 
> https://github.com/ClangBuiltLinux/linux/issues/1285
> https://lore.kernel.org/all/CAHk-=wg80je=k7madf4e7wrrnp37e3qh6y10svhdc7o8sz_...@mail.gmail.com/
> https://lore.kernel.org/all/20230522105049.1467313-1-schne...@linux.ibm.com/
> 
> But now, due to CONFIG_DRM_WERROR getting enabled by all{mod,yes}config
> and -Wextra being unconditionally enabled for DRM, those warnings hard
> break the build despite CONFIG_WERROR=n...

Would making DRM_WERROR depends on WERROR address your concerns?

Maxime


signature.asc
Description: PGP signature


[PATCH v11 26/28] drm/vc4: tests: Convert to plane creation helper

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

Reviewed-by: Maíra Canal 
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_NOT_ERR_OR_NULL(test, plane);
+   KUNIT_ASSERT_EQ(test, type, DRM_PLANE_TYPE_PRIMARY);
 
-   drm_plane_helper_add(plane, _dummy_plane_helper_funcs);
+   plane = drm_kunit_helper_create_primary_plane(test, drm,
+ NULL,
+ NULL,
+ NULL, 0,
+ NULL);
+   KUNIT_ASSERT_NOT_ERR_OR_NULL(test, plane);
 
return plane;
 }

-- 
2.44.0



[PATCH v11 27/28] drm/rockchip: inno_hdmi: Switch to HDMI connector

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

Reviewed-by: Heiko Stuebner 
Acked-by: Heiko Stuebner 
Signed-off-by: Maxime Ripard 
---
 drivers/gpu/drm/rockchip/Kconfig |   1 +
 drivers/gpu/drm/rockchip/inno_hdmi.c | 143 +--
 2 files changed, 53 insertions(+), 91 deletions(-)

diff --git a/drivers/gpu/drm/rockchip/Kconfig b/drivers/gpu/drm/rockchip/Kconfig
index 04300e5c6d14..82e04cebd108 100644
--- a/drivers/gpu/drm/rockchip/Kconfig
+++ b/drivers/gpu/drm/rockchip/Kconfig
@@ -72,10 +72,11 @@ config ROCKCHIP_DW_MIPI_DSI
  enable MIPI DSI on RK3288 or RK3399 based SoC, you should
  select this option.
 
 config ROCKCHIP_INNO_HDMI
bool "Rockchip specific extensions for Innosilicon HDMI"
+   depends on DRM_HDMI_STATE_HELPER
help
  This selects support for Rockchip SoC specific extensions
  for the Innosilicon HDMI driver. If you want to enable
  HDMI on RK3036 based SoC, you should select this option.
 
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
@@ -65,13 +65,11 @@ struct inno_hdmi {
const struct inno_hdmi_variant *variant;
 };
 
 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)
 {
struct rockchip_encoder *rkencoder = to_rockchip_encoder(encoder);
@@ -255,90 +253,53 @@ static void inno_hdmi_reset(struct inno_hdmi *hdmi)
hdmi_modb(hdmi, HDMI_SYS_CTRL, msk, val);
 
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;
-
-   if (type != HDMI_INFOFRAME_TYPE_AVI) {
-   drm_err(connector->dev,
-   "Unsupported infoframe type: %u\n", type);
-   return;
-   }
-
-   hdmi_writeb(hdmi, HDMI_CONTROL_PACKET_BUF_INDEX, INFOFRAME_AVI);
-}
-
-static int inno_hdmi_upload_frame(struct inno_hdmi *hdmi,
- union hdmi_infoframe *frame, enum 
hdmi_infoframe_type type)
-{
-   struct drm_connector *connector = >connector;
-   u8 packed_frame[HDMI_MAXIMUM_INFO_FRAME_SIZE];
-   ssize_t rc, i;
+   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 0;
}
 
-   inno_hdmi_disable_frame(hdmi, type);
+   hdmi_writeb(hdmi, HDMI_CONTROL_PACKET_BUF_INDEX, INFOFRAME_AVI);
 
-   rc = hdmi_infoframe_pack(frame, packed_frame,
-sizeof(packed_frame));
-   if (rc < 0)
-   return rc;
+   return 0;
+}
 
-   for (i = 0; i < rc; i++)
+static int inno_hdmi_upload_frame(struct drm_connector *connector,
+ enum hdmi_infoframe_type type,
+ const u8 *buffer, size_t len)
+{
+   struct inno_hdmi *hdmi = connector_to_inno_hdmi(connector);
+   u8 packed_frame[HDMI_MAXIMUM_INFO_FRAME_SIZE];
+   ssize_t i;
+
+   if (type != HDMI_INFOFRAME_TYPE_AVI) {
+   drm_err(connector->dev,
+   "Unsupported infoframe type: %u\n", type);
+   return 0;
+   }
+
+   inno_hdmi_disable_frame(connector, type);
+
+   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

[PATCH v11 28/28] drm/sun4i: hdmi: Switch to HDMI connector

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

Reviewed-by: Jernej Skrabec 
Acked-by: Sui Jingfeng 
Signed-off-by: Maxime Ripard 
---
 drivers/gpu/drm/sun4i/Kconfig  |  1 +
 drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c | 80 ++
 2 files changed, 52 insertions(+), 29 deletions(-)

diff --git a/drivers/gpu/drm/sun4i/Kconfig b/drivers/gpu/drm/sun4i/Kconfig
index 4741d9f6544c..cef3af4bd3a6 100644
--- a/drivers/gpu/drm/sun4i/Kconfig
+++ b/drivers/gpu/drm/sun4i/Kconfig
@@ -16,10 +16,11 @@ config DRM_SUN4I
 if DRM_SUN4I
 
 config DRM_SUN4I_HDMI
tristate "Allwinner A10/A10s/A20/A31 HDMI Controller Support"
depends on ARM || COMPILE_TEST
+   depends on DRM_HDMI_STATE_HELPER
default DRM_SUN4I
help
  Choose this option if you have an Allwinner A10/A10s/A20/A31
  SoC with an HDMI controller.
 
diff --git a/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c 
b/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c
index 2d1880c61b50..7ac085aa0a35 100644
--- a/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c
+++ b/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c
@@ -35,34 +35,28 @@
container_of_const(e, struct sun4i_hdmi, encoder)
 
 #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,
   struct drm_atomic_state *state)
 {
@@ -81,18 +75,22 @@ static void sun4i_hdmi_disable(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);
-   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,
   hdmi->base + SUN4I_HDMI_UNKNOWN_REG);
 
@@ -141,11 +139,12 @@ static void sun4i_hdmi_enable(struct drm_encoder *encoder,
 
writel(val, hdmi->base + SUN4I_HDMI_VID_TIMING_POL_REG);
 
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));
 
val = SUN4I_HDMI_VID_CTRL_ENABLE;
@@ -194,23 +193,26 @@ static int sun4i_hdmi_connector_atomic_check(struct 
drm_connector *connector,
struct drm_crtc_state *crtc_state = crtc->state;
struct drm_display_mode *mode = _state->adjusted_mode;
enum drm_mode_status status;
 
   

[PATCH v11 21/28] drm/connector: hdmi: Add Infoframes generation

2024-03-26 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/display/drm_hdmi_state_helper.c| 336 +
 drivers/gpu/drm/drm_connector.c|  14 +
 drivers/gpu/drm/tests/drm_connector_test.c |  12 +
 drivers/gpu/drm/tests/drm_hdmi_state_helper_test.c |   1 +
 include/drm/display/drm_hdmi_state_helper.h|   7 +
 include/drm/drm_connector.h| 109 +++
 6 files changed, 479 insertions(+)

diff --git a/drivers/gpu/drm/display/drm_hdmi_state_helper.c 
b/drivers/gpu/drm/display/drm_hdmi_state_helper.c
index e693fe51abf5..0fc97edac9ae 100644
--- a/drivers/gpu/drm/display/drm_hdmi_state_helper.c
+++ b/drivers/gpu/drm/display/drm_hdmi_state_helper.c
@@ -311,10 +311,148 @@ 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 *conn_state)
+{
+   const struct drm_display_mode *mode =
+   connector_state_get_mode(conn_state);
+   struct drm_connector_hdmi_infoframe *infoframe =
+   _state->hdmi.infoframes.avi;
+   struct hdmi_avi_infoframe *frame =
+   >data.avi;
+   bool is_full_range = conn_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 = conn_state->hdmi.output_format;
+
+   /*
+* FIXME: drm_hdmi_avi_infoframe_quant_range() doesn't handle
+* YUV formats at all at the moment, so if we ever support YUV
+* formats this needs to be revised.
+*/
+   drm_hdmi_avi_infoframe_quant_range(frame, connector, mode, 
rgb_quant_range);
+   drm_hdmi_avi_infoframe_colorimetry(frame, conn_state);
+   drm_hdmi_avi_infoframe_bars(frame, conn_state);
+
+   infoframe->set = true;
+
+   return 0;
+}
+
+static int hdmi_generate_spd_infoframe(const struct drm_connector *connector,
+  struct drm_connector_state *conn_state)
+{
+   struct drm_connector_hdmi_infoframe *infoframe =
+   _state->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 *conn_state)
+{
+   struct drm_connector_hdmi_infoframe *infoframe =
+   _state->hdmi.infoframes.hdr_drm;
+   struct hdmi_drm_infoframe *frame =
+   >data.drm;
+   int ret;
+
+   if (connector->max_bpc < 10)
+   return 0;
+
+   if (!conn_state->hdr_output_metadata)
+   return 0;
+
+   ret = drm_hdmi_infoframe_set_hdr_metadata(frame, conn_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 
*conn_state)
+{
+   const struct drm_display_info *info = >display_info;
+   const struct drm_display_mode *mode =
+   connector_state_get_mode(conn_state);
+   struct drm_connector_hdmi_infoframe *infoframe =
+   _state->hdmi.infoframes.hdmi;
+   struct hdmi_vendor_infoframe *frame =
+   >data.vendor.hdmi;
+   int ret;
+
+   if (!info->has_hdmi_infoframe)
+   return 0;
+
+   ret = drm_hdmi_vendor_infoframe_from_display_mode(frame, connector, 
mode);
+   if (ret)
+   return ret;
+
+   infoframe->set = true;
+
+   return 0;
+}
+
+static int
+hdmi_generate_infoframes(const struct drm_connector *connector,
+struct drm_connector_state *conn_state)
+{
+   const struct drm_display_info *info = >display_info;
+   int re

[PATCH v11 19/28] drm/connector: hdmi: Add RGB Quantization Range to the connector state

2024-03-26 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/display/drm_hdmi_state_helper.c | 29 +
 drivers/gpu/drm/drm_atomic.c|  1 +
 include/drm/drm_connector.h |  6 +
 3 files changed, 36 insertions(+)

diff --git a/drivers/gpu/drm/display/drm_hdmi_state_helper.c 
b/drivers/gpu/drm/display/drm_hdmi_state_helper.c
index c844cbeb675b..e693fe51abf5 100644
--- a/drivers/gpu/drm/display/drm_hdmi_state_helper.c
+++ b/drivers/gpu/drm/display/drm_hdmi_state_helper.c
@@ -49,10 +49,37 @@ connector_state_get_mode(const struct drm_connector_state 
*conn_state)
return NULL;
 
return _state->mode;
 }
 
+static bool hdmi_is_full_range(const struct drm_connector *connector,
+  const struct drm_connector_state *conn_state)
+{
+   const struct drm_display_info *display = >display_info;
+   const struct drm_display_mode *mode =
+   connector_state_get_mode(conn_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 (conn_state->hdmi.output_format != HDMI_COLORSPACE_RGB)
+   return false;
+
+   if (conn_state->hdmi.broadcast_rgb == DRM_HDMI_BROADCAST_RGB_FULL)
+   return true;
+
+   if (conn_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,
 const struct drm_display_mode *mode,
 unsigned int format, unsigned int bpc)
@@ -307,10 +334,12 @@ int drm_atomic_helper_connector_hdmi_check(struct 
drm_connector *connector,
drm_atomic_get_new_connector_state(state, connector);
const struct drm_display_mode *mode =
connector_state_get_mode(new_conn_state);
int ret;
 
+   new_conn_state->hdmi.is_full_range = hdmi_is_full_range(connector, 
new_conn_state);
+
ret = hdmi_compute_config(connector, new_conn_state, mode);
if (ret)
return ret;
 
if (old_conn_state->hdmi.broadcast_rgb != 
new_conn_state->hdmi.broadcast_rgb ||
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
@@ -1145,10 +1145,11 @@ 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, "\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));
drm_printf(p, "\ttmds_char_rate=%llu\n", 
state->hdmi.tmds_char_rate);
}
diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h
index a40eaf3a8ce4..f5e960e89de3 100644
--- a/include/drm/drm_connector.h
+++ b/include/drm/drm_connector.h
@@ -1068,10 +1068,16 @@ struct drm_connector_state {
 * @broadcast_rgb: Connector property to pass the
 * Broadcast RGB selection value.
 */
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.
 */
unsigned int output_bpc;
 

-- 
2.44.0



[PATCH v11 20/28] drm/tests: Add RGB Quantization tests

2024-03-26 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 
---
 drivers/gpu/drm/tests/drm_hdmi_state_helper_test.c | 355 +
 1 file changed, 355 insertions(+)

diff --git a/drivers/gpu/drm/tests/drm_hdmi_state_helper_test.c 
b/drivers/gpu/drm/tests/drm_hdmi_state_helper_test.c
index ff9a882201eb..84c081b99582 100644
--- a/drivers/gpu/drm/tests/drm_hdmi_state_helper_test.c
+++ b/drivers/gpu/drm/tests/drm_hdmi_state_helper_test.c
@@ -353,10 +353,354 @@ static void 
drm_test_check_broadcast_rgb_crtc_mode_not_changed(struct kunit *tes
crtc_state = drm_atomic_get_new_crtc_state(state, crtc);
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, crtc_state);
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);
+
+   drm = >drm;
+   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);
+
+  

[PATCH v11 24/28] drm/vc4: hdmi: Switch to HDMI connector

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

Acked-by: Sui Jingfeng 
Signed-off-by: Maxime Ripard 
---
 drivers/gpu/drm/vc4/Kconfig|   1 +
 drivers/gpu/drm/vc4/vc4_hdmi.c | 644 +
 drivers/gpu/drm/vc4/vc4_hdmi.h |  44 +--
 drivers/gpu/drm/vc4/vc4_hdmi_phy.c |   6 +-
 4 files changed, 92 insertions(+), 603 deletions(-)

diff --git a/drivers/gpu/drm/vc4/Kconfig b/drivers/gpu/drm/vc4/Kconfig
index 4801f8b64d3d..0d3629291a1f 100644
--- a/drivers/gpu/drm/vc4/Kconfig
+++ b/drivers/gpu/drm/vc4/Kconfig
@@ -3,10 +3,11 @@ config DRM_VC4
tristate "Broadcom VC4 Graphics"
depends on ARCH_BCM || ARCH_BCM2835 || COMPILE_TEST
depends on COMMON_CLK
depends on DRM
depends on DRM_DISPLAY_HDMI_HELPER
+   depends on DRM_DISPLAY_HDMI_STATE_HELPER
depends on DRM_DISPLAY_HELPER
depends on PM
# Make sure not 'y' when RASPBERRYPI_FIRMWARE is 'm'. This can only
# happen when COMPILE_TEST=y, hence the added !RASPBERRYPI_FIRMWARE.
depends on RASPBERRYPI_FIRMWARE || (COMPILE_TEST && 
!RASPBERRYPI_FIRMWARE)
diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
index 34f807ed1c31..14f2f3e9d78b 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
@@ -30,10 +30,11 @@
  * The driver does not yet support CEC control, though the HDMI
  * encoder block has CEC support.
  */
 
 #include 
+#include 
 #include 
 #include 
 #include 
 #include 
 #include 
@@ -108,29 +109,10 @@
 #define HSM_MIN_CLOCK_FREQ 12000
 #define CEC_CLOCK_FREQ 4
 
 #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;
 
lockdep_assert_held(_hdmi->mutex);
@@ -145,32 +127,17 @@ static bool vc4_hdmi_supports_scrambling(struct vc4_hdmi 
*vc4_hdmi)
return true;
 }
 
 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_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;
struct vc4_hdmi *vc4_hdmi = entry->file.data;
struct drm_device *drm = vc4_hdmi->connector.dev;
@@ -518,11 +485,11 @@ static int vc4_hdmi_connector_get_modes(struct 
drm_connector *connector)
if (!vc4->hvs->vc5_hdmi_enable_hdmi_20) {
struct drm_device *drm = connector->dev;
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.");

[PATCH v11 17/28] drm/connector: hdmi: Add Broadcast RGB property

2024-03-26 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 
Acked-by: Pekka Paalanen 
Reviewed-by: Sebastian Wick 
Signed-off-by: Maxime Ripard 
---
 Documentation/gpu/kms-properties.csv|  1 -
 drivers/gpu/drm/display/drm_hdmi_state_helper.c |  4 +-
 drivers/gpu/drm/drm_atomic.c|  2 +
 drivers/gpu/drm/drm_atomic_uapi.c   |  4 ++
 drivers/gpu/drm/drm_connector.c | 88 +
 include/drm/drm_connector.h | 36 ++
 6 files changed, 133 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
@@ -15,11 +15,10 @@ Owner Module/Drivers,Group,Property Name,Type,Property 
Values,Object attached,De
 ,,“saturation”,RANGE,"Min=0, Max=100",Connector,TBD
 ,,“hue”,RANGE,"Min=0, Max=100",Connector,TBD
 ,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
 ,,"""right_margin""",RANGE,"Min=0, Max= SDVO dependent",Connector,TBD
 ,,"""top_margin""",RANGE,"Min=0, Max= SDVO dependent",Connector,TBD
diff --git a/drivers/gpu/drm/display/drm_hdmi_state_helper.c 
b/drivers/gpu/drm/display/drm_hdmi_state_helper.c
index b9bc0fb027ea..c844cbeb675b 100644
--- a/drivers/gpu/drm/display/drm_hdmi_state_helper.c
+++ b/drivers/gpu/drm/display/drm_hdmi_state_helper.c
@@ -23,10 +23,11 @@ void __drm_atomic_helper_connector_hdmi_reset(struct 
drm_connector *connector,
 {
unsigned int max_bpc = connector->max_bpc;
 
new_conn_state->max_bpc = max_bpc;
new_conn_state->max_requested_bpc = max_bpc;
+   new_conn_state->hdmi.broadcast_rgb = DRM_HDMI_BROADCAST_RGB_AUTO;
 }
 EXPORT_SYMBOL(__drm_atomic_helper_connector_hdmi_reset);
 
 static const struct drm_display_mode *
 connector_state_get_mode(const struct drm_connector_state *conn_state)
@@ -310,11 +311,12 @@ int drm_atomic_helper_connector_hdmi_check(struct 
drm_connector *connector,
 
ret = hdmi_compute_config(connector, new_conn_state, mode);
if (ret)
return ret;
 
-   if (old_conn_state->hdmi.output_bpc != new_conn_state->hdmi.output_bpc 
||
+   if (old_conn_state->hdmi.broadcast_rgb != 
new_conn_state->hdmi.broadcast_rgb ||
+   old_conn_state->hdmi.output_bpc != new_conn_state->hdmi.output_bpc 
||
old_conn_state->hdmi.output_format != 
new_conn_state->hdmi.output_format) {
struct drm_crtc *crtc = new_conn_state->crtc;
struct drm_crtc_state *crtc_state;
 
crtc_state = drm_atomic_get_crtc_state(state, crtc);
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
@@ -1143,10 +1143,12 @@ static void drm_atomic_connector_print_state(struct 
drm_printer *p,
drm_printf(p, "\tmax_requested_bpc=%d\n", state->max_requested_bpc);
drm_printf(p, "\tcolorsp

[PATCH v11 18/28] drm/tests: Add tests for Broadcast RGB property

2024-03-26 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 
---
 drivers/gpu/drm/tests/drm_connector_test.c | 116 
 drivers/gpu/drm/tests/drm_hdmi_state_helper_test.c | 151 +
 2 files changed, 267 insertions(+)

diff --git a/drivers/gpu/drm/tests/drm_connector_test.c 
b/drivers/gpu/drm/tests/drm_connector_test.c
index 31fa9160213f..1d11f802c36d 100644
--- a/drivers/gpu/drm/tests/drm_connector_test.c
+++ b/drivers/gpu/drm/tests/drm_connector_test.c
@@ -564,10 +564,67 @@ static struct kunit_case 
drm_get_tv_mode_from_name_tests[] = {
 static struct kunit_suite drm_get_tv_mode_from_name_test_suite = {
.name = "drm_get_tv_mode_from_name",
.test_cases = drm_get_tv_mode_from_name_tests,
 };
 
+struct drm_hdmi_connector_get_broadcast_rgb_name_test {
+   unsigned int kind;
+   const char *expected_name;
+};
+
+#define BROADCAST_RGB_TEST(_kind, _name)   \
+   {   \
+   .kind = _kind,  \
+   .expected_name = _name, \
+   }
+
+static void drm_test_drm_hdmi_connector_get_broadcast_rgb_name(struct kunit 
*test)
+{
+   const struct drm_hdmi_connector_get_broadcast_rgb_name_test *params =
+   test->param_value;
+
+   KUNIT_EXPECT_STREQ(test,
+  
drm_hdmi_connector_get_broadcast_rgb_name(params->kind),
+  params->expected_name);
+}
+
+static const
+struct drm_hdmi_connector_get_broadcast_rgb_name_test
+drm_hdmi_connector_get_broadcast_rgb_name_valid_tests[] = {
+   BROADCAST_RGB_TEST(DRM_HDMI_BROADCAST_RGB_AUTO, "Automatic"),
+   BROADCAST_RGB_TEST(DRM_HDMI_BROADCAST_RGB_FULL, "Full"),
+   BROADCAST_RGB_TEST(DRM_HDMI_BROADCAST_RGB_LIMITED, "Limited 16:235"),
+};
+
+static void
+drm_hdmi_connector_get_broadcast_rgb_name_valid_desc(const struct 
drm_hdmi_connector_get_broadcast_rgb_name_test *t,
+char *desc)
+{
+   sprintf(desc, "%s", t->expected_name);
+}
+
+KUNIT_ARRAY_PARAM(drm_hdmi_connector_get_broadcast_rgb_name_valid,
+ drm_hdmi_connector_get_broadcast_rgb_name_valid_tests,
+ drm_hdmi_connector_get_broadcast_rgb_name_valid_desc);
+
+static void drm_test_drm_hdmi_connector_get_broadcast_rgb_name_invalid(struct 
kunit *test)
+{
+   KUNIT_EXPECT_NULL(test, drm_hdmi_connector_get_broadcast_rgb_name(3));
+};
+
+static struct kunit_case drm_hdmi_connector_get_broadcast_rgb_name_tests[] = {
+   KUNIT_CASE_PARAM(drm_test_drm_hdmi_connector_get_broadcast_rgb_name,
+
drm_hdmi_connector_get_broadcast_rgb_name_valid_gen_params),
+   KUNIT_CASE(drm_test_drm_hdmi_connector_get_broadcast_rgb_name_invalid),
+   { }
+};
+
+static struct kunit_suite drm_hdmi_connector_get_broadcast_rgb_name_test_suite 
= {
+   .name = "drm_hdmi_connector_get_broadcast_rgb_name",
+   .test_cases = drm_hdmi_connector_get_broadcast_rgb_name_tests,
+};
+
 struct drm_hdmi_connector_get_output_format_name_test {
unsigned int kind;
const char *expected_name;
 };
 
@@ -622,10 +679,67 @@ static struct kunit_case 
drm_hdmi_connector_get_output_format_name_tests[] = {
 static struct kunit_suite drm_hdmi_connector_get_output_format_name_test_suite 
= {
.name = "drm_hdmi_connector_get_output_format_name",
.test_cases = drm_hdmi_connector_get_output_format_name_tests,
 };
 
+static void drm_test_drm_connector_attach_broadcast_rgb_property(struct kunit 
*test)
+{
+   struct drm_connector_init_priv *priv = test->priv;
+   struct drm_connector *connector = >connector;
+   struct drm_property *prop;
+   int ret;
+
+   ret = drmm_connector_init(>drm, connector,
+ _funcs,
+ DRM_MODE_CONNECTOR_HDMIA,
+ >ddc);
+   KUNIT_ASSERT_EQ(test, ret, 0);
+
+   ret = drm_connector_attach_broadcast_rgb_property(connector);
+   KUNIT_ASSERT_EQ(test, ret, 0);
+
+   prop = connector->broadcast_rgb_property;
+   KUNIT_ASSERT_NOT_NULL(test, prop);
+   KUNIT_EXPECT_NOT_NULL(test, drm_mode_obj_find_prop_id(>base, 
prop->base.id));
+}
+
+static void 
drm_test_drm_connector_attach_broadcast_rgb_property_hdmi_connector(struct 
kunit *test)
+{
+   struct drm_connector_init_priv *priv = test->priv;
+   struct drm_connector *connector = >connector;
+   struct drm_property *prop;
+   int ret;
+
+   ret = drmm_connector_hdmi_init(>drm, connector,
+  _funcs,
+  

[PATCH v11 23/28] drm/connector: hdmi: Create Infoframe DebugFS entries

2024-03-26 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 | 152 ++
 1 file changed, 152 insertions(+)

diff --git a/drivers/gpu/drm/drm_debugfs.c b/drivers/gpu/drm/drm_debugfs.c
index 08fcefd804bc..dd39a5b7a711 100644
--- a/drivers/gpu/drm/drm_debugfs.c
+++ b/drivers/gpu/drm/drm_debugfs.c
@@ -518,10 +518,160 @@ static const struct file_operations drm_connector_fops = 
{
.llseek = seq_lseek,
.release = single_release,
.write = connector_write
 };
 
+#define HDMI_MAX_INFOFRAME_SIZE29
+
+static ssize_t
+audio_infoframe_read(struct file *filp, char __user *ubuf, size_t count, 
loff_t *ppos)
+{
+   struct drm_connector_hdmi_infoframe *infoframe;
+   struct drm_connector *connector;
+   union hdmi_infoframe *frame;
+   u8 buf[HDMI_INFOFRAME_SIZE(AUDIO)];
+   ssize_t len = 0;
+
+   connector = filp->private_data;
+   mutex_lock(>hdmi.infoframes.lock);
+
+   infoframe = >hdmi.infoframes.audio;
+   if (!infoframe->set)
+   goto out;
+
+   frame = >data;
+   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 audio_infoframe_fops = {
+   .owner   = THIS_MODULE,
+   .open= simple_open,
+   .read= audio_infoframe_read,
+};
+
+static int create_hdmi_audio_infoframe_file(struct drm_connector *connector,
+   struct dentry *parent)
+{
+   struct dentry *file;
+
+   file = debugfs_create_file("audio", 0400, parent, connector, 
_infoframe_fops);
+   if (IS_ERR(file))
+   return PTR_ERR(file);
+
+   return 0;
+}
+
+#define DEFINE_INFOFRAME_FILE(_f) \
+static ssize_t _f##_read_infoframe(struct file *filp, \
+  char __user *ubuf, \
+  size_t count,  \
+  loff_t *ppos)  \
+{ \
+   struct drm_connector_hdmi_infoframe *infoframe; \
+   struct drm_connector_state *conn_state; \
+   struct drm_connector *connector; \
+   union hdmi_infoframe *frame; \
+   struct drm_device *dev; \
+   u8 buf[HDMI_MAX_INFOFRAME_SIZE]; \
+   ssize_t len = 0; \
+   \
+   connector = filp->private_data; \
+   dev = connector->dev; \
+   \
+   drm_modeset_lock(>mode_config.connection_mutex, NULL); \
+   \
+   conn_state = connector->state; \
+   infoframe = _state->hdmi.infoframes._f; \
+   if (!infoframe->set) \
+   goto out; \
+   \
+   frame = >data; \
+   len = hdmi_infoframe_pack(frame, buf, sizeof(buf)); \
+   if (len < 0) \
+   goto out; \
+   \
+   len = simple_read_from_buffer(ubuf, count, ppos, buf, len); \
+   \
+out: \
+   drm_modeset_unlock(>mode_config.connection_mutex); \
+   return len; \
+} \
+\
+static const struct file_operations _f##_infoframe_fops = { \
+   .owner = THIS_MODULE, \
+   .open = simple_open, \
+   .read = _f##_read_infoframe, \
+}; \
+\
+static int create_hdmi_## _f ## _infoframe_file (struct drm_connector 
*connector, \
+struct dentry *parent) \
+{ \
+   struct dentry *file; \
+   \
+   file = debugfs_create_file(#_f, 0400, parent, connector, & _f ## 
_infoframe_fops); \
+   if (IS_ERR(file)) \
+   return PTR_ERR(file); \
+   \
+   return 0; \
+}
+
+DEFINE_INFOFRAME_FILE(avi);
+DEFINE_INFOFRAME_FILE(hdmi);
+DEFINE_INFOFRAME_FILE(hdr_drm);
+DEFINE_INFOFRAME_FILE(spd);
+
+static int create_hdmi_infoframe_files(struct drm_connector *connector,
+  struct dentry *parent)
+{
+   int ret;
+
+   ret = create_hdmi_audio_infoframe_file(connector, parent);
+   if (ret)
+   return ret;
+
+   ret = create_hdmi_avi_infoframe_file(connector, parent);
+   if (ret)
+   return ret;
+
+   ret = create_hdmi_hdmi_infoframe_file(connector, parent);
+   if (ret)
+   return ret;
+
+   ret = create_hdmi_hdr_drm_infoframe_file(connector, parent);
+   if (ret)
+   return ret;
+
+   ret = create_hdmi_spd_infoframe_file(connector, parent);
+   if (ret)
+  

[PATCH v11 22/28] drm/tests: Add infoframes test

2024-03-26 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 9129cee56975..9260aa378421 100644
--- a/drivers/gpu/drm/tests/drm_connector_test.c
+++ b/drivers/gpu/drm/tests/drm_connector_test.c
@@ -219,10 +219,221 @@ static void drm_test_connector_hdmi_init_null_ddc(struct 
kunit *test)
   BIT(HDMI_COLORSPACE_RGB),
   8);
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));
+}
+
+/*
+ * T

[PATCH v11 25/28] drm/vc4: tests: Remove vc4_dummy_plane structure

2024-03-26 Thread Maxime Ripard
The vc4_dummy_plane structure was introduced as a mean to add
mock-specific fields.

However, we never really used it and it's still strictly equivalent to
vc4_plane (which is in the same situation vs drm_plane), so we can
simply remove the vc4_dummy_plane structure and make the mock code
cleaner.

Reviewed-by: Maíra Canal 
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
@@ -107,20 +107,18 @@ 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);
 
crtc = _crtc->crtc.base;
for (i = 0; i < pipe->noutputs; i++) {
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
@@ -19,17 +19,12 @@ struct drm_crtc *vc4_find_crtc_for_encoder(struct kunit 
*test,
return crtc;
 
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
@@ -20,28 +20,24 @@ static const struct drm_plane_funcs vc4_dummy_plane_funcs = 
{
 
 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,
 
ARRAY_SIZE(vc4_dummy_plane_formats),
 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.44.0



[PATCH v11 16/28] drm/tests: Add HDMI connector bpc and format tests

2024-03-26 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 
---
 drivers/gpu/drm/tests/drm_hdmi_state_helper_test.c | 509 +
 drivers/gpu/drm/tests/drm_kunit_edid.h | 160 +++
 2 files changed, 669 insertions(+)

diff --git a/drivers/gpu/drm/tests/drm_hdmi_state_helper_test.c 
b/drivers/gpu/drm/tests/drm_hdmi_state_helper_test.c
index a49a544d7b49..968204781928 100644
--- a/drivers/gpu/drm/tests/drm_hdmi_state_helper_test.c
+++ b/drivers/gpu/drm/tests/drm_hdmi_state_helper_test.c
@@ -15,10 +15,11 @@
 #include 
 #include 
 #include 
 #include 
 
+#include 
 #include 
 
 #include "../drm_crtc_internal.h"
 
 #include 
@@ -370,10 +371,60 @@ static void 
drm_test_check_output_bpc_crtc_mode_not_changed(struct kunit *test)
crtc_state = drm_atomic_get_new_crtc_state(state, crtc);
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, crtc_state);
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
  */
 static void drm_test_check_tmds_char_rate_rgb_8bpc(struct kunit *test)
@@ -562,14 +613,472 @@ static void drm_test_check_hdmi_funcs_reject_rate(struct 
kunit *test)
 
ret = drm_atomic_check_only(state);
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

[PATCH v11 14/28] drm/tests: Add HDMI connector rate filter hook tests

2024-03-26 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 
---
 drivers/gpu/drm/tests/drm_hdmi_state_helper_test.c | 65 ++
 1 file changed, 65 insertions(+)

diff --git a/drivers/gpu/drm/tests/drm_hdmi_state_helper_test.c 
b/drivers/gpu/drm/tests/drm_hdmi_state_helper_test.c
index 7f9a48902db4..ead998a691e7 100644
--- a/drivers/gpu/drm/tests/drm_hdmi_state_helper_test.c
+++ b/drivers/gpu/drm/tests/drm_hdmi_state_helper_test.c
@@ -113,10 +113,22 @@ 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 =
connector_to_priv(connector);
const struct drm_edid *edid;
@@ -491,11 +503,64 @@ static void 
drm_test_check_tmds_char_rate_rgb_12bpc(struct kunit *test)
KUNIT_ASSERT_EQ(test, conn_state->hdmi.output_bpc, 12);
KUNIT_ASSERT_EQ(test, conn_state->hdmi.output_format, 
HDMI_COLORSPACE_RGB);
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),
KUNIT_CASE(drm_test_check_tmds_char_rate_rgb_10bpc),
KUNIT_CASE(drm_test_check_tmds_char_rate_rgb_12bpc),

-- 
2.44.0



[PATCH v11 15/28] drm/connector: hdmi: Compute bpc and format automatically

2024-03-26 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/display/drm_hdmi_state_helper.c| 197 -
 drivers/gpu/drm/tests/drm_hdmi_state_helper_test.c |  25 ++-
 2 files changed, 210 insertions(+), 12 deletions(-)

diff --git a/drivers/gpu/drm/display/drm_hdmi_state_helper.c 
b/drivers/gpu/drm/display/drm_hdmi_state_helper.c
index 063421835dba..b9bc0fb027ea 100644
--- a/drivers/gpu/drm/display/drm_hdmi_state_helper.c
+++ b/drivers/gpu/drm/display/drm_hdmi_state_helper.c
@@ -1,9 +1,11 @@
 // SPDX-License-Identifier: MIT
 
 #include 
 #include 
+#include 
+#include 
 
 #include 
 #include 
 
 /**
@@ -46,10 +48,110 @@ connector_state_get_mode(const struct drm_connector_state 
*conn_state)
return NULL;
 
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);
+
+   /*
+* CTA-861-F, section 5.4 - Color Coding & Quantization states
+* that the bpc must be 8, 10, 12 or 16 except for the default
+* 640x480 VIC1 where the value must be 8.
+*
+* The definition of default here is ambiguous but the spec
+* refers to VIC1 being the default timing in several occasions
+* so our understanding is that for the default timing (ie,
+* VIC1), the bpc must be 8.
+*/
+   if (vic == 1 && bpc != 8) {
+   drm_dbg_kms(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_kms(dev, "DVI Monitors require an RGB output at 8 
bpc\n");
+   return false;
+   }
+
+   if (!(connector->hdmi.supported_formats & BIT(format))) {
+   drm_dbg_kms(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_kms(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_kms(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_kms(dev, "12 BPC but sink doesn't support Deep 
Color 36.\n");
+   return false;
+   }
+
+   drm_dbg_kms(dev, "RGB format supported in that 
configuration.\n");
+
+   return true;
+
+   case HDMI_COLORSPACE_YUV422:
+   drm_dbg_kms(dev, "YUV422 format, checking the constraints.\n");
+
+   if (!(info->color_formats & DRM_COLOR_FORMAT_YCBCR422)) {
+   drm_dbg_kms(dev, "Sink doesn't support YUV422.\n");
+   return false;
+   }
+
+   if (bpc != 12) {
+   drm_dbg_kms(dev, "YUV422 only supports 12 bpc.\n");
+   return false;
+   }
+
+   drm_dbg_kms(dev, "YUV422 format supported in that 
configuration.\n");
+
+   return true;
+
+   case HDMI_COLORSPACE_YUV444:
+   drm_dbg_kms(dev, "YUV444 format, checking the constraints.\n");
+
+   if (!(info->color_formats & DRM_COLOR_FORMAT_YCBCR444)) {
+   drm_dbg_kms(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_kms(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_kms(dev, "12 BPC but sink doesn't support Deep 
Color 36.\n");
+  

  1   2   3   4   5   6   7   8   9   10   >