@@ -3840,8 +3840,7 @@ static void update_stream_scaling_settings(const struct drm_display_mode *mode,
38403840
38413841static enum dc_color_depth
38423842convert_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 *
42324230create_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+
48424881enum 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
48914915fail :
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