Prep work for DP branch device handling
This series of patches reads DPCD register 0x80h for receiver capabilities for DP branch devices. The branch device types are converters for the following standards
- DP to VGA - DP to DVI - DP to HDMI - DP++ dual mode - Wireless WiGig
DPCD register defines max pixel rate for VGA dongles. This check is carried out during mode validation.
[1] git://github.com/mkahola/drm-intel-mika.git dp_branch_device
v2: DPCD register read outs moved to drm (Ville, Daniel) v3: Max pixel rate computation moved to drm (Daniel) v4: Use of drm_dp_helper routines to collect data (Ville) v5: Remove duplicate code and unnecessary functions from drm_dp_helper (Ville) v6: Rebase and i915_debugfs cleanup v7: Structure cleanups and initial step to move DP debugging info to drm_dp_helpers v8: Cleanups and TMDS clock frequency check for HDMI adapter
Mika Kahola (12): drm: Add missing DP downstream port types drm: Drop VGA from bpc definitions drm: Helper to read max clock rate drm: Helper to read max bits per component drm: Read DP branch device id drm/i915: Cleanup DisplayPort AUX channel initialization drm/i915: Read DP branch device HW revision drm/i915: Read DP branch device SW revision drm/i915: Check pixel rate for DP to VGA dongle drm/i915: Update bits per component for display info drm: Add DP branch device info on debugfs drm/i915: Check TMDS clock DP to HDMI dongle
drivers/gpu/drm/drm_dp_helper.c | 168 ++++++++++++++++++++++++++++++++++++ drivers/gpu/drm/i915/i915_debugfs.c | 3 + drivers/gpu/drm/i915/intel_dp.c | 89 ++++++++++++++++++- drivers/gpu/drm/i915/intel_drv.h | 3 + drivers/gpu/drm/i915/intel_hdmi.c | 27 ++++++ include/drm/drm_dp_helper.h | 22 +++-- 6 files changed, 303 insertions(+), 9 deletions(-)
Add missing DisplayPort downstream port types. The introduced new port types are DP++ and Wireless.
Reviewed-by: Jim Bride jim.bride@linux.intel.com Signed-off-by: Mika Kahola mika.kahola@intel.com --- include/drm/drm_dp_helper.h | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h index 63b8bd5..ba9731e 100644 --- a/include/drm/drm_dp_helper.h +++ b/include/drm/drm_dp_helper.h @@ -211,6 +211,8 @@ # define DP_DS_PORT_TYPE_DVI 2 # define DP_DS_PORT_TYPE_HDMI 3 # define DP_DS_PORT_TYPE_NON_EDID 4 +# define DP_DS_PORT_TYPE_DP_DUALMODE 5 +# define DP_DS_PORT_TYPE_WIRELESS 6 # define DP_DS_PORT_HPD (1 << 3) /* offset 1 for VGA is maximum megapixels per second / 8 */ /* offset 2 */
Drop "VGA" from bits per component definitions as these are also used by other standards such as DVI, HDMI, DP++.
Reviewed-by: Jim Bride jim.bride@linux.intel.com Signed-off-by: Mika Kahola mika.kahola@intel.com --- include/drm/drm_dp_helper.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h index ba9731e..0d84046 100644 --- a/include/drm/drm_dp_helper.h +++ b/include/drm/drm_dp_helper.h @@ -216,11 +216,11 @@ # define DP_DS_PORT_HPD (1 << 3) /* offset 1 for VGA is maximum megapixels per second / 8 */ /* offset 2 */ -# define DP_DS_VGA_MAX_BPC_MASK (3 << 0) -# define DP_DS_VGA_8BPC 0 -# define DP_DS_VGA_10BPC 1 -# define DP_DS_VGA_12BPC 2 -# define DP_DS_VGA_16BPC 3 +# define DP_DS_MAX_BPC_MASK (3 << 0) +# define DP_DS_8BPC 0 +# define DP_DS_10BPC 1 +# define DP_DS_12BPC 2 +# define DP_DS_16BPC 3
/* link configuration */ #define DP_LINK_BW_SET 0x100
Helper routine to read out maximum supported pixel rate for DisplayPort legay VGA converter or TMDS clock rate for other digital legacy converters. The helper returns clock rate in kHz.
v2: Return early if detailed port cap info is not available. Replace if-else ladder with switch-case (Ville)
Reviewed-by: Jim Bride jim.bride@linux.intel.com Signed-off-by: Mika Kahola mika.kahola@intel.com --- drivers/gpu/drm/drm_dp_helper.c | 33 +++++++++++++++++++++++++++++++++ include/drm/drm_dp_helper.h | 2 ++ 2 files changed, 35 insertions(+)
diff --git a/drivers/gpu/drm/drm_dp_helper.c b/drivers/gpu/drm/drm_dp_helper.c index 031c4d3..7497490 100644 --- a/drivers/gpu/drm/drm_dp_helper.c +++ b/drivers/gpu/drm/drm_dp_helper.c @@ -439,6 +439,39 @@ int drm_dp_link_configure(struct drm_dp_aux *aux, struct drm_dp_link *link) } EXPORT_SYMBOL(drm_dp_link_configure);
+/** + * drm_dp_downstream_max_clock() - extract branch device max + * pixel rate for legacy VGA + * converter or max TMDS clock + * rate for others + * @dpcd: DisplayPort configuration data + * @port_cap: port capabilities + * + * Returns max clock in kHz on success or 0 if max clock not defined + */ +int drm_dp_downstream_max_clock(const u8 dpcd[DP_RECEIVER_CAP_SIZE], + const u8 port_cap[4]) +{ + int type = port_cap[0] & DP_DS_PORT_TYPE_MASK; + bool detailed_cap_info = dpcd[DP_DOWNSTREAMPORT_PRESENT] & + DP_DETAILED_CAP_INFO_AVAILABLE; + + if (!detailed_cap_info) + return 0; + + switch (type) { + case DP_DS_PORT_TYPE_VGA: + return port_cap[1] * 8 * 1000; + case DP_DS_PORT_TYPE_DVI: + case DP_DS_PORT_TYPE_HDMI: + case DP_DS_PORT_TYPE_DP_DUALMODE: + return port_cap[1] * 2500; + default: + return 0; + } +} +EXPORT_SYMBOL(drm_dp_downstream_max_clock); + /* * I2C-over-AUX implementation */ diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h index 0d84046..60dd9dc 100644 --- a/include/drm/drm_dp_helper.h +++ b/include/drm/drm_dp_helper.h @@ -815,6 +815,8 @@ int drm_dp_link_probe(struct drm_dp_aux *aux, struct drm_dp_link *link); int drm_dp_link_power_up(struct drm_dp_aux *aux, struct drm_dp_link *link); int drm_dp_link_power_down(struct drm_dp_aux *aux, struct drm_dp_link *link); int drm_dp_link_configure(struct drm_dp_aux *aux, struct drm_dp_link *link); +int drm_dp_downstream_max_clock(const u8 dpcd[DP_RECEIVER_CAP_SIZE], + const u8 port_cap[4]);
void drm_dp_aux_init(struct drm_dp_aux *aux); int drm_dp_aux_register(struct drm_dp_aux *aux);
On Wed, Aug 17, 2016 at 01:49:39PM +0300, Mika Kahola wrote:
Helper routine to read out maximum supported pixel rate for DisplayPort legay VGA converter or TMDS clock rate for other digital legacy converters. The helper returns clock rate in kHz.
v2: Return early if detailed port cap info is not available. Replace if-else ladder with switch-case (Ville)
Reviewed-by: Jim Bride jim.bride@linux.intel.com Signed-off-by: Mika Kahola mika.kahola@intel.com
drivers/gpu/drm/drm_dp_helper.c | 33 +++++++++++++++++++++++++++++++++ include/drm/drm_dp_helper.h | 2 ++ 2 files changed, 35 insertions(+)
diff --git a/drivers/gpu/drm/drm_dp_helper.c b/drivers/gpu/drm/drm_dp_helper.c index 031c4d3..7497490 100644 --- a/drivers/gpu/drm/drm_dp_helper.c +++ b/drivers/gpu/drm/drm_dp_helper.c @@ -439,6 +439,39 @@ int drm_dp_link_configure(struct drm_dp_aux *aux, struct drm_dp_link *link) } EXPORT_SYMBOL(drm_dp_link_configure);
+/**
- drm_dp_downstream_max_clock() - extract branch device max
pixel rate for legacy VGA
converter or max TMDS clock
rate for others
- @dpcd: DisplayPort configuration data
- @port_cap: port capabilities
- Returns max clock in kHz on success or 0 if max clock not defined
- */
+int drm_dp_downstream_max_clock(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
const u8 port_cap[4])
+{
- int type = port_cap[0] & DP_DS_PORT_TYPE_MASK;
- bool detailed_cap_info = dpcd[DP_DOWNSTREAMPORT_PRESENT] &
DP_DETAILED_CAP_INFO_AVAILABLE;
- if (!detailed_cap_info)
return 0;
- switch (type) {
- case DP_DS_PORT_TYPE_VGA:
return port_cap[1] * 8 * 1000;
- case DP_DS_PORT_TYPE_DVI:
- case DP_DS_PORT_TYPE_HDMI:
- case DP_DS_PORT_TYPE_DP_DUALMODE:
return port_cap[1] * 2500;
The spec says that if the detailed_cap_info==0, then DVI/HDMI/DP++ must support at least 165 MHz TMDS clock. I was thinking we might want to limit things to 165 in that case to guarantee that we advertize only modes guaranteed to work.
- default:
return 0;
- }
+} +EXPORT_SYMBOL(drm_dp_downstream_max_clock);
/*
- I2C-over-AUX implementation
*/ diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h index 0d84046..60dd9dc 100644 --- a/include/drm/drm_dp_helper.h +++ b/include/drm/drm_dp_helper.h @@ -815,6 +815,8 @@ int drm_dp_link_probe(struct drm_dp_aux *aux, struct drm_dp_link *link); int drm_dp_link_power_up(struct drm_dp_aux *aux, struct drm_dp_link *link); int drm_dp_link_power_down(struct drm_dp_aux *aux, struct drm_dp_link *link); int drm_dp_link_configure(struct drm_dp_aux *aux, struct drm_dp_link *link); +int drm_dp_downstream_max_clock(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
const u8 port_cap[4]);
void drm_dp_aux_init(struct drm_dp_aux *aux); int drm_dp_aux_register(struct drm_dp_aux *aux); -- 1.9.1
-----Original Message----- From: Ville Syrjälä [mailto:ville.syrjala@linux.intel.com] Sent: Thursday, September 8, 2016 4:02 PM To: Kahola, Mika mika.kahola@intel.com Cc: intel-gfx@lists.freedesktop.org; dri-devel@lists.freedesktop.org; jim.bride@linux.intel.com; daniel.vetter@ffwll.ch Subject: Re: [PATCH v8 03/12] drm: Helper to read max clock rate
On Wed, Aug 17, 2016 at 01:49:39PM +0300, Mika Kahola wrote:
Helper routine to read out maximum supported pixel rate for DisplayPort legay VGA converter or TMDS clock rate for other digital legacy converters. The helper returns clock rate in kHz.
v2: Return early if detailed port cap info is not available. Replace if-else ladder with switch-case (Ville)
Reviewed-by: Jim Bride jim.bride@linux.intel.com Signed-off-by: Mika Kahola mika.kahola@intel.com
drivers/gpu/drm/drm_dp_helper.c | 33
+++++++++++++++++++++++++++++++++
include/drm/drm_dp_helper.h | 2 ++ 2 files changed, 35 insertions(+)
diff --git a/drivers/gpu/drm/drm_dp_helper.c b/drivers/gpu/drm/drm_dp_helper.c index 031c4d3..7497490 100644 --- a/drivers/gpu/drm/drm_dp_helper.c +++ b/drivers/gpu/drm/drm_dp_helper.c @@ -439,6 +439,39 @@ int drm_dp_link_configure(struct drm_dp_aux
*aux,
struct drm_dp_link *link) } EXPORT_SYMBOL(drm_dp_link_configure);
+/**
- drm_dp_downstream_max_clock() - extract branch device max
pixel rate for legacy VGA
converter or max TMDS clock
rate for others
- @dpcd: DisplayPort configuration data
- @port_cap: port capabilities
- Returns max clock in kHz on success or 0 if max clock not defined
+*/ int drm_dp_downstream_max_clock(const u8 +dpcd[DP_RECEIVER_CAP_SIZE],
const u8 port_cap[4])
+{
- int type = port_cap[0] & DP_DS_PORT_TYPE_MASK;
- bool detailed_cap_info = dpcd[DP_DOWNSTREAMPORT_PRESENT] &
DP_DETAILED_CAP_INFO_AVAILABLE;
- if (!detailed_cap_info)
return 0;
- switch (type) {
- case DP_DS_PORT_TYPE_VGA:
return port_cap[1] * 8 * 1000;
- case DP_DS_PORT_TYPE_DVI:
- case DP_DS_PORT_TYPE_HDMI:
- case DP_DS_PORT_TYPE_DP_DUALMODE:
return port_cap[1] * 2500;
The spec says that if the detailed_cap_info==0, then DVI/HDMI/DP++ must support at least 165 MHz TMDS clock. I was thinking we might want to limit things to 165 in that case to guarantee that we advertize only modes guaranteed to work.
That is a valid point. What I had in mind was by returning 0 from this function it is indicated that the value is not found. With the remaining patches that call this function the check is in place so we can skip the step if explicit clock rate is not found.
- default:
return 0;
- }
+} +EXPORT_SYMBOL(drm_dp_downstream_max_clock);
/*
- I2C-over-AUX implementation
*/ diff --git a/include/drm/drm_dp_helper.h
b/include/drm/drm_dp_helper.h
index 0d84046..60dd9dc 100644 --- a/include/drm/drm_dp_helper.h +++ b/include/drm/drm_dp_helper.h @@ -815,6 +815,8 @@ int drm_dp_link_probe(struct drm_dp_aux *aux, struct drm_dp_link *link); int drm_dp_link_power_up(struct drm_dp_aux *aux, struct drm_dp_link *link); int drm_dp_link_power_down(struct drm_dp_aux *aux, struct drm_dp_link *link); int drm_dp_link_configure(struct drm_dp_aux *aux, struct drm_dp_link *link); +int drm_dp_downstream_max_clock(const u8
dpcd[DP_RECEIVER_CAP_SIZE],
const u8 port_cap[4]);
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
Helper routine to read out maximum supported bits per component for DisplayPort legay converters.
v2: Return early if detailed port cap info is not available. Replace if-else ladder with switch-case (Ville)
Reviewed-by: Jim Bride jim.bride@linux.intel.com Signed-off-by: Mika Kahola mika.kahola@intel.com --- drivers/gpu/drm/drm_dp_helper.c | 42 +++++++++++++++++++++++++++++++++++++++++ include/drm/drm_dp_helper.h | 2 ++ 2 files changed, 44 insertions(+)
diff --git a/drivers/gpu/drm/drm_dp_helper.c b/drivers/gpu/drm/drm_dp_helper.c index 7497490..14e8ea0 100644 --- a/drivers/gpu/drm/drm_dp_helper.c +++ b/drivers/gpu/drm/drm_dp_helper.c @@ -472,6 +472,48 @@ int drm_dp_downstream_max_clock(const u8 dpcd[DP_RECEIVER_CAP_SIZE], } EXPORT_SYMBOL(drm_dp_downstream_max_clock);
+/** + * drm_dp_downstream_max_bpc() - extract branch device max + * bits per component + * @dpcd: DisplayPort configuration data + * @port_cap: port capabilities + * + * Returns max bpc on success or 0 if max bpc not defined + */ +int drm_dp_downstream_max_bpc(const u8 dpcd[DP_RECEIVER_CAP_SIZE], + const u8 port_cap[4]) +{ + int type = port_cap[0] & DP_DS_PORT_TYPE_MASK; + bool detailed_cap_info = dpcd[DP_DOWNSTREAMPORT_PRESENT] & + DP_DETAILED_CAP_INFO_AVAILABLE; + int bpc; + + if (!detailed_cap_info) + return 0; + + switch (type) { + case DP_DS_PORT_TYPE_VGA: + case DP_DS_PORT_TYPE_DVI: + case DP_DS_PORT_TYPE_HDMI: + case DP_DS_PORT_TYPE_DP_DUALMODE: + bpc = port_cap[2] & DP_DS_MAX_BPC_MASK; + + switch (bpc) { + case DP_DS_8BPC: + return 8; + case DP_DS_10BPC: + return 10; + case DP_DS_12BPC: + return 12; + case DP_DS_16BPC: + return 16; + } + default: + return 0; + } +} +EXPORT_SYMBOL(drm_dp_downstream_max_bpc); + /* * I2C-over-AUX implementation */ diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h index 60dd9dc..f3d1424 100644 --- a/include/drm/drm_dp_helper.h +++ b/include/drm/drm_dp_helper.h @@ -817,6 +817,8 @@ int drm_dp_link_power_down(struct drm_dp_aux *aux, struct drm_dp_link *link); int drm_dp_link_configure(struct drm_dp_aux *aux, struct drm_dp_link *link); int drm_dp_downstream_max_clock(const u8 dpcd[DP_RECEIVER_CAP_SIZE], const u8 port_cap[4]); +int drm_dp_downstream_max_bpc(const u8 dpcd[DP_RECEIVER_CAP_SIZE], + const u8 port_cap[4]);
void drm_dp_aux_init(struct drm_dp_aux *aux); int drm_dp_aux_register(struct drm_dp_aux *aux);
On Wed, Aug 17, 2016 at 01:49:40PM +0300, Mika Kahola wrote:
Helper routine to read out maximum supported bits per component for DisplayPort legay converters.
v2: Return early if detailed port cap info is not available. Replace if-else ladder with switch-case (Ville)
Reviewed-by: Jim Bride jim.bride@linux.intel.com Signed-off-by: Mika Kahola mika.kahola@intel.com
drivers/gpu/drm/drm_dp_helper.c | 42 +++++++++++++++++++++++++++++++++++++++++ include/drm/drm_dp_helper.h | 2 ++ 2 files changed, 44 insertions(+)
diff --git a/drivers/gpu/drm/drm_dp_helper.c b/drivers/gpu/drm/drm_dp_helper.c index 7497490..14e8ea0 100644 --- a/drivers/gpu/drm/drm_dp_helper.c +++ b/drivers/gpu/drm/drm_dp_helper.c @@ -472,6 +472,48 @@ int drm_dp_downstream_max_clock(const u8 dpcd[DP_RECEIVER_CAP_SIZE], } EXPORT_SYMBOL(drm_dp_downstream_max_clock);
+/**
- drm_dp_downstream_max_bpc() - extract branch device max
bits per component
- @dpcd: DisplayPort configuration data
- @port_cap: port capabilities
- Returns max bpc on success or 0 if max bpc not defined
- */
+int drm_dp_downstream_max_bpc(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
const u8 port_cap[4])
+{
- int type = port_cap[0] & DP_DS_PORT_TYPE_MASK;
- bool detailed_cap_info = dpcd[DP_DOWNSTREAMPORT_PRESENT] &
DP_DETAILED_CAP_INFO_AVAILABLE;
- int bpc;
- if (!detailed_cap_info)
return 0;
- switch (type) {
- case DP_DS_PORT_TYPE_VGA:
- case DP_DS_PORT_TYPE_DVI:
- case DP_DS_PORT_TYPE_HDMI:
- case DP_DS_PORT_TYPE_DP_DUALMODE:
I think we might want return 8; for the detailed_cap_info==0 case with these port types.
bpc = port_cap[2] & DP_DS_MAX_BPC_MASK;
switch (bpc) {
case DP_DS_8BPC:
return 8;
case DP_DS_10BPC:
return 10;
case DP_DS_12BPC:
return 12;
case DP_DS_16BPC:
return 16;
}
- default:
return 0;
- }
+} +EXPORT_SYMBOL(drm_dp_downstream_max_bpc);
/*
- I2C-over-AUX implementation
*/ diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h index 60dd9dc..f3d1424 100644 --- a/include/drm/drm_dp_helper.h +++ b/include/drm/drm_dp_helper.h @@ -817,6 +817,8 @@ int drm_dp_link_power_down(struct drm_dp_aux *aux, struct drm_dp_link *link); int drm_dp_link_configure(struct drm_dp_aux *aux, struct drm_dp_link *link); int drm_dp_downstream_max_clock(const u8 dpcd[DP_RECEIVER_CAP_SIZE], const u8 port_cap[4]); +int drm_dp_downstream_max_bpc(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
const u8 port_cap[4]);
void drm_dp_aux_init(struct drm_dp_aux *aux); int drm_dp_aux_register(struct drm_dp_aux *aux); -- 1.9.1
Read DisplayPort branch device id string.
Reviewed-by: Jim Bride jim.bride@linux.intel.com Signed-off-by: Mika Kahola mika.kahola@intel.com --- drivers/gpu/drm/drm_dp_helper.c | 12 ++++++++++++ include/drm/drm_dp_helper.h | 2 ++ 2 files changed, 14 insertions(+)
diff --git a/drivers/gpu/drm/drm_dp_helper.c b/drivers/gpu/drm/drm_dp_helper.c index 14e8ea0..01ee7af 100644 --- a/drivers/gpu/drm/drm_dp_helper.c +++ b/drivers/gpu/drm/drm_dp_helper.c @@ -514,6 +514,18 @@ int drm_dp_downstream_max_bpc(const u8 dpcd[DP_RECEIVER_CAP_SIZE], } EXPORT_SYMBOL(drm_dp_downstream_max_bpc);
+/** + * drm_dp_downstream_id() - identify branch device + * @aux: DisplayPort AUX channel + * + * Returns branch device id on success or NULL on failure + */ +int drm_dp_downstream_id(struct drm_dp_aux *aux, char id[6]) +{ + return drm_dp_dpcd_read(aux, DP_BRANCH_ID, id, 6); +} +EXPORT_SYMBOL(drm_dp_downstream_id); + /* * I2C-over-AUX implementation */ diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h index f3d1424..faea76b 100644 --- a/include/drm/drm_dp_helper.h +++ b/include/drm/drm_dp_helper.h @@ -445,6 +445,7 @@ #define DP_SOURCE_OUI 0x300 #define DP_SINK_OUI 0x400 #define DP_BRANCH_OUI 0x500 +#define DP_BRANCH_ID 0x503
#define DP_SET_POWER 0x600 # define DP_SET_POWER_D0 0x1 @@ -819,6 +820,7 @@ int drm_dp_downstream_max_clock(const u8 dpcd[DP_RECEIVER_CAP_SIZE], const u8 port_cap[4]); 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]);
void drm_dp_aux_init(struct drm_dp_aux *aux); int drm_dp_aux_register(struct drm_dp_aux *aux);
Let's remove reference to "struct intel_connector *connector" in intel_dp_aux_init() function as it is no longer required.
Signed-off-by: Mika Kahola mika.kahola@intel.com --- drivers/gpu/drm/i915/intel_dp.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 364db90..3dab3bf 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -1243,7 +1243,7 @@ intel_dp_aux_fini(struct intel_dp *intel_dp) }
static void -intel_dp_aux_init(struct intel_dp *intel_dp, struct intel_connector *connector) +intel_dp_aux_init(struct intel_dp *intel_dp) { struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); enum port port = intel_dig_port->port; @@ -5598,7 +5598,7 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port, connector->interlace_allowed = true; connector->doublescan_allowed = 0;
- intel_dp_aux_init(intel_dp, intel_connector); + intel_dp_aux_init(intel_dp);
INIT_DELAYED_WORK(&intel_dp->panel_vdd_work, edp_panel_vdd_work);
On Wed, Aug 17, 2016 at 01:49:42PM +0300, Mika Kahola wrote:
Let's remove reference to "struct intel_connector *connector" in intel_dp_aux_init() function as it is no longer required.
Signed-off-by: Mika Kahola mika.kahola@intel.com
Reviewed-by: Jim Bride jim.bride@linux.intel.com
drivers/gpu/drm/i915/intel_dp.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 364db90..3dab3bf 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -1243,7 +1243,7 @@ intel_dp_aux_fini(struct intel_dp *intel_dp) }
static void -intel_dp_aux_init(struct intel_dp *intel_dp, struct intel_connector *connector) +intel_dp_aux_init(struct intel_dp *intel_dp) { struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); enum port port = intel_dig_port->port; @@ -5598,7 +5598,7 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port, connector->interlace_allowed = true; connector->doublescan_allowed = 0;
- intel_dp_aux_init(intel_dp, intel_connector);
intel_dp_aux_init(intel_dp);
INIT_DELAYED_WORK(&intel_dp->panel_vdd_work, edp_panel_vdd_work);
-- 1.9.1
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) v3: remove dependency to drm_dp_helper but instead parse DPCD and print HW revision info to dmesg (Ville)
Signed-off-by: Mika Kahola mika.kahola@intel.com --- drivers/gpu/drm/i915/intel_dp.c | 21 +++++++++++++++++++++ include/drm/drm_dp_helper.h | 1 + 2 files changed, 22 insertions(+)
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 3dab3bf..9aebdf6 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -1419,6 +1419,25 @@ static void intel_dp_print_rates(struct intel_dp *intel_dp) DRM_DEBUG_KMS("common rates: %s\n", str); }
+static void intel_dp_print_hw_revision(struct intel_dp *intel_dp) +{ + uint8_t rev; + int len; + + if ((drm_debug & DRM_UT_KMS) == 0) + return; + + if (!(intel_dp->dpcd[DP_DOWNSTREAMPORT_PRESENT] & + DP_DWN_STRM_PORT_PRESENT)) + return; + + len = drm_dp_dpcd_read(&intel_dp->aux, DP_BRANCH_HW_REV, &rev, 1); + if (len < 0) + return; + + DRM_DEBUG_KMS("sink hw revision: %d.%d\n", (rev & 0xf0) >> 4, rev & 0xf); +} + static int rate_to_index(int find, const int *rates) { int i = 0; @@ -4282,6 +4301,8 @@ intel_dp_long_pulse(struct intel_connector *intel_connector)
intel_dp_probe_oui(intel_dp);
+ intel_dp_print_hw_revision(intel_dp); + intel_dp_configure_mst(intel_dp);
if (intel_dp->is_mst) { diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h index faea76b..19ac599 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
On Wed, Aug 17, 2016 at 01:49:43PM +0300, Mika Kahola wrote:
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) v3: remove dependency to drm_dp_helper but instead parse DPCD and print HW revision info to dmesg (Ville)
Signed-off-by: Mika Kahola mika.kahola@intel.com
Reviewed-by: Jim Bride jim.bride@linux.intel.com
drivers/gpu/drm/i915/intel_dp.c | 21 +++++++++++++++++++++ include/drm/drm_dp_helper.h | 1 + 2 files changed, 22 insertions(+)
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 3dab3bf..9aebdf6 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -1419,6 +1419,25 @@ static void intel_dp_print_rates(struct intel_dp *intel_dp) DRM_DEBUG_KMS("common rates: %s\n", str); }
+static void intel_dp_print_hw_revision(struct intel_dp *intel_dp) +{
- uint8_t rev;
- int len;
- if ((drm_debug & DRM_UT_KMS) == 0)
return;
- if (!(intel_dp->dpcd[DP_DOWNSTREAMPORT_PRESENT] &
DP_DWN_STRM_PORT_PRESENT))
return;
- len = drm_dp_dpcd_read(&intel_dp->aux, DP_BRANCH_HW_REV, &rev, 1);
- if (len < 0)
return;
- DRM_DEBUG_KMS("sink hw revision: %d.%d\n", (rev & 0xf0) >> 4, rev & 0xf);
+}
static int rate_to_index(int find, const int *rates) { int i = 0; @@ -4282,6 +4301,8 @@ intel_dp_long_pulse(struct intel_connector *intel_connector)
intel_dp_probe_oui(intel_dp);
intel_dp_print_hw_revision(intel_dp);
intel_dp_configure_mst(intel_dp);
if (intel_dp->is_mst) {
diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h index faea76b..19ac599 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
1.9.1
SW revision is mandatory field for DisplayPort branch devices. This is defined in DPCD register field 0x50A.
v2: move drm_dp_ds_revision structure to be part of drm_dp_link structure (Daniel) v3: remove dependency to drm_dp_helper but instead parse DPCD and print SW revision info to dmesg (Ville)
Signed-off-by: Mika Kahola mika.kahola@intel.com --- drivers/gpu/drm/i915/intel_dp.c | 20 ++++++++++++++++++++ include/drm/drm_dp_helper.h | 1 + 2 files changed, 21 insertions(+)
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 9aebdf6..91ffb79 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -1438,6 +1438,25 @@ static void intel_dp_print_hw_revision(struct intel_dp *intel_dp) DRM_DEBUG_KMS("sink hw revision: %d.%d\n", (rev & 0xf0) >> 4, rev & 0xf); }
+static void intel_dp_print_sw_revision(struct intel_dp *intel_dp) +{ + uint8_t rev[2]; + int len; + + if ((drm_debug & DRM_UT_KMS) == 0) + return; + + if (!(intel_dp->dpcd[DP_DOWNSTREAMPORT_PRESENT] & + DP_DWN_STRM_PORT_PRESENT)) + return; + + len = drm_dp_dpcd_read(&intel_dp->aux, DP_BRANCH_SW_REV, &rev, 2); + if (len < 0) + return; + + DRM_DEBUG_KMS("sink sw revision: %d.%d\n", rev[0], rev[1]); +} + static int rate_to_index(int find, const int *rates) { int i = 0; @@ -4302,6 +4321,7 @@ intel_dp_long_pulse(struct intel_connector *intel_connector) intel_dp_probe_oui(intel_dp);
intel_dp_print_hw_revision(intel_dp); + intel_dp_print_sw_revision(intel_dp);
intel_dp_configure_mst(intel_dp);
diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h index 19ac599..215202f 100644 --- a/include/drm/drm_dp_helper.h +++ b/include/drm/drm_dp_helper.h @@ -447,6 +447,7 @@ #define DP_BRANCH_OUI 0x500 #define DP_BRANCH_ID 0x503 #define DP_BRANCH_HW_REV 0x509 +#define DP_BRANCH_SW_REV 0x50A
#define DP_SET_POWER 0x600 # define DP_SET_POWER_D0 0x1
On Wed, Aug 17, 2016 at 01:49:44PM +0300, Mika Kahola wrote:
SW revision is mandatory field for DisplayPort branch devices. This is defined in DPCD register field 0x50A.
To be precise, the revision info is in 0x50A and 0x50B. Since both the major and minor versions are called out separately in the DP spec it's probably worth mentioning both addresses in the commit message.
v2: move drm_dp_ds_revision structure to be part of drm_dp_link structure (Daniel) v3: remove dependency to drm_dp_helper but instead parse DPCD and print SW revision info to dmesg (Ville)
Signed-off-by: Mika Kahola mika.kahola@intel.com
With the commit message change requested above, this is:
Reviewed-by: Jim Bride jim.bride@linux.intel.com
drivers/gpu/drm/i915/intel_dp.c | 20 ++++++++++++++++++++ include/drm/drm_dp_helper.h | 1 + 2 files changed, 21 insertions(+)
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 9aebdf6..91ffb79 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -1438,6 +1438,25 @@ static void intel_dp_print_hw_revision(struct intel_dp *intel_dp) DRM_DEBUG_KMS("sink hw revision: %d.%d\n", (rev & 0xf0) >> 4, rev & 0xf); }
+static void intel_dp_print_sw_revision(struct intel_dp *intel_dp) +{
- uint8_t rev[2];
- int len;
- if ((drm_debug & DRM_UT_KMS) == 0)
return;
- if (!(intel_dp->dpcd[DP_DOWNSTREAMPORT_PRESENT] &
DP_DWN_STRM_PORT_PRESENT))
return;
- len = drm_dp_dpcd_read(&intel_dp->aux, DP_BRANCH_SW_REV, &rev, 2);
- if (len < 0)
return;
- DRM_DEBUG_KMS("sink sw revision: %d.%d\n", rev[0], rev[1]);
+}
static int rate_to_index(int find, const int *rates) { int i = 0; @@ -4302,6 +4321,7 @@ intel_dp_long_pulse(struct intel_connector *intel_connector) intel_dp_probe_oui(intel_dp);
intel_dp_print_hw_revision(intel_dp);
intel_dp_print_sw_revision(intel_dp);
intel_dp_configure_mst(intel_dp);
diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h index 19ac599..215202f 100644 --- a/include/drm/drm_dp_helper.h +++ b/include/drm/drm_dp_helper.h @@ -447,6 +447,7 @@ #define DP_BRANCH_OUI 0x500 #define DP_BRANCH_ID 0x503 #define DP_BRANCH_HW_REV 0x509 +#define DP_BRANCH_SW_REV 0x50A
#define DP_SET_POWER 0x600
# define DP_SET_POWER_D0 0x1
1.9.1
-----Original Message----- From: Jim Bride [mailto:jim.bride@linux.intel.com] Sent: Thursday, September 8, 2016 12:20 AM To: Kahola, Mika mika.kahola@intel.com Cc: intel-gfx@lists.freedesktop.org; dri-devel@lists.freedesktop.org; ville.syrjala@linux.intel.com; daniel.vetter@ffwll.ch Subject: Re: [PATCH v8 08/12] drm/i915: Read DP branch device SW revision
On Wed, Aug 17, 2016 at 01:49:44PM +0300, Mika Kahola wrote:
SW revision is mandatory field for DisplayPort branch devices. This is defined in DPCD register field 0x50A.
To be precise, the revision info is in 0x50A and 0x50B. Since both the major and minor versions are called out separately in the DP spec it's probably worth mentioning both addresses in the commit message.
You're right. I will update the commit message to be more exact.
v2: move drm_dp_ds_revision structure to be part of drm_dp_link structure (Daniel) v3: remove dependency to drm_dp_helper but instead parse DPCD and print SW revision info to dmesg (Ville)
Signed-off-by: Mika Kahola mika.kahola@intel.com
With the commit message change requested above, this is:
Reviewed-by: Jim Bride jim.bride@linux.intel.com
drivers/gpu/drm/i915/intel_dp.c | 20 ++++++++++++++++++++ include/drm/drm_dp_helper.h | 1 + 2 files changed, 21 insertions(+)
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 9aebdf6..91ffb79 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -1438,6 +1438,25 @@ static void intel_dp_print_hw_revision(struct
intel_dp *intel_dp)
DRM_DEBUG_KMS("sink hw revision: %d.%d\n", (rev & 0xf0) >> 4,
rev &
0xf); }
+static void intel_dp_print_sw_revision(struct intel_dp *intel_dp) {
- uint8_t rev[2];
- int len;
- if ((drm_debug & DRM_UT_KMS) == 0)
return;
- if (!(intel_dp->dpcd[DP_DOWNSTREAMPORT_PRESENT] &
DP_DWN_STRM_PORT_PRESENT))
return;
- len = drm_dp_dpcd_read(&intel_dp->aux, DP_BRANCH_SW_REV,
&rev, 2);
- if (len < 0)
return;
- DRM_DEBUG_KMS("sink sw revision: %d.%d\n", rev[0], rev[1]); }
static int rate_to_index(int find, const int *rates) { int i = 0; @@ -4302,6 +4321,7 @@ intel_dp_long_pulse(struct intel_connector
*intel_connector)
intel_dp_probe_oui(intel_dp);
intel_dp_print_hw_revision(intel_dp);
intel_dp_print_sw_revision(intel_dp);
intel_dp_configure_mst(intel_dp);
diff --git a/include/drm/drm_dp_helper.h
b/include/drm/drm_dp_helper.h
index 19ac599..215202f 100644 --- a/include/drm/drm_dp_helper.h +++ b/include/drm/drm_dp_helper.h @@ -447,6 +447,7 @@ #define DP_BRANCH_OUI 0x500 #define DP_BRANCH_ID 0x503 #define DP_BRANCH_HW_REV 0x509 +#define DP_BRANCH_SW_REV 0x50A
#define DP_SET_POWER 0x600
# define DP_SET_POWER_D0 0x1
1.9.1
Filter out a mode that exceeds the max pixel rate setting for DP to VGA dongle. This is defined in DPCD register 0x81 if detailed cap info i.e. info field is 4 bytes long and it is available for DP downstream port.
The register defines the pixel rate divided by 8 in MP/s.
v2: DPCD read outs and computation moved to drm (Ville, Daniel) v3: Sink pixel rate computation moved to drm_dp_max_sink_dotclock() function (Daniel) v4: Use of drm_dp_helper.c routines to compute max pixel clock (Ville) v5: Use of intel_dp->downstream_ports to read out port capabilities. Code restructuring (Ville) v6: Move DP branch device check to drm_dp_helper.c (Daniel) v7: Cleanup as suggested by Ville
Signed-off-by: Mika Kahola mika.kahola@intel.com --- drivers/gpu/drm/i915/intel_dp.c | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 91ffb79..25f459e 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -190,6 +190,29 @@ intel_dp_max_data_rate(int max_link_clock, int max_lanes) return (max_link_clock * max_lanes * 8) / 10; }
+static int +intel_dp_downstream_max_dotclock(struct intel_dp *intel_dp) +{ + struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); + struct intel_encoder *encoder = &intel_dig_port->base; + struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); + int max_dotclk = dev_priv->max_dotclk_freq; + int ds_max_dotclk; + + int type = intel_dp->downstream_ports[0] & DP_DS_PORT_TYPE_MASK; + + if (type != DP_DS_PORT_TYPE_VGA) + return max_dotclk; + + ds_max_dotclk = drm_dp_downstream_max_clock(intel_dp->dpcd, + intel_dp->downstream_ports); + + if (ds_max_dotclk != 0) + max_dotclk = min(max_dotclk, ds_max_dotclk);; + + return max_dotclk; +} + static enum drm_mode_status intel_dp_mode_valid(struct drm_connector *connector, struct drm_display_mode *mode) @@ -199,7 +222,9 @@ intel_dp_mode_valid(struct drm_connector *connector, struct drm_display_mode *fixed_mode = intel_connector->panel.fixed_mode; int target_clock = mode->clock; int max_rate, mode_rate, max_lanes, max_link_clock; - int max_dotclk = to_i915(connector->dev)->max_dotclk_freq; + int max_dotclk; + + max_dotclk = intel_dp_downstream_max_dotclock(intel_dp);
if (is_edp(intel_dp) && fixed_mode) { if (mode->hdisplay > fixed_mode->hdisplay)
On Wed, Aug 17, 2016 at 01:49:45PM +0300, Mika Kahola wrote:
Filter out a mode that exceeds the max pixel rate setting for DP to VGA dongle. This is defined in DPCD register 0x81 if detailed cap info i.e. info field is 4 bytes long and it is available for DP downstream port.
The register defines the pixel rate divided by 8 in MP/s.
v2: DPCD read outs and computation moved to drm (Ville, Daniel) v3: Sink pixel rate computation moved to drm_dp_max_sink_dotclock() function (Daniel) v4: Use of drm_dp_helper.c routines to compute max pixel clock (Ville) v5: Use of intel_dp->downstream_ports to read out port capabilities. Code restructuring (Ville) v6: Move DP branch device check to drm_dp_helper.c (Daniel) v7: Cleanup as suggested by Ville
Signed-off-by: Mika Kahola mika.kahola@intel.com
Reviewed-by: Jim Bride jim.bride@linux.intel.com
drivers/gpu/drm/i915/intel_dp.c | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 91ffb79..25f459e 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -190,6 +190,29 @@ intel_dp_max_data_rate(int max_link_clock, int max_lanes) return (max_link_clock * max_lanes * 8) / 10; }
+static int +intel_dp_downstream_max_dotclock(struct intel_dp *intel_dp) +{
- struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
- struct intel_encoder *encoder = &intel_dig_port->base;
- struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
- int max_dotclk = dev_priv->max_dotclk_freq;
- int ds_max_dotclk;
- int type = intel_dp->downstream_ports[0] & DP_DS_PORT_TYPE_MASK;
- if (type != DP_DS_PORT_TYPE_VGA)
return max_dotclk;
- ds_max_dotclk = drm_dp_downstream_max_clock(intel_dp->dpcd,
intel_dp->downstream_ports);
- if (ds_max_dotclk != 0)
max_dotclk = min(max_dotclk, ds_max_dotclk);;
- return max_dotclk;
+}
static enum drm_mode_status intel_dp_mode_valid(struct drm_connector *connector, struct drm_display_mode *mode) @@ -199,7 +222,9 @@ intel_dp_mode_valid(struct drm_connector *connector, struct drm_display_mode *fixed_mode = intel_connector->panel.fixed_mode; int target_clock = mode->clock; int max_rate, mode_rate, max_lanes, max_link_clock;
- int max_dotclk = to_i915(connector->dev)->max_dotclk_freq;
int max_dotclk;
max_dotclk = intel_dp_downstream_max_dotclock(intel_dp);
if (is_edp(intel_dp) && fixed_mode) { if (mode->hdisplay > fixed_mode->hdisplay)
-- 1.9.1
Filter out a mode that exceeds the max pixel rate setting for DP to VGA dongle. This is defined in DPCD register 0x81 if detailed cap info i.e. info field is 4 bytes long and it is available for DP downstream port.
The register defines the pixel rate divided by 8 in MP/s.
v2: DPCD read outs and computation moved to drm (Ville, Daniel) v3: Sink pixel rate computation moved to drm_dp_max_sink_dotclock() function (Daniel) v4: Use of drm_dp_helper.c routines to compute max pixel clock (Ville) v5: Use of intel_dp->downstream_ports to read out port capabilities. Code restructuring (Ville) v6: Move DP branch device check to drm_dp_helper.c (Daniel) v7: Cleanup as suggested by Ville
Signed-off-by: Mika Kahola mika.kahola@intel.com --- drivers/gpu/drm/i915/intel_dp.c | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 91ffb79..25f459e 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -190,6 +190,29 @@ intel_dp_max_data_rate(int max_link_clock, int max_lanes) return (max_link_clock * max_lanes * 8) / 10; }
+static int +intel_dp_downstream_max_dotclock(struct intel_dp *intel_dp) +{ + struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); + struct intel_encoder *encoder = &intel_dig_port->base; + struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); + int max_dotclk = dev_priv->max_dotclk_freq; + int ds_max_dotclk; + + int type = intel_dp->downstream_ports[0] & DP_DS_PORT_TYPE_MASK; + + if (type != DP_DS_PORT_TYPE_VGA) + return max_dotclk; + + ds_max_dotclk = drm_dp_downstream_max_clock(intel_dp->dpcd, + intel_dp->downstream_ports); + + if (ds_max_dotclk != 0) + max_dotclk = min(max_dotclk, ds_max_dotclk);; + + return max_dotclk; +} + static enum drm_mode_status intel_dp_mode_valid(struct drm_connector *connector, struct drm_display_mode *mode) @@ -199,7 +222,9 @@ intel_dp_mode_valid(struct drm_connector *connector, struct drm_display_mode *fixed_mode = intel_connector->panel.fixed_mode; int target_clock = mode->clock; int max_rate, mode_rate, max_lanes, max_link_clock; - int max_dotclk = to_i915(connector->dev)->max_dotclk_freq; + int max_dotclk; + + max_dotclk = intel_dp_downstream_max_dotclock(intel_dp);
if (is_edp(intel_dp) && fixed_mode) { if (mode->hdisplay > fixed_mode->hdisplay)
DisplayPort branch device may define max supported bits per component. Update display info based on this value if bpc is defined.
v2: cleanup to match the drm_dp_helper.c patches introduced earlier in this series v3: Fill bpc for connector's display info in separate drm_dp_helper function (Daniel) v4: remove updating bpc for display info as it may be overridden when parsing EDID. Instead, check bpc for DP branch device during compute_config
Signed-off-by: Mika Kahola mika.kahola@intel.com --- drivers/gpu/drm/i915/intel_dp.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 25f459e..17110d1 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -1524,6 +1524,20 @@ void intel_dp_compute_rate(struct intel_dp *intel_dp, int port_clock, } }
+int intel_dp_compute_bpp(struct intel_dp *intel_dp, + struct intel_crtc_state *pipe_config) +{ + int bpp, bpc; + + bpp = pipe_config->pipe_bpp; + bpc = drm_dp_downstream_max_bpc(intel_dp->dpcd, intel_dp->downstream_ports); + + if (bpc > 0) + bpp = min(bpp, 3*bpc); + + return bpp; +} + bool intel_dp_compute_config(struct intel_encoder *encoder, struct intel_crtc_state *pipe_config) @@ -1589,7 +1603,8 @@ intel_dp_compute_config(struct intel_encoder *encoder,
/* Walk through all bpp values. Luckily they're all nicely spaced with 2 * bpc in between. */ - bpp = pipe_config->pipe_bpp; + bpp = intel_dp_compute_bpp(intel_dp, pipe_config); + if (is_edp(intel_dp)) {
/* Get bpp from vbt only for panels that dont have bpp in edid */
On Wed, Aug 17, 2016 at 01:49:47PM +0300, Mika Kahola wrote:
DisplayPort branch device may define max supported bits per component. Update display info based on this value if bpc is defined.
v2: cleanup to match the drm_dp_helper.c patches introduced earlier in this series v3: Fill bpc for connector's display info in separate drm_dp_helper function (Daniel) v4: remove updating bpc for display info as it may be overridden when parsing EDID. Instead, check bpc for DP branch device during compute_config
Signed-off-by: Mika Kahola mika.kahola@intel.com
drivers/gpu/drm/i915/intel_dp.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 25f459e..17110d1 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -1524,6 +1524,20 @@ void intel_dp_compute_rate(struct intel_dp *intel_dp, int port_clock, } }
+int intel_dp_compute_bpp(struct intel_dp *intel_dp,
struct intel_crtc_state *pipe_config)
Indentation seems off.
+{
- int bpp, bpc;
- bpp = pipe_config->pipe_bpp;
- bpc = drm_dp_downstream_max_bpc(intel_dp->dpcd, intel_dp->downstream_ports);
- if (bpc > 0)
Do we need to ensure that bpp is sane before this calculation as well?
bpp = min(bpp, 3*bpc);
- return bpp;
+}
bool intel_dp_compute_config(struct intel_encoder *encoder, struct intel_crtc_state *pipe_config)
Indentation again.
Jim
@@ -1589,7 +1603,8 @@ intel_dp_compute_config(struct intel_encoder *encoder,
/* Walk through all bpp values. Luckily they're all nicely spaced with 2 * bpc in between. */
- bpp = pipe_config->pipe_bpp;
bpp = intel_dp_compute_bpp(intel_dp, pipe_config);
if (is_edp(intel_dp)) {
/* Get bpp from vbt only for panels that dont have bpp in edid */
-- 1.9.1
Thanks for the review. I'll fix those indentations.
-----Original Message----- From: Jim Bride [mailto:jim.bride@linux.intel.com] Sent: Thursday, September 8, 2016 12:27 AM To: Kahola, Mika mika.kahola@intel.com Cc: intel-gfx@lists.freedesktop.org; dri-devel@lists.freedesktop.org; ville.syrjala@linux.intel.com; daniel.vetter@ffwll.ch Subject: Re: [PATCH v8 10/12] drm/i915: Update bits per component for display info
On Wed, Aug 17, 2016 at 01:49:47PM +0300, Mika Kahola wrote:
DisplayPort branch device may define max supported bits per component. Update display info based on this value if bpc is defined.
v2: cleanup to match the drm_dp_helper.c patches introduced earlier in this series v3: Fill bpc for connector's display info in separate drm_dp_helper function (Daniel) v4: remove updating bpc for display info as it may be overridden when parsing EDID. Instead, check bpc for DP branch device during compute_config
Signed-off-by: Mika Kahola mika.kahola@intel.com
drivers/gpu/drm/i915/intel_dp.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 25f459e..17110d1 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -1524,6 +1524,20 @@ void intel_dp_compute_rate(struct intel_dp
*intel_dp, int port_clock,
} }
+int intel_dp_compute_bpp(struct intel_dp *intel_dp,
struct intel_crtc_state *pipe_config)
Indentation seems off.
+{
- int bpp, bpc;
- bpp = pipe_config->pipe_bpp;
- bpc = drm_dp_downstream_max_bpc(intel_dp->dpcd,
+intel_dp->downstream_ports);
- if (bpc > 0)
Do we need to ensure that bpp is sane before this calculation as well?
drm_dp_downstream_max_bpc() routine returns 0 if we can't find bpc from DPCD. Therefore bpc sanity is checked so to ensure that bpp has some meaningful value other than 0.
bpp = min(bpp, 3*bpc);
- return bpp;
+}
bool intel_dp_compute_config(struct intel_encoder *encoder, struct intel_crtc_state *pipe_config)
Indentation again.
Jim
@@ -1589,7 +1603,8 @@ intel_dp_compute_config(struct intel_encoder *encoder,
/* Walk through all bpp values. Luckily they're all nicely spaced with 2 * bpc in between. */
- bpp = pipe_config->pipe_bpp;
bpp = intel_dp_compute_bpp(intel_dp, pipe_config);
if (is_edp(intel_dp)) {
/* Get bpp from vbt only for panels that dont have bpp in
edid */
-- 1.9.1
Read DisplayPort branch device info from through debugfs interface.
v2: use drm_dp_helper routines to collect data v3: cleanup to match the drm_dp_helper.c patches introduced earlier in this series v4: move DP branch device info to function 'intel_dp_branch_device_info()' v5: initial step to move debugging info from intel_dp. to drm_dp_helper.c (Daniel) v6: read hw and sw revision without using specific drm_dp_helper routines
Signed-off-by: Mika Kahola mika.kahola@intel.com --- drivers/gpu/drm/drm_dp_helper.c | 81 +++++++++++++++++++++++++++++++++++++ drivers/gpu/drm/i915/i915_debugfs.c | 3 ++ include/drm/drm_dp_helper.h | 2 + 3 files changed, 86 insertions(+)
diff --git a/drivers/gpu/drm/drm_dp_helper.c b/drivers/gpu/drm/drm_dp_helper.c index 01ee7af..23cd6dc 100644 --- a/drivers/gpu/drm/drm_dp_helper.c +++ b/drivers/gpu/drm/drm_dp_helper.c @@ -526,6 +526,87 @@ int drm_dp_downstream_id(struct drm_dp_aux *aux, char id[6]) } EXPORT_SYMBOL(drm_dp_downstream_id);
+/** + * drm_dp_downstream_debug() - debug DP branch devices + * @m: pointer for debugfs file + * @dpcd: DisplayPort configuration data + * @port_cap: port capabilities + * @aux: DisplayPort AUX channel + * + */ +void drm_dp_downstream_debug(struct seq_file *m, const u8 dpcd[DP_RECEIVER_CAP_SIZE], + const u8 port_cap[4], struct drm_dp_aux *aux) +{ + bool detailed_cap_info = dpcd[DP_DOWNSTREAMPORT_PRESENT] & + DP_DETAILED_CAP_INFO_AVAILABLE; + int clk; + int bpc; + char id[6]; + int len; + uint8_t rev[2]; + int type = port_cap[0] & DP_DS_PORT_TYPE_MASK; + bool branch_device = dpcd[DP_DOWNSTREAMPORT_PRESENT] & DP_DWN_STRM_PORT_PRESENT; + + seq_printf(m, "\tDP branch device present: %s\n", branch_device ? "yes" : "no"); + + if (!branch_device) + return; + + switch (type) { + case DP_DS_PORT_TYPE_DP: + seq_printf(m, "\t\tType: DisplayPort\n"); + break; + case DP_DS_PORT_TYPE_VGA: + seq_printf(m, "\t\tType: VGA\n"); + break; + case DP_DS_PORT_TYPE_DVI: + seq_printf(m, "\t\tType: DVI\n"); + break; + case DP_DS_PORT_TYPE_HDMI: + seq_printf(m, "\t\tType: HDMI\n"); + break; + case DP_DS_PORT_TYPE_NON_EDID: + seq_printf(m, "\t\tType: others without EDID support\n"); + break; + case DP_DS_PORT_TYPE_DP_DUALMODE: + seq_printf(m, "\t\tType: DP++\n"); + break; + case DP_DS_PORT_TYPE_WIRELESS: + seq_printf(m, "\t\tType: Wireless\n"); + break; + default: + seq_printf(m, "\t\tType: N/A\n"); + } + + drm_dp_downstream_id(aux, id); + seq_printf(m, "\t\tID: %s\n", id); + + len = drm_dp_dpcd_read(aux, DP_BRANCH_HW_REV, &rev[0], 1); + if (len > 0) + seq_printf(m, "\t\tHW: %d.%d\n", (rev[0] & 0xf0) >> 4, rev[0] & 0xf); + + len = drm_dp_dpcd_read(aux, DP_BRANCH_SW_REV, &rev, 2); + if (len > 0) + seq_printf(m, "\t\tSW: %d.%d\n", rev[0], rev[1]); + + if (detailed_cap_info) { + clk = drm_dp_downstream_max_clock(dpcd, port_cap); + + if (clk > 0) { + if (type == DP_DS_PORT_TYPE_VGA) + seq_printf(m, "\t\tMax dot clock: %d kHz\n", clk); + else + seq_printf(m, "\t\tMax TMDS clock: %d kHz\n", clk); + } + + bpc = drm_dp_downstream_max_bpc(dpcd, port_cap); + + if (bpc > 0) + seq_printf(m, "\t\tMax bpc: %d\n", bpc); + } +} +EXPORT_SYMBOL(drm_dp_downstream_debug); + /* * I2C-over-AUX implementation */ diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 01ae5ee..90c736f 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -2923,6 +2923,9 @@ static void intel_dp_info(struct seq_file *m, seq_printf(m, "\taudio support: %s\n", yesno(intel_dp->has_audio)); if (intel_connector->base.connector_type == DRM_MODE_CONNECTOR_eDP) intel_panel_info(m, &intel_connector->panel); + + drm_dp_downstream_debug(m, intel_dp->dpcd, intel_dp->downstream_ports, + &intel_dp->aux); }
static void intel_hdmi_info(struct seq_file *m, diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h index 215202f..2a79882 100644 --- a/include/drm/drm_dp_helper.h +++ b/include/drm/drm_dp_helper.h @@ -823,6 +823,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]); +void drm_dp_downstream_debug(struct seq_file *m, const u8 dpcd[DP_RECEIVER_CAP_SIZE], + const u8 port_cap[4], struct drm_dp_aux *aux);
void drm_dp_aux_init(struct drm_dp_aux *aux); int drm_dp_aux_register(struct drm_dp_aux *aux);
On Wed, Aug 17, 2016 at 01:49:48PM +0300, Mika Kahola wrote:
Read DisplayPort branch device info from through debugfs interface.
v2: use drm_dp_helper routines to collect data v3: cleanup to match the drm_dp_helper.c patches introduced earlier in this series v4: move DP branch device info to function 'intel_dp_branch_device_info()' v5: initial step to move debugging info from intel_dp. to drm_dp_helper.c (Daniel) v6: read hw and sw revision without using specific drm_dp_helper routines
Signed-off-by: Mika Kahola mika.kahola@intel.com
drivers/gpu/drm/drm_dp_helper.c | 81 +++++++++++++++++++++++++++++++++++++ drivers/gpu/drm/i915/i915_debugfs.c | 3 ++ include/drm/drm_dp_helper.h | 2 + 3 files changed, 86 insertions(+)
diff --git a/drivers/gpu/drm/drm_dp_helper.c b/drivers/gpu/drm/drm_dp_helper.c index 01ee7af..23cd6dc 100644 --- a/drivers/gpu/drm/drm_dp_helper.c +++ b/drivers/gpu/drm/drm_dp_helper.c @@ -526,6 +526,87 @@ int drm_dp_downstream_id(struct drm_dp_aux *aux, char id[6]) } EXPORT_SYMBOL(drm_dp_downstream_id);
+/**
- drm_dp_downstream_debug() - debug DP branch devices
- @m: pointer for debugfs file
- @dpcd: DisplayPort configuration data
- @port_cap: port capabilities
- @aux: DisplayPort AUX channel
- */
+void drm_dp_downstream_debug(struct seq_file *m, const u8 dpcd[DP_RECEIVER_CAP_SIZE],
const u8 port_cap[4], struct drm_dp_aux *aux)
Indentation.
+{
- bool detailed_cap_info = dpcd[DP_DOWNSTREAMPORT_PRESENT] &
DP_DETAILED_CAP_INFO_AVAILABLE;
Indentation.
- int clk;
- int bpc;
- char id[6];
- int len;
- uint8_t rev[2];
- int type = port_cap[0] & DP_DS_PORT_TYPE_MASK;
- bool branch_device = dpcd[DP_DOWNSTREAMPORT_PRESENT] & DP_DWN_STRM_PORT_PRESENT;
- seq_printf(m, "\tDP branch device present: %s\n", branch_device ? "yes" : "no");
- if (!branch_device)
return;
- switch (type) {
- case DP_DS_PORT_TYPE_DP:
seq_printf(m, "\t\tType: DisplayPort\n");
break;
- case DP_DS_PORT_TYPE_VGA:
seq_printf(m, "\t\tType: VGA\n");
break;
- case DP_DS_PORT_TYPE_DVI:
seq_printf(m, "\t\tType: DVI\n");
break;
- case DP_DS_PORT_TYPE_HDMI:
seq_printf(m, "\t\tType: HDMI\n");
break;
- case DP_DS_PORT_TYPE_NON_EDID:
seq_printf(m, "\t\tType: others without EDID support\n");
break;
- case DP_DS_PORT_TYPE_DP_DUALMODE:
seq_printf(m, "\t\tType: DP++\n");
break;
- case DP_DS_PORT_TYPE_WIRELESS:
seq_printf(m, "\t\tType: Wireless\n");
break;
- default:
seq_printf(m, "\t\tType: N/A\n");
- }
- drm_dp_downstream_id(aux, id);
- seq_printf(m, "\t\tID: %s\n", id);
- len = drm_dp_dpcd_read(aux, DP_BRANCH_HW_REV, &rev[0], 1);
- if (len > 0)
seq_printf(m, "\t\tHW: %d.%d\n", (rev[0] & 0xf0) >> 4, rev[0] & 0xf);
- len = drm_dp_dpcd_read(aux, DP_BRANCH_SW_REV, &rev, 2);
- if (len > 0)
seq_printf(m, "\t\tSW: %d.%d\n", rev[0], rev[1]);
- if (detailed_cap_info) {
clk = drm_dp_downstream_max_clock(dpcd, port_cap);
if (clk > 0) {
if (type == DP_DS_PORT_TYPE_VGA)
seq_printf(m, "\t\tMax dot clock: %d kHz\n", clk);
else
seq_printf(m, "\t\tMax TMDS clock: %d kHz\n", clk);
}
bpc = drm_dp_downstream_max_bpc(dpcd, port_cap);
if (bpc > 0)
seq_printf(m, "\t\tMax bpc: %d\n", bpc);
- }
+} +EXPORT_SYMBOL(drm_dp_downstream_debug);
/*
- I2C-over-AUX implementation
*/ diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 01ae5ee..90c736f 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -2923,6 +2923,9 @@ static void intel_dp_info(struct seq_file *m, seq_printf(m, "\taudio support: %s\n", yesno(intel_dp->has_audio)); if (intel_connector->base.connector_type == DRM_MODE_CONNECTOR_eDP) intel_panel_info(m, &intel_connector->panel);
- drm_dp_downstream_debug(m, intel_dp->dpcd, intel_dp->downstream_ports,
&intel_dp->aux);
}
static void intel_hdmi_info(struct seq_file *m, diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h index 215202f..2a79882 100644 --- a/include/drm/drm_dp_helper.h +++ b/include/drm/drm_dp_helper.h @@ -823,6 +823,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]); +void drm_dp_downstream_debug(struct seq_file *m, const u8 dpcd[DP_RECEIVER_CAP_SIZE],
const u8 port_cap[4], struct drm_dp_aux *aux);
Indentation.
Jim
void drm_dp_aux_init(struct drm_dp_aux *aux); int drm_dp_aux_register(struct drm_dp_aux *aux); -- 1.9.1
Respect max TMDS clock frequency from DPCD for active DP to HDMI adapters.
Signed-off-by: Mika Kahola mika.kahola@intel.com --- drivers/gpu/drm/i915/intel_drv.h | 3 +++ drivers/gpu/drm/i915/intel_hdmi.c | 27 +++++++++++++++++++++++++++ 2 files changed, 30 insertions(+)
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 1c700b0..b7fd551 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -817,6 +817,9 @@ struct intel_hdmi { i915_reg_t hdmi_reg; int ddc_bus; struct { + int max_tmds_clock; + } dp_to_hdmi; + struct { enum drm_dp_dual_mode_type type; int max_tmds_clock; } dp_dual_mode; diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c index 4df9f38..1469d00 100644 --- a/drivers/gpu/drm/i915/intel_hdmi.c +++ b/drivers/gpu/drm/i915/intel_hdmi.c @@ -1204,6 +1204,9 @@ static int hdmi_port_clock_limit(struct intel_hdmi *hdmi, int max_tmds_clock = intel_hdmi_source_max_tmds_clock(to_i915(dev));
if (respect_downstream_limits) { + if (hdmi->dp_to_hdmi.max_tmds_clock) + max_tmds_clock = min(max_tmds_clock, + hdmi->dp_to_hdmi.max_tmds_clock); if (hdmi->dp_dual_mode.max_tmds_clock) max_tmds_clock = min(max_tmds_clock, hdmi->dp_dual_mode.max_tmds_clock); @@ -1373,11 +1376,33 @@ intel_hdmi_unset_edid(struct drm_connector *connector) intel_hdmi->dp_dual_mode.type = DRM_DP_DUAL_MODE_NONE; intel_hdmi->dp_dual_mode.max_tmds_clock = 0;
+ intel_hdmi->dp_to_hdmi.max_tmds_clock = 0; + kfree(to_intel_connector(connector)->detect_edid); to_intel_connector(connector)->detect_edid = NULL; }
static void +intel_hdmi_dp_adapter_detect(struct drm_connector *connector) +{ + struct intel_hdmi *intel_hdmi = intel_attached_hdmi(connector); + struct intel_digital_port *intel_dig_port = + hdmi_to_dig_port(intel_hdmi); + struct intel_dp *intel_dp = &intel_dig_port->dp; + int type = intel_dp->downstream_ports[0] & DP_DS_PORT_TYPE_MASK; + + if (type != DP_DS_PORT_TYPE_HDMI) + return; + + intel_hdmi->dp_to_hdmi.max_tmds_clock = + drm_dp_downstream_max_clock(intel_dp->dpcd, + intel_dp->downstream_ports); + + DRM_DEBUG_KMS("DP HDMI adaptor detected (max TMDS clock : %d kHz\n", + intel_hdmi->dp_to_hdmi.max_tmds_clock); +} + +static void intel_hdmi_dp_dual_mode_detect(struct drm_connector *connector, bool has_edid) { struct drm_i915_private *dev_priv = to_i915(connector->dev); @@ -1438,6 +1463,8 @@ intel_hdmi_set_edid(struct drm_connector *connector, bool force)
intel_hdmi_dp_dual_mode_detect(connector, edid != NULL);
+ intel_hdmi_dp_adapter_detect(connector); + intel_display_power_put(dev_priv, POWER_DOMAIN_GMBUS); }
On Wed, Aug 17, 2016 at 01:49:49PM +0300, Mika Kahola wrote:
Respect max TMDS clock frequency from DPCD for active DP to HDMI adapters.
Signed-off-by: Mika Kahola mika.kahola@intel.com
Reviewed-by: Jim Bride jim.bride@linux.intel.com
drivers/gpu/drm/i915/intel_drv.h | 3 +++ drivers/gpu/drm/i915/intel_hdmi.c | 27 +++++++++++++++++++++++++++ 2 files changed, 30 insertions(+)
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 1c700b0..b7fd551 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -817,6 +817,9 @@ struct intel_hdmi { i915_reg_t hdmi_reg; int ddc_bus; struct {
int max_tmds_clock;
- } dp_to_hdmi;
- struct { enum drm_dp_dual_mode_type type; int max_tmds_clock; } dp_dual_mode;
diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c index 4df9f38..1469d00 100644 --- a/drivers/gpu/drm/i915/intel_hdmi.c +++ b/drivers/gpu/drm/i915/intel_hdmi.c @@ -1204,6 +1204,9 @@ static int hdmi_port_clock_limit(struct intel_hdmi *hdmi, int max_tmds_clock = intel_hdmi_source_max_tmds_clock(to_i915(dev));
if (respect_downstream_limits) {
if (hdmi->dp_to_hdmi.max_tmds_clock)
max_tmds_clock = min(max_tmds_clock,
if (hdmi->dp_dual_mode.max_tmds_clock) max_tmds_clock = min(max_tmds_clock, hdmi->dp_dual_mode.max_tmds_clock);hdmi->dp_to_hdmi.max_tmds_clock);
@@ -1373,11 +1376,33 @@ intel_hdmi_unset_edid(struct drm_connector *connector) intel_hdmi->dp_dual_mode.type = DRM_DP_DUAL_MODE_NONE; intel_hdmi->dp_dual_mode.max_tmds_clock = 0;
- intel_hdmi->dp_to_hdmi.max_tmds_clock = 0;
- kfree(to_intel_connector(connector)->detect_edid); to_intel_connector(connector)->detect_edid = NULL;
}
static void +intel_hdmi_dp_adapter_detect(struct drm_connector *connector) +{
- struct intel_hdmi *intel_hdmi = intel_attached_hdmi(connector);
- struct intel_digital_port *intel_dig_port =
hdmi_to_dig_port(intel_hdmi);
- struct intel_dp *intel_dp = &intel_dig_port->dp;
- int type = intel_dp->downstream_ports[0] & DP_DS_PORT_TYPE_MASK;
- if (type != DP_DS_PORT_TYPE_HDMI)
return;
- intel_hdmi->dp_to_hdmi.max_tmds_clock =
drm_dp_downstream_max_clock(intel_dp->dpcd,
intel_dp->downstream_ports);
- DRM_DEBUG_KMS("DP HDMI adaptor detected (max TMDS clock : %d kHz\n",
intel_hdmi->dp_to_hdmi.max_tmds_clock);
+}
+static void intel_hdmi_dp_dual_mode_detect(struct drm_connector *connector, bool has_edid) { struct drm_i915_private *dev_priv = to_i915(connector->dev); @@ -1438,6 +1463,8 @@ intel_hdmi_set_edid(struct drm_connector *connector, bool force)
intel_hdmi_dp_dual_mode_detect(connector, edid != NULL);
intel_hdmi_dp_adapter_detect(connector);
- intel_display_power_put(dev_priv, POWER_DOMAIN_GMBUS); }
-- 1.9.1
On Wed, Aug 17, 2016 at 01:49:49PM +0300, Mika Kahola wrote:
Respect max TMDS clock frequency from DPCD for active DP to HDMI adapters.
Signed-off-by: Mika Kahola mika.kahola@intel.com
drivers/gpu/drm/i915/intel_drv.h | 3 +++ drivers/gpu/drm/i915/intel_hdmi.c | 27 +++++++++++++++++++++++++++ 2 files changed, 30 insertions(+)
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 1c700b0..b7fd551 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -817,6 +817,9 @@ struct intel_hdmi { i915_reg_t hdmi_reg; int ddc_bus; struct {
int max_tmds_clock;
- } dp_to_hdmi;
- struct { enum drm_dp_dual_mode_type type; int max_tmds_clock; } dp_dual_mode;
diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c index 4df9f38..1469d00 100644 --- a/drivers/gpu/drm/i915/intel_hdmi.c +++ b/drivers/gpu/drm/i915/intel_hdmi.c @@ -1204,6 +1204,9 @@ static int hdmi_port_clock_limit(struct intel_hdmi *hdmi, int max_tmds_clock = intel_hdmi_source_max_tmds_clock(to_i915(dev));
if (respect_downstream_limits) {
if (hdmi->dp_to_hdmi.max_tmds_clock)
max_tmds_clock = min(max_tmds_clock,
if (hdmi->dp_dual_mode.max_tmds_clock) max_tmds_clock = min(max_tmds_clock, hdmi->dp_dual_mode.max_tmds_clock);hdmi->dp_to_hdmi.max_tmds_clock);
@@ -1373,11 +1376,33 @@ intel_hdmi_unset_edid(struct drm_connector *connector) intel_hdmi->dp_dual_mode.type = DRM_DP_DUAL_MODE_NONE; intel_hdmi->dp_dual_mode.max_tmds_clock = 0;
- intel_hdmi->dp_to_hdmi.max_tmds_clock = 0;
- kfree(to_intel_connector(connector)->detect_edid); to_intel_connector(connector)->detect_edid = NULL;
}
static void +intel_hdmi_dp_adapter_detect(struct drm_connector *connector) +{
- struct intel_hdmi *intel_hdmi = intel_attached_hdmi(connector);
- struct intel_digital_port *intel_dig_port =
hdmi_to_dig_port(intel_hdmi);
- struct intel_dp *intel_dp = &intel_dig_port->dp;
- int type = intel_dp->downstream_ports[0] & DP_DS_PORT_TYPE_MASK;
- if (type != DP_DS_PORT_TYPE_HDMI)
return;
- intel_hdmi->dp_to_hdmi.max_tmds_clock =
drm_dp_downstream_max_clock(intel_dp->dpcd,
intel_dp->downstream_ports);
Poets driven by intel_hdmi don't have DPCD, so I don't know what this is supposed to achieve.
- DRM_DEBUG_KMS("DP HDMI adaptor detected (max TMDS clock : %d kHz\n",
intel_hdmi->dp_to_hdmi.max_tmds_clock);
+}
+static void intel_hdmi_dp_dual_mode_detect(struct drm_connector *connector, bool has_edid) { struct drm_i915_private *dev_priv = to_i915(connector->dev); @@ -1438,6 +1463,8 @@ intel_hdmi_set_edid(struct drm_connector *connector, bool force)
intel_hdmi_dp_dual_mode_detect(connector, edid != NULL);
intel_hdmi_dp_adapter_detect(connector);
- intel_display_power_put(dev_priv, POWER_DOMAIN_GMBUS); }
-- 1.9.1
On Thu, 2016-09-08 at 15:48 +0300, Ville Syrjälä wrote:
On Wed, Aug 17, 2016 at 01:49:49PM +0300, Mika Kahola wrote:
Respect max TMDS clock frequency from DPCD for active DP to HDMI adapters.
Signed-off-by: Mika Kahola mika.kahola@intel.com
drivers/gpu/drm/i915/intel_drv.h | 3 +++ drivers/gpu/drm/i915/intel_hdmi.c | 27 +++++++++++++++++++++++++++ 2 files changed, 30 insertions(+)
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 1c700b0..b7fd551 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -817,6 +817,9 @@ struct intel_hdmi { i915_reg_t hdmi_reg; int ddc_bus; struct {
int max_tmds_clock;
- } dp_to_hdmi;
- struct {
enum drm_dp_dual_mode_type type; int max_tmds_clock; } dp_dual_mode; diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c index 4df9f38..1469d00 100644 --- a/drivers/gpu/drm/i915/intel_hdmi.c +++ b/drivers/gpu/drm/i915/intel_hdmi.c @@ -1204,6 +1204,9 @@ static int hdmi_port_clock_limit(struct intel_hdmi *hdmi, int max_tmds_clock = intel_hdmi_source_max_tmds_clock(to_i915(dev)); if (respect_downstream_limits) {
if (hdmi->dp_to_hdmi.max_tmds_clock)
max_tmds_clock = min(max_tmds_clock,
hdmi-
dp_to_hdmi.max_tmds_clock);
if (hdmi->dp_dual_mode.max_tmds_clock) max_tmds_clock = min(max_tmds_clock, hdmi-
dp_dual_mode.max_tmds_clock);
@@ -1373,11 +1376,33 @@ intel_hdmi_unset_edid(struct drm_connector *connector) intel_hdmi->dp_dual_mode.type = DRM_DP_DUAL_MODE_NONE; intel_hdmi->dp_dual_mode.max_tmds_clock = 0;
- intel_hdmi->dp_to_hdmi.max_tmds_clock = 0;
kfree(to_intel_connector(connector)->detect_edid); to_intel_connector(connector)->detect_edid = NULL; } static void +intel_hdmi_dp_adapter_detect(struct drm_connector *connector) +{
- struct intel_hdmi *intel_hdmi =
intel_attached_hdmi(connector);
- struct intel_digital_port *intel_dig_port =
hdmi_to_dig_port(intel_hdmi);
- struct intel_dp *intel_dp = &intel_dig_port->dp;
- int type = intel_dp->downstream_ports[0] &
DP_DS_PORT_TYPE_MASK;
- if (type != DP_DS_PORT_TYPE_HDMI)
return;
- intel_hdmi->dp_to_hdmi.max_tmds_clock =
drm_dp_downstream_max_clock(intel_dp->dpcd,
intel_dp-
downstream_ports);
Poets driven by intel_hdmi don't have DPCD, so I don't know what this is supposed to achieve.
My understanding is that these HDMI adapters has DPCD and therefore I placed this function. In addition, I think we should respect the clocks if the adapter provides that information.
- DRM_DEBUG_KMS("DP HDMI adaptor detected (max TMDS clock :
%d kHz\n",
intel_hdmi->dp_to_hdmi.max_tmds_clock);
+}
+static void intel_hdmi_dp_dual_mode_detect(struct drm_connector *connector, bool has_edid) { struct drm_i915_private *dev_priv = to_i915(connector-
dev);
@@ -1438,6 +1463,8 @@ intel_hdmi_set_edid(struct drm_connector *connector, bool force) intel_hdmi_dp_dual_mode_detect(connector, edid != NULL);
intel_hdmi_dp_adapter_detect(connector);
intel_display_power_put(dev_priv, POWER_DOMAIN_GMBUS); } -- 1.9.1
On Fri, Sep 09, 2016 at 10:45:27AM +0300, Mika Kahola wrote:
On Thu, 2016-09-08 at 15:48 +0300, Ville Syrjälä wrote:
On Wed, Aug 17, 2016 at 01:49:49PM +0300, Mika Kahola wrote:
Respect max TMDS clock frequency from DPCD for active DP to HDMI adapters.
Signed-off-by: Mika Kahola mika.kahola@intel.com
drivers/gpu/drm/i915/intel_drv.h | 3 +++ drivers/gpu/drm/i915/intel_hdmi.c | 27 +++++++++++++++++++++++++++ 2 files changed, 30 insertions(+)
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 1c700b0..b7fd551 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -817,6 +817,9 @@ struct intel_hdmi { i915_reg_t hdmi_reg; int ddc_bus; struct {
int max_tmds_clock;
- } dp_to_hdmi;
- struct {
enum drm_dp_dual_mode_type type; int max_tmds_clock; } dp_dual_mode; diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c index 4df9f38..1469d00 100644 --- a/drivers/gpu/drm/i915/intel_hdmi.c +++ b/drivers/gpu/drm/i915/intel_hdmi.c @@ -1204,6 +1204,9 @@ static int hdmi_port_clock_limit(struct intel_hdmi *hdmi, int max_tmds_clock = intel_hdmi_source_max_tmds_clock(to_i915(dev)); if (respect_downstream_limits) {
if (hdmi->dp_to_hdmi.max_tmds_clock)
max_tmds_clock = min(max_tmds_clock,
hdmi-
dp_to_hdmi.max_tmds_clock);
if (hdmi->dp_dual_mode.max_tmds_clock) max_tmds_clock = min(max_tmds_clock, hdmi-
dp_dual_mode.max_tmds_clock);
@@ -1373,11 +1376,33 @@ intel_hdmi_unset_edid(struct drm_connector *connector) intel_hdmi->dp_dual_mode.type = DRM_DP_DUAL_MODE_NONE; intel_hdmi->dp_dual_mode.max_tmds_clock = 0;
- intel_hdmi->dp_to_hdmi.max_tmds_clock = 0;
kfree(to_intel_connector(connector)->detect_edid); to_intel_connector(connector)->detect_edid = NULL; } static void +intel_hdmi_dp_adapter_detect(struct drm_connector *connector) +{
- struct intel_hdmi *intel_hdmi =
intel_attached_hdmi(connector);
- struct intel_digital_port *intel_dig_port =
hdmi_to_dig_port(intel_hdmi);
- struct intel_dp *intel_dp = &intel_dig_port->dp;
- int type = intel_dp->downstream_ports[0] &
DP_DS_PORT_TYPE_MASK;
- if (type != DP_DS_PORT_TYPE_HDMI)
return;
- intel_hdmi->dp_to_hdmi.max_tmds_clock =
drm_dp_downstream_max_clock(intel_dp->dpcd,
intel_dp-
downstream_ports);
Poets driven by intel_hdmi don't have DPCD, so I don't know what this is supposed to achieve.
My understanding is that these HDMI adapters has DPCD and therefore I placed this function. In addition, I think we should respect the clocks if the adapter provides that information.
Only stuff driven by intel_dp has DPCD.
- DRM_DEBUG_KMS("DP HDMI adaptor detected (max TMDS clock :
%d kHz\n",
intel_hdmi->dp_to_hdmi.max_tmds_clock);
+}
+static void intel_hdmi_dp_dual_mode_detect(struct drm_connector *connector, bool has_edid) { struct drm_i915_private *dev_priv = to_i915(connector-
dev);
@@ -1438,6 +1463,8 @@ intel_hdmi_set_edid(struct drm_connector *connector, bool force) intel_hdmi_dp_dual_mode_detect(connector, edid != NULL);
intel_hdmi_dp_adapter_detect(connector);
intel_display_power_put(dev_priv, POWER_DOMAIN_GMBUS); } -- 1.9.1
-- Mika Kahola - Intel OTC
On Fri, 2016-09-09 at 12:09 +0300, Ville Syrjälä wrote:
On Fri, Sep 09, 2016 at 10:45:27AM +0300, Mika Kahola wrote:
On Thu, 2016-09-08 at 15:48 +0300, Ville Syrjälä wrote:
On Wed, Aug 17, 2016 at 01:49:49PM +0300, Mika Kahola wrote:
Respect max TMDS clock frequency from DPCD for active DP to HDMI adapters.
Signed-off-by: Mika Kahola mika.kahola@intel.com
drivers/gpu/drm/i915/intel_drv.h | 3 +++ drivers/gpu/drm/i915/intel_hdmi.c | 27 +++++++++++++++++++++++++++ 2 files changed, 30 insertions(+)
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 1c700b0..b7fd551 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -817,6 +817,9 @@ struct intel_hdmi { i915_reg_t hdmi_reg; int ddc_bus; struct {
int max_tmds_clock;
- } dp_to_hdmi;
- struct {
enum drm_dp_dual_mode_type type; int max_tmds_clock; } dp_dual_mode; diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c index 4df9f38..1469d00 100644 --- a/drivers/gpu/drm/i915/intel_hdmi.c +++ b/drivers/gpu/drm/i915/intel_hdmi.c @@ -1204,6 +1204,9 @@ static int hdmi_port_clock_limit(struct intel_hdmi *hdmi, int max_tmds_clock = intel_hdmi_source_max_tmds_clock(to_i915(dev)); if (respect_downstream_limits) {
if (hdmi->dp_to_hdmi.max_tmds_clock)
max_tmds_clock = min(max_tmds_clock,
hdmi-
dp_to_hdmi.max_tmds_clock);
if (hdmi->dp_dual_mode.max_tmds_clock) max_tmds_clock = min(max_tmds_clock, hdmi-
dp_dual_mode.max_tmds_clock);
@@ -1373,11 +1376,33 @@ intel_hdmi_unset_edid(struct drm_connector *connector) intel_hdmi->dp_dual_mode.type = DRM_DP_DUAL_MODE_NONE; intel_hdmi->dp_dual_mode.max_tmds_clock = 0;
- intel_hdmi->dp_to_hdmi.max_tmds_clock = 0;
kfree(to_intel_connector(connector)->detect_edid); to_intel_connector(connector)->detect_edid = NULL; } static void +intel_hdmi_dp_adapter_detect(struct drm_connector *connector) +{
- struct intel_hdmi *intel_hdmi =
intel_attached_hdmi(connector);
- struct intel_digital_port *intel_dig_port =
hdmi_to_dig_port(intel_hdmi);
- struct intel_dp *intel_dp = &intel_dig_port->dp;
- int type = intel_dp->downstream_ports[0] &
DP_DS_PORT_TYPE_MASK;
- if (type != DP_DS_PORT_TYPE_HDMI)
return;
- intel_hdmi->dp_to_hdmi.max_tmds_clock =
drm_dp_downstream_max_clock(intel_dp->dpcd,
intel_dp-
downstream_ports);
Poets driven by intel_hdmi don't have DPCD, so I don't know what this is supposed to achieve.
My understanding is that these HDMI adapters has DPCD and therefore I placed this function. In addition, I think we should respect the clocks if the adapter provides that information.
Only stuff driven by intel_dp has DPCD.
All right. Then this patch can be discarded. Or maybe I move this stuff into intel_dp.
- DRM_DEBUG_KMS("DP HDMI adaptor detected (max TMDS
clock : %d kHz\n",
intel_hdmi->dp_to_hdmi.max_tmds_clock);
+}
+static void intel_hdmi_dp_dual_mode_detect(struct drm_connector *connector, bool has_edid) { struct drm_i915_private *dev_priv = to_i915(connector-
dev);
@@ -1438,6 +1463,8 @@ intel_hdmi_set_edid(struct drm_connector *connector, bool force) intel_hdmi_dp_dual_mode_detect(connector, edid != NULL);
intel_hdmi_dp_adapter_detect(connector);
intel_display_power_put(dev_priv, POWER_DOMAIN_GMBUS); } -- 1.9.1
-- Mika Kahola - Intel OTC
dri-devel@lists.freedesktop.org