Skip to content

Commit c14702d

Browse files
lillizhuo-amdgregkh
authored andcommitted
drm/amd/display: force connector state when bpc changes during compliance
commit 028c4cc upstream. [Why] During DP DSC compliance tests, bpc requested would change between sub-tests, which requires stream to be recommited. [How] Force connector to disconnect and reconnect whenever there is a bpc change in automated test. Reviewed-by: Jerry Zuo <[email protected]> Acked-by: Alan Liu <[email protected]> Signed-off-by: Qingqing Zhuo <[email protected]> Signed-off-by: hersen wu <[email protected]> Tested-by: Daniel Wheeler <[email protected]> Signed-off-by: Alex Deucher <[email protected]> [ Adjustments for headers that were moved around in later commits. ] Signed-off-by: Mario Limonciello <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent 00f68f5 commit c14702d

File tree

5 files changed

+209
-121
lines changed

5 files changed

+209
-121
lines changed

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

Lines changed: 54 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,9 @@
4040
#include "dc/dc_stat.h"
4141
#include "amdgpu_dm_trace.h"
4242
#include "dc/inc/dc_link_ddc.h"
43+
#include "dpcd_defs.h"
44+
#include "dc/inc/link_dpcd.h"
45+
#include "link_service_types.h"
4346

4447
#include "vid.h"
4548
#include "amdgpu.h"
@@ -1273,6 +1276,21 @@ static void mmhub_read_system_context(struct amdgpu_device *adev, struct dc_phy_
12731276

12741277
}
12751278

1279+
static void force_connector_state(
1280+
struct amdgpu_dm_connector *aconnector,
1281+
enum drm_connector_force force_state)
1282+
{
1283+
struct drm_connector *connector = &aconnector->base;
1284+
1285+
mutex_lock(&connector->dev->mode_config.mutex);
1286+
aconnector->base.force = force_state;
1287+
mutex_unlock(&connector->dev->mode_config.mutex);
1288+
1289+
mutex_lock(&aconnector->hpd_lock);
1290+
drm_kms_helper_connector_hotplug_event(connector);
1291+
mutex_unlock(&aconnector->hpd_lock);
1292+
}
1293+
12761294
static void dm_handle_hpd_rx_offload_work(struct work_struct *work)
12771295
{
12781296
struct hpd_rx_irq_offload_work *offload_work;
@@ -1281,6 +1299,9 @@ static void dm_handle_hpd_rx_offload_work(struct work_struct *work)
12811299
struct amdgpu_device *adev;
12821300
enum dc_connection_type new_connection_type = dc_connection_none;
12831301
unsigned long flags;
1302+
union test_response test_response;
1303+
1304+
memset(&test_response, 0, sizeof(test_response));
12841305

12851306
offload_work = container_of(work, struct hpd_rx_irq_offload_work, work);
12861307
aconnector = offload_work->offload_wq->aconnector;
@@ -1305,8 +1326,24 @@ static void dm_handle_hpd_rx_offload_work(struct work_struct *work)
13051326
goto skip;
13061327

13071328
mutex_lock(&adev->dm.dc_lock);
1308-
if (offload_work->data.bytes.device_service_irq.bits.AUTOMATED_TEST)
1329+
if (offload_work->data.bytes.device_service_irq.bits.AUTOMATED_TEST) {
13091330
dc_link_dp_handle_automated_test(dc_link);
1331+
1332+
if (aconnector->timing_changed) {
1333+
/* force connector disconnect and reconnect */
1334+
force_connector_state(aconnector, DRM_FORCE_OFF);
1335+
msleep(100);
1336+
force_connector_state(aconnector, DRM_FORCE_UNSPECIFIED);
1337+
}
1338+
1339+
test_response.bits.ACK = 1;
1340+
1341+
core_link_write_dpcd(
1342+
dc_link,
1343+
DP_TEST_RESPONSE,
1344+
&test_response.raw,
1345+
sizeof(test_response));
1346+
}
13101347
else if ((dc_link->connector_signal != SIGNAL_TYPE_EDP) &&
13111348
hpd_rx_irq_check_link_loss_status(dc_link, &offload_work->data) &&
13121349
dc_link_dp_allow_hpd_rx_irq(dc_link)) {
@@ -3076,6 +3113,10 @@ void amdgpu_dm_update_connector_after_detect(
30763113
aconnector->edid);
30773114
}
30783115

3116+
aconnector->timing_requested = kzalloc(sizeof(struct dc_crtc_timing), GFP_KERNEL);
3117+
if (!aconnector->timing_requested)
3118+
dm_error("%s: failed to create aconnector->requested_timing\n", __func__);
3119+
30793120
drm_connector_update_edid_property(connector, aconnector->edid);
30803121
amdgpu_dm_update_freesync_caps(connector, aconnector->edid);
30813122
update_connector_ext_caps(aconnector);
@@ -3087,6 +3128,8 @@ void amdgpu_dm_update_connector_after_detect(
30873128
dc_sink_release(aconnector->dc_sink);
30883129
aconnector->dc_sink = NULL;
30893130
aconnector->edid = NULL;
3131+
kfree(aconnector->timing_requested);
3132+
aconnector->timing_requested = NULL;
30903133
#ifdef CONFIG_DRM_AMD_DC_HDCP
30913134
/* Set CP to DESIRED if it was ENABLED, so we can re-enable it again on hotplug */
30923135
if (connector->state->content_protection == DRM_MODE_CONTENT_PROTECTION_ENABLED)
@@ -3131,6 +3174,8 @@ static void handle_hpd_irq_helper(struct amdgpu_dm_connector *aconnector)
31313174
if (aconnector->fake_enable)
31323175
aconnector->fake_enable = false;
31333176

3177+
aconnector->timing_changed = false;
3178+
31343179
if (!dc_link_detect_sink(aconnector->dc_link, &new_connection_type))
31353180
DRM_ERROR("KMS: Failed to detect connector\n");
31363181

@@ -5896,6 +5941,14 @@ create_stream_for_sink(struct amdgpu_dm_connector *aconnector,
58965941
stream, &mode, &aconnector->base, con_state, old_stream,
58975942
requested_bpc);
58985943

5944+
if (aconnector->timing_changed) {
5945+
DC_LOG_DEBUG("%s: overriding timing for automated test, bpc %d, changing to %d\n",
5946+
__func__,
5947+
stream->timing.display_color_depth,
5948+
aconnector->timing_requested->display_color_depth);
5949+
stream->timing = *aconnector->timing_requested;
5950+
}
5951+
58995952
#if defined(CONFIG_DRM_AMD_DC_DCN)
59005953
/* SST DSC determination policy */
59015954
update_dsc_caps(aconnector, sink, stream, &dsc_caps);

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
#include <drm/drm_connector.h>
3232
#include <drm/drm_crtc.h>
3333
#include <drm/drm_plane.h>
34+
#include "link_service_types.h"
3435

3536
/*
3637
* This file contains the definition for amdgpu_display_manager
@@ -650,6 +651,10 @@ struct amdgpu_dm_connector {
650651

651652
/* Record progress status of mst*/
652653
uint8_t mst_status;
654+
655+
/* Automated testing */
656+
bool timing_changed;
657+
struct dc_crtc_timing *timing_requested;
653658
};
654659

655660
static inline void amdgpu_dm_set_mst_status(uint8_t *status,

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

Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,9 @@
3838
#include "amdgpu_dm.h"
3939
#include "amdgpu_dm_irq.h"
4040
#include "amdgpu_dm_mst_types.h"
41+
#include "dpcd_defs.h"
42+
#include "dc/inc/core_types.h"
43+
#include "dc_link_dp.h"
4144

4245
#include "dm_helpers.h"
4346
#include "ddc_service_types.h"
@@ -1056,6 +1059,128 @@ void dm_helpers_mst_enable_stream_features(const struct dc_stream_state *stream)
10561059
sizeof(new_downspread));
10571060
}
10581061

1062+
bool dm_helpers_dp_handle_test_pattern_request(
1063+
struct dc_context *ctx,
1064+
const struct dc_link *link,
1065+
union link_test_pattern dpcd_test_pattern,
1066+
union test_misc dpcd_test_params)
1067+
{
1068+
enum dp_test_pattern test_pattern;
1069+
enum dp_test_pattern_color_space test_pattern_color_space =
1070+
DP_TEST_PATTERN_COLOR_SPACE_UNDEFINED;
1071+
enum dc_color_depth requestColorDepth = COLOR_DEPTH_UNDEFINED;
1072+
enum dc_pixel_encoding requestPixelEncoding = PIXEL_ENCODING_UNDEFINED;
1073+
struct pipe_ctx *pipes = link->dc->current_state->res_ctx.pipe_ctx;
1074+
struct pipe_ctx *pipe_ctx = NULL;
1075+
struct amdgpu_dm_connector *aconnector = link->priv;
1076+
int i;
1077+
1078+
for (i = 0; i < MAX_PIPES; i++) {
1079+
if (pipes[i].stream == NULL)
1080+
continue;
1081+
1082+
if (pipes[i].stream->link == link && !pipes[i].top_pipe &&
1083+
!pipes[i].prev_odm_pipe) {
1084+
pipe_ctx = &pipes[i];
1085+
break;
1086+
}
1087+
}
1088+
1089+
if (pipe_ctx == NULL)
1090+
return false;
1091+
1092+
switch (dpcd_test_pattern.bits.PATTERN) {
1093+
case LINK_TEST_PATTERN_COLOR_RAMP:
1094+
test_pattern = DP_TEST_PATTERN_COLOR_RAMP;
1095+
break;
1096+
case LINK_TEST_PATTERN_VERTICAL_BARS:
1097+
test_pattern = DP_TEST_PATTERN_VERTICAL_BARS;
1098+
break; /* black and white */
1099+
case LINK_TEST_PATTERN_COLOR_SQUARES:
1100+
test_pattern = (dpcd_test_params.bits.DYN_RANGE ==
1101+
TEST_DYN_RANGE_VESA ?
1102+
DP_TEST_PATTERN_COLOR_SQUARES :
1103+
DP_TEST_PATTERN_COLOR_SQUARES_CEA);
1104+
break;
1105+
default:
1106+
test_pattern = DP_TEST_PATTERN_VIDEO_MODE;
1107+
break;
1108+
}
1109+
1110+
if (dpcd_test_params.bits.CLR_FORMAT == 0)
1111+
test_pattern_color_space = DP_TEST_PATTERN_COLOR_SPACE_RGB;
1112+
else
1113+
test_pattern_color_space = dpcd_test_params.bits.YCBCR_COEFS ?
1114+
DP_TEST_PATTERN_COLOR_SPACE_YCBCR709 :
1115+
DP_TEST_PATTERN_COLOR_SPACE_YCBCR601;
1116+
1117+
switch (dpcd_test_params.bits.BPC) {
1118+
case 0: // 6 bits
1119+
requestColorDepth = COLOR_DEPTH_666;
1120+
break;
1121+
case 1: // 8 bits
1122+
requestColorDepth = COLOR_DEPTH_888;
1123+
break;
1124+
case 2: // 10 bits
1125+
requestColorDepth = COLOR_DEPTH_101010;
1126+
break;
1127+
case 3: // 12 bits
1128+
requestColorDepth = COLOR_DEPTH_121212;
1129+
break;
1130+
default:
1131+
break;
1132+
}
1133+
1134+
switch (dpcd_test_params.bits.CLR_FORMAT) {
1135+
case 0:
1136+
requestPixelEncoding = PIXEL_ENCODING_RGB;
1137+
break;
1138+
case 1:
1139+
requestPixelEncoding = PIXEL_ENCODING_YCBCR422;
1140+
break;
1141+
case 2:
1142+
requestPixelEncoding = PIXEL_ENCODING_YCBCR444;
1143+
break;
1144+
default:
1145+
requestPixelEncoding = PIXEL_ENCODING_RGB;
1146+
break;
1147+
}
1148+
1149+
if ((requestColorDepth != COLOR_DEPTH_UNDEFINED
1150+
&& pipe_ctx->stream->timing.display_color_depth != requestColorDepth)
1151+
|| (requestPixelEncoding != PIXEL_ENCODING_UNDEFINED
1152+
&& pipe_ctx->stream->timing.pixel_encoding != requestPixelEncoding)) {
1153+
DC_LOG_DEBUG("%s: original bpc %d pix encoding %d, changing to %d %d\n",
1154+
__func__,
1155+
pipe_ctx->stream->timing.display_color_depth,
1156+
pipe_ctx->stream->timing.pixel_encoding,
1157+
requestColorDepth,
1158+
requestPixelEncoding);
1159+
pipe_ctx->stream->timing.display_color_depth = requestColorDepth;
1160+
pipe_ctx->stream->timing.pixel_encoding = requestPixelEncoding;
1161+
1162+
dp_update_dsc_config(pipe_ctx);
1163+
1164+
aconnector->timing_changed = true;
1165+
/* store current timing */
1166+
if (aconnector->timing_requested)
1167+
*aconnector->timing_requested = pipe_ctx->stream->timing;
1168+
else
1169+
DC_LOG_ERROR("%s: timing storage failed\n", __func__);
1170+
1171+
}
1172+
1173+
dc_link_dp_set_test_pattern(
1174+
(struct dc_link *) link,
1175+
test_pattern,
1176+
test_pattern_color_space,
1177+
NULL,
1178+
NULL,
1179+
0);
1180+
1181+
return false;
1182+
}
1183+
10591184
void dm_set_phyd32clk(struct dc_context *ctx, int freq_khz)
10601185
{
10611186
// TODO

0 commit comments

Comments
 (0)