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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.