On 2018-10-11 12:39 PM, Nicholas Kazlauskas wrote:
> Support for AMDGPU specific FreeSync properties and ioctls are dropped
> from amdgpu_dm in favor of supporting drm variable refresh rate
> properties.
> 
> The drm vrr_capable property is now attached to any DP/HDMI connector.
> Its value is updated accordingly to the connector's FreeSync capabiltiy.
> 
> The freesync_enable logic and ioctl control has has been dropped in
> favor of utilizing the vrr_enabled on the drm CRTC. This allows for more
> fine grained atomic control over which CRTCs should support variable
> refresh rate.
> 
> To handle state changes for vrr_enabled it was easiest to drop the
> forced modeset on freesync_enabled change. This patch now performs the
> required stream updates when planes are flipped.
> 
> This is done for a few reasons:
> 
> (1) VRR stream updates can be done in the fast update path
> 
> (2) amdgpu_dm_atomic_check would need to be hacked apart to check
>     desired variable refresh state and capability before the CRTC
>     disable pass.
> 
> (3) Performing VRR stream updates on-flip is needed for enabling BTR
>     support.
> 
> VRR packets and timing adjustments are now tracked and compared to
> previous values sent to the hardware.
> 
> Signed-off-by: Nicholas Kazlauskas <nicholas.kazlaus...@amd.com>
> ---
>  .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 255 +++++++++---------
>  .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h |   7 +-
>  2 files changed, 138 insertions(+), 124 deletions(-)
> 
> diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c 
> b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> index 6a2342d72742..d5de4b91e144 100644
> --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> @@ -1802,72 +1802,6 @@ static void dm_bandwidth_update(struct amdgpu_device 
> *adev)
>       /* TODO: implement later */
>  }
>  
> -static int amdgpu_notify_freesync(struct drm_device *dev, void *data,
> -                             struct drm_file *filp)
> -{
> -     struct drm_atomic_state *state;
> -     struct drm_modeset_acquire_ctx ctx;
> -     struct drm_crtc *crtc;
> -     struct drm_connector *connector;
> -     struct drm_connector_state *old_con_state, *new_con_state;
> -     int ret = 0;
> -     uint8_t i;
> -     bool enable = false;
> -
> -     drm_modeset_acquire_init(&ctx, 0);
> -
> -     state = drm_atomic_state_alloc(dev);
> -     if (!state) {
> -             ret = -ENOMEM;
> -             goto out;
> -     }
> -     state->acquire_ctx = &ctx;
> -
> -retry:
> -     drm_for_each_crtc(crtc, dev) {
> -             ret = drm_atomic_add_affected_connectors(state, crtc);
> -             if (ret)
> -                     goto fail;
> -
> -             /* TODO rework amdgpu_dm_commit_planes so we don't need this */
> -             ret = drm_atomic_add_affected_planes(state, crtc);
> -             if (ret)
> -                     goto fail;
> -     }
> -
> -     for_each_oldnew_connector_in_state(state, connector, old_con_state, 
> new_con_state, i) {
> -             struct dm_connector_state *dm_new_con_state = 
> to_dm_connector_state(new_con_state);
> -             struct drm_crtc_state *new_crtc_state;
> -             struct amdgpu_crtc *acrtc = 
> to_amdgpu_crtc(dm_new_con_state->base.crtc);
> -             struct dm_crtc_state *dm_new_crtc_state;
> -
> -             if (!acrtc) {
> -                     ASSERT(0);
> -                     continue;
> -             }
> -
> -             new_crtc_state = drm_atomic_get_new_crtc_state(state, 
> &acrtc->base);
> -             dm_new_crtc_state = to_dm_crtc_state(new_crtc_state);
> -
> -             dm_new_crtc_state->freesync_enabled = enable;
> -     }
> -
> -     ret = drm_atomic_commit(state);
> -
> -fail:
> -     if (ret == -EDEADLK) {
> -             drm_atomic_state_clear(state);
> -             drm_modeset_backoff(&ctx);
> -             goto retry;
> -     }
> -
> -     drm_atomic_state_put(state);
> -
> -out:
> -     drm_modeset_drop_locks(&ctx);
> -     drm_modeset_acquire_fini(&ctx);
> -     return ret;
> -}
>  
>  static const struct amdgpu_display_funcs dm_display_funcs = {
>       .bandwidth_update = dm_bandwidth_update, /* called unconditionally */
> @@ -1881,7 +1815,6 @@ static const struct amdgpu_display_funcs 
> dm_display_funcs = {
>               dm_crtc_get_scanoutpos,/* called unconditionally */
>       .add_encoder = NULL, /* VBIOS parsing. DAL does it. */
>       .add_connector = NULL, /* VBIOS parsing. DAL does it. */
> -     .notify_freesync = amdgpu_notify_freesync,

Please also drop from amdgpu_display_funcs definition in amdgpu_mode.h. Might 
want to drop the set_freesync_property from there as well.

>  
>  };
>  
> @@ -2834,7 +2767,8 @@ dm_crtc_duplicate_state(struct drm_crtc *crtc)
>  
>       state->adjust = cur->adjust;
>       state->vrr_infopacket = cur->vrr_infopacket;
> -     state->freesync_enabled = cur->freesync_enabled;
> +     state->vrr_supported = cur->vrr_supported;
> +     state->freesync_config = cur->freesync_config;
>  
>       /* TODO Duplicate dc_stream after objects are stream object is 
> flattened */
>  
> @@ -3053,8 +2987,6 @@ amdgpu_dm_connector_atomic_duplicate_state(struct 
> drm_connector *connector)
>       __drm_atomic_helper_connector_duplicate_state(connector, 
> &new_state->base);
>  
>       new_state->freesync_capable = state->freesync_capable;
> -     new_state->freesync_enable = state->freesync_enable;
> -
>       return &new_state->base;
>  }
>  
> @@ -3800,6 +3732,11 @@ void amdgpu_dm_connector_init_helper(struct 
> amdgpu_display_manager *dm,
>                               adev->mode_info.underscan_vborder_property,
>                               0);
>  
> +     if (connector_type == DRM_MODE_CONNECTOR_HDMIA ||
> +         connector_type == DRM_MODE_CONNECTOR_DisplayPort) {
> +             drm_connector_attach_vrr_capable_property(
> +                     &aconnector->base);
> +     }
>  }
>  
>  static int amdgpu_dm_i2c_xfer(struct i2c_adapter *i2c_adap,
> @@ -4176,6 +4113,77 @@ static void prepare_flip_isr(struct amdgpu_crtc *acrtc)
>                                                acrtc->crtc_id);
>  }
>  
> +static void update_freesync_state_on_stream(
> +     struct amdgpu_display_manager *dm,
> +     struct dm_crtc_state *new_crtc_state,
> +     struct dc_stream_state *new_stream)
> +{
> +     struct mod_vrr_params vrr = {0};
> +     struct dc_info_packet vrr_infopacket = {0};
> +     struct mod_freesync_config config = new_crtc_state->freesync_config;
> +
> +     if (!new_stream)
> +             return;
> +
> +     /*
> +      * TODO: Determine why min/max totals and vrefresh can be 0 here.
> +      * For now it's sufficient to just guard against these conditions.
> +      */
> +
> +     if (!new_stream->timing.h_total || !new_stream->timing.v_total)
> +             return;
> +
> +     if (new_crtc_state->vrr_supported &&
> +         config.min_refresh_in_uhz &&
> +         config.max_refresh_in_uhz) {
> +             config.state = new_crtc_state->base.vrr_enabled ?
> +                     VRR_STATE_ACTIVE_VARIABLE :
> +                     VRR_STATE_INACTIVE;
> +     } else {
> +             config.state = VRR_STATE_UNSUPPORTED;
> +     }
> +
> +     mod_freesync_build_vrr_params(dm->freesync_module,
> +                                   new_stream,
> +                                   &config, &vrr);
> +
> +     mod_freesync_build_vrr_infopacket(
> +             dm->freesync_module,
> +             new_stream,
> +             &vrr,
> +             packet_type_vrr,
> +             transfer_func_unknown,
> +             &vrr_infopacket);
> +
> +     new_crtc_state->freesync_timing_changed =
> +             (memcmp(&new_crtc_state->adjust,
> +                     &vrr.adjust,
> +                     sizeof(vrr.adjust)) != 0);
> +
> +     new_crtc_state->freesync_vrr_info_changed =
> +             (memcmp(&new_crtc_state->vrr_infopacket,
> +                     &vrr_infopacket,
> +                     sizeof(vrr_infopacket)) != 0);
> +
> +     new_crtc_state->adjust = vrr.adjust;
> +     new_crtc_state->vrr_infopacket = vrr_infopacket;
> +
> +     new_stream->adjust = new_crtc_state->adjust;
> +     new_stream->vrr_infopacket = vrr_infopacket;
> +
> +     if (new_crtc_state->freesync_vrr_info_changed)
> +             DRM_DEBUG_KMS("VRR packet update: crtc=%u enabled=%d state=%d",
> +                           new_crtc_state->base.crtc->base.id,
> +                           (int)new_crtc_state->base.vrr_enabled,
> +                           (int)vrr.state);
> +
> +     if (new_crtc_state->freesync_timing_changed)
> +             DRM_DEBUG_KMS("VRR timing update: crtc=%u min=%u max=%u\n",
> +                           new_crtc_state->base.crtc->base.id,
> +                           vrr.adjust.v_total_min,
> +                           vrr.adjust.v_total_max);
> +}
> +
>  /*
>   * Executes flip
>   *
> @@ -4197,6 +4205,7 @@ static void amdgpu_dm_do_flip(struct drm_crtc *crtc,
>       struct dc_flip_addrs addr = { {0} };
>       /* TODO eliminate or rename surface_update */
>       struct dc_surface_update surface_updates[1] = { {0} };
> +     struct dc_stream_update stream_update = {0};
>       struct dm_crtc_state *acrtc_state = to_dm_crtc_state(crtc->state);
>       struct dc_stream_status *stream_status;
>  
> @@ -4269,11 +4278,26 @@ static void amdgpu_dm_do_flip(struct drm_crtc *crtc,
>       }
>       surface_updates->flip_addr = &addr;
>  
> +     if (acrtc_state->stream) {
> +             update_freesync_state_on_stream(
> +                     &adev->dm,
> +                     acrtc_state,
> +                     acrtc_state->stream);
> +
> +             if (acrtc_state->freesync_timing_changed)
> +                     stream_update.adjust =
> +                             &acrtc_state->stream->adjust;
> +
> +             if (acrtc_state->freesync_vrr_info_changed)
> +                     stream_update.vrr_infopacket =
> +                             &acrtc_state->stream->vrr_infopacket;
> +     }
> +

For consistency we might also want to do this in commit_planes_to_stream before 
the call to dc_commit_updates_for_stream.

We should really merge the two codepaths for dc_commit_updates_for_stream one 
of these days.

>       dc_commit_updates_for_stream(adev->dm.dc,
>                                            surface_updates,
>                                            1,
>                                            acrtc_state->stream,
> -                                          NULL,
> +                                          &stream_update,
>                                            &surface_updates->surface,
>                                            state);
>  
> @@ -4333,11 +4357,6 @@ static bool commit_planes_to_stream(
>       stream_update->dst = dc_stream->dst;
>       stream_update->out_transfer_func = dc_stream->out_transfer_func;
>  
> -     if (dm_new_crtc_state->freesync_enabled != 
> dm_old_crtc_state->freesync_enabled) {
> -             stream_update->vrr_infopacket = &dc_stream->vrr_infopacket;
> -             stream_update->adjust = &dc_stream->adjust;
> -     }
> -
>       for (i = 0; i < new_plane_count; i++) {
>               updates[i].surface = plane_states[i];
>               updates[i].gamma =
> @@ -4473,9 +4492,6 @@ static void amdgpu_dm_commit_planes(struct 
> drm_atomic_state *state,
>                       spin_unlock_irqrestore(&pcrtc->dev->event_lock, flags);
>               }
>  
> -             dc_stream_attach->adjust = acrtc_state->adjust;
> -             dc_stream_attach->vrr_infopacket = acrtc_state->vrr_infopacket;
> -
>               if (false == commit_planes_to_stream(dm->dc,
>                                                       
> plane_states_constructed,
>                                                       planes_count,
> @@ -4679,9 +4695,6 @@ static void amdgpu_dm_atomic_commit_tail(struct 
> drm_atomic_state *state)
>               WARN_ON(!status);
>               WARN_ON(!status->plane_count);
>  
> -             dm_new_crtc_state->stream->adjust = dm_new_crtc_state->adjust;
> -             dm_new_crtc_state->stream->vrr_infopacket = 
> dm_new_crtc_state->vrr_infopacket;
> -
>               /*TODO How it works with MPO ?*/
>               if (!commit_planes_to_stream(
>                               dm->dc,
> @@ -4899,20 +4912,18 @@ static int do_aquire_global_lock(struct drm_device 
> *dev,
>       return ret < 0 ? ret : 0;
>  }
>  
> -void set_freesync_on_stream(struct amdgpu_display_manager *dm,
> -                         struct dm_crtc_state *new_crtc_state,
> -                         struct dm_connector_state *new_con_state,
> -                         struct dc_stream_state *new_stream)
> +static void get_freesync_config_for_crtc(
> +     struct dm_crtc_state *new_crtc_state,
> +     struct dm_connector_state *new_con_state)
>  {
>       struct mod_freesync_config config = {0};
> -     struct mod_vrr_params vrr = {0};
> -     struct dc_info_packet vrr_infopacket = {0};
>       struct amdgpu_dm_connector *aconnector =
>                       to_amdgpu_dm_connector(new_con_state->base.connector);
>  
> -     if (new_con_state->freesync_capable &&
> -         new_con_state->freesync_enable) {
> -             config.state = new_crtc_state->freesync_enabled ?
> +     new_crtc_state->vrr_supported = new_con_state->freesync_capable;
> +
> +     if (new_con_state->freesync_capable) {
> +             config.state = new_crtc_state->base.vrr_enabled ?
>                               VRR_STATE_ACTIVE_VARIABLE :
>                               VRR_STATE_INACTIVE;
>               config.min_refresh_in_uhz =
> @@ -4922,19 +4933,18 @@ void set_freesync_on_stream(struct 
> amdgpu_display_manager *dm,
>               config.vsif_supported = true;
>       }
>  
> -     mod_freesync_build_vrr_params(dm->freesync_module,
> -                                   new_stream,
> -                                   &config, &vrr);
> +     new_crtc_state->freesync_config = config;
> +}
>  
> -     mod_freesync_build_vrr_infopacket(dm->freesync_module,
> -                                       new_stream,
> -                                       &vrr,
> -                                       packet_type_fs1,
> -                                       NULL,
> -                                       &vrr_infopacket);
> +static void reset_freesync_config_for_crtc(
> +     struct dm_crtc_state *new_crtc_state)
> +{
> +     new_crtc_state->vrr_supported = false;
>  
> -     new_crtc_state->adjust = vrr.adjust;
> -     new_crtc_state->vrr_infopacket = vrr_infopacket;
> +     memset(&new_crtc_state->adjust, 0,
> +            sizeof(new_crtc_state->adjust));
> +     memset(&new_crtc_state->vrr_infopacket, 0,
> +            sizeof(new_crtc_state->vrr_infopacket));
>  }
>  
>  static int dm_update_crtcs_state(struct amdgpu_display_manager *dm,
> @@ -5009,9 +5019,6 @@ static int dm_update_crtcs_state(struct 
> amdgpu_display_manager *dm,
>                               break;
>                       }
>  
> -                     set_freesync_on_stream(dm, dm_new_crtc_state,
> -                                            dm_new_conn_state, new_stream);
> -
>                       if (dc_is_stream_unchanged(new_stream, 
> dm_old_crtc_state->stream) &&
>                           dc_is_stream_scaling_unchanged(new_stream, 
> dm_old_crtc_state->stream)) {
>                               new_crtc_state->mode_changed = false;
> @@ -5020,9 +5027,6 @@ static int dm_update_crtcs_state(struct 
> amdgpu_display_manager *dm,
>                       }
>               }
>  
> -             if (dm_old_crtc_state->freesync_enabled != 
> dm_new_crtc_state->freesync_enabled)
> -                     new_crtc_state->mode_changed = true;
> -
>               if (!drm_atomic_crtc_needs_modeset(new_crtc_state))
>                       goto next_crtc;
>  
> @@ -5059,6 +5063,8 @@ static int dm_update_crtcs_state(struct 
> amdgpu_display_manager *dm,
>                       dc_stream_release(dm_old_crtc_state->stream);
>                       dm_new_crtc_state->stream = NULL;
>  
> +                     reset_freesync_config_for_crtc(dm_new_crtc_state);
> +
>                       *lock_and_validation_needed = true;
>  
>               } else {/* Add stream for any updated/enabled CRTC */
> @@ -5136,7 +5142,9 @@ static int dm_update_crtcs_state(struct 
> amdgpu_display_manager *dm,
>                       amdgpu_dm_set_ctm(dm_new_crtc_state);
>               }
>  
> -
> +             /* Update Freesync settings. */
> +             get_freesync_config_for_crtc(dm_new_crtc_state,
> +                                          dm_new_conn_state);
>       }
>  
>       return ret;
> @@ -5401,12 +5409,9 @@ static int amdgpu_dm_atomic_check(struct drm_device 
> *dev,
>               goto fail;
>  
>       for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, 
> new_crtc_state, i) {
> -             struct dm_crtc_state *dm_new_crtc_state = 
> to_dm_crtc_state(new_crtc_state);
> -             struct dm_crtc_state *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 &&
> -                 (dm_old_crtc_state->freesync_enabled == 
> dm_new_crtc_state->freesync_enabled))
> +                 !new_crtc_state->vrr_enabled)
>                       continue;
>  
>               if (!new_crtc_state->enable)
> @@ -5558,14 +5563,15 @@ void amdgpu_dm_update_freesync_caps(struct 
> drm_connector *connector,
>       struct detailed_data_monitor_range *range;
>       struct amdgpu_dm_connector *amdgpu_dm_connector =
>                       to_amdgpu_dm_connector(connector);
> -     struct dm_connector_state *dm_con_state;
> +     struct dm_connector_state *dm_con_state = NULL;
>  
>       struct drm_device *dev = connector->dev;
>       struct amdgpu_device *adev = dev->dev_private;
> +     bool freesync_capable = false;
>  
>       if (!connector->state) {
>               DRM_ERROR("%s - Connector has no state", __func__);
> -             return;
> +             goto update;
>       }
>  
>       if (!edid) {
> @@ -5575,9 +5581,7 @@ void amdgpu_dm_update_freesync_caps(struct 
> drm_connector *connector,
>               amdgpu_dm_connector->max_vfreq = 0;
>               amdgpu_dm_connector->pixel_clock_mhz = 0;
>  
> -             dm_con_state->freesync_capable = false;
> -             dm_con_state->freesync_enable = false;
> -             return;
> +             goto update;
>       }
>  
>       dm_con_state = to_dm_connector_state(connector->state);
> @@ -5585,10 +5589,10 @@ void amdgpu_dm_update_freesync_caps(struct 
> drm_connector *connector,
>       edid_check_required = false;
>       if (!amdgpu_dm_connector->dc_sink) {
>               DRM_ERROR("dc_sink NULL, could not add free_sync module.\n");
> -             return;
> +             goto update;
>       }
>       if (!adev->dm.freesync_module)
> -             return;
> +             goto update;
>       /*
>        * if edid non zero restrict freesync only for dp and edp
>        */
> @@ -5600,7 +5604,6 @@ void amdgpu_dm_update_freesync_caps(struct 
> drm_connector *connector,
>                                               amdgpu_dm_connector);
>               }
>       }
> -     dm_con_state->freesync_capable = false;
>       if (edid_check_required == true && (edid->version > 1 ||
>          (edid->version == 1 && edid->revision > 1))) {
>               for (i = 0; i < 4; i++) {
> @@ -5632,8 +5635,16 @@ void amdgpu_dm_update_freesync_caps(struct 
> drm_connector *connector,
>               if (amdgpu_dm_connector->max_vfreq -
>                   amdgpu_dm_connector->min_vfreq > 10) {
>  
> -                     dm_con_state->freesync_capable = true;
> +                     freesync_capable = true;
>               }
>       }
> +
> +update:
> +     if (dm_con_state)
> +             dm_con_state->freesync_capable = freesync_capable;
> +

Interesting. Looks like we could just grab this from the drm_connector property 
as this isn't something that changes with the state but DRM forces us to track 
it on the connector state as drm_object_property_get_value() throws a WARN_ON 
for atomic drivers. Not sure I like it but it's what we got, I guess.

Harry

> +     if (connector->vrr_capable_property)
> +             drm_connector_set_vrr_capable_property(connector,
> +                                                    freesync_capable);
>  }
>  
> diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h 
> b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
> index 978b34a5011c..a5aaf8b08968 100644
> --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
> +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
> @@ -185,7 +185,11 @@ struct dm_crtc_state {
>       int crc_skip_count;
>       bool crc_enabled;
>  
> -     bool freesync_enabled;
> +     bool freesync_timing_changed;
> +     bool freesync_vrr_info_changed;
> +
> +     bool vrr_supported;
> +     struct mod_freesync_config freesync_config;
>       struct dc_crtc_timing_adjust adjust;
>       struct dc_info_packet vrr_infopacket;
>  };
> @@ -207,7 +211,6 @@ struct dm_connector_state {
>       uint8_t underscan_vborder;
>       uint8_t underscan_hborder;
>       bool underscan_enable;
> -     bool freesync_enable;
>       bool freesync_capable;
>  };
>  
> 
_______________________________________________
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

Reply via email to