Commit b333730d authored by Bhawanpreet Lakha's avatar Bhawanpreet Lakha Committed by Alex Deucher

drm/amd/display: Fix Scaling (RMX_*) for DC driver

Before:
We use drm_match_cea_mode() to get the vic for any mode we
want to set, most of the time vic will be different for the new mode.

DC uses memcmp to check if timing changed, in this case DC will
say timing changed and we endup doing a full modeset.

Current:
Now we check if !RMX_OFF and old_refresh == new_refresh if so
we copy the vic from old timing. In a case where we are currently on
a lower timing and want to change to higher mode, stream->dst will be
different and cause us to do a full modeset, which is what we want.
Signed-off-by: default avatarBhawanpreet Lakha <Bhawanpreet.Lakha@amd.com>
Reviewed-by: default avatarLeo Li <sunpeng.li@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent 91b66c47
...@@ -2549,7 +2549,8 @@ static void adjust_colour_depth_from_display_info(struct dc_crtc_timing *timing_ ...@@ -2549,7 +2549,8 @@ static void adjust_colour_depth_from_display_info(struct dc_crtc_timing *timing_
static void static void
fill_stream_properties_from_drm_display_mode(struct dc_stream_state *stream, fill_stream_properties_from_drm_display_mode(struct dc_stream_state *stream,
const struct drm_display_mode *mode_in, const struct drm_display_mode *mode_in,
const struct drm_connector *connector) const struct drm_connector *connector,
const struct dc_stream_state *old_stream)
{ {
struct dc_crtc_timing *timing_out = &stream->timing; struct dc_crtc_timing *timing_out = &stream->timing;
const struct drm_display_info *info = &connector->display_info; const struct drm_display_info *info = &connector->display_info;
...@@ -2575,7 +2576,18 @@ fill_stream_properties_from_drm_display_mode(struct dc_stream_state *stream, ...@@ -2575,7 +2576,18 @@ fill_stream_properties_from_drm_display_mode(struct dc_stream_state *stream,
connector); connector);
timing_out->scan_type = SCANNING_TYPE_NODATA; timing_out->scan_type = SCANNING_TYPE_NODATA;
timing_out->hdmi_vic = 0; timing_out->hdmi_vic = 0;
timing_out->vic = drm_match_cea_mode(mode_in);
if(old_stream) {
timing_out->vic = old_stream->timing.vic;
timing_out->flags.HSYNC_POSITIVE_POLARITY = old_stream->timing.flags.HSYNC_POSITIVE_POLARITY;
timing_out->flags.VSYNC_POSITIVE_POLARITY = old_stream->timing.flags.VSYNC_POSITIVE_POLARITY;
} else {
timing_out->vic = drm_match_cea_mode(mode_in);
if (mode_in->flags & DRM_MODE_FLAG_PHSYNC)
timing_out->flags.HSYNC_POSITIVE_POLARITY = 1;
if (mode_in->flags & DRM_MODE_FLAG_PVSYNC)
timing_out->flags.VSYNC_POSITIVE_POLARITY = 1;
}
timing_out->h_addressable = mode_in->crtc_hdisplay; timing_out->h_addressable = mode_in->crtc_hdisplay;
timing_out->h_total = mode_in->crtc_htotal; timing_out->h_total = mode_in->crtc_htotal;
...@@ -2591,10 +2603,6 @@ fill_stream_properties_from_drm_display_mode(struct dc_stream_state *stream, ...@@ -2591,10 +2603,6 @@ fill_stream_properties_from_drm_display_mode(struct dc_stream_state *stream,
mode_in->crtc_vsync_end - mode_in->crtc_vsync_start; mode_in->crtc_vsync_end - mode_in->crtc_vsync_start;
timing_out->pix_clk_khz = mode_in->crtc_clock; timing_out->pix_clk_khz = mode_in->crtc_clock;
timing_out->aspect_ratio = get_aspect_ratio(mode_in); timing_out->aspect_ratio = get_aspect_ratio(mode_in);
if (mode_in->flags & DRM_MODE_FLAG_PHSYNC)
timing_out->flags.HSYNC_POSITIVE_POLARITY = 1;
if (mode_in->flags & DRM_MODE_FLAG_PVSYNC)
timing_out->flags.VSYNC_POSITIVE_POLARITY = 1;
stream->output_color_space = get_output_color_space(timing_out); stream->output_color_space = get_output_color_space(timing_out);
...@@ -2757,13 +2765,18 @@ static void dm_enable_per_frame_crtc_master_sync(struct dc_state *context) ...@@ -2757,13 +2765,18 @@ static void dm_enable_per_frame_crtc_master_sync(struct dc_state *context)
static struct dc_stream_state * static struct dc_stream_state *
create_stream_for_sink(struct amdgpu_dm_connector *aconnector, create_stream_for_sink(struct amdgpu_dm_connector *aconnector,
const struct drm_display_mode *drm_mode, const struct drm_display_mode *drm_mode,
const struct dm_connector_state *dm_state) const struct dm_connector_state *dm_state,
const struct dc_stream_state *old_stream)
{ {
struct drm_display_mode *preferred_mode = NULL; struct drm_display_mode *preferred_mode = NULL;
struct drm_connector *drm_connector; struct drm_connector *drm_connector;
struct dc_stream_state *stream = NULL; struct dc_stream_state *stream = NULL;
struct drm_display_mode mode = *drm_mode; struct drm_display_mode mode = *drm_mode;
bool native_mode_found = false; bool native_mode_found = false;
bool scale = dm_state ? (dm_state->scaling != RMX_OFF) : false;
int mode_refresh;
int preferred_refresh;
struct dc_sink *sink = NULL; struct dc_sink *sink = NULL;
if (aconnector == NULL) { if (aconnector == NULL) {
DRM_ERROR("aconnector is NULL!\n"); DRM_ERROR("aconnector is NULL!\n");
...@@ -2802,6 +2815,8 @@ create_stream_for_sink(struct amdgpu_dm_connector *aconnector, ...@@ -2802,6 +2815,8 @@ create_stream_for_sink(struct amdgpu_dm_connector *aconnector,
struct drm_display_mode, struct drm_display_mode,
head); head);
mode_refresh = drm_mode_vrefresh(&mode);
if (preferred_mode == NULL) { if (preferred_mode == NULL) {
/* /*
* This may not be an error, the use case is when we have no * This may not be an error, the use case is when we have no
...@@ -2819,8 +2834,19 @@ create_stream_for_sink(struct amdgpu_dm_connector *aconnector, ...@@ -2819,8 +2834,19 @@ create_stream_for_sink(struct amdgpu_dm_connector *aconnector,
if (!dm_state) if (!dm_state)
drm_mode_set_crtcinfo(&mode, 0); drm_mode_set_crtcinfo(&mode, 0);
fill_stream_properties_from_drm_display_mode(stream, preferred_refresh = drm_mode_vrefresh(preferred_mode);
&mode, &aconnector->base);
/*
* If scaling is enabled and refresh rate didn't change
* we copy the vic and polarities of the old timings
*/
if (!scale || mode_refresh != preferred_refresh)
fill_stream_properties_from_drm_display_mode(stream,
&mode, &aconnector->base, NULL);
else
fill_stream_properties_from_drm_display_mode(stream,
&mode, &aconnector->base, old_stream);
update_stream_scaling_settings(&mode, dm_state, stream); update_stream_scaling_settings(&mode, dm_state, stream);
fill_audio_info( fill_audio_info(
...@@ -3229,7 +3255,7 @@ enum drm_mode_status amdgpu_dm_connector_mode_valid(struct drm_connector *connec ...@@ -3229,7 +3255,7 @@ enum drm_mode_status amdgpu_dm_connector_mode_valid(struct drm_connector *connec
goto fail; goto fail;
} }
stream = create_stream_for_sink(aconnector, mode, NULL); stream = create_stream_for_sink(aconnector, mode, NULL, NULL);
if (stream == NULL) { if (stream == NULL) {
DRM_ERROR("Failed to create stream for sink!\n"); DRM_ERROR("Failed to create stream for sink!\n");
goto fail; goto fail;
...@@ -5085,7 +5111,8 @@ static int dm_update_crtcs_state(struct amdgpu_display_manager *dm, ...@@ -5085,7 +5111,8 @@ static int dm_update_crtcs_state(struct amdgpu_display_manager *dm,
new_stream = create_stream_for_sink(aconnector, new_stream = create_stream_for_sink(aconnector,
&new_crtc_state->mode, &new_crtc_state->mode,
dm_new_conn_state); dm_new_conn_state,
dm_old_crtc_state->stream);
/* /*
* we can have no stream on ACTION_SET if a display * we can have no stream on ACTION_SET if a display
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment