diff mbox

[3/6] drm/mst: cached EDID for logical ports

Message ID 1413945127-31793-4-git-send-email-airlied@gmail.com (mailing list archive)
State New, archived
Headers show

Commit Message

Dave Airlie Oct. 22, 2014, 2:32 a.m. UTC
From: Dave Airlie <airlied@redhat.com>

Logical ports are never going to have EDID changes,
they are used for the internal ports on MST monitors.

We cache the EDIDs from these to save time at MST probe.

Signed-off-by: Dave Airlie <airlied@redhat.com>
---
 drivers/gpu/drm/drm_dp_mst_topology.c | 20 ++++++++++++++++++--
 drivers/gpu/drm/i915/intel_dp_mst.c   |  2 +-
 include/drm/drm_dp_mst_helper.h       |  4 +++-
 3 files changed, 22 insertions(+), 4 deletions(-)

Comments

Daniel Vetter Oct. 22, 2014, 9:06 a.m. UTC | #1
On Wed, Oct 22, 2014 at 12:32:04PM +1000, Dave Airlie wrote:
> From: Dave Airlie <airlied@redhat.com>
> 
> Logical ports are never going to have EDID changes,
> they are used for the internal ports on MST monitors.
> 
> We cache the EDIDs from these to save time at MST probe.
> 
> Signed-off-by: Dave Airlie <airlied@redhat.com>
> ---
>  drivers/gpu/drm/drm_dp_mst_topology.c | 20 ++++++++++++++++++--
>  drivers/gpu/drm/i915/intel_dp_mst.c   |  2 +-
>  include/drm/drm_dp_mst_helper.h       |  4 +++-
>  3 files changed, 22 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/gpu/drm/drm_dp_mst_topology.c b/drivers/gpu/drm/drm_dp_mst_topology.c
> index 50926db..ce1113c 100644
> --- a/drivers/gpu/drm/drm_dp_mst_topology.c
> +++ b/drivers/gpu/drm/drm_dp_mst_topology.c
> @@ -858,6 +858,8 @@ static void drm_dp_destroy_port(struct kref *kref)
>  	struct drm_dp_mst_topology_mgr *mgr = port->mgr;
>  	if (!port->input) {
>  		port->vcpi.num_slots = 0;
> +
> +		kfree(port->cached_edid);
>  		if (port->connector)
>  			(*port->mgr->cbs->destroy_connector)(mgr, port->connector);
>  		drm_dp_port_teardown_pdt(port, port->pdt);
> @@ -1096,6 +1098,10 @@ static void drm_dp_add_port(struct drm_dp_mst_branch *mstb,
>  		char proppath[255];
>  		build_mst_prop_path(port, mstb, proppath);
>  		port->connector = (*mstb->mgr->cbs->add_connector)(mstb->mgr, port, proppath);
> +
> +		if (port->port_num >= 8) {
> +			port->cached_edid = drm_get_edid(port->connector, &port->aux.ddc);
> +		}

I'm confused about how this works ... the tile property gets added in the
intel ->add_connector callback already, but that relies upon drm_get_edid
having parsed the displayid stuff. What am I missing?
-Daniel

>  	}
>  
>  	/* put reference to this port */
> @@ -2149,7 +2155,8 @@ EXPORT_SYMBOL(drm_dp_mst_hpd_irq);
>   * This returns the current connection state for a port. It validates the
>   * port pointer still exists so the caller doesn't require a reference
>   */
> -enum drm_connector_status drm_dp_mst_detect_port(struct drm_dp_mst_topology_mgr *mgr, struct drm_dp_mst_port *port)
> +enum drm_connector_status drm_dp_mst_detect_port(struct drm_connector *connector,
> +						 struct drm_dp_mst_topology_mgr *mgr, struct drm_dp_mst_port *port)
>  {
>  	enum drm_connector_status status = connector_status_disconnected;
>  
> @@ -2168,6 +2175,10 @@ enum drm_connector_status drm_dp_mst_detect_port(struct drm_dp_mst_topology_mgr
>  
>  	case DP_PEER_DEVICE_SST_SINK:
>  		status = connector_status_connected;
> +		/* for logical ports - cache the EDID */
> +		if (port->port_num >= 8 && !port->cached_edid) {
> +			port->cached_edid = drm_get_edid(connector, &port->aux.ddc);
> +		}
>  		break;
>  	case DP_PEER_DEVICE_DP_LEGACY_CONV:
>  		if (port->ldps)
> @@ -2199,7 +2210,12 @@ struct edid *drm_dp_mst_get_edid(struct drm_connector *connector, struct drm_dp_
>  	if (!port)
>  		return NULL;
>  
> -	edid = drm_get_edid(connector, &port->aux.ddc);
> +	if (port->cached_edid)
> +		edid = drm_edid_duplicate(port->cached_edid);
> +	else
> +		edid = drm_get_edid(connector, &port->aux.ddc);
> +
> +	drm_mode_connector_set_tile_property(connector);
>  	drm_dp_put_port(port);
>  	return edid;
>  }
> diff --git a/drivers/gpu/drm/i915/intel_dp_mst.c b/drivers/gpu/drm/i915/intel_dp_mst.c
> index d9a7a78..c66e73a 100644
> --- a/drivers/gpu/drm/i915/intel_dp_mst.c
> +++ b/drivers/gpu/drm/i915/intel_dp_mst.c
> @@ -283,7 +283,7 @@ intel_mst_port_dp_detect(struct drm_connector *connector)
>  	struct intel_connector *intel_connector = to_intel_connector(connector);
>  	struct intel_dp *intel_dp = intel_connector->mst_port;
>  
> -	return drm_dp_mst_detect_port(&intel_dp->mst_mgr, intel_connector->port);
> +	return drm_dp_mst_detect_port(connector, &intel_dp->mst_mgr, intel_connector->port);
>  }
>  
>  static enum drm_connector_status
> diff --git a/include/drm/drm_dp_mst_helper.h b/include/drm/drm_dp_mst_helper.h
> index 338fc10..ee6fbad 100644
> --- a/include/drm/drm_dp_mst_helper.h
> +++ b/include/drm/drm_dp_mst_helper.h
> @@ -92,6 +92,8 @@ struct drm_dp_mst_port {
>  	struct drm_dp_vcpi vcpi;
>  	struct drm_connector *connector;
>  	struct drm_dp_mst_topology_mgr *mgr;
> +
> +	struct edid *cached_edid; /* for DP logical ports - make tiling work */
>  };
>  
>  /**
> @@ -474,7 +476,7 @@ int drm_dp_mst_topology_mgr_set_mst(struct drm_dp_mst_topology_mgr *mgr, bool ms
>  int drm_dp_mst_hpd_irq(struct drm_dp_mst_topology_mgr *mgr, u8 *esi, bool *handled);
>  
>  
> -enum drm_connector_status drm_dp_mst_detect_port(struct drm_dp_mst_topology_mgr *mgr, struct drm_dp_mst_port *port);
> +enum drm_connector_status drm_dp_mst_detect_port(struct drm_connector *connector, struct drm_dp_mst_topology_mgr *mgr, struct drm_dp_mst_port *port);
>  
>  struct edid *drm_dp_mst_get_edid(struct drm_connector *connector, struct drm_dp_mst_topology_mgr *mgr, struct drm_dp_mst_port *port);
>  
> -- 
> 2.1.0
> 
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx
Dave Airlie Nov. 10, 2014, 2:11 a.m. UTC | #2
On 22 October 2014 19:06, Daniel Vetter <daniel@ffwll.ch> wrote:
> On Wed, Oct 22, 2014 at 12:32:04PM +1000, Dave Airlie wrote:
>> From: Dave Airlie <airlied@redhat.com>
>>
>> Logical ports are never going to have EDID changes,
>> they are used for the internal ports on MST monitors.
>>
>> We cache the EDIDs from these to save time at MST probe.
>>
>> Signed-off-by: Dave Airlie <airlied@redhat.com>
>> ---
>>  drivers/gpu/drm/drm_dp_mst_topology.c | 20 ++++++++++++++++++--
>>  drivers/gpu/drm/i915/intel_dp_mst.c   |  2 +-
>>  include/drm/drm_dp_mst_helper.h       |  4 +++-
>>  3 files changed, 22 insertions(+), 4 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/drm_dp_mst_topology.c b/drivers/gpu/drm/drm_dp_mst_topology.c
>> index 50926db..ce1113c 100644
>> --- a/drivers/gpu/drm/drm_dp_mst_topology.c
>> +++ b/drivers/gpu/drm/drm_dp_mst_topology.c
>> @@ -858,6 +858,8 @@ static void drm_dp_destroy_port(struct kref *kref)
>>       struct drm_dp_mst_topology_mgr *mgr = port->mgr;
>>       if (!port->input) {
>>               port->vcpi.num_slots = 0;
>> +
>> +             kfree(port->cached_edid);
>>               if (port->connector)
>>                       (*port->mgr->cbs->destroy_connector)(mgr, port->connector);
>>               drm_dp_port_teardown_pdt(port, port->pdt);
>> @@ -1096,6 +1098,10 @@ static void drm_dp_add_port(struct drm_dp_mst_branch *mstb,
>>               char proppath[255];
>>               build_mst_prop_path(port, mstb, proppath);
>>               port->connector = (*mstb->mgr->cbs->add_connector)(mstb->mgr, port, proppath);
>> +
>> +             if (port->port_num >= 8) {
>> +                     port->cached_edid = drm_get_edid(port->connector, &port->aux.ddc);
>> +             }
>
> I'm confused about how this works ... the tile property gets added in the
> intel ->add_connector callback already, but that relies upon drm_get_edid
> having parsed the displayid stuff. What am I missing?

The tile property gets added to the connector with no value, but only
gets set with a value here.

Since we rely on the EDID to know the value.

Also previous version of the patch had the call to set the property up
in the wrong patch.

Dave.
diff mbox

Patch

diff --git a/drivers/gpu/drm/drm_dp_mst_topology.c b/drivers/gpu/drm/drm_dp_mst_topology.c
index 50926db..ce1113c 100644
--- a/drivers/gpu/drm/drm_dp_mst_topology.c
+++ b/drivers/gpu/drm/drm_dp_mst_topology.c
@@ -858,6 +858,8 @@  static void drm_dp_destroy_port(struct kref *kref)
 	struct drm_dp_mst_topology_mgr *mgr = port->mgr;
 	if (!port->input) {
 		port->vcpi.num_slots = 0;
+
+		kfree(port->cached_edid);
 		if (port->connector)
 			(*port->mgr->cbs->destroy_connector)(mgr, port->connector);
 		drm_dp_port_teardown_pdt(port, port->pdt);
@@ -1096,6 +1098,10 @@  static void drm_dp_add_port(struct drm_dp_mst_branch *mstb,
 		char proppath[255];
 		build_mst_prop_path(port, mstb, proppath);
 		port->connector = (*mstb->mgr->cbs->add_connector)(mstb->mgr, port, proppath);
+
+		if (port->port_num >= 8) {
+			port->cached_edid = drm_get_edid(port->connector, &port->aux.ddc);
+		}
 	}
 
 	/* put reference to this port */
@@ -2149,7 +2155,8 @@  EXPORT_SYMBOL(drm_dp_mst_hpd_irq);
  * This returns the current connection state for a port. It validates the
  * port pointer still exists so the caller doesn't require a reference
  */
-enum drm_connector_status drm_dp_mst_detect_port(struct drm_dp_mst_topology_mgr *mgr, struct drm_dp_mst_port *port)
+enum drm_connector_status drm_dp_mst_detect_port(struct drm_connector *connector,
+						 struct drm_dp_mst_topology_mgr *mgr, struct drm_dp_mst_port *port)
 {
 	enum drm_connector_status status = connector_status_disconnected;
 
@@ -2168,6 +2175,10 @@  enum drm_connector_status drm_dp_mst_detect_port(struct drm_dp_mst_topology_mgr
 
 	case DP_PEER_DEVICE_SST_SINK:
 		status = connector_status_connected;
+		/* for logical ports - cache the EDID */
+		if (port->port_num >= 8 && !port->cached_edid) {
+			port->cached_edid = drm_get_edid(connector, &port->aux.ddc);
+		}
 		break;
 	case DP_PEER_DEVICE_DP_LEGACY_CONV:
 		if (port->ldps)
@@ -2199,7 +2210,12 @@  struct edid *drm_dp_mst_get_edid(struct drm_connector *connector, struct drm_dp_
 	if (!port)
 		return NULL;
 
-	edid = drm_get_edid(connector, &port->aux.ddc);
+	if (port->cached_edid)
+		edid = drm_edid_duplicate(port->cached_edid);
+	else
+		edid = drm_get_edid(connector, &port->aux.ddc);
+
+	drm_mode_connector_set_tile_property(connector);
 	drm_dp_put_port(port);
 	return edid;
 }
diff --git a/drivers/gpu/drm/i915/intel_dp_mst.c b/drivers/gpu/drm/i915/intel_dp_mst.c
index d9a7a78..c66e73a 100644
--- a/drivers/gpu/drm/i915/intel_dp_mst.c
+++ b/drivers/gpu/drm/i915/intel_dp_mst.c
@@ -283,7 +283,7 @@  intel_mst_port_dp_detect(struct drm_connector *connector)
 	struct intel_connector *intel_connector = to_intel_connector(connector);
 	struct intel_dp *intel_dp = intel_connector->mst_port;
 
-	return drm_dp_mst_detect_port(&intel_dp->mst_mgr, intel_connector->port);
+	return drm_dp_mst_detect_port(connector, &intel_dp->mst_mgr, intel_connector->port);
 }
 
 static enum drm_connector_status
diff --git a/include/drm/drm_dp_mst_helper.h b/include/drm/drm_dp_mst_helper.h
index 338fc10..ee6fbad 100644
--- a/include/drm/drm_dp_mst_helper.h
+++ b/include/drm/drm_dp_mst_helper.h
@@ -92,6 +92,8 @@  struct drm_dp_mst_port {
 	struct drm_dp_vcpi vcpi;
 	struct drm_connector *connector;
 	struct drm_dp_mst_topology_mgr *mgr;
+
+	struct edid *cached_edid; /* for DP logical ports - make tiling work */
 };
 
 /**
@@ -474,7 +476,7 @@  int drm_dp_mst_topology_mgr_set_mst(struct drm_dp_mst_topology_mgr *mgr, bool ms
 int drm_dp_mst_hpd_irq(struct drm_dp_mst_topology_mgr *mgr, u8 *esi, bool *handled);
 
 
-enum drm_connector_status drm_dp_mst_detect_port(struct drm_dp_mst_topology_mgr *mgr, struct drm_dp_mst_port *port);
+enum drm_connector_status drm_dp_mst_detect_port(struct drm_connector *connector, struct drm_dp_mst_topology_mgr *mgr, struct drm_dp_mst_port *port);
 
 struct edid *drm_dp_mst_get_edid(struct drm_connector *connector, struct drm_dp_mst_topology_mgr *mgr, struct drm_dp_mst_port *port);