[PATCH 12/13] drm/dp_mst: Add DSC enablement helpers to DRM

Lyude Paul lyude at redhat.com
Tue Nov 5 00:31:13 UTC 2019


Hey! Great start so far, some comments down below:

On Wed, 2019-10-30 at 15:24 -0400, mikita.lipski at amd.com wrote:
> From: Mikita Lipski <mikita.lipski at amd.com>
> 
> Adding the following elements to add MST DSC support to DRM:
> 
> - dsc_enable boolean flag to drm_dp_vcpi_allocation structure to signal,
> which port got DSC enabled
> 
> - function drm_dp_helper_update_vcpi_slots_for_dsc allows reallocation
> of newly recalculated VCPI slots and raises dsc_enable flag on the port.
> 
> - function drm_dp_mst_update_dsc_crtcs is called in drm_dp_mst_atomic_check,
> its purpose is to iterate through all the ports in the topology and set
> mode_changed flag on crtc if DSC has been enabled.
> 
> Cc: Harry Wentland <harry.wentland at amd.com>
> Cc: Lyude Paul <lyude at redhat.com>
> Signed-off-by: Mikita Lipski <mikita.lipski at amd.com>
> ---
>  drivers/gpu/drm/drm_dp_mst_topology.c | 103 +++++++++++++++++++++++++-
>  include/drm/drm_dp_mst_helper.h       |   4 +
>  2 files changed, 106 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/gpu/drm/drm_dp_mst_topology.c
> b/drivers/gpu/drm/drm_dp_mst_topology.c
> index d5df02315e14..4f2f09fe32f8 100644
> --- a/drivers/gpu/drm/drm_dp_mst_topology.c
> +++ b/drivers/gpu/drm/drm_dp_mst_topology.c
> @@ -73,6 +73,7 @@ static bool drm_dp_validate_guid(struct
> drm_dp_mst_topology_mgr *mgr,
>  static int drm_dp_mst_register_i2c_bus(struct drm_dp_aux *aux);
>  static void drm_dp_mst_unregister_i2c_bus(struct drm_dp_aux *aux);
>  static void drm_dp_mst_kick_tx(struct drm_dp_mst_topology_mgr *mgr);
> +static void drm_dp_mst_update_dsc_crtcs(struct drm_dp_mst_topology_state
> *mst_state);
>  
>  #define DP_STR(x) [DP_ ## x] = #x
>  
> @@ -3293,6 +3294,65 @@ int drm_dp_atomic_find_vcpi_slots(struct
> drm_atomic_state *state,
>  }
>  EXPORT_SYMBOL(drm_dp_atomic_find_vcpi_slots);
>  
> +/**
> + * drm_dp_helper_update_vcpi_slots_for_dsc() - Update VCPI slots with new
> on the state
> + *
> + * @state: global atomic state
> + * @port: port to find vcpi slots
> + * @pbn: updated bandwidth required for the mode in PBN
> + *
> + * Function reallocates VCPI slots to the @port by calling
> + * drm_dp_atomic_find_vcpi_slots. The assumption is that VCPI slots
> + * have already been allocated and this is second call overwritting
> + * initial values. After the VCPI is allocated dsc_enable flag is set to
> + * true for atomic check.
> + *
> + * It is driver's responsibility to call this function after it decides
> + * to enable DSC.
> + *
> + * See also:
> + * drm_dp_mst_update_dsc_crtcs()
> + *
> + * Returns:
> + * Total slots in the atomic state assigned for this port, or a negative
> error
> + * code if the port no longer exists or vcpi slots haven't been assigned.
> + */
> +int drm_dp_helper_update_vcpi_slots_for_dsc(struct drm_atomic_state *state,
> +					    struct drm_dp_mst_port *port,
> +					    int pbn)
> +{
> +	struct drm_dp_mst_topology_state *topology_state;
> +	struct drm_dp_vcpi_allocation *pos;
> +	bool found = false;
> +	int vcpi = 0;
> +
> +	topology_state = drm_atomic_get_mst_topology_state(state, port->mgr);
> +
> +	if (IS_ERR(topology_state))
> +		return PTR_ERR(topology_state);
> +
> +	list_for_each_entry(pos, &topology_state->vcpis, next) {
> +		if (pos->port == port) {
> +			found = true;
> +			break;
> +		}
> +	}
> +
> +	if (!found || !pos->vcpi)
> +		return -EINVAL;
> +
> +	vcpi = drm_dp_atomic_find_vcpi_slots(state, port->mgr,
> +					     port, pbn);
> +
> +	if (vcpi < 0)
> +		return -EINVAL;
> +
> +	pos->dsc_enable = true;
> +
> +	return vcpi;
> +}
> +
This helper I think we can simplify a bit by dropping it and merging it with
drm_dp_mst_update_dsc_crtcs(). I've got a more in-depth explanation of what I
mean down below:

> +EXPORT_SYMBOL(drm_dp_helper_update_vcpi_slots_for_dsc);
>  /**
>   * drm_dp_atomic_release_vcpi_slots() - Release allocated vcpi slots
>   * @state: global atomic state
> @@ -3871,6 +3931,46 @@ drm_dp_mst_atomic_check_topology_state(struct
> drm_dp_mst_topology_mgr *mgr,
>  	return 0;
>  }
>  
> +/**
> + * drm_dp_mst_update_dsc_crtcs - Set mode change flag on CRTCs which
> + * just got DSC enabled
> + * @state: Pointer to the new &struct drm_dp_mst_topology_state
> + *
> + * Itearate through all the ports in MST topology to check if DSC
> + * has been enabled on any of them. Set mode_changed to true on
> + * crtc state that just got DSC enabled.
> + *
> + * See also:
> + * drm_dp_helper_update_vcpi_slots_for_dsc()
> + */
> +static void
> +drm_dp_mst_update_dsc_crtcs(struct drm_dp_mst_topology_state *mst_state)
> +{

Just grab the atomic state from within this function, not really much point in
making the caller pull in the mst topoloy state since we're the only ones
using it

> +	struct drm_dp_vcpi_allocation *pos;
> +	struct drm_dp_mst_port *port;
> +	struct drm_connector_state *conn_state;
> +	struct drm_crtc *crtc;
> +	struct drm_crtc_state *crtc_state;
> +
> +	list_for_each_entry(pos, &mst_state->vcpis, next) {
> +
> +		port = pos->port;
> +		conn_state = drm_atomic_get_connector_state(mst_state-
> >base.state,
> +							    port->connector);
> +		crtc = conn_state->crtc;
> +		if (!crtc)
> +			continue;
> +
> +		crtc_state = drm_atomic_get_crtc_state(mst_state->base.state,
> crtc);

You're forgetting to check the return status of drm_atomic_get_crtc_state(),
since it can fail here. You need something like:

if (IS_ERR(crtc_state))
	return PTR_ERR(crtc_state);


> +		if (port->vcpi.vcpi == pos->vcpi)
> +			continue;
> +
> +		if (pos->dsc_enable) {
> +			crtc_state->mode_changed = true;
> +			pos->dsc_enable = false;
> +		}
> +	}
> +}

So: I think we can simply this a bit. Why not rename
drm_dp_mst_update_dsc_crtcs() to drm_dp_mst_atomic_enable_dsc(), and rework it
to look like this psuedocode:

int drm_dp_mst_atomic_set_dsc(struct drm_atomic_state *state,
                              struct drm_dp_mst_port *port,
                              bool enabled)
{
	struct drm_dp_mst_topology_state *mst_state = /* ... */;
	/* ... */
	if (port->dsc_enable == enabled)
		return 0;

	port->dsc_enable = enabled;
	for_each_mst_port() {
		if (port->dsc_enable == enabled)
			continue;
		port->dsc_enable = enabled;

		conn_state = drm_atomic_get_connector_state(port->connector);
		/* error handling ... */
		if (!conn_state->crtc)
			continue;
		
		crtc_state = drm_atomic_get_crtc_state(conn_state->crtc);
		/* error handling... */
		crtc_state->mode_changed = true;
	}

	return 0;
}

IMO this works a bit better since all we really need is something to pull in
crtcs affected by the state change.

Also, more DRM_DEBUG_ATOMIC() statements similar to what I've got in the vcpi
helpers would be nice :)

Otherwise, looks great so far!
>  /**
>   * drm_dp_mst_atomic_check - Check that the new state of an MST topology in
> an
>   * atomic update is valid
> @@ -3887,9 +3987,9 @@ drm_dp_mst_atomic_check_topology_state(struct
> drm_dp_mst_topology_mgr *mgr,
>   * See also:
>   * drm_dp_atomic_find_vcpi_slots()
>   * drm_dp_atomic_release_vcpi_slots()
> - *
>   * Returns:
>   *
> + *
>   * 0 if the new state is valid, negative error code otherwise.
>   */
>  int drm_dp_mst_atomic_check(struct drm_atomic_state *state)
> @@ -3902,6 +4002,7 @@ int drm_dp_mst_atomic_check(struct drm_atomic_state
> *state)
>  		ret = drm_dp_mst_atomic_check_topology_state(mgr, mst_state);
>  		if (ret)
>  			break;
> +		drm_dp_mst_update_dsc_crtcs(mst_state);
>  	}
>  
>  	return ret;
> diff --git a/include/drm/drm_dp_mst_helper.h
> b/include/drm/drm_dp_mst_helper.h
> index 4cf738545dfb..185e29895f5f 100644
> --- a/include/drm/drm_dp_mst_helper.h
> +++ b/include/drm/drm_dp_mst_helper.h
> @@ -431,6 +431,7 @@ struct drm_dp_payload {
>  struct drm_dp_vcpi_allocation {
>  	struct drm_dp_mst_port *port;
>  	int vcpi;
> +	bool dsc_enable;
>  	struct list_head next;
>  };
>  
> @@ -662,6 +663,9 @@ int __must_check
>  drm_dp_atomic_find_vcpi_slots(struct drm_atomic_state *state,
>  			      struct drm_dp_mst_topology_mgr *mgr,
>  			      struct drm_dp_mst_port *port, int pbn);
> +int drm_dp_helper_update_vcpi_slots_for_dsc(struct drm_atomic_state *state,
> +					    struct drm_dp_mst_port *port,
> +					    int pbn);
>  int __must_check
>  drm_dp_atomic_release_vcpi_slots(struct drm_atomic_state *state,
>  				 struct drm_dp_mst_topology_mgr *mgr,
-- 
Cheers,
	Lyude Paul



More information about the amd-gfx mailing list