From: David Francis <David.Francis-5C7GfCeVMHo@public.gmane.org>
To: dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW@public.gmane.org,
amd-gfx-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW@public.gmane.org
Cc: Wenjing Liu <Wenjing.Liu-5C7GfCeVMHo@public.gmane.org>,
David Francis <David.Francis-5C7GfCeVMHo@public.gmane.org>,
Nikola Cornij <Nikola.Cornij-5C7GfCeVMHo@public.gmane.org>
Subject: [PATCH v3 12/16] drm/dp-mst: Add helpers for querying and enabling MST DSC
Date: Wed, 21 Aug 2019 16:01:25 -0400 [thread overview]
Message-ID: <20190821200129.11575-13-David.Francis@amd.com> (raw)
In-Reply-To: <20190821200129.11575-1-David.Francis-5C7GfCeVMHo@public.gmane.org>
Add drm_dp_mst_dsc_caps_for_port and drm_dp_mst_dsc_enable,
two helper functions for MST DSC
The former, given a port, returns the raw DPCD DSC caps off
that port.
The latter, given a port, enables or disables DSC on that port.
In both cases, the port given as input should be a leaf of
the MST tree with an attached display.
The logic for this is somewhat complicated, as DSC can be
enabled in 4 different ways.
Case 1: DP-to-DP peer device
if the branch immediately upstream has
- PDT = DP_PEER_DEVICE_DP_MST_BRANCHING (2)
- DPCD rev. >= DP 1.4
- Exactly one input and one output
- The output has PDT = DP_PEER_DEVICE_SST_SINK (3)
In this case, DSC could be possible either on the endpoint
or the peer device. Prefer the endpoint, which is possible if
- The endpoint has DP_DSC_DECOMPRESSION_IS_SUPPORTED bit set
- The endpoint has DP_FEC_CAPABLE bit set
- The peer device has DSC_PASSTHROUGH_CAPABILITY bit set (from DP v2.0)
Otherwise, use the peer device
Case 2: DP-to-HDMI peer device
If the output port has
- PDT = DP_PEER_DEVICE_DP_LEGACY_CONV (4)
- DPCD rev. >= DP 1.4
- LDPS = true
- MCS = false
In this case, DSC can only be attempted on the peer device
(the output port)
Case 3: Virtual DP Sink (Internal Display Panel)
If the output port has
- DPCD rev. >= DP 1.4
- port_num >= 8
In this case, DSC can only be attempted on the peer device
(the output port)
Case 4: Synaptix Workaround
If the output has
- link DPCD rev. >= DP 1.4
- link branch_dev_id = 0x90CC24 (Synaptix)
- There is exactly one branch device between the link and output
In this case, DSC can be attempted, but only using the *link*
aux device's caps. This is a quirk.
Cc: Lyude Paul <lyude@redhat.com>
Cc: Wenjing Liu <Wenjing.Liu@amd.com>
Cc: Nikola Cornij <Nikola.Cornij@amd.com>
Signed-off-by: David Francis <David.Francis@amd.com>
---
drivers/gpu/drm/drm_dp_mst_topology.c | 192 ++++++++++++++++++++++++++
include/drm/drm_dp_mst_helper.h | 3 +
2 files changed, 195 insertions(+)
diff --git a/drivers/gpu/drm/drm_dp_mst_topology.c b/drivers/gpu/drm/drm_dp_mst_topology.c
index 7decb5bef062..94742538551e 100644
--- a/drivers/gpu/drm/drm_dp_mst_topology.c
+++ b/drivers/gpu/drm/drm_dp_mst_topology.c
@@ -4183,3 +4183,195 @@ static void drm_dp_mst_unregister_i2c_bus(struct drm_dp_aux *aux)
{
i2c_del_adapter(&aux->ddc);
}
+
+/**
+ * drm_dp_mst_is_virtual_dpcd() - Is the given port a virtual DPCD device?
+ * @port: The port to check
+ *
+ * Returns:
+ * true if the port is a virtual DPCD peer device, false otherwise
+ */
+static bool drm_dp_mst_is_virtual_dpcd(struct drm_dp_mst_port *port)
+{
+ struct drm_dp_mst_port *downstream_port;
+
+ if (!port)
+ return false;
+
+ /* Virtual DP Sink (Internal Display Panel) */
+ if (port->port_num >= 8 && port->dpcd_rev >= DP_DPCD_REV_14)
+ return true;
+
+ /* DP-to-HDMI Protocol Converter */
+ if (port->pdt == DP_PEER_DEVICE_DP_LEGACY_CONV &&
+ !port->mcs &&
+ port->ldps &&
+ port->dpcd_rev >= DP_DPCD_REV_14)
+ return true;
+
+ /* DP-to-DP */
+ if (port->pdt == DP_PEER_DEVICE_MST_BRANCHING &&
+ port->mstb &&
+ port->dpcd_rev >= DP_DPCD_REV_14 &&
+ port->mstb->num_ports == 2) {
+ list_for_each_entry(downstream_port, &port->mstb->ports, next) {
+ if (!downstream_port->input &&
+ downstream_port->pdt == DP_PEER_DEVICE_SST_SINK)
+ return true;
+ }
+ }
+
+ return false;
+}
+
+/**
+ * drm_dp_mst_is_virtual_dpcd() - Does this port require Synaptix DSC workaround?
+ * @port: The port to check
+ *
+ * Some Synaptix MST hubs support DSC even though they do not support virtual
+ * DPCD. This is a quirk.
+ *
+ * Returns:
+ * true if the Synaptix workaround is required, false otherwise
+ */
+static bool drm_dp_mst_dsc_synaptix_workaround(struct drm_dp_mst_port *port)
+{
+ u8 data[3] = { 0 };
+ u32 dev_id;
+ struct drm_dp_aux *phys_aux;
+
+ /* The hub must be directly connected to the connector */
+ if (port->mgr->mst_primary != port->parent)
+ return false;
+
+ phys_aux = port->mgr->aux;
+ if (drm_dp_dpcd_read(phys_aux, DP_BRANCH_OUI, data, 3) < 0)
+ return false;
+ dev_id = (data[0] << 16) & (data[1] << 8) & data[3];
+ /* Synaptix device ID */
+ if (dev_id != 0x90CC24)
+ return false;
+
+ if (drm_dp_dpcd_read(phys_aux, DP_DPCD_REV, data, 1) < 0)
+ return false;
+ /* Must be DPCD rev. 1.4 or later */
+ if (data[0] < DP_DPCD_REV_14)
+ return false;
+
+ if (drm_dp_dpcd_read(&port->aux, DP_DOWNSTREAMPORT_PRESENT, data, 1) < 0)
+ return false;
+ /* Must not be a VGA converter */
+ if ((data[0] & 7) == 3)
+ return false;
+
+ return true;
+}
+
+/**
+ * drm_dp_mst_dsc_aux_for_port() - Find the correct aux for DSC
+ * @port: The port to check. A leaf of the MST tree with an attached display.
+ *
+ * Depending on the situation, DSC may be enabled via the endpoint aux,
+ * the immediately upstream aux, or the connector's physical aux.
+ *
+ * Returns:
+ * NULL if DSC cannot be enabled on this port, otherwise the aux device
+ */
+struct drm_dp_aux *drm_dp_mst_dsc_aux_for_port(struct drm_dp_mst_port *port)
+{
+ u8 upstream_dsc_caps = 0;
+ u8 endpoint_dsc_caps = 0;
+ u8 endpoint_fec_caps = 0;
+ struct drm_dp_mst_port *immediate_upstream_port;
+ struct drm_dp_mst_port *fec_port;
+
+ if (port && port->parent)
+ immediate_upstream_port = port->parent->port_parent;
+ else
+ immediate_upstream_port = NULL;
+
+ fec_port = immediate_upstream_port;
+ while (fec_port) {
+ if (!fec_port->fec_capable)
+ return NULL;
+
+ fec_port = fec_port->parent->port_parent;
+ }
+
+ if (immediate_upstream_port) {
+ if (drm_dp_dpcd_read(&immediate_upstream_port->aux,
+ DP_DSC_SUPPORT, &upstream_dsc_caps, 1) < 0)
+ return NULL;
+ }
+
+ if (drm_dp_dpcd_read(&port->aux, DP_DSC_SUPPORT, &endpoint_dsc_caps, 1) < 0)
+ return NULL;
+ if (drm_dp_dpcd_read(&port->aux, DP_FEC_CAPABILITY, &endpoint_fec_caps, 1) < 0)
+ return NULL;
+
+ /* Enpoint decompression with DP-to-DP peer device */
+ if (drm_dp_mst_is_virtual_dpcd(immediate_upstream_port)
+ && (upstream_dsc_caps & 0x2) /* DSC passthrough capability */
+ && (endpoint_fec_caps & DP_FEC_CAPABLE)
+ && (endpoint_dsc_caps & DP_DSC_DECOMPRESSION_IS_SUPPORTED))
+ return &port->aux;
+
+ /* Virtual DPCD decompression with DP-to-DP peer device */
+ if (drm_dp_mst_is_virtual_dpcd(immediate_upstream_port))
+ return &immediate_upstream_port->aux;
+
+ /* Virtual DPCD decompression with DP-to-HDMI or Virtual DP Sink */
+ if (drm_dp_mst_is_virtual_dpcd(port))
+ return &port->aux;
+
+ /* Synaptix workaround */
+ if (drm_dp_mst_dsc_synaptix_workaround(port))
+ return port->mgr->aux;
+
+ return NULL;
+}
+
+/**
+ * drm_dp_mst_dsc_aux_for_port() - Retrieve the DSC capability registers
+ * @port: The port to check. A leaf of the MST tree with an attached display.
+ * @caps: Output. A pointer to an array at least 16 bytes long
+ *
+ * Reads the DSC capability registers (DSC_SUPPORT through
+ * BITS_PER_PIXEL_INCREMENT) and store them in the given pointer. Use
+ * the correct aux for DSC on the given port.
+ *
+ * Returns:
+ * The number of bytes read on success, or a negative error code on failure
+ */
+int drm_dp_mst_dsc_caps_for_port(struct drm_dp_mst_port *port, u8 *caps)
+{
+ struct drm_dp_aux *aux = drm_dp_mst_dsc_aux_for_port(port);
+
+ if (!aux)
+ return -EINVAL;
+
+ return drm_dp_dpcd_read(aux, DP_DSC_SUPPORT, caps, 16);
+}
+EXPORT_SYMBOL(drm_dp_mst_dsc_caps_for_port);
+
+/**
+ * drm_dp_mst_dsc_aux_for_port() - Enable DSC on an MST endpoint
+ * @port: The port to check. A leaf of the MST tree with an attached display.
+ * @enable: true for turn on DSC, false for turn off DSC
+ *
+ * Writes DP_DSC_ENABLE on the correct aux for the given port.
+ *
+ * Returns:
+ * The number of bytes written on success, or a negative error code on failure
+ */
+int drm_dp_mst_dsc_enable(struct drm_dp_mst_port *port, bool enable)
+{
+ struct drm_dp_aux *aux = drm_dp_mst_dsc_aux_for_port(port);
+ u8 enable_dsc = enable ? 1 : 0;
+
+ if (!aux)
+ return -EINVAL;
+
+ return drm_dp_dpcd_write(aux, DP_DSC_ENABLE, &enable_dsc, 1);
+}
+EXPORT_SYMBOL(drm_dp_mst_dsc_enable);
diff --git a/include/drm/drm_dp_mst_helper.h b/include/drm/drm_dp_mst_helper.h
index fa973773a4a7..0f70dc8dfbeb 100644
--- a/include/drm/drm_dp_mst_helper.h
+++ b/include/drm/drm_dp_mst_helper.h
@@ -674,6 +674,9 @@ int __must_check drm_dp_mst_atomic_check(struct drm_atomic_state *state);
void drm_dp_mst_get_port_malloc(struct drm_dp_mst_port *port);
void drm_dp_mst_put_port_malloc(struct drm_dp_mst_port *port);
+int drm_dp_mst_dsc_caps_for_port(struct drm_dp_mst_port *port, u8 *caps);
+int drm_dp_mst_dsc_enable(struct drm_dp_mst_port *port, bool enable);
+
extern const struct drm_private_state_funcs drm_dp_mst_topology_state_funcs;
/**
--
2.17.1
_______________________________________________
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx
next prev parent reply other threads:[~2019-08-21 20:01 UTC|newest]
Thread overview: 24+ messages / expand[flat|nested] mbox.gz Atom feed top
2019-08-21 20:01 [PATCH v3 00/16] Display Stream Compression (DSC) for AMD Navi David Francis
2019-08-21 20:01 ` [PATCH v3 01/16] Revert "drm/amd/display: skip dsc config for navi10 bring up" David Francis
2019-08-21 20:01 ` [PATCH v3 02/16] Revert "drm/amd/display: navi10 bring up skip dsc encoder config" David Francis
2019-08-21 20:01 ` [PATCH v3 03/16] Revert "drm/amd/display: add global master update lock for DCN2" David Francis
2019-08-21 20:01 ` [PATCH v3 04/16] Revert "drm/amd/display: Fix underscan not using proper scaling" David Francis
2019-08-21 20:01 ` [PATCH v3 05/16] drm/amd/display: Enable SST DSC in DM David Francis
2019-08-21 20:01 ` [PATCH v3 09/16] drm/dp-mst: Parse FEC capability on MST ports David Francis
[not found] ` <20190821200129.11575-1-David.Francis-5C7GfCeVMHo@public.gmane.org>
2019-08-21 20:01 ` [PATCH v3 06/16] drm/dp-mst: Add PBN calculation for DSC modes David Francis
[not found] ` <20190821200129.11575-7-David.Francis-5C7GfCeVMHo@public.gmane.org>
2019-08-21 20:03 ` Lyude Paul
2019-08-21 20:01 ` [PATCH v3 07/16] drm/amd/display: Use correct helpers to compute timeslots David Francis
2019-08-21 20:01 ` [PATCH v3 08/16] drm/amd/display: Initialize DSC PPS variables to 0 David Francis
2019-08-21 20:01 ` [PATCH v3 10/16] drm/dp-mst: Add MST support to DP DPCD R/W functions David Francis
[not found] ` <20190821200129.11575-11-David.Francis-5C7GfCeVMHo@public.gmane.org>
2019-08-21 21:08 ` Lyude Paul
2019-08-21 20:01 ` [PATCH v3 11/16] drm/dp-mst: Fill branch->num_ports David Francis
2019-08-21 20:01 ` David Francis [this message]
2019-08-21 20:01 ` [PATCH v3 13/16] drm/amd/display: Validate DSC caps on MST endpoints David Francis
2019-08-22 13:26 ` Francis, David
2019-08-21 20:01 ` [PATCH v3 14/16] drm/amd/display: Write DSC enable to MST DPCD David Francis
2019-08-21 20:01 ` [PATCH v3 15/16] drm/amd/display: MST DSC compute fair share David Francis
2019-08-21 20:01 ` [PATCH v3 16/16] drm/amd/display: Trigger modesets on MST DSC connectors David Francis
2019-08-21 20:02 ` Francis, David
[not found] ` <BN8PR12MB3217348063E5E6798009996AEFAA0-h6+T2+wrnx1RCczRXbE7rwdYzm3356FpvxpqHgZTriW3zl9H0oFU5g@public.gmane.org>
2019-08-21 20:43 ` Lyude Paul
2019-08-21 21:20 ` [PATCH v3 00/16] Display Stream Compression (DSC) for AMD Navi Lyude Paul
[not found] ` <731de9e59c86128c01ff5473a908888545f10390.camel-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
2019-08-22 13:47 ` Francis, David
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20190821200129.11575-13-David.Francis@amd.com \
--to=david.francis-5c7gfcevmho@public.gmane.org \
--cc=Nikola.Cornij-5C7GfCeVMHo@public.gmane.org \
--cc=Wenjing.Liu-5C7GfCeVMHo@public.gmane.org \
--cc=amd-gfx-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW@public.gmane.org \
--cc=dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW@public.gmane.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox