diff --git a/Makefile b/Makefile index 86475705..f9133c26 100644 --- a/Makefile +++ b/Makefile @@ -402,7 +402,8 @@ backport += \ backport/drivers/gpu/drm/drm_property.o \ backport/drivers/gpu/drm/drm_edid.o \ backport/drivers/gpu/drm/display/drm_dp_helper.o \ - backport/drivers/gpu/drm/display/drm_dp_cec.o + backport/drivers/gpu/drm/display/drm_dp_cec.o \ + backport/drivers/gpu/drm/display/drm_dp_mst_topology.o i915-y := $(backport) \ $(i915-y) diff --git a/backport/drivers/gpu/drm/display/drm_dp_cec.c b/backport/drivers/gpu/drm/display/drm_dp_cec.c index 61fea244..496a8f4c 100644 --- a/backport/drivers/gpu/drm/display/drm_dp_cec.c +++ b/backport/drivers/gpu/drm/display/drm_dp_cec.c @@ -16,6 +16,15 @@ #include #include +#if LINUX_VERSION_CODE < KERNEL_VERSION(6,7,0) +// https://github.com/gregkh/linux/commit/113cdddcded6d597b64d824a59d0186db150113a +/* + * A new EDID is set. If there is no CEC adapter, then create one. If + * there was a CEC adapter, then check if the CEC adapter properties + * were unchanged and just update the CEC physical address. Otherwise + * unregister the old CEC adapter and create a new one. + */ + static bool drm_dp_cec_cap(struct drm_dp_aux *aux, u8 *cec_cap) { u8 cap = 0; @@ -117,14 +126,6 @@ static void drm_dp_cec_adap_status(struct cec_adapter *adap, id->sw_major_rev, id->sw_minor_rev); } -#if LINUX_VERSION_CODE < KERNEL_VERSION(6,7,0) -// https://github.com/gregkh/linux/commit/113cdddcded6d597b64d824a59d0186db150113a -/* - * A new EDID is set. If there is no CEC adapter, then create one. If - * there was a CEC adapter, then check if the CEC adapter properties - * were unchanged and just update the CEC physical address. Otherwise - * unregister the old CEC adapter and create a new one. - */ static const struct cec_adap_ops drm_dp_cec_adap_ops = { .adap_enable = drm_dp_cec_adap_enable, .adap_log_addr = drm_dp_cec_adap_log_addr, diff --git a/backport/drivers/gpu/drm/display/drm_dp_mst_topology.c b/backport/drivers/gpu/drm/display/drm_dp_mst_topology.c new file mode 100644 index 00000000..90098967 --- /dev/null +++ b/backport/drivers/gpu/drm/display/drm_dp_mst_topology.c @@ -0,0 +1,131 @@ +/* + * Copyright © 2014 Red Hat + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting documentation, and + * that the name of the copyright holders not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. The copyright holders make no representations + * about the suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if IS_ENABLED(CONFIG_DRM_DEBUG_DP_MST_TOPOLOGY_REFS) +#include +#include +#include +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include + +#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 8, 0) +// https://github.com/gregkh/linux/commit/9dcf67deeab6fbc4984175278b1b2c59881dca52 + +static bool drm_dp_mst_port_downstream_of_branch(struct drm_dp_mst_port *port, + struct drm_dp_mst_branch *branch) +{ + while (port->parent) { + if (port->parent == branch) + return true; + + if (port->parent->port_parent) + port = port->parent->port_parent; + else + break; + } + return false; +} + +static struct drm_dp_mst_port * +drm_dp_mst_topology_get_port_validated_locked(struct drm_dp_mst_branch *mstb, + struct drm_dp_mst_port *to_find) +{ + struct drm_dp_mst_port *port, *mport; + + list_for_each_entry(port, &mstb->ports, next) { + if (port == to_find) + return port; + + if (port->mstb) { + mport = drm_dp_mst_topology_get_port_validated_locked( + port->mstb, to_find); + if (mport) + return mport; + } + } + return NULL; +} + +static bool +drm_dp_mst_port_downstream_of_parent_locked(struct drm_dp_mst_topology_mgr *mgr, + struct drm_dp_mst_port *port, + struct drm_dp_mst_port *parent) +{ + if (!mgr->mst_primary) + return false; + port = drm_dp_mst_topology_get_port_validated_locked(mgr->mst_primary, + port); + if (!port) + return false; + if (!parent) + return true; + parent = drm_dp_mst_topology_get_port_validated_locked(mgr->mst_primary, + parent); + if (!parent) + return false; + if (!parent->mstb) + return false; + return drm_dp_mst_port_downstream_of_branch(port, parent->mstb); +} +/** + * drm_dp_mst_port_downstream_of_parent - check if a port is downstream of a parent port + * @mgr: MST topology manager + * @port: the port being looked up + * @parent: the parent port + * + * The function returns %true if @port is downstream of @parent. If @parent is + * %NULL - denoting the root port - the function returns %true if @port is in + * @mgr's topology. + */ +bool +drm_dp_mst_port_downstream_of_parent(struct drm_dp_mst_topology_mgr *mgr, + struct drm_dp_mst_port *port, + struct drm_dp_mst_port *parent) +{ + bool ret; + mutex_lock(&mgr->lock); + ret = drm_dp_mst_port_downstream_of_parent_locked(mgr, port, parent); + mutex_unlock(&mgr->lock); + return ret; +} +#endif \ No newline at end of file diff --git a/dkms.conf b/dkms.conf index c8e3ee19..3c943967 100644 --- a/dkms.conf +++ b/dkms.conf @@ -8,4 +8,4 @@ BUILT_MODULE_NAME[0]="i915" DEST_MODULE_LOCATION[0]=/kernel/drivers/gpu/drm/i915 AUTOINSTALL=yes -BUILD_EXCLUSIVE_KERNEL="^6\.6\." +BUILD_EXCLUSIVE_KERNEL="^6\." diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index 3ef5f44e..82c71af3 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -32,6 +32,7 @@ #include #include #include +#include #include @@ -5589,6 +5590,9 @@ intel_dp_set_edid(struct intel_dp *intel_dp) struct drm_i915_private *i915 = dp_to_i915(intel_dp); struct intel_connector *connector = intel_dp->attached_connector; const struct drm_edid *drm_edid; +#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 7, 0) + const struct edid *edid; +#endif bool vrr_capable; intel_dp_unset_edid(intel_dp); @@ -5606,8 +5610,14 @@ intel_dp_set_edid(struct intel_dp *intel_dp) intel_dp_update_dfp(intel_dp, drm_edid); intel_dp_update_420(intel_dp); +#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 7, 0) + /* FIXME: Get rid of drm_edid_raw() */ + edid = drm_edid_raw(drm_edid); + drm_dp_cec_set_edid(&intel_dp->aux, edid); +#else drm_dp_cec_attach(&intel_dp->aux, connector->base.display_info.source_physical_address); +#endif } static void diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c index 1d966812..403119ac 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_mst.c +++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c @@ -22,6 +22,7 @@ * IN THE SOFTWARE. * */ +#include #include #include @@ -179,10 +180,15 @@ static int intel_dp_mst_find_vcpi_slots_for_bpp(struct intel_encoder *encoder, min_bpp, max_bpp); for (bpp = max_bpp; bpp >= min_bpp; bpp -= step) { +#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 8, 0) + struct intel_link_m_n remote_m_n; +#else + int remote_tu; +#endif int local_bw_overhead; int remote_bw_overhead; int link_bpp_x16; - int remote_tu; + drm_dbg_kms(&i915->drm, "Trying bpp %d\n", bpp); @@ -202,6 +208,11 @@ static int intel_dp_mst_find_vcpi_slots_for_bpp(struct intel_encoder *encoder, local_bw_overhead, link_bpp_x16, &crtc_state->dp_m_n); + + intel_dp_mst_compute_m_n(crtc_state, connector, + remote_bw_overhead, + link_bpp_x16, + &remote_m_n); /* * The TU size programmed to the HW determines which slots in @@ -217,6 +228,11 @@ static int intel_dp_mst_find_vcpi_slots_for_bpp(struct intel_encoder *encoder, * crtc_state->dp_m_n.tu), provided that the driver doesn't * enable SSC on the corresponding link. */ +#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 8, 0) + drm_WARN_ON(&i915->drm, remote_m_n.tu < crtc_state->dp_m_n.tu); + crtc_state->dp_m_n.tu = remote_m_n.tu; + crtc_state->pbn = remote_m_n.tu * mst_state->pbn_div; +#else crtc_state->pbn = intel_dp_mst_calc_pbn(adjusted_mode->crtc_clock, link_bpp_x16, remote_bw_overhead); @@ -224,8 +240,8 @@ static int intel_dp_mst_find_vcpi_slots_for_bpp(struct intel_encoder *encoder, remote_tu = DIV_ROUND_UP(dfixed_const(crtc_state->pbn), mst_state->pbn_div.full); drm_WARN_ON(&i915->drm, remote_tu < crtc_state->dp_m_n.tu); - crtc_state->dp_m_n.tu = remote_tu; - + crtc_state->dp_m_n.tu = remote_tu; +#endif slots = drm_dp_atomic_find_time_slots(state, &intel_dp->mst_mgr, connector->port, crtc_state->pbn); diff --git a/include/drm/display/drm_dp_mst_helper.h b/include/drm/display/drm_dp_mst_helper.h new file mode 100644 index 00000000..6ee3dd4f --- /dev/null +++ b/include/drm/display/drm_dp_mst_helper.h @@ -0,0 +1,16 @@ +/* SPDX-License-Identifier: MIT */ + +#ifndef __BACKPORT_DRM_DP_MST_HELPER_H__ +#define __BACKPORT_DRM_DP_MST_HELPER_H__ + +#include +#include_next + +#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 8, 0) +// https://github.com/gregkh/linux/commit/9dcf67deeab6fbc4984175278b1b2c59881dca52 +bool drm_dp_mst_port_downstream_of_parent(struct drm_dp_mst_topology_mgr *mgr, + struct drm_dp_mst_port *port, + struct drm_dp_mst_port *parent); +#endif + +#endif /* __DRM_DRM_DP_MST_HELPER_H__ */