]> git.baikalelectronics.ru Git - kernel.git/commitdiff
drm/amd/display: Update connector on DSC property change
authorEryk Brol <eryk.brol@amd.com>
Thu, 15 Oct 2020 17:07:09 +0000 (13:07 -0400)
committerAlex Deucher <alexander.deucher@amd.com>
Mon, 2 Nov 2020 20:31:16 +0000 (15:31 -0500)
[Why]
We want to trigger atomic check on connector when
DSC debugfs properties are changed. The previous
method was reverted because it accessed connector
properties unsafely and would also heavily
impact performance.

[How]
Add a flag for forcing DSC update in CRTC state
and add connector to the state if the flag is set.

Signed-off-by: Eryk Brol <eryk.brol@amd.com>
Reviewed-by: Nicholas Kazlauskas <Nicholas.Kazlauskas@amd.com>
Acked-by: Qingqing Zhuo <qingqing.zhuo@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c

index cfa7126e54f646197e05639357bc91d963292d72..0448835e3e34fab76f96b477a593f8f1ee2d7f45 100644 (file)
@@ -9120,6 +9120,7 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev,
        enum dc_status status;
        int ret, i;
        bool lock_and_validation_needed = false;
+       struct dm_crtc_state *dm_old_crtc_state;
 
        trace_amdgpu_dm_atomic_check_begin(state);
 
@@ -9162,9 +9163,12 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev,
        }
 #endif
        for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) {
+               dm_old_crtc_state = to_dm_crtc_state(old_crtc_state);
+
                if (!drm_atomic_crtc_needs_modeset(new_crtc_state) &&
                    !new_crtc_state->color_mgmt_changed &&
-                   old_crtc_state->vrr_enabled == new_crtc_state->vrr_enabled)
+                   old_crtc_state->vrr_enabled == new_crtc_state->vrr_enabled &&
+                       dm_old_crtc_state->dsc_force_changed == false)
                        continue;
 
                if (!new_crtc_state->enable)
index 03e7e4f231789c1f40d4ec8ceba3f6e3e40ddfe5..7798eb018257b1edec49edb7352153f740e0f6e3 100644 (file)
@@ -438,6 +438,7 @@ struct dm_crtc_state {
        bool freesync_timing_changed;
        bool freesync_vrr_info_changed;
 
+       bool dsc_force_changed;
        bool vrr_supported;
        struct mod_freesync_config freesync_config;
        struct dc_info_packet vrr_infopacket;
index cdc8dd220a775535cb82ab6b751aeaeb8d8797f0..d31380ea57dc5db907e89dfc1d183e831c86a7c4 100644 (file)
@@ -1253,6 +1253,10 @@ static ssize_t dp_dsc_clock_en_write(struct file *f, const char __user *buf,
                                     size_t size, loff_t *pos)
 {
        struct amdgpu_dm_connector *aconnector = file_inode(f)->i_private;
+       struct drm_connector *connector = &aconnector->base;
+       struct drm_device *dev = connector->dev;
+       struct drm_crtc *crtc = NULL;
+       struct dm_crtc_state *dm_crtc_state = NULL;
        struct pipe_ctx *pipe_ctx;
        int i;
        char *wr_buf = NULL;
@@ -1295,6 +1299,25 @@ static ssize_t dp_dsc_clock_en_write(struct file *f, const char __user *buf,
        if (!pipe_ctx || !pipe_ctx->stream)
                goto done;
 
+       // Get CRTC state
+       mutex_lock(&dev->mode_config.mutex);
+       drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
+
+       if (connector->state == NULL)
+               goto unlock;
+
+       crtc = connector->state->crtc;
+       if (crtc == NULL)
+               goto unlock;
+
+       drm_modeset_lock(&crtc->mutex, NULL);
+       if (crtc->state == NULL)
+               goto unlock;
+
+       dm_crtc_state = to_dm_crtc_state(crtc->state);
+       if (dm_crtc_state->stream == NULL)
+               goto unlock;
+
        if (param[0] == 1)
                aconnector->dsc_settings.dsc_force_enable = DSC_CLK_FORCE_ENABLE;
        else if (param[0] == 2)
@@ -1302,6 +1325,14 @@ static ssize_t dp_dsc_clock_en_write(struct file *f, const char __user *buf,
        else
                aconnector->dsc_settings.dsc_force_enable = DSC_CLK_FORCE_DEFAULT;
 
+       dm_crtc_state->dsc_force_changed = true;
+
+unlock:
+       if (crtc)
+               drm_modeset_unlock(&crtc->mutex);
+       drm_modeset_unlock(&dev->mode_config.connection_mutex);
+       mutex_unlock(&dev->mode_config.mutex);
+
 done:
        kfree(wr_buf);
        return size;
@@ -1408,6 +1439,10 @@ static ssize_t dp_dsc_slice_width_write(struct file *f, const char __user *buf,
 {
        struct amdgpu_dm_connector *aconnector = file_inode(f)->i_private;
        struct pipe_ctx *pipe_ctx;
+       struct drm_connector *connector = &aconnector->base;
+       struct drm_device *dev = connector->dev;
+       struct drm_crtc *crtc = NULL;
+       struct dm_crtc_state *dm_crtc_state = NULL;
        int i;
        char *wr_buf = NULL;
        uint32_t wr_buf_size = 42;
@@ -1449,6 +1484,25 @@ static ssize_t dp_dsc_slice_width_write(struct file *f, const char __user *buf,
        if (!pipe_ctx || !pipe_ctx->stream)
                goto done;
 
+       // Safely get CRTC state
+       mutex_lock(&dev->mode_config.mutex);
+       drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
+
+       if (connector->state == NULL)
+               goto unlock;
+
+       crtc = connector->state->crtc;
+       if (crtc == NULL)
+               goto unlock;
+
+       drm_modeset_lock(&crtc->mutex, NULL);
+       if (crtc->state == NULL)
+               goto unlock;
+
+       dm_crtc_state = to_dm_crtc_state(crtc->state);
+       if (dm_crtc_state->stream == NULL)
+               goto unlock;
+
        if (param[0] > 0)
                aconnector->dsc_settings.dsc_num_slices_h = DIV_ROUND_UP(
                                        pipe_ctx->stream->timing.h_addressable,
@@ -1456,6 +1510,14 @@ static ssize_t dp_dsc_slice_width_write(struct file *f, const char __user *buf,
        else
                aconnector->dsc_settings.dsc_num_slices_h = 0;
 
+       dm_crtc_state->dsc_force_changed = true;
+
+unlock:
+       if (crtc)
+               drm_modeset_unlock(&crtc->mutex);
+       drm_modeset_unlock(&dev->mode_config.connection_mutex);
+       mutex_unlock(&dev->mode_config.mutex);
+
 done:
        kfree(wr_buf);
        return size;
@@ -1561,6 +1623,10 @@ static ssize_t dp_dsc_slice_height_write(struct file *f, const char __user *buf,
                                     size_t size, loff_t *pos)
 {
        struct amdgpu_dm_connector *aconnector = file_inode(f)->i_private;
+       struct drm_connector *connector = &aconnector->base;
+       struct drm_device *dev = connector->dev;
+       struct drm_crtc *crtc = NULL;
+       struct dm_crtc_state *dm_crtc_state = NULL;
        struct pipe_ctx *pipe_ctx;
        int i;
        char *wr_buf = NULL;
@@ -1603,6 +1669,25 @@ static ssize_t dp_dsc_slice_height_write(struct file *f, const char __user *buf,
        if (!pipe_ctx || !pipe_ctx->stream)
                goto done;
 
+       // Get CRTC state
+       mutex_lock(&dev->mode_config.mutex);
+       drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
+
+       if (connector->state == NULL)
+               goto unlock;
+
+       crtc = connector->state->crtc;
+       if (crtc == NULL)
+               goto unlock;
+
+       drm_modeset_lock(&crtc->mutex, NULL);
+       if (crtc->state == NULL)
+               goto unlock;
+
+       dm_crtc_state = to_dm_crtc_state(crtc->state);
+       if (dm_crtc_state->stream == NULL)
+               goto unlock;
+
        if (param[0] > 0)
                aconnector->dsc_settings.dsc_num_slices_v = DIV_ROUND_UP(
                                        pipe_ctx->stream->timing.v_addressable,
@@ -1610,6 +1695,14 @@ static ssize_t dp_dsc_slice_height_write(struct file *f, const char __user *buf,
        else
                aconnector->dsc_settings.dsc_num_slices_v = 0;
 
+       dm_crtc_state->dsc_force_changed = true;
+
+unlock:
+       if (crtc)
+               drm_modeset_unlock(&crtc->mutex);
+       drm_modeset_unlock(&dev->mode_config.connection_mutex);
+       mutex_unlock(&dev->mode_config.mutex);
+
 done:
        kfree(wr_buf);
        return size;
@@ -1708,6 +1801,10 @@ static ssize_t dp_dsc_bits_per_pixel_write(struct file *f, const char __user *bu
                                     size_t size, loff_t *pos)
 {
        struct amdgpu_dm_connector *aconnector = file_inode(f)->i_private;
+       struct drm_connector *connector = &aconnector->base;
+       struct drm_device *dev = connector->dev;
+       struct drm_crtc *crtc = NULL;
+       struct dm_crtc_state *dm_crtc_state = NULL;
        struct pipe_ctx *pipe_ctx;
        int i;
        char *wr_buf = NULL;
@@ -1750,8 +1847,35 @@ static ssize_t dp_dsc_bits_per_pixel_write(struct file *f, const char __user *bu
        if (!pipe_ctx || !pipe_ctx->stream)
                goto done;
 
+       // Get CRTC state
+       mutex_lock(&dev->mode_config.mutex);
+       drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
+
+       if (connector->state == NULL)
+               goto unlock;
+
+       crtc = connector->state->crtc;
+       if (crtc == NULL)
+               goto unlock;
+
+       drm_modeset_lock(&crtc->mutex, NULL);
+       if (crtc->state == NULL)
+               goto unlock;
+
+       dm_crtc_state = to_dm_crtc_state(crtc->state);
+       if (dm_crtc_state->stream == NULL)
+               goto unlock;
+
        aconnector->dsc_settings.dsc_bits_per_pixel = param[0];
 
+       dm_crtc_state->dsc_force_changed = true;
+
+unlock:
+       if (crtc)
+               drm_modeset_unlock(&crtc->mutex);
+       drm_modeset_unlock(&dev->mode_config.connection_mutex);
+       mutex_unlock(&dev->mode_config.mutex);
+
 done:
        kfree(wr_buf);
        return size;