Skip to content

Commit cbd14ae

Browse files
Stylon Wangalexdeucher
authored andcommitted
drm/amd/display: Fix incorrectly pruned modes with deep color
[Why] When "max bpc" is set to enable deep color, some modes are removed from the list if they fail validation on max bpc. These modes should be kept if they validates fine with lower bpc. [How] - Retry with lower bpc in mode validation. - Same in atomic commit to apply working bpc, not necessarily max bpc. Signed-off-by: Stylon Wang <stylon.wang@amd.com> Reviewed-by: Nicholas Kazlauskas <Nicholas.Kazlauskas@amd.com> Acked-by: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
1 parent fdcf62f commit cbd14ae

1 file changed

Lines changed: 64 additions & 38 deletions

File tree

drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c

Lines changed: 64 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -3840,8 +3840,7 @@ static void update_stream_scaling_settings(const struct drm_display_mode *mode,
38403840

38413841
static enum dc_color_depth
38423842
convert_color_depth_from_display_info(const struct drm_connector *connector,
3843-
const struct drm_connector_state *state,
3844-
bool is_y420)
3843+
bool is_y420, int requested_bpc)
38453844
{
38463845
uint8_t bpc;
38473846

@@ -3861,10 +3860,7 @@ convert_color_depth_from_display_info(const struct drm_connector *connector,
38613860
bpc = bpc ? bpc : 8;
38623861
}
38633862

3864-
if (!state)
3865-
state = connector->state;
3866-
3867-
if (state) {
3863+
if (requested_bpc > 0) {
38683864
/*
38693865
* Cap display bpc based on the user requested value.
38703866
*
@@ -3873,7 +3869,7 @@ convert_color_depth_from_display_info(const struct drm_connector *connector,
38733869
* or if this was called outside of atomic check, so it
38743870
* can't be used directly.
38753871
*/
3876-
bpc = min(bpc, state->max_requested_bpc);
3872+
bpc = min_t(u8, bpc, requested_bpc);
38773873

38783874
/* Round down to the nearest even number. */
38793875
bpc = bpc - (bpc & 1);
@@ -3995,7 +3991,8 @@ static void fill_stream_properties_from_drm_display_mode(
39953991
const struct drm_display_mode *mode_in,
39963992
const struct drm_connector *connector,
39973993
const struct drm_connector_state *connector_state,
3998-
const struct dc_stream_state *old_stream)
3994+
const struct dc_stream_state *old_stream,
3995+
int requested_bpc)
39993996
{
40003997
struct dc_crtc_timing *timing_out = &stream->timing;
40013998
const struct drm_display_info *info = &connector->display_info;
@@ -4025,8 +4022,9 @@ static void fill_stream_properties_from_drm_display_mode(
40254022

40264023
timing_out->timing_3d_format = TIMING_3D_FORMAT_NONE;
40274024
timing_out->display_color_depth = convert_color_depth_from_display_info(
4028-
connector, connector_state,
4029-
(timing_out->pixel_encoding == PIXEL_ENCODING_YCBCR420));
4025+
connector,
4026+
(timing_out->pixel_encoding == PIXEL_ENCODING_YCBCR420),
4027+
requested_bpc);
40304028
timing_out->scan_type = SCANNING_TYPE_NODATA;
40314029
timing_out->hdmi_vic = 0;
40324030

@@ -4232,7 +4230,8 @@ static struct dc_stream_state *
42324230
create_stream_for_sink(struct amdgpu_dm_connector *aconnector,
42334231
const struct drm_display_mode *drm_mode,
42344232
const struct dm_connector_state *dm_state,
4235-
const struct dc_stream_state *old_stream)
4233+
const struct dc_stream_state *old_stream,
4234+
int requested_bpc)
42364235
{
42374236
struct drm_display_mode *preferred_mode = NULL;
42384237
struct drm_connector *drm_connector;
@@ -4317,10 +4316,10 @@ create_stream_for_sink(struct amdgpu_dm_connector *aconnector,
43174316
*/
43184317
if (!scale || mode_refresh != preferred_refresh)
43194318
fill_stream_properties_from_drm_display_mode(stream,
4320-
&mode, &aconnector->base, con_state, NULL);
4319+
&mode, &aconnector->base, con_state, NULL, requested_bpc);
43214320
else
43224321
fill_stream_properties_from_drm_display_mode(stream,
4323-
&mode, &aconnector->base, con_state, old_stream);
4322+
&mode, &aconnector->base, con_state, old_stream, requested_bpc);
43244323

43254324
stream->timing.flags.DSC = 0;
43264325

@@ -4839,16 +4838,54 @@ static void handle_edid_mgmt(struct amdgpu_dm_connector *aconnector)
48394838
create_eml_sink(aconnector);
48404839
}
48414840

4841+
static struct dc_stream_state *
4842+
create_validate_stream_for_sink(struct amdgpu_dm_connector *aconnector,
4843+
const struct drm_display_mode *drm_mode,
4844+
const struct dm_connector_state *dm_state,
4845+
const struct dc_stream_state *old_stream)
4846+
{
4847+
struct drm_connector *connector = &aconnector->base;
4848+
struct amdgpu_device *adev = connector->dev->dev_private;
4849+
struct dc_stream_state *stream;
4850+
int requested_bpc = connector->state ? connector->state->max_requested_bpc : 8;
4851+
enum dc_status dc_result = DC_OK;
4852+
4853+
do {
4854+
stream = create_stream_for_sink(aconnector, drm_mode,
4855+
dm_state, old_stream,
4856+
requested_bpc);
4857+
if (stream == NULL) {
4858+
DRM_ERROR("Failed to create stream for sink!\n");
4859+
break;
4860+
}
4861+
4862+
dc_result = dc_validate_stream(adev->dm.dc, stream);
4863+
4864+
if (dc_result != DC_OK) {
4865+
DRM_DEBUG_KMS("Mode %dx%d (clk %d) failed DC validation with error %d\n",
4866+
drm_mode->hdisplay,
4867+
drm_mode->vdisplay,
4868+
drm_mode->clock,
4869+
dc_result);
4870+
4871+
dc_stream_release(stream);
4872+
stream = NULL;
4873+
requested_bpc -= 2; /* lower bpc to retry validation */
4874+
}
4875+
4876+
} while (stream == NULL && requested_bpc >= 6);
4877+
4878+
return stream;
4879+
}
4880+
48424881
enum drm_mode_status amdgpu_dm_connector_mode_valid(struct drm_connector *connector,
48434882
struct drm_display_mode *mode)
48444883
{
48454884
int result = MODE_ERROR;
48464885
struct dc_sink *dc_sink;
4847-
struct amdgpu_device *adev = connector->dev->dev_private;
48484886
/* TODO: Unhardcode stream count */
48494887
struct dc_stream_state *stream;
48504888
struct amdgpu_dm_connector *aconnector = to_amdgpu_dm_connector(connector);
4851-
enum dc_status dc_result = DC_OK;
48524889

48534890
if ((mode->flags & DRM_MODE_FLAG_INTERLACE) ||
48544891
(mode->flags & DRM_MODE_FLAG_DBLSCAN))
@@ -4869,24 +4906,11 @@ enum drm_mode_status amdgpu_dm_connector_mode_valid(struct drm_connector *connec
48694906
goto fail;
48704907
}
48714908

4872-
stream = create_stream_for_sink(aconnector, mode, NULL, NULL);
4873-
if (stream == NULL) {
4874-
DRM_ERROR("Failed to create stream for sink!\n");
4875-
goto fail;
4876-
}
4877-
4878-
dc_result = dc_validate_stream(adev->dm.dc, stream);
4879-
4880-
if (dc_result == DC_OK)
4909+
stream = create_validate_stream_for_sink(aconnector, mode, NULL, NULL);
4910+
if (stream) {
4911+
dc_stream_release(stream);
48814912
result = MODE_OK;
4882-
else
4883-
DRM_DEBUG_KMS("Mode %dx%d (clk %d) failed DC validation with error %d\n",
4884-
mode->hdisplay,
4885-
mode->vdisplay,
4886-
mode->clock,
4887-
dc_result);
4888-
4889-
dc_stream_release(stream);
4913+
}
48904914

48914915
fail:
48924916
/* TODO: error handling*/
@@ -5209,10 +5233,12 @@ static int dm_encoder_helper_atomic_check(struct drm_encoder *encoder,
52095233
return 0;
52105234

52115235
if (!state->duplicated) {
5236+
int max_bpc = conn_state->max_requested_bpc;
52125237
is_y420 = drm_mode_is_420_also(&connector->display_info, adjusted_mode) &&
52135238
aconnector->force_yuv420_output;
5214-
color_depth = convert_color_depth_from_display_info(connector, conn_state,
5215-
is_y420);
5239+
color_depth = convert_color_depth_from_display_info(connector,
5240+
is_y420,
5241+
max_bpc);
52165242
bpp = convert_dc_color_depth_into_bpc(color_depth) * 3;
52175243
clock = adjusted_mode->clock;
52185244
dm_new_connector_state->pbn = drm_dp_calc_pbn_mode(clock, bpp, false);
@@ -7642,10 +7668,10 @@ static int dm_update_crtc_state(struct amdgpu_display_manager *dm,
76427668
if (!drm_atomic_crtc_needs_modeset(new_crtc_state))
76437669
goto skip_modeset;
76447670

7645-
new_stream = create_stream_for_sink(aconnector,
7646-
&new_crtc_state->mode,
7647-
dm_new_conn_state,
7648-
dm_old_crtc_state->stream);
7671+
new_stream = create_validate_stream_for_sink(aconnector,
7672+
&new_crtc_state->mode,
7673+
dm_new_conn_state,
7674+
dm_old_crtc_state->stream);
76497675

76507676
/*
76517677
* we can have no stream on ACTION_SET if a display

0 commit comments

Comments
 (0)