diff mbox

[v7,1/5] drm: Read DP branch device HW revision

Message ID 1470661230-15988-2-git-send-email-mika.kahola@intel.com (mailing list archive)
State New, archived
Headers show

Commit Message

Kahola, Mika Aug. 8, 2016, 1 p.m. UTC
HW revision is mandatory field for DisplayPort branch
devices. This is defined in DPCD register field 0x509.

v2: move drm_dp_ds_revision structure to be part of
    drm_dp_link structure (Daniel)

Signed-off-by: Mika Kahola <mika.kahola@intel.com>
---
 drivers/gpu/drm/drm_dp_helper.c  | 27 +++++++++++++++++++++++++++
 drivers/gpu/drm/i915/intel_drv.h |  1 +
 include/drm/drm_dp_helper.h      |  9 +++++++++
 3 files changed, 37 insertions(+)

Comments

Ville Syrjala Aug. 11, 2016, 7:10 a.m. UTC | #1
On Mon, Aug 08, 2016 at 04:00:26PM +0300, Mika Kahola wrote:
> HW revision is mandatory field for DisplayPort branch
> devices. This is defined in DPCD register field 0x509.

But what do we want to do with it? Me, I don't see a point in parsing a
bunch of stuff from the DPCD unless there's a real use case for it.
/dev/drm_dp_aux will provide all the debug aid we need if we need to
check random pieces of data from the DPCD, so even exposing this sort
of stuff via debugfs is IMO pretty pointless.

If there's a good reason for a debug print, then I think we could parse
something and dump it out so that it's always in the dmesg. But so far
I'm not aware of any bug that would have required to deal with different
hw revisions of things and whatnot.

> 
> v2: move drm_dp_ds_revision structure to be part of
>     drm_dp_link structure (Daniel)
> 
> Signed-off-by: Mika Kahola <mika.kahola@intel.com>
> ---
>  drivers/gpu/drm/drm_dp_helper.c  | 27 +++++++++++++++++++++++++++
>  drivers/gpu/drm/i915/intel_drv.h |  1 +
>  include/drm/drm_dp_helper.h      |  9 +++++++++
>  3 files changed, 37 insertions(+)
> 
> diff --git a/drivers/gpu/drm/drm_dp_helper.c b/drivers/gpu/drm/drm_dp_helper.c
> index 75b2873..5fecdc1 100644
> --- a/drivers/gpu/drm/drm_dp_helper.c
> +++ b/drivers/gpu/drm/drm_dp_helper.c
> @@ -514,6 +514,33 @@ int drm_dp_downstream_max_bpc(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
>  EXPORT_SYMBOL(drm_dp_downstream_max_bpc);
>  
>  /**
> + * drm_dp_downstream_hw_rev() - read DP branch device HW revision
> + * @aux: DisplayPort AUX channel
> + *
> + * Returns 0 on succes or negative error code on failure
> + */
> +int drm_dp_downstream_hw_rev(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
> +			     struct drm_dp_aux *aux, struct drm_dp_link *link)
> +{
> +	uint8_t tmp;
> +	int err;
> +
> +	if (!(dpcd[DP_DOWNSTREAMPORT_PRESENT] & DP_DWN_STRM_PORT_PRESENT))
> +		return -EINVAL;
> +
> +	err = drm_dp_dpcd_read(aux, DP_BRANCH_HW_REV, &tmp, 1);
> +
> +	if (err < 0)
> +		return err;
> +
> +	link->ds_hw_rev.major = (tmp & 0xf0) >> 4;
> +	link->ds_hw_rev.minor = tmp & 0xf;
> +
> +	return 0;
> +}
> +EXPORT_SYMBOL(drm_dp_downstream_hw_rev);
> +
> +/**
>   * drm_dp_downstream_id() - identify branch device
>   * @aux: DisplayPort AUX channel
>   *
> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> index e74d851..a6eccf5 100644
> --- a/drivers/gpu/drm/i915/intel_drv.h
> +++ b/drivers/gpu/drm/i915/intel_drv.h
> @@ -865,6 +865,7 @@ struct intel_dp {
>  	uint8_t num_sink_rates;
>  	int sink_rates[DP_MAX_SUPPORTED_RATES];
>  	struct drm_dp_aux aux;
> +	struct drm_dp_link link;
>  	uint8_t train_set[4];
>  	int panel_power_up_delay;
>  	int panel_power_down_delay;
> diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h
> index 8e1fe58..1127948 100644
> --- a/include/drm/drm_dp_helper.h
> +++ b/include/drm/drm_dp_helper.h
> @@ -446,6 +446,7 @@
>  #define DP_SINK_OUI			    0x400
>  #define DP_BRANCH_OUI			    0x500
>  #define DP_BRANCH_ID                        0x503
> +#define DP_BRANCH_HW_REV                    0x509
>  
>  #define DP_SET_POWER                        0x600
>  # define DP_SET_POWER_D0                    0x1
> @@ -803,11 +804,17 @@ int drm_dp_dpcd_read_link_status(struct drm_dp_aux *aux,
>   */
>  #define DP_LINK_CAP_ENHANCED_FRAMING (1 << 0)
>  
> +struct drm_dp_ds_revision {
> +	int major;
> +	int minor;
> +};
> +
>  struct drm_dp_link {
>  	unsigned char revision;
>  	unsigned int rate;
>  	unsigned int num_lanes;
>  	unsigned long capabilities;
> +	struct drm_dp_ds_revision ds_hw_rev;
>  };
>  
>  int drm_dp_link_probe(struct drm_dp_aux *aux, struct drm_dp_link *link);
> @@ -819,6 +826,8 @@ int drm_dp_downstream_max_clock(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
>  int drm_dp_downstream_max_bpc(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
>  			      const u8 port_cap[4]);
>  int drm_dp_downstream_id(struct drm_dp_aux *aux, char id[6]);
> +int drm_dp_downstream_hw_rev(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
> +			     struct drm_dp_aux *aux, struct drm_dp_link *link);
>  
>  void drm_dp_aux_init(struct drm_dp_aux *aux);
>  int drm_dp_aux_register(struct drm_dp_aux *aux);
> -- 
> 1.9.1
Kahola, Mika Aug. 11, 2016, 8:14 a.m. UTC | #2
On Thu, 2016-08-11 at 10:10 +0300, Ville Syrjälä wrote:
> On Mon, Aug 08, 2016 at 04:00:26PM +0300, Mika Kahola wrote:
> > HW revision is mandatory field for DisplayPort branch
> > devices. This is defined in DPCD register field 0x509.
> 
> But what do we want to do with it? Me, I don't see a point in parsing a
> bunch of stuff from the DPCD unless there's a real use case for it.
> /dev/drm_dp_aux will provide all the debug aid we need if we need to
> check random pieces of data from the DPCD, so even exposing this sort
> of stuff via debugfs is IMO pretty pointless.
> 
> If there's a good reason for a debug print, then I think we could parse
> something and dump it out so that it's always in the dmesg. But so far
> I'm not aware of any bug that would have required to deal with different
> hw revisions of things and whatnot.
> 
Digging up the HW and SW revisions are just for debugging purposes. My
idea here was that it would be handy if this information would be
available if we face a problem let's say with VGA dongle for example. It
is true that at the moment we don't have a single bug that would require
HW/SW revision information but maybe in the future we have one.

So, if we don't want to have this stuff in drm_dp_helpers and/or debugfs
I could make a change and print this info on dmesg when DP branch device
is plugged in.

Cheers,
Mika

> > 
> > v2: move drm_dp_ds_revision structure to be part of
> >     drm_dp_link structure (Daniel)
> > 
> > Signed-off-by: Mika Kahola <mika.kahola@intel.com>
> > ---
> >  drivers/gpu/drm/drm_dp_helper.c  | 27 +++++++++++++++++++++++++++
> >  drivers/gpu/drm/i915/intel_drv.h |  1 +
> >  include/drm/drm_dp_helper.h      |  9 +++++++++
> >  3 files changed, 37 insertions(+)
> > 
> > diff --git a/drivers/gpu/drm/drm_dp_helper.c b/drivers/gpu/drm/drm_dp_helper.c
> > index 75b2873..5fecdc1 100644
> > --- a/drivers/gpu/drm/drm_dp_helper.c
> > +++ b/drivers/gpu/drm/drm_dp_helper.c
> > @@ -514,6 +514,33 @@ int drm_dp_downstream_max_bpc(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
> >  EXPORT_SYMBOL(drm_dp_downstream_max_bpc);
> >  
> >  /**
> > + * drm_dp_downstream_hw_rev() - read DP branch device HW revision
> > + * @aux: DisplayPort AUX channel
> > + *
> > + * Returns 0 on succes or negative error code on failure
> > + */
> > +int drm_dp_downstream_hw_rev(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
> > +			     struct drm_dp_aux *aux, struct drm_dp_link *link)
> > +{
> > +	uint8_t tmp;
> > +	int err;
> > +
> > +	if (!(dpcd[DP_DOWNSTREAMPORT_PRESENT] & DP_DWN_STRM_PORT_PRESENT))
> > +		return -EINVAL;
> > +
> > +	err = drm_dp_dpcd_read(aux, DP_BRANCH_HW_REV, &tmp, 1);
> > +
> > +	if (err < 0)
> > +		return err;
> > +
> > +	link->ds_hw_rev.major = (tmp & 0xf0) >> 4;
> > +	link->ds_hw_rev.minor = tmp & 0xf;
> > +
> > +	return 0;
> > +}
> > +EXPORT_SYMBOL(drm_dp_downstream_hw_rev);
> > +
> > +/**
> >   * drm_dp_downstream_id() - identify branch device
> >   * @aux: DisplayPort AUX channel
> >   *
> > diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> > index e74d851..a6eccf5 100644
> > --- a/drivers/gpu/drm/i915/intel_drv.h
> > +++ b/drivers/gpu/drm/i915/intel_drv.h
> > @@ -865,6 +865,7 @@ struct intel_dp {
> >  	uint8_t num_sink_rates;
> >  	int sink_rates[DP_MAX_SUPPORTED_RATES];
> >  	struct drm_dp_aux aux;
> > +	struct drm_dp_link link;
> >  	uint8_t train_set[4];
> >  	int panel_power_up_delay;
> >  	int panel_power_down_delay;
> > diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h
> > index 8e1fe58..1127948 100644
> > --- a/include/drm/drm_dp_helper.h
> > +++ b/include/drm/drm_dp_helper.h
> > @@ -446,6 +446,7 @@
> >  #define DP_SINK_OUI			    0x400
> >  #define DP_BRANCH_OUI			    0x500
> >  #define DP_BRANCH_ID                        0x503
> > +#define DP_BRANCH_HW_REV                    0x509
> >  
> >  #define DP_SET_POWER                        0x600
> >  # define DP_SET_POWER_D0                    0x1
> > @@ -803,11 +804,17 @@ int drm_dp_dpcd_read_link_status(struct drm_dp_aux *aux,
> >   */
> >  #define DP_LINK_CAP_ENHANCED_FRAMING (1 << 0)
> >  
> > +struct drm_dp_ds_revision {
> > +	int major;
> > +	int minor;
> > +};
> > +
> >  struct drm_dp_link {
> >  	unsigned char revision;
> >  	unsigned int rate;
> >  	unsigned int num_lanes;
> >  	unsigned long capabilities;
> > +	struct drm_dp_ds_revision ds_hw_rev;
> >  };
> >  
> >  int drm_dp_link_probe(struct drm_dp_aux *aux, struct drm_dp_link *link);
> > @@ -819,6 +826,8 @@ int drm_dp_downstream_max_clock(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
> >  int drm_dp_downstream_max_bpc(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
> >  			      const u8 port_cap[4]);
> >  int drm_dp_downstream_id(struct drm_dp_aux *aux, char id[6]);
> > +int drm_dp_downstream_hw_rev(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
> > +			     struct drm_dp_aux *aux, struct drm_dp_link *link);
> >  
> >  void drm_dp_aux_init(struct drm_dp_aux *aux);
> >  int drm_dp_aux_register(struct drm_dp_aux *aux);
> > -- 
> > 1.9.1
>
Ville Syrjala Aug. 11, 2016, 8:22 a.m. UTC | #3
On Thu, Aug 11, 2016 at 11:14:43AM +0300, Mika Kahola wrote:
> On Thu, 2016-08-11 at 10:10 +0300, Ville Syrjälä wrote:
> > On Mon, Aug 08, 2016 at 04:00:26PM +0300, Mika Kahola wrote:
> > > HW revision is mandatory field for DisplayPort branch
> > > devices. This is defined in DPCD register field 0x509.
> > 
> > But what do we want to do with it? Me, I don't see a point in parsing a
> > bunch of stuff from the DPCD unless there's a real use case for it.
> > /dev/drm_dp_aux will provide all the debug aid we need if we need to
> > check random pieces of data from the DPCD, so even exposing this sort
> > of stuff via debugfs is IMO pretty pointless.
> > 
> > If there's a good reason for a debug print, then I think we could parse
> > something and dump it out so that it's always in the dmesg. But so far
> > I'm not aware of any bug that would have required to deal with different
> > hw revisions of things and whatnot.
> > 
> Digging up the HW and SW revisions are just for debugging purposes. My
> idea here was that it would be handy if this information would be
> available if we face a problem let's say with VGA dongle for example. It
> is true that at the moment we don't have a single bug that would require
> HW/SW revision information but maybe in the future we have one.
> 
> So, if we don't want to have this stuff in drm_dp_helpers and/or debugfs
> I could make a change and print this info on dmesg when DP branch device
> is plugged in.

Perhaps. We do print out the OUI as well, so there is some precedent.

> 
> Cheers,
> Mika
> 
> > > 
> > > v2: move drm_dp_ds_revision structure to be part of
> > >     drm_dp_link structure (Daniel)
> > > 
> > > Signed-off-by: Mika Kahola <mika.kahola@intel.com>
> > > ---
> > >  drivers/gpu/drm/drm_dp_helper.c  | 27 +++++++++++++++++++++++++++
> > >  drivers/gpu/drm/i915/intel_drv.h |  1 +
> > >  include/drm/drm_dp_helper.h      |  9 +++++++++
> > >  3 files changed, 37 insertions(+)
> > > 
> > > diff --git a/drivers/gpu/drm/drm_dp_helper.c b/drivers/gpu/drm/drm_dp_helper.c
> > > index 75b2873..5fecdc1 100644
> > > --- a/drivers/gpu/drm/drm_dp_helper.c
> > > +++ b/drivers/gpu/drm/drm_dp_helper.c
> > > @@ -514,6 +514,33 @@ int drm_dp_downstream_max_bpc(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
> > >  EXPORT_SYMBOL(drm_dp_downstream_max_bpc);
> > >  
> > >  /**
> > > + * drm_dp_downstream_hw_rev() - read DP branch device HW revision
> > > + * @aux: DisplayPort AUX channel
> > > + *
> > > + * Returns 0 on succes or negative error code on failure
> > > + */
> > > +int drm_dp_downstream_hw_rev(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
> > > +			     struct drm_dp_aux *aux, struct drm_dp_link *link)
> > > +{
> > > +	uint8_t tmp;
> > > +	int err;
> > > +
> > > +	if (!(dpcd[DP_DOWNSTREAMPORT_PRESENT] & DP_DWN_STRM_PORT_PRESENT))
> > > +		return -EINVAL;
> > > +
> > > +	err = drm_dp_dpcd_read(aux, DP_BRANCH_HW_REV, &tmp, 1);
> > > +
> > > +	if (err < 0)
> > > +		return err;
> > > +
> > > +	link->ds_hw_rev.major = (tmp & 0xf0) >> 4;
> > > +	link->ds_hw_rev.minor = tmp & 0xf;
> > > +
> > > +	return 0;
> > > +}
> > > +EXPORT_SYMBOL(drm_dp_downstream_hw_rev);
> > > +
> > > +/**
> > >   * drm_dp_downstream_id() - identify branch device
> > >   * @aux: DisplayPort AUX channel
> > >   *
> > > diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> > > index e74d851..a6eccf5 100644
> > > --- a/drivers/gpu/drm/i915/intel_drv.h
> > > +++ b/drivers/gpu/drm/i915/intel_drv.h
> > > @@ -865,6 +865,7 @@ struct intel_dp {
> > >  	uint8_t num_sink_rates;
> > >  	int sink_rates[DP_MAX_SUPPORTED_RATES];
> > >  	struct drm_dp_aux aux;
> > > +	struct drm_dp_link link;
> > >  	uint8_t train_set[4];
> > >  	int panel_power_up_delay;
> > >  	int panel_power_down_delay;
> > > diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h
> > > index 8e1fe58..1127948 100644
> > > --- a/include/drm/drm_dp_helper.h
> > > +++ b/include/drm/drm_dp_helper.h
> > > @@ -446,6 +446,7 @@
> > >  #define DP_SINK_OUI			    0x400
> > >  #define DP_BRANCH_OUI			    0x500
> > >  #define DP_BRANCH_ID                        0x503
> > > +#define DP_BRANCH_HW_REV                    0x509
> > >  
> > >  #define DP_SET_POWER                        0x600
> > >  # define DP_SET_POWER_D0                    0x1
> > > @@ -803,11 +804,17 @@ int drm_dp_dpcd_read_link_status(struct drm_dp_aux *aux,
> > >   */
> > >  #define DP_LINK_CAP_ENHANCED_FRAMING (1 << 0)
> > >  
> > > +struct drm_dp_ds_revision {
> > > +	int major;
> > > +	int minor;
> > > +};
> > > +
> > >  struct drm_dp_link {
> > >  	unsigned char revision;
> > >  	unsigned int rate;
> > >  	unsigned int num_lanes;
> > >  	unsigned long capabilities;
> > > +	struct drm_dp_ds_revision ds_hw_rev;
> > >  };
> > >  
> > >  int drm_dp_link_probe(struct drm_dp_aux *aux, struct drm_dp_link *link);
> > > @@ -819,6 +826,8 @@ int drm_dp_downstream_max_clock(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
> > >  int drm_dp_downstream_max_bpc(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
> > >  			      const u8 port_cap[4]);
> > >  int drm_dp_downstream_id(struct drm_dp_aux *aux, char id[6]);
> > > +int drm_dp_downstream_hw_rev(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
> > > +			     struct drm_dp_aux *aux, struct drm_dp_link *link);
> > >  
> > >  void drm_dp_aux_init(struct drm_dp_aux *aux);
> > >  int drm_dp_aux_register(struct drm_dp_aux *aux);
> > > -- 
> > > 1.9.1
> > 
>
jim.bride@linux.intel.com Aug. 11, 2016, 5:21 p.m. UTC | #4
On Thu, Aug 11, 2016 at 11:22:15AM +0300, Ville Syrjälä wrote:
> On Thu, Aug 11, 2016 at 11:14:43AM +0300, Mika Kahola wrote:
> > On Thu, 2016-08-11 at 10:10 +0300, Ville Syrjälä wrote:
> > > On Mon, Aug 08, 2016 at 04:00:26PM +0300, Mika Kahola wrote:
> > > > HW revision is mandatory field for DisplayPort branch
> > > > devices. This is defined in DPCD register field 0x509.
> > > 
> > > But what do we want to do with it? Me, I don't see a point in parsing a
> > > bunch of stuff from the DPCD unless there's a real use case for it.
> > > /dev/drm_dp_aux will provide all the debug aid we need if we need to
> > > check random pieces of data from the DPCD, so even exposing this sort
> > > of stuff via debugfs is IMO pretty pointless.
> > > 
> > > If there's a good reason for a debug print, then I think we could parse
> > > something and dump it out so that it's always in the dmesg. But so far
> > > I'm not aware of any bug that would have required to deal with different
> > > hw revisions of things and whatnot.
> > > 
> > Digging up the HW and SW revisions are just for debugging purposes. My
> > idea here was that it would be handy if this information would be
> > available if we face a problem let's say with VGA dongle for example. It
> > is true that at the moment we don't have a single bug that would require
> > HW/SW revision information but maybe in the future we have one.
> > 
> > So, if we don't want to have this stuff in drm_dp_helpers and/or debugfs
> > I could make a change and print this info on dmesg when DP branch device
> > is plugged in.
> 
> Perhaps. We do print out the OUI as well, so there is some precedent.

Even if we don't dump stuff out to dmesg, I'd like to see this information
in the mst_info debugfs file or someplace similar.  As has been pointed out,
having this information available in the event that we need to work with a
vendor on a problem would be a help.

Jim


> 
> > 
> > Cheers,
> > Mika
> > 
> > > > 
> > > > v2: move drm_dp_ds_revision structure to be part of
> > > >     drm_dp_link structure (Daniel)
> > > > 
> > > > Signed-off-by: Mika Kahola <mika.kahola@intel.com>
> > > > ---
> > > >  drivers/gpu/drm/drm_dp_helper.c  | 27 +++++++++++++++++++++++++++
> > > >  drivers/gpu/drm/i915/intel_drv.h |  1 +
> > > >  include/drm/drm_dp_helper.h      |  9 +++++++++
> > > >  3 files changed, 37 insertions(+)
> > > > 
> > > > diff --git a/drivers/gpu/drm/drm_dp_helper.c b/drivers/gpu/drm/drm_dp_helper.c
> > > > index 75b2873..5fecdc1 100644
> > > > --- a/drivers/gpu/drm/drm_dp_helper.c
> > > > +++ b/drivers/gpu/drm/drm_dp_helper.c
> > > > @@ -514,6 +514,33 @@ int drm_dp_downstream_max_bpc(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
> > > >  EXPORT_SYMBOL(drm_dp_downstream_max_bpc);
> > > >  
> > > >  /**
> > > > + * drm_dp_downstream_hw_rev() - read DP branch device HW revision
> > > > + * @aux: DisplayPort AUX channel
> > > > + *
> > > > + * Returns 0 on succes or negative error code on failure
> > > > + */
> > > > +int drm_dp_downstream_hw_rev(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
> > > > +			     struct drm_dp_aux *aux, struct drm_dp_link *link)
> > > > +{
> > > > +	uint8_t tmp;
> > > > +	int err;
> > > > +
> > > > +	if (!(dpcd[DP_DOWNSTREAMPORT_PRESENT] & DP_DWN_STRM_PORT_PRESENT))
> > > > +		return -EINVAL;
> > > > +
> > > > +	err = drm_dp_dpcd_read(aux, DP_BRANCH_HW_REV, &tmp, 1);
> > > > +
> > > > +	if (err < 0)
> > > > +		return err;
> > > > +
> > > > +	link->ds_hw_rev.major = (tmp & 0xf0) >> 4;
> > > > +	link->ds_hw_rev.minor = tmp & 0xf;
> > > > +
> > > > +	return 0;
> > > > +}
> > > > +EXPORT_SYMBOL(drm_dp_downstream_hw_rev);
> > > > +
> > > > +/**
> > > >   * drm_dp_downstream_id() - identify branch device
> > > >   * @aux: DisplayPort AUX channel
> > > >   *
> > > > diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> > > > index e74d851..a6eccf5 100644
> > > > --- a/drivers/gpu/drm/i915/intel_drv.h
> > > > +++ b/drivers/gpu/drm/i915/intel_drv.h
> > > > @@ -865,6 +865,7 @@ struct intel_dp {
> > > >  	uint8_t num_sink_rates;
> > > >  	int sink_rates[DP_MAX_SUPPORTED_RATES];
> > > >  	struct drm_dp_aux aux;
> > > > +	struct drm_dp_link link;
> > > >  	uint8_t train_set[4];
> > > >  	int panel_power_up_delay;
> > > >  	int panel_power_down_delay;
> > > > diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h
> > > > index 8e1fe58..1127948 100644
> > > > --- a/include/drm/drm_dp_helper.h
> > > > +++ b/include/drm/drm_dp_helper.h
> > > > @@ -446,6 +446,7 @@
> > > >  #define DP_SINK_OUI			    0x400
> > > >  #define DP_BRANCH_OUI			    0x500
> > > >  #define DP_BRANCH_ID                        0x503
> > > > +#define DP_BRANCH_HW_REV                    0x509
> > > >  
> > > >  #define DP_SET_POWER                        0x600
> > > >  # define DP_SET_POWER_D0                    0x1
> > > > @@ -803,11 +804,17 @@ int drm_dp_dpcd_read_link_status(struct drm_dp_aux *aux,
> > > >   */
> > > >  #define DP_LINK_CAP_ENHANCED_FRAMING (1 << 0)
> > > >  
> > > > +struct drm_dp_ds_revision {
> > > > +	int major;
> > > > +	int minor;
> > > > +};
> > > > +
> > > >  struct drm_dp_link {
> > > >  	unsigned char revision;
> > > >  	unsigned int rate;
> > > >  	unsigned int num_lanes;
> > > >  	unsigned long capabilities;
> > > > +	struct drm_dp_ds_revision ds_hw_rev;
> > > >  };
> > > >  
> > > >  int drm_dp_link_probe(struct drm_dp_aux *aux, struct drm_dp_link *link);
> > > > @@ -819,6 +826,8 @@ int drm_dp_downstream_max_clock(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
> > > >  int drm_dp_downstream_max_bpc(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
> > > >  			      const u8 port_cap[4]);
> > > >  int drm_dp_downstream_id(struct drm_dp_aux *aux, char id[6]);
> > > > +int drm_dp_downstream_hw_rev(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
> > > > +			     struct drm_dp_aux *aux, struct drm_dp_link *link);
> > > >  
> > > >  void drm_dp_aux_init(struct drm_dp_aux *aux);
> > > >  int drm_dp_aux_register(struct drm_dp_aux *aux);
> > > > -- 
> > > > 1.9.1
> > > 
> > 
> 
> -- 
> Ville Syrjälä
> Intel OTC
Ville Syrjala Aug. 11, 2016, 5:46 p.m. UTC | #5
On Thu, Aug 11, 2016 at 10:21:36AM -0700, Jim Bride wrote:
> On Thu, Aug 11, 2016 at 11:22:15AM +0300, Ville Syrjälä wrote:
> > On Thu, Aug 11, 2016 at 11:14:43AM +0300, Mika Kahola wrote:
> > > On Thu, 2016-08-11 at 10:10 +0300, Ville Syrjälä wrote:
> > > > On Mon, Aug 08, 2016 at 04:00:26PM +0300, Mika Kahola wrote:
> > > > > HW revision is mandatory field for DisplayPort branch
> > > > > devices. This is defined in DPCD register field 0x509.
> > > > 
> > > > But what do we want to do with it? Me, I don't see a point in parsing a
> > > > bunch of stuff from the DPCD unless there's a real use case for it.
> > > > /dev/drm_dp_aux will provide all the debug aid we need if we need to
> > > > check random pieces of data from the DPCD, so even exposing this sort
> > > > of stuff via debugfs is IMO pretty pointless.
> > > > 
> > > > If there's a good reason for a debug print, then I think we could parse
> > > > something and dump it out so that it's always in the dmesg. But so far
> > > > I'm not aware of any bug that would have required to deal with different
> > > > hw revisions of things and whatnot.
> > > > 
> > > Digging up the HW and SW revisions are just for debugging purposes. My
> > > idea here was that it would be handy if this information would be
> > > available if we face a problem let's say with VGA dongle for example. It
> > > is true that at the moment we don't have a single bug that would require
> > > HW/SW revision information but maybe in the future we have one.
> > > 
> > > So, if we don't want to have this stuff in drm_dp_helpers and/or debugfs
> > > I could make a change and print this info on dmesg when DP branch device
> > > is plugged in.
> > 
> > Perhaps. We do print out the OUI as well, so there is some precedent.
> 
> Even if we don't dump stuff out to dmesg, I'd like to see this information
> in the mst_info debugfs file or someplace similar.  As has been pointed out,
> having this information available in the event that we need to work with a
> vendor on a problem would be a help.

Just dump the whole thing via /dev/drm_dp_aux<n>. The problem with
getting parsed data for debugging is that the parser itself might be
buggy or just incomplete. So IMO it's always much better to get the
raw data. This way you can be sure that it's not affected by the parser,
and that you get all of the data and don't have to back asking for more all
the time.

I really hate it when someone attaches a parsed VBT dump to a bug for
instance. It's pretty much useless.

I've been waiting for someone to step up and write a userspace tool for
pretty printing the entire DPCD dumps. So far no one has volunteered.

> Jim
> 
> 
> > 
> > > 
> > > Cheers,
> > > Mika
> > > 
> > > > > 
> > > > > v2: move drm_dp_ds_revision structure to be part of
> > > > >     drm_dp_link structure (Daniel)
> > > > > 
> > > > > Signed-off-by: Mika Kahola <mika.kahola@intel.com>
> > > > > ---
> > > > >  drivers/gpu/drm/drm_dp_helper.c  | 27 +++++++++++++++++++++++++++
> > > > >  drivers/gpu/drm/i915/intel_drv.h |  1 +
> > > > >  include/drm/drm_dp_helper.h      |  9 +++++++++
> > > > >  3 files changed, 37 insertions(+)
> > > > > 
> > > > > diff --git a/drivers/gpu/drm/drm_dp_helper.c b/drivers/gpu/drm/drm_dp_helper.c
> > > > > index 75b2873..5fecdc1 100644
> > > > > --- a/drivers/gpu/drm/drm_dp_helper.c
> > > > > +++ b/drivers/gpu/drm/drm_dp_helper.c
> > > > > @@ -514,6 +514,33 @@ int drm_dp_downstream_max_bpc(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
> > > > >  EXPORT_SYMBOL(drm_dp_downstream_max_bpc);
> > > > >  
> > > > >  /**
> > > > > + * drm_dp_downstream_hw_rev() - read DP branch device HW revision
> > > > > + * @aux: DisplayPort AUX channel
> > > > > + *
> > > > > + * Returns 0 on succes or negative error code on failure
> > > > > + */
> > > > > +int drm_dp_downstream_hw_rev(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
> > > > > +			     struct drm_dp_aux *aux, struct drm_dp_link *link)
> > > > > +{
> > > > > +	uint8_t tmp;
> > > > > +	int err;
> > > > > +
> > > > > +	if (!(dpcd[DP_DOWNSTREAMPORT_PRESENT] & DP_DWN_STRM_PORT_PRESENT))
> > > > > +		return -EINVAL;
> > > > > +
> > > > > +	err = drm_dp_dpcd_read(aux, DP_BRANCH_HW_REV, &tmp, 1);
> > > > > +
> > > > > +	if (err < 0)
> > > > > +		return err;
> > > > > +
> > > > > +	link->ds_hw_rev.major = (tmp & 0xf0) >> 4;
> > > > > +	link->ds_hw_rev.minor = tmp & 0xf;
> > > > > +
> > > > > +	return 0;
> > > > > +}
> > > > > +EXPORT_SYMBOL(drm_dp_downstream_hw_rev);
> > > > > +
> > > > > +/**
> > > > >   * drm_dp_downstream_id() - identify branch device
> > > > >   * @aux: DisplayPort AUX channel
> > > > >   *
> > > > > diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> > > > > index e74d851..a6eccf5 100644
> > > > > --- a/drivers/gpu/drm/i915/intel_drv.h
> > > > > +++ b/drivers/gpu/drm/i915/intel_drv.h
> > > > > @@ -865,6 +865,7 @@ struct intel_dp {
> > > > >  	uint8_t num_sink_rates;
> > > > >  	int sink_rates[DP_MAX_SUPPORTED_RATES];
> > > > >  	struct drm_dp_aux aux;
> > > > > +	struct drm_dp_link link;
> > > > >  	uint8_t train_set[4];
> > > > >  	int panel_power_up_delay;
> > > > >  	int panel_power_down_delay;
> > > > > diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h
> > > > > index 8e1fe58..1127948 100644
> > > > > --- a/include/drm/drm_dp_helper.h
> > > > > +++ b/include/drm/drm_dp_helper.h
> > > > > @@ -446,6 +446,7 @@
> > > > >  #define DP_SINK_OUI			    0x400
> > > > >  #define DP_BRANCH_OUI			    0x500
> > > > >  #define DP_BRANCH_ID                        0x503
> > > > > +#define DP_BRANCH_HW_REV                    0x509
> > > > >  
> > > > >  #define DP_SET_POWER                        0x600
> > > > >  # define DP_SET_POWER_D0                    0x1
> > > > > @@ -803,11 +804,17 @@ int drm_dp_dpcd_read_link_status(struct drm_dp_aux *aux,
> > > > >   */
> > > > >  #define DP_LINK_CAP_ENHANCED_FRAMING (1 << 0)
> > > > >  
> > > > > +struct drm_dp_ds_revision {
> > > > > +	int major;
> > > > > +	int minor;
> > > > > +};
> > > > > +
> > > > >  struct drm_dp_link {
> > > > >  	unsigned char revision;
> > > > >  	unsigned int rate;
> > > > >  	unsigned int num_lanes;
> > > > >  	unsigned long capabilities;
> > > > > +	struct drm_dp_ds_revision ds_hw_rev;
> > > > >  };
> > > > >  
> > > > >  int drm_dp_link_probe(struct drm_dp_aux *aux, struct drm_dp_link *link);
> > > > > @@ -819,6 +826,8 @@ int drm_dp_downstream_max_clock(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
> > > > >  int drm_dp_downstream_max_bpc(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
> > > > >  			      const u8 port_cap[4]);
> > > > >  int drm_dp_downstream_id(struct drm_dp_aux *aux, char id[6]);
> > > > > +int drm_dp_downstream_hw_rev(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
> > > > > +			     struct drm_dp_aux *aux, struct drm_dp_link *link);
> > > > >  
> > > > >  void drm_dp_aux_init(struct drm_dp_aux *aux);
> > > > >  int drm_dp_aux_register(struct drm_dp_aux *aux);
> > > > > -- 
> > > > > 1.9.1
> > > > 
> > > 
> > 
> > -- 
> > Ville Syrjälä
> > Intel OTC
diff mbox

Patch

diff --git a/drivers/gpu/drm/drm_dp_helper.c b/drivers/gpu/drm/drm_dp_helper.c
index 75b2873..5fecdc1 100644
--- a/drivers/gpu/drm/drm_dp_helper.c
+++ b/drivers/gpu/drm/drm_dp_helper.c
@@ -514,6 +514,33 @@  int drm_dp_downstream_max_bpc(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
 EXPORT_SYMBOL(drm_dp_downstream_max_bpc);
 
 /**
+ * drm_dp_downstream_hw_rev() - read DP branch device HW revision
+ * @aux: DisplayPort AUX channel
+ *
+ * Returns 0 on succes or negative error code on failure
+ */
+int drm_dp_downstream_hw_rev(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
+			     struct drm_dp_aux *aux, struct drm_dp_link *link)
+{
+	uint8_t tmp;
+	int err;
+
+	if (!(dpcd[DP_DOWNSTREAMPORT_PRESENT] & DP_DWN_STRM_PORT_PRESENT))
+		return -EINVAL;
+
+	err = drm_dp_dpcd_read(aux, DP_BRANCH_HW_REV, &tmp, 1);
+
+	if (err < 0)
+		return err;
+
+	link->ds_hw_rev.major = (tmp & 0xf0) >> 4;
+	link->ds_hw_rev.minor = tmp & 0xf;
+
+	return 0;
+}
+EXPORT_SYMBOL(drm_dp_downstream_hw_rev);
+
+/**
  * drm_dp_downstream_id() - identify branch device
  * @aux: DisplayPort AUX channel
  *
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index e74d851..a6eccf5 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -865,6 +865,7 @@  struct intel_dp {
 	uint8_t num_sink_rates;
 	int sink_rates[DP_MAX_SUPPORTED_RATES];
 	struct drm_dp_aux aux;
+	struct drm_dp_link link;
 	uint8_t train_set[4];
 	int panel_power_up_delay;
 	int panel_power_down_delay;
diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h
index 8e1fe58..1127948 100644
--- a/include/drm/drm_dp_helper.h
+++ b/include/drm/drm_dp_helper.h
@@ -446,6 +446,7 @@ 
 #define DP_SINK_OUI			    0x400
 #define DP_BRANCH_OUI			    0x500
 #define DP_BRANCH_ID                        0x503
+#define DP_BRANCH_HW_REV                    0x509
 
 #define DP_SET_POWER                        0x600
 # define DP_SET_POWER_D0                    0x1
@@ -803,11 +804,17 @@  int drm_dp_dpcd_read_link_status(struct drm_dp_aux *aux,
  */
 #define DP_LINK_CAP_ENHANCED_FRAMING (1 << 0)
 
+struct drm_dp_ds_revision {
+	int major;
+	int minor;
+};
+
 struct drm_dp_link {
 	unsigned char revision;
 	unsigned int rate;
 	unsigned int num_lanes;
 	unsigned long capabilities;
+	struct drm_dp_ds_revision ds_hw_rev;
 };
 
 int drm_dp_link_probe(struct drm_dp_aux *aux, struct drm_dp_link *link);
@@ -819,6 +826,8 @@  int drm_dp_downstream_max_clock(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
 int drm_dp_downstream_max_bpc(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
 			      const u8 port_cap[4]);
 int drm_dp_downstream_id(struct drm_dp_aux *aux, char id[6]);
+int drm_dp_downstream_hw_rev(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
+			     struct drm_dp_aux *aux, struct drm_dp_link *link);
 
 void drm_dp_aux_init(struct drm_dp_aux *aux);
 int drm_dp_aux_register(struct drm_dp_aux *aux);