Commit 051d9007 authored by George Shen's avatar George Shen Committed by Alex Deucher
Browse files

drm/amd/display: Refactor DPG test pattern logic for ODM cases



[Why]
Current DPG test pattern logic does not account for ODM configuration
changes after test pattern has already been programmed. For example, if
ODM2:1 is enabled after test pattern is already being output, the second
pipe is not programmed to output test pattern, causing half the screen
to be black.

[How]
Move DPG test pattern parameter calculations into separate function.
Whenever ODM pipe configuration changes, re-calculate DPG test pattern
parameters and program DPG if test pattern is currently enabled.

Reviewed-by: default avatarWenjing Liu <wenjing.liu@amd.com>
Acked-by: default avatarTom Chung <chiahsuan.chung@amd.com>
Signed-off-by: default avatarGeorge Shen <george.shen@amd.com>
Tested-by: default avatarDaniel Wheeler <daniel.wheeler@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent ef013f6f
Loading
Loading
Loading
Loading
+8 −0
Original line number Diff line number Diff line
@@ -3169,6 +3169,14 @@ static bool update_planes_and_stream_state(struct dc *dc,
			BREAK_TO_DEBUGGER();
			goto fail;
		}

		for (i = 0; i < context->stream_count; i++) {
			struct pipe_ctx *otg_master = resource_get_otg_master_for_stream(&context->res_ctx,
					context->streams[i]);

			if (otg_master->stream->test_pattern.type != DP_TEST_PATTERN_VIDEO_MODE)
				resource_build_test_pattern_params(&context->res_ctx, otg_master);
		}
	}

	*new_context = context;
+104 −0
Original line number Diff line number Diff line
@@ -1367,6 +1367,110 @@ static bool is_subvp_high_refresh_candidate(struct dc_stream_state *stream)
	return false;
}

static enum controller_dp_test_pattern convert_dp_to_controller_test_pattern(
				enum dp_test_pattern test_pattern)
{
	enum controller_dp_test_pattern controller_test_pattern;

	switch (test_pattern) {
	case DP_TEST_PATTERN_COLOR_SQUARES:
		controller_test_pattern =
				CONTROLLER_DP_TEST_PATTERN_COLORSQUARES;
	break;
	case DP_TEST_PATTERN_COLOR_SQUARES_CEA:
		controller_test_pattern =
				CONTROLLER_DP_TEST_PATTERN_COLORSQUARES_CEA;
	break;
	case DP_TEST_PATTERN_VERTICAL_BARS:
		controller_test_pattern =
				CONTROLLER_DP_TEST_PATTERN_VERTICALBARS;
	break;
	case DP_TEST_PATTERN_HORIZONTAL_BARS:
		controller_test_pattern =
				CONTROLLER_DP_TEST_PATTERN_HORIZONTALBARS;
	break;
	case DP_TEST_PATTERN_COLOR_RAMP:
		controller_test_pattern =
				CONTROLLER_DP_TEST_PATTERN_COLORRAMP;
	break;
	default:
		controller_test_pattern =
				CONTROLLER_DP_TEST_PATTERN_VIDEOMODE;
	break;
	}

	return controller_test_pattern;
}

static enum controller_dp_color_space convert_dp_to_controller_color_space(
		enum dp_test_pattern_color_space color_space)
{
	enum controller_dp_color_space controller_color_space;

	switch (color_space) {
	case DP_TEST_PATTERN_COLOR_SPACE_RGB:
		controller_color_space = CONTROLLER_DP_COLOR_SPACE_RGB;
		break;
	case DP_TEST_PATTERN_COLOR_SPACE_YCBCR601:
		controller_color_space = CONTROLLER_DP_COLOR_SPACE_YCBCR601;
		break;
	case DP_TEST_PATTERN_COLOR_SPACE_YCBCR709:
		controller_color_space = CONTROLLER_DP_COLOR_SPACE_YCBCR709;
		break;
	case DP_TEST_PATTERN_COLOR_SPACE_UNDEFINED:
	default:
		controller_color_space = CONTROLLER_DP_COLOR_SPACE_UDEFINED;
		break;
	}

	return controller_color_space;
}

void resource_build_test_pattern_params(struct resource_context *res_ctx,
				struct pipe_ctx *otg_master)
{
	int odm_slice_width, last_odm_slice_width, offset = 0;
	struct pipe_ctx *opp_heads[MAX_PIPES];
	struct test_pattern_params *params;
	int odm_cnt = 1;
	enum controller_dp_test_pattern controller_test_pattern;
	enum controller_dp_color_space controller_color_space;
	enum dc_color_depth color_depth = otg_master->stream->timing.display_color_depth;
	int h_active = otg_master->stream->timing.h_addressable +
		otg_master->stream->timing.h_border_left +
		otg_master->stream->timing.h_border_right;
	int v_active = otg_master->stream->timing.v_addressable +
		otg_master->stream->timing.v_border_bottom +
		otg_master->stream->timing.v_border_top;
	int i;

	controller_test_pattern = convert_dp_to_controller_test_pattern(
			otg_master->stream->test_pattern.type);
	controller_color_space = convert_dp_to_controller_color_space(
			otg_master->stream->test_pattern.color_space);

	odm_cnt = resource_get_opp_heads_for_otg_master(otg_master, res_ctx, opp_heads);

	odm_slice_width = h_active / odm_cnt;
	last_odm_slice_width = h_active - odm_slice_width * (odm_cnt - 1);

	for (i = 0; i < odm_cnt; i++) {
		params = &opp_heads[i]->stream_res.test_pattern_params;
		params->test_pattern = controller_test_pattern;
		params->color_space = controller_color_space;
		params->color_depth = color_depth;
		params->height = v_active;
		params->offset = offset;

		if (i < odm_cnt - 1)
			params->width = odm_slice_width;
		else
			params->width = last_odm_slice_width;

		offset += odm_slice_width;
	}
}

bool resource_build_scaling_params(struct pipe_ctx *pipe_ctx)
{
	const struct dc_plane_state *plane_state = pipe_ctx->plane_state;
+22 −0
Original line number Diff line number Diff line
@@ -1538,6 +1538,11 @@ static void dcn20_detect_pipe_changes(struct pipe_ctx *old_pipe, struct pipe_ctx

	if (old_pipe->unbounded_req != new_pipe->unbounded_req)
		new_pipe->update_flags.bits.unbounded_req = 1;

	if (memcmp(&old_pipe->stream_res.test_pattern_params,
				&new_pipe->stream_res.test_pattern_params, sizeof(struct test_pattern_params))) {
		new_pipe->update_flags.bits.test_pattern_changed = 1;
	}
}

static void dcn20_update_dchubp_dpp(
@@ -1846,6 +1851,23 @@ static void dcn20_program_pipe(
				pipe_ctx->stream->abm_level);
		}
	}

	if (pipe_ctx->update_flags.bits.test_pattern_changed) {
		struct output_pixel_processor *odm_opp = pipe_ctx->stream_res.opp;
		struct bit_depth_reduction_params params;

		memset(&params, 0, sizeof(params));
		odm_opp->funcs->opp_program_bit_depth_reduction(odm_opp, &params);
		dc->hwss.set_disp_pattern_generator(dc,
				pipe_ctx,
				pipe_ctx->stream_res.test_pattern_params.test_pattern,
				pipe_ctx->stream_res.test_pattern_params.color_space,
				pipe_ctx->stream_res.test_pattern_params.color_depth,
				NULL,
				pipe_ctx->stream_res.test_pattern_params.width,
				pipe_ctx->stream_res.test_pattern_params.height,
				pipe_ctx->stream_res.test_pattern_params.offset);
	}
}

void dcn20_program_front_end_for_ctx(
+13 −0
Original line number Diff line number Diff line
@@ -308,6 +308,16 @@ struct dcn_fe_bandwidth {

};

/* Parameters needed to call set_disp_pattern_generator */
struct test_pattern_params {
	enum controller_dp_test_pattern test_pattern;
	enum controller_dp_color_space color_space;
	enum dc_color_depth color_depth;
	int width;
	int height;
	int offset;
};

struct stream_resource {
	struct output_pixel_processor *opp;
	struct display_stream_compressor *dsc;
@@ -324,6 +334,8 @@ struct stream_resource {
	 * otherwise it's using group number 'gsl_group-1'
	 */
	uint8_t gsl_group;

	struct test_pattern_params test_pattern_params;
};

struct plane_resource {
@@ -367,6 +379,7 @@ union pipe_update_flags {
		uint32_t plane_changed : 1;
		uint32_t det_size : 1;
		uint32_t unbounded_req : 1;
		uint32_t test_pattern_changed : 1;
	} bits;
	uint32_t raw;
};
+4 −0
Original line number Diff line number Diff line
@@ -103,6 +103,10 @@ enum dc_status resource_map_pool_resources(
		struct dc_state *context,
		struct dc_stream_state *stream);

void resource_build_test_pattern_params(
		struct resource_context *res_ctx,
		struct pipe_ctx *pipe_ctx);

bool resource_build_scaling_params(struct pipe_ctx *pipe_ctx);

enum dc_status resource_build_scaling_params_for_context(
Loading