Re: [PATCH 3/7] drm/amd/display: Add handling for new "active color format" property
Hi, Am 10.01.24 um 18:15 schrieb Andri Yngvason: Hi Werner, mið., 10. jan. 2024 kl. 13:14 skrifaði Werner Sembach : Hi, Am 10.01.24 um 14:09 schrieb Daniel Vetter: On Wed, 10 Jan 2024 at 13:53, Andri Yngvason wrote: mið., 10. jan. 2024 kl. 11:10 skrifaði Daniel Vetter : On Tue, Jan 09, 2024 at 06:11:00PM +, Andri Yngvason wrote: + /* Extract information from crtc to communicate it to userspace as connector properties */ + for_each_new_connector_in_state(state, connector, new_con_state, i) { + struct drm_crtc *crtc = new_con_state->crtc; + struct dc_stream_state *stream; + + if (crtc) { + new_crtc_state = drm_atomic_get_new_crtc_state(state, crtc); + dm_new_crtc_state = to_dm_crtc_state(new_crtc_state); + stream = dm_new_crtc_state->stream; + + if (stream) { + drm_connector_set_active_color_format_property(connector, + convert_dc_pixel_encoding_into_drm_color_format( + dm_new_crtc_state->stream->timing.pixel_encoding)); + } + } else { + drm_connector_set_active_color_format_property(connector, 0); Just realized an even bigger reason why your current design doesn't work: You don't have locking here. And you cannot grab the required lock, which is drm_dev->mode_config.mutex, because that would result in deadlocks. So this really needs to use the atomic state based design I've described. Maybe we should just drop "actual color format" and instead fail the modeset if the "preferred color format" property cannot be satisfied? It seems like the simplest thing to do here, though it is perhaps less convenient for userspace. In that case, the "preferred color format" property should just be called "color format". Yeah that's more in line with how other atomic properties work. This way userspace can figure out what works with a TEST_ONLY commit too. And for this to work you probably want to have an "automatic" setting too. -Sima The problem with TEST_ONLY probing is that color format settings are interdependent: https://gitlab.freedesktop.org/drm/amd/-/issues/476#note_966634 So changing any other setting may require every color format to be TEST_ONLY probed again. If we put a bit map containing the possible color formats into drm_mode_mode_info (I'm thinking that it could go into flags), we'd be able to eliminate a bunch of combinations early on. Do you think that would make things more bearable? That would eliminate some, but note that for example YCBCR444 needs a faster pixel clock then YCBCR420, so it's interdependent with everything else that changes the required pixel clock like bpc, resolution and refresh rate. So the config space is n-dimensional with no "right angle box" clearly separating working from non working combinations. But I just had the idea: Currently in KDE and Gnome UI you first select the resolution, to then wee what refresh rates are available. So I guess this concept could be appended to color properties -> Define a sequence for the different properties to be applied across all drivers and as soon as you select one, the next property in the sequence is TEST_ONLYed. e.g.: 1. Select resolution -> Available refresh rates are updated 2. Select refresh rate -> Available color formats are updated 3. Select color format -> Available bpc are updated etc. So you can't select a bpc that doesn't fit your current color format. Changing color format can change the available bpc. One maybe counter intuitive thing here is that color format "auto" might not have all bpc settings available, as auto will for example actually be RGB which has higher pixel clock requirements then ycbcr420. And in this model, color format is always decided first. Or vice versa if bpc is decided to be before color format in the sequence. I'm thinking, something like this: diff --git a/include/uapi/drm/drm_mode.h b/include/uapi/drm/drm_mode.h index 128d09138ceb3..59980803cb89e 100644 --- a/include/uapi/drm/drm_mode.h +++ b/include/uapi/drm/drm_mode.h @@ -124,6 +124,13 @@ extern "C" { #define DRM_MODE_FLAG_PIC_AR_256_135 \ (DRM_MODE_PICTURE_ASPECT_256_135<<19) +/* Possible color formats (4 bits) */ +#define DRM_MODE_FLAG_COLOR_FORMAT_MASK (0x0f << 22) +#define DRM_MODE_FLAG_COLOR_FORMAT_RGB (1 << 22) +#define DRM_MODE_FLAG_COLOR_FORMAT_YCBCR444 (1 << 23) +#define DRM_MODE_FLAG_COLOR_FORMAT_YCBCR422 (1 << 24) +#define DRM_MODE_FLAG_COLOR_FORMAT_YCBCR420 (1 << 25) + #define DRM_MODE_FLAG_ALL (DRM_MODE_FLAG_PHSYNC | \ DRM_MODE_FLAG_NHSYNC | \ DRM_MODE_FLAG_PVSYNC | \ @@ -136,7 +143,8 @@ extern "C" { DRM_MODE_FLAG_HSKEW | \
Re: [PATCH 3/7] drm/amd/display: Add handling for new "active color format" property
Hi Werner, mið., 10. jan. 2024 kl. 13:14 skrifaði Werner Sembach : > > Hi, > > Am 10.01.24 um 14:09 schrieb Daniel Vetter: > > On Wed, 10 Jan 2024 at 13:53, Andri Yngvason wrote: > >> mið., 10. jan. 2024 kl. 11:10 skrifaði Daniel Vetter : > >>> On Tue, Jan 09, 2024 at 06:11:00PM +, Andri Yngvason wrote: > + /* Extract information from crtc to communicate it to userspace as > connector properties */ > + for_each_new_connector_in_state(state, connector, new_con_state, > i) { > + struct drm_crtc *crtc = new_con_state->crtc; > + struct dc_stream_state *stream; > + > + if (crtc) { > + new_crtc_state = > drm_atomic_get_new_crtc_state(state, crtc); > + dm_new_crtc_state = > to_dm_crtc_state(new_crtc_state); > + stream = dm_new_crtc_state->stream; > + > + if (stream) { > + > drm_connector_set_active_color_format_property(connector, > + > convert_dc_pixel_encoding_into_drm_color_format( > + > dm_new_crtc_state->stream->timing.pixel_encoding)); > + } > + } else { > + > drm_connector_set_active_color_format_property(connector, 0); > >>> Just realized an even bigger reason why your current design doesn't work: > >>> You don't have locking here. > >>> > >>> And you cannot grab the required lock, which is > >>> drm_dev->mode_config.mutex, because that would result in deadlocks. So > >>> this really needs to use the atomic state based design I've described. > >>> > >> Maybe we should just drop "actual color format" and instead fail the > >> modeset if the "preferred color format" property cannot be satisfied? > >> It seems like the simplest thing to do here, though it is perhaps less > >> convenient for userspace. In that case, the "preferred color format" > >> property should just be called "color format". > > Yeah that's more in line with how other atomic properties work. This > > way userspace can figure out what works with a TEST_ONLY commit too. > > And for this to work you probably want to have an "automatic" setting > > too. > > -Sima > > The problem with TEST_ONLY probing is that color format settings are > interdependent: > https://gitlab.freedesktop.org/drm/amd/-/issues/476#note_966634 > > So changing any other setting may require every color format to be TEST_ONLY > probed again. > If we put a bit map containing the possible color formats into drm_mode_mode_info (I'm thinking that it could go into flags), we'd be able to eliminate a bunch of combinations early on. Do you think that would make things more bearable? I'm thinking, something like this: diff --git a/include/uapi/drm/drm_mode.h b/include/uapi/drm/drm_mode.h index 128d09138ceb3..59980803cb89e 100644 --- a/include/uapi/drm/drm_mode.h +++ b/include/uapi/drm/drm_mode.h @@ -124,6 +124,13 @@ extern "C" { #define DRM_MODE_FLAG_PIC_AR_256_135 \ (DRM_MODE_PICTURE_ASPECT_256_135<<19) +/* Possible color formats (4 bits) */ +#define DRM_MODE_FLAG_COLOR_FORMAT_MASK (0x0f << 22) +#define DRM_MODE_FLAG_COLOR_FORMAT_RGB (1 << 22) +#define DRM_MODE_FLAG_COLOR_FORMAT_YCBCR444 (1 << 23) +#define DRM_MODE_FLAG_COLOR_FORMAT_YCBCR422 (1 << 24) +#define DRM_MODE_FLAG_COLOR_FORMAT_YCBCR420 (1 << 25) + #define DRM_MODE_FLAG_ALL (DRM_MODE_FLAG_PHSYNC | \ DRM_MODE_FLAG_NHSYNC | \ DRM_MODE_FLAG_PVSYNC | \ @@ -136,7 +143,8 @@ extern "C" { DRM_MODE_FLAG_HSKEW | \ DRM_MODE_FLAG_DBLCLK | \ DRM_MODE_FLAG_CLKDIV2 |\ -DRM_MODE_FLAG_3D_MASK) +DRM_MODE_FLAG_3D_MASK |\ +DRM_MODE_FLAG_COLOR_FORMAT_MASK) /* DPMS flags */ /* bit compatible with the xorg definitions. */
Re: [PATCH 3/7] drm/amd/display: Add handling for new "active color format" property
Hi, Am 10.01.24 um 14:09 schrieb Daniel Vetter: On Wed, 10 Jan 2024 at 13:53, Andri Yngvason wrote: mið., 10. jan. 2024 kl. 11:10 skrifaði Daniel Vetter : On Tue, Jan 09, 2024 at 06:11:00PM +, Andri Yngvason wrote: + /* Extract information from crtc to communicate it to userspace as connector properties */ + for_each_new_connector_in_state(state, connector, new_con_state, i) { + struct drm_crtc *crtc = new_con_state->crtc; + struct dc_stream_state *stream; + + if (crtc) { + new_crtc_state = drm_atomic_get_new_crtc_state(state, crtc); + dm_new_crtc_state = to_dm_crtc_state(new_crtc_state); + stream = dm_new_crtc_state->stream; + + if (stream) { + drm_connector_set_active_color_format_property(connector, + convert_dc_pixel_encoding_into_drm_color_format( + dm_new_crtc_state->stream->timing.pixel_encoding)); + } + } else { + drm_connector_set_active_color_format_property(connector, 0); Just realized an even bigger reason why your current design doesn't work: You don't have locking here. And you cannot grab the required lock, which is drm_dev->mode_config.mutex, because that would result in deadlocks. So this really needs to use the atomic state based design I've described. Maybe we should just drop "actual color format" and instead fail the modeset if the "preferred color format" property cannot be satisfied? It seems like the simplest thing to do here, though it is perhaps less convenient for userspace. In that case, the "preferred color format" property should just be called "color format". Yeah that's more in line with how other atomic properties work. This way userspace can figure out what works with a TEST_ONLY commit too. And for this to work you probably want to have an "automatic" setting too. -Sima The problem with TEST_ONLY probing is that color format settings are interdependent: https://gitlab.freedesktop.org/drm/amd/-/issues/476#note_966634 So changing any other setting may require every color format to be TEST_ONLY probed again. Greetings Werner
Re: [PATCH 3/7] drm/amd/display: Add handling for new "active color format" property
On Wed, 10 Jan 2024 at 13:53, Andri Yngvason wrote: > > mið., 10. jan. 2024 kl. 11:10 skrifaði Daniel Vetter : > > > > On Tue, Jan 09, 2024 at 06:11:00PM +, Andri Yngvason wrote: > > > + /* Extract information from crtc to communicate it to userspace as > > > connector properties */ > > > + for_each_new_connector_in_state(state, connector, new_con_state, i) > > > { > > > + struct drm_crtc *crtc = new_con_state->crtc; > > > + struct dc_stream_state *stream; > > > + > > > + if (crtc) { > > > + new_crtc_state = > > > drm_atomic_get_new_crtc_state(state, crtc); > > > + dm_new_crtc_state = > > > to_dm_crtc_state(new_crtc_state); > > > + stream = dm_new_crtc_state->stream; > > > + > > > + if (stream) { > > > + > > > drm_connector_set_active_color_format_property(connector, > > > + > > > convert_dc_pixel_encoding_into_drm_color_format( > > > + > > > dm_new_crtc_state->stream->timing.pixel_encoding)); > > > + } > > > + } else { > > > + > > > drm_connector_set_active_color_format_property(connector, 0); > > > > Just realized an even bigger reason why your current design doesn't work: > > You don't have locking here. > > > > And you cannot grab the required lock, which is > > drm_dev->mode_config.mutex, because that would result in deadlocks. So > > this really needs to use the atomic state based design I've described. > > > > Maybe we should just drop "actual color format" and instead fail the > modeset if the "preferred color format" property cannot be satisfied? > It seems like the simplest thing to do here, though it is perhaps less > convenient for userspace. In that case, the "preferred color format" > property should just be called "color format". Yeah that's more in line with how other atomic properties work. This way userspace can figure out what works with a TEST_ONLY commit too. And for this to work you probably want to have an "automatic" setting too. -Sima -- Daniel Vetter Software Engineer, Intel Corporation http://blog.ffwll.ch
Re: [PATCH 3/7] drm/amd/display: Add handling for new "active color format" property
mið., 10. jan. 2024 kl. 11:10 skrifaði Daniel Vetter : > > On Tue, Jan 09, 2024 at 06:11:00PM +, Andri Yngvason wrote: > > + /* Extract information from crtc to communicate it to userspace as > > connector properties */ > > + for_each_new_connector_in_state(state, connector, new_con_state, i) { > > + struct drm_crtc *crtc = new_con_state->crtc; > > + struct dc_stream_state *stream; > > + > > + if (crtc) { > > + new_crtc_state = drm_atomic_get_new_crtc_state(state, > > crtc); > > + dm_new_crtc_state = to_dm_crtc_state(new_crtc_state); > > + stream = dm_new_crtc_state->stream; > > + > > + if (stream) { > > + > > drm_connector_set_active_color_format_property(connector, > > + > > convert_dc_pixel_encoding_into_drm_color_format( > > + > > dm_new_crtc_state->stream->timing.pixel_encoding)); > > + } > > + } else { > > + > > drm_connector_set_active_color_format_property(connector, 0); > > Just realized an even bigger reason why your current design doesn't work: > You don't have locking here. > > And you cannot grab the required lock, which is > drm_dev->mode_config.mutex, because that would result in deadlocks. So > this really needs to use the atomic state based design I've described. > Maybe we should just drop "actual color format" and instead fail the modeset if the "preferred color format" property cannot be satisfied? It seems like the simplest thing to do here, though it is perhaps less convenient for userspace. In that case, the "preferred color format" property should just be called "color format". Thanks, Andri
Re: [PATCH 3/7] drm/amd/display: Add handling for new "active color format" property
On Tue, Jan 09, 2024 at 06:11:00PM +, Andri Yngvason wrote: > From: Werner Sembach > > This commit implements the "active color format" drm property for the AMD > GPU driver. > > Signed-off-by: Werner Sembach > Signed-off-by: Andri Yngvason > Tested-by: Andri Yngvason > --- > .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 42 ++- > .../display/amdgpu_dm/amdgpu_dm_mst_types.c | 4 ++ > 2 files changed, 45 insertions(+), 1 deletion(-) > > diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c > b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c > index 10e041a3b2545..b44d06c3b1706 100644 > --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c > +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c > @@ -6882,6 +6882,24 @@ int convert_dc_color_depth_into_bpc(enum > dc_color_depth display_color_depth) > return 0; > } > > +static int convert_dc_pixel_encoding_into_drm_color_format( > + enum dc_pixel_encoding display_pixel_encoding) > +{ > + switch (display_pixel_encoding) { > + case PIXEL_ENCODING_RGB: > + return DRM_COLOR_FORMAT_RGB444; > + case PIXEL_ENCODING_YCBCR422: > + return DRM_COLOR_FORMAT_YCBCR422; > + case PIXEL_ENCODING_YCBCR444: > + return DRM_COLOR_FORMAT_YCBCR444; > + case PIXEL_ENCODING_YCBCR420: > + return DRM_COLOR_FORMAT_YCBCR420; > + default: > + break; > + } > + return 0; > +} > + > static int dm_encoder_helper_atomic_check(struct drm_encoder *encoder, > struct drm_crtc_state *crtc_state, > struct drm_connector_state > *conn_state) > @@ -7436,8 +7454,10 @@ void amdgpu_dm_connector_init_helper(struct > amdgpu_display_manager *dm, > adev->mode_info.underscan_vborder_property, > 0); > > - if (!aconnector->mst_root) > + if (!aconnector->mst_root) { > drm_connector_attach_max_bpc_property(>base, 8, 16); > + > drm_connector_attach_active_color_format_property(>base); > + } > > aconnector->base.state->max_bpc = 16; > aconnector->base.state->max_requested_bpc = > aconnector->base.state->max_bpc; > @@ -8969,6 +8989,26 @@ static void amdgpu_dm_atomic_commit_tail(struct > drm_atomic_state *state) > kfree(dummy_updates); > } > > + /* Extract information from crtc to communicate it to userspace as > connector properties */ > + for_each_new_connector_in_state(state, connector, new_con_state, i) { > + struct drm_crtc *crtc = new_con_state->crtc; > + struct dc_stream_state *stream; > + > + if (crtc) { > + new_crtc_state = drm_atomic_get_new_crtc_state(state, > crtc); > + dm_new_crtc_state = to_dm_crtc_state(new_crtc_state); > + stream = dm_new_crtc_state->stream; > + > + if (stream) { > + > drm_connector_set_active_color_format_property(connector, > + > convert_dc_pixel_encoding_into_drm_color_format( > + > dm_new_crtc_state->stream->timing.pixel_encoding)); > + } > + } else { > + > drm_connector_set_active_color_format_property(connector, 0); Just realized an even bigger reason why your current design doesn't work: You don't have locking here. And you cannot grab the required lock, which is drm_dev->mode_config.mutex, because that would result in deadlocks. So this really needs to use the atomic state based design I've described. A bit a tanget, but it would be really good to add a lockdep assert into drm_object_property_set_value, that at least for atomic drivers and connectors the above lock must be held for changing property values. But it will be quite a bit of audit to make sure all current users obey that rule. Cheers, Sima > + } > + } > + > /** >* Enable interrupts for CRTCs that are newly enabled or went through >* a modeset. It was intentionally deferred until after the front end > diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c > b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c > index 11da0eebee6c4..a4d1b3ea8f81c 100644 > --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c > +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c > @@ -600,6 +600,10 @@ dm_dp_add_mst_connector(struct drm_dp_mst_topology_mgr > *mgr, > if (connector->max_bpc_property) > drm_connector_attach_max_bpc_property(connector, 8, 16); > > + connector->active_color_format_property = > master->base.active_color_format_property; > + if (connector->active_color_format_property) > + >
[PATCH 3/7] drm/amd/display: Add handling for new "active color format" property
From: Werner Sembach This commit implements the "active color format" drm property for the AMD GPU driver. Signed-off-by: Werner Sembach Signed-off-by: Andri Yngvason Tested-by: Andri Yngvason --- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 42 ++- .../display/amdgpu_dm/amdgpu_dm_mst_types.c | 4 ++ 2 files changed, 45 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 10e041a3b2545..b44d06c3b1706 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -6882,6 +6882,24 @@ int convert_dc_color_depth_into_bpc(enum dc_color_depth display_color_depth) return 0; } +static int convert_dc_pixel_encoding_into_drm_color_format( + enum dc_pixel_encoding display_pixel_encoding) +{ + switch (display_pixel_encoding) { + case PIXEL_ENCODING_RGB: + return DRM_COLOR_FORMAT_RGB444; + case PIXEL_ENCODING_YCBCR422: + return DRM_COLOR_FORMAT_YCBCR422; + case PIXEL_ENCODING_YCBCR444: + return DRM_COLOR_FORMAT_YCBCR444; + case PIXEL_ENCODING_YCBCR420: + return DRM_COLOR_FORMAT_YCBCR420; + default: + break; + } + return 0; +} + static int dm_encoder_helper_atomic_check(struct drm_encoder *encoder, struct drm_crtc_state *crtc_state, struct drm_connector_state *conn_state) @@ -7436,8 +7454,10 @@ void amdgpu_dm_connector_init_helper(struct amdgpu_display_manager *dm, adev->mode_info.underscan_vborder_property, 0); - if (!aconnector->mst_root) + if (!aconnector->mst_root) { drm_connector_attach_max_bpc_property(>base, 8, 16); + drm_connector_attach_active_color_format_property(>base); + } aconnector->base.state->max_bpc = 16; aconnector->base.state->max_requested_bpc = aconnector->base.state->max_bpc; @@ -8969,6 +8989,26 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state) kfree(dummy_updates); } + /* Extract information from crtc to communicate it to userspace as connector properties */ + for_each_new_connector_in_state(state, connector, new_con_state, i) { + struct drm_crtc *crtc = new_con_state->crtc; + struct dc_stream_state *stream; + + if (crtc) { + new_crtc_state = drm_atomic_get_new_crtc_state(state, crtc); + dm_new_crtc_state = to_dm_crtc_state(new_crtc_state); + stream = dm_new_crtc_state->stream; + + if (stream) { + drm_connector_set_active_color_format_property(connector, + convert_dc_pixel_encoding_into_drm_color_format( + dm_new_crtc_state->stream->timing.pixel_encoding)); + } + } else { + drm_connector_set_active_color_format_property(connector, 0); + } + } + /** * Enable interrupts for CRTCs that are newly enabled or went through * a modeset. It was intentionally deferred until after the front end diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c index 11da0eebee6c4..a4d1b3ea8f81c 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c @@ -600,6 +600,10 @@ dm_dp_add_mst_connector(struct drm_dp_mst_topology_mgr *mgr, if (connector->max_bpc_property) drm_connector_attach_max_bpc_property(connector, 8, 16); + connector->active_color_format_property = master->base.active_color_format_property; + if (connector->active_color_format_property) + drm_connector_attach_active_color_format_property(>base); + connector->vrr_capable_property = master->base.vrr_capable_property; if (connector->vrr_capable_property) drm_connector_attach_vrr_capable_property(connector); -- 2.43.0