Re: [PATCH v3 1/4] drm: add devm release action
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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"
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
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
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
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
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
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
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
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
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
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
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
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
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()`
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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"); +