summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVagrant Cascadian <vagrant@debian.org>2022-11-06 17:53:50 -0800
committerVagrant Cascadian <vagrant@debian.org>2022-11-25 14:49:07 -0800
commite6873749e57348c2ed8aca1b05d943ea9975e886 (patch)
tree0d7837b5c4ded245f2c9f745a3a328babcf88fdc
parent7e0ad0dd0f2829d6f3776648ba7c88acf9888d7a (diff)
Patches for mnt/reform
https://source.mnt.re/reform/reform-debian-packages.git commit 5e674cbe439408e1e7a9c225543bbfe46a9a6778
-rw-r--r--gnu/packages/patches/linux-libre-mnt-reform-0001-nwl-dsi-fixup-mode-only-for-LCDIF-input-not-DCSS.patch37
-rw-r--r--gnu/packages/patches/linux-libre-mnt-reform-0002-pci-imx6-add-support-for-internal-refclk-imx8mq.patch95
-rw-r--r--gnu/packages/patches/linux-libre-mnt-reform-0003-lcdif-fix-pcie-interference.patch70
-rw-r--r--gnu/packages/patches/linux-libre-mnt-reform-0004-mnt4002-imx-gpcv2-wake-smccc.patch.patch94
-rw-r--r--gnu/packages/patches/linux-libre-mnt-reform-0006-drm-bridge-ti-sn65dsi86-fetch-bpc-using-drm_atomic_s.patch96
-rw-r--r--gnu/packages/patches/linux-libre-mnt-reform-0007-drm-bridge-ti-sn65dsi86-support-DRM_BRIDGE_ATTACH_NO.patch59
6 files changed, 451 insertions, 0 deletions
diff --git a/gnu/packages/patches/linux-libre-mnt-reform-0001-nwl-dsi-fixup-mode-only-for-LCDIF-input-not-DCSS.patch b/gnu/packages/patches/linux-libre-mnt-reform-0001-nwl-dsi-fixup-mode-only-for-LCDIF-input-not-DCSS.patch
new file mode 100644
index 0000000000..e0ac8080e5
--- /dev/null
+++ b/gnu/packages/patches/linux-libre-mnt-reform-0001-nwl-dsi-fixup-mode-only-for-LCDIF-input-not-DCSS.patch
@@ -0,0 +1,37 @@
+From e0ab52e9cfe03580140e18aaae15b5127b4e10b3 Mon Sep 17 00:00:00 2001
+From: "Lukas F. Hartmann" <lukas@mntre.com>
+Date: Wed, 7 Sep 2022 06:20:37 +0200
+Subject: [PATCH 1/7] nwl-dsi-fixup-mode-only-for-LCDIF-input-not-DCSS
+
+---
+ drivers/gpu/drm/bridge/nwl-dsi.c | 13 ++++++++++---
+ 1 file changed, 10 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/gpu/drm/bridge/nwl-dsi.c b/drivers/gpu/drm/bridge/nwl-dsi.c
+index 6dc2a4e..13c5ade 100644
+--- a/drivers/gpu/drm/bridge/nwl-dsi.c
++++ b/drivers/gpu/drm/bridge/nwl-dsi.c
+@@ -822,10 +822,17 @@ static int nwl_dsi_bridge_atomic_check(struct drm_bridge *bridge,
+ struct drm_connector_state *conn_state)
+ {
+ struct drm_display_mode *adjusted_mode = &crtc_state->adjusted_mode;
++ struct device_node *remote;
++ struct nwl_dsi *dsi = bridge_to_dsi(bridge);
+
+- /* At least LCDIF + NWL needs active high sync */
+- adjusted_mode->flags |= (DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC);
+- adjusted_mode->flags &= ~(DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC);
++ remote = of_graph_get_remote_node(dsi->dev->of_node, 0,
++ NWL_DSI_ENDPOINT_LCDIF);
++
++ if (remote) {
++ /* At least LCDIF + NWL needs active high sync */
++ adjusted_mode->flags |= (DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC);
++ adjusted_mode->flags &= ~(DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC);
++ }
+
+ /*
+ * Do a full modeset if crtc_state->active is changed to be true.
+--
+2.37.2
+
diff --git a/gnu/packages/patches/linux-libre-mnt-reform-0002-pci-imx6-add-support-for-internal-refclk-imx8mq.patch b/gnu/packages/patches/linux-libre-mnt-reform-0002-pci-imx6-add-support-for-internal-refclk-imx8mq.patch
new file mode 100644
index 0000000000..b8fe7ef6c6
--- /dev/null
+++ b/gnu/packages/patches/linux-libre-mnt-reform-0002-pci-imx6-add-support-for-internal-refclk-imx8mq.patch
@@ -0,0 +1,95 @@
+From 3b78052d1470fd1ec8d745430a728033b159b793 Mon Sep 17 00:00:00 2001
+From: "Lukas F. Hartmann" <lukas@mntre.com>
+Date: Sat, 22 Oct 2022 17:11:19 +0200
+Subject: [PATCH 2/7] pci-imx6-add-support-for-internal-refclk-imx8mq
+
+---
+ drivers/pci/controller/dwc/pci-imx6.c | 44 +++++++++++++++++++++++++--
+ 1 file changed, 42 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/pci/controller/dwc/pci-imx6.c b/drivers/pci/controller/dwc/pci-imx6.c
+index 6e5debd..e1014b2 100644
+--- a/drivers/pci/controller/dwc/pci-imx6.c
++++ b/drivers/pci/controller/dwc/pci-imx6.c
+@@ -67,6 +67,7 @@ struct imx6_pcie {
+ struct dw_pcie *pci;
+ int reset_gpio;
+ bool gpio_active_high;
++ bool internal_refclk;
+ bool link_is_up;
+ struct clk *pcie_bus;
+ struct clk *pcie_phy;
+@@ -154,6 +155,40 @@ static unsigned int imx6_pcie_grp_offset(const struct imx6_pcie *imx6_pcie)
+ return imx6_pcie->controller_id == 1 ? IOMUXC_GPR16 : IOMUXC_GPR14;
+ }
+
++#define IMX8MQ_ANA_PLLOUT_REG 0x74
++#define IMX8MQ_ANA_PLLOUT_CKE BIT(4)
++#define IMX8MQ_ANA_PLLOUT_SEL_MASK 0xF
++#define IMX8MQ_ANA_PLLOUT_SEL_SYSPLL1 0xB
++#define IMX8MQ_ANA_PLLOUT_DIV_REG 0x7C
++#define IMX8MQ_ANA_PLLOUT_SYSPLL1_DIV 0x7
++
++static void imx6_pcie_enable_internal_refclk(void)
++{
++ uint32_t val;
++ struct device_node* np;
++ void __iomem *base;
++
++ np = of_find_compatible_node(NULL, NULL,
++ "fsl,imx8mq-anatop");
++ base = of_iomap(np, 0);
++ WARN_ON(!base);
++
++ val = readl(base + IMX8MQ_ANA_PLLOUT_REG);
++ val &= ~IMX8MQ_ANA_PLLOUT_SEL_MASK;
++ val |= IMX8MQ_ANA_PLLOUT_SEL_SYSPLL1;
++ writel(val, base + IMX8MQ_ANA_PLLOUT_REG);
++ /* SYS_PLL1 is 800M, PCIE REF CLK is 100M */
++ val = readl(base + IMX8MQ_ANA_PLLOUT_DIV_REG);
++ val |= IMX8MQ_ANA_PLLOUT_SYSPLL1_DIV;
++ writel(val, base + IMX8MQ_ANA_PLLOUT_DIV_REG);
++
++ val = readl(base + IMX8MQ_ANA_PLLOUT_REG);
++ val |= IMX8MQ_ANA_PLLOUT_CKE;
++ writel(val, base + IMX8MQ_ANA_PLLOUT_REG);
++
++ usleep_range(9000,10000);
++}
++
+ static void imx6_pcie_configure_type(struct imx6_pcie *imx6_pcie)
+ {
+ unsigned int mask, val;
+@@ -299,6 +334,9 @@ static int pcie_phy_write(struct imx6_pcie *imx6_pcie, int addr, u16 data)
+
+ static void imx6_pcie_init_phy(struct imx6_pcie *imx6_pcie)
+ {
++ if (imx6_pcie->internal_refclk)
++ imx6_pcie_enable_internal_refclk();
++
+ switch (imx6_pcie->drvdata->variant) {
+ case IMX8MM:
+ /*
+@@ -314,7 +352,8 @@ static void imx6_pcie_init_phy(struct imx6_pcie *imx6_pcie)
+ regmap_update_bits(imx6_pcie->iomuxc_gpr,
+ imx6_pcie_grp_offset(imx6_pcie),
+ IMX8MQ_GPR_PCIE_REF_USE_PAD,
+- IMX8MQ_GPR_PCIE_REF_USE_PAD);
++ (imx6_pcie->internal_refclk ?
++ 0 : IMX8MQ_GPR_PCIE_REF_USE_PAD));
+ /*
+ * Regarding the datasheet, the PCIE_VPH is suggested
+ * to be 1.8V. If the PCIE_VPH is supplied by 3.3V, the
+@@ -1158,7 +1197,8 @@ static int imx6_pcie_probe(struct platform_device *pdev)
+ imx6_pcie->pcie_aux = devm_clk_get(dev, "pcie_aux");
+ if (IS_ERR(imx6_pcie->pcie_aux))
+ return dev_err_probe(dev, PTR_ERR(imx6_pcie->pcie_aux),
+- "pcie_aux clock source missing or invalid\n");
++ "pcie_aux clock source missing or invalid\n");
++ imx6_pcie->internal_refclk = of_property_read_bool(node, "internal-refclk");
+ fallthrough;
+ case IMX7D:
+ if (dbi_base->start == IMX8MQ_PCIE2_BASE_ADDR)
+--
+2.37.2
+
diff --git a/gnu/packages/patches/linux-libre-mnt-reform-0003-lcdif-fix-pcie-interference.patch b/gnu/packages/patches/linux-libre-mnt-reform-0003-lcdif-fix-pcie-interference.patch
new file mode 100644
index 0000000000..9a3a97e309
--- /dev/null
+++ b/gnu/packages/patches/linux-libre-mnt-reform-0003-lcdif-fix-pcie-interference.patch
@@ -0,0 +1,70 @@
+From bcc4ac93892276613ab6791659ad1418adf5a887 Mon Sep 17 00:00:00 2001
+From: "Lukas F. Hartmann" <lukas@mntre.com>
+Date: Wed, 7 Sep 2022 06:23:35 +0200
+Subject: [PATCH 3/7] lcdif-fix-pcie-interference
+
+---
+ drivers/gpu/drm/mxsfb/mxsfb_kms.c | 34 ++++++++++++++++++++++++++++++-
+ 1 file changed, 33 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/gpu/drm/mxsfb/mxsfb_kms.c b/drivers/gpu/drm/mxsfb/mxsfb_kms.c
+index e38ce57..25f80a6 100644
+--- a/drivers/gpu/drm/mxsfb/mxsfb_kms.c
++++ b/drivers/gpu/drm/mxsfb/mxsfb_kms.c
+@@ -304,7 +304,7 @@ static void mxsfb_crtc_mode_set_nofb(struct mxsfb_drm_private *mxsfb,
+
+ mxsfb_set_formats(mxsfb, bus_format);
+
+- clk_set_rate(mxsfb->clk, m->crtc_clock * 1000);
++ clk_set_rate(mxsfb->clk, m->crtc_clock * 660);
+
+ mxsfb_set_mode(mxsfb, bus_flags);
+ }
+@@ -663,12 +663,44 @@ static const uint64_t mxsfb_modifiers[] = {
+ * Initialization
+ */
+
++void imx8mq_pcie_qos_for_lcdif(void)
++{
++ void __iomem *qosc = ioremap(0x307f0000, 0x2100);
++ // clock and unlock QoSC registers
++ writel(0x0, qosc);
++ writel(0x1, qosc);
++ writel(0x0, qosc+0x60);
++
++ // limit number of outstanding transactions for PCIe1
++ writel(0x0, qosc+0x1000);
++ writel(0x1, qosc+0x1000);
++ writel(0x01010100, qosc+0x1050);
++ writel(0x01010100, qosc+0x1060);
++ writel(0x01010100, qosc+0x1070);
++ writel(0x1, qosc+0x1000);
++
++ // limit number of outstanding transactions for PCIe2
++ writel(0x0, qosc+0x2000);
++ writel(0x1, qosc+0x2000);
++ writel(0x01010100, qosc+0x2050);
++ writel(0x01010100, qosc+0x2060);
++ writel(0x01010100, qosc+0x2070);
++ writel(0x1, qosc+0x2000);
++
++ iounmap(qosc);
++}
++
+ int mxsfb_kms_init(struct mxsfb_drm_private *mxsfb)
+ {
+ struct drm_encoder *encoder = &mxsfb->encoder;
+ struct drm_crtc *crtc = &mxsfb->crtc;
+ int ret;
+
++ /*
++ FIXME Workaround to fix PCIe interfering with LCDIF refresh (MNT Reform)
++ */
++ imx8mq_pcie_qos_for_lcdif();
++
+ drm_plane_helper_add(&mxsfb->planes.primary,
+ &mxsfb_plane_primary_helper_funcs);
+ ret = drm_universal_plane_init(mxsfb->drm, &mxsfb->planes.primary, 1,
+--
+2.37.2
+
diff --git a/gnu/packages/patches/linux-libre-mnt-reform-0004-mnt4002-imx-gpcv2-wake-smccc.patch.patch b/gnu/packages/patches/linux-libre-mnt-reform-0004-mnt4002-imx-gpcv2-wake-smccc.patch.patch
new file mode 100644
index 0000000000..6939d5e92e
--- /dev/null
+++ b/gnu/packages/patches/linux-libre-mnt-reform-0004-mnt4002-imx-gpcv2-wake-smccc.patch.patch
@@ -0,0 +1,94 @@
+From 8bdade8b2e46a32aba6a44ef8814c1f902012fa8 Mon Sep 17 00:00:00 2001
+From: "Lukas F. Hartmann" <lukas@mntre.com>
+Date: Wed, 7 Sep 2022 06:24:04 +0200
+Subject: [PATCH 4/7] mnt4002-imx-gpcv2-wake-smccc.patch
+
+---
+ drivers/irqchip/irq-imx-gpcv2.c | 24 ++++++++++++++++++++++++
+ 1 file changed, 24 insertions(+)
+
+diff --git a/drivers/irqchip/irq-imx-gpcv2.c b/drivers/irqchip/irq-imx-gpcv2.c
+index b9c22f7..4f6d924 100644
+--- a/drivers/irqchip/irq-imx-gpcv2.c
++++ b/drivers/irqchip/irq-imx-gpcv2.c
+@@ -3,6 +3,7 @@
+ * Copyright (C) 2015 Freescale Semiconductor, Inc.
+ */
+
++#include <linux/arm-smccc.h>
+ #include <linux/of_address.h>
+ #include <linux/of_irq.h>
+ #include <linux/slab.h>
+@@ -17,6 +18,13 @@
+ #define GPC_IMR1_CORE2 0x1c0
+ #define GPC_IMR1_CORE3 0x1d0
+
++#define FSL_SIP_GPC 0xC2000000
++#define FSL_SIP_CONFIG_GPC_MASK 0x00
++#define FSL_SIP_CONFIG_GPC_UNMASK 0x01
++#define FSL_SIP_CONFIG_GPC_SET_WAKE 0x02
++#define FSL_SIP_CONFIG_GPC_PM_DOMAIN 0x03
++#define FSL_SIP_CONFIG_GPC_SET_AFF 0x04
++#define FSL_SIP_CONFIG_GPC_CORE_WAKE 0x05
+
+ struct gpcv2_irqchip_data {
+ struct raw_spinlock rlock;
+@@ -76,12 +84,17 @@ static int imx_gpcv2_irq_set_wake(struct irq_data *d, unsigned int on)
+ unsigned int idx = d->hwirq / 32;
+ unsigned long flags;
+ u32 mask, val;
++ struct arm_smccc_res res;
+
+ raw_spin_lock_irqsave(&cd->rlock, flags);
+ mask = BIT(d->hwirq % 32);
+ val = cd->wakeup_sources[idx];
+
+ cd->wakeup_sources[idx] = on ? (val & ~mask) : (val | mask);
++
++ // save wakeup config in vendor tf-a
++ arm_smccc_smc(FSL_SIP_GPC, FSL_SIP_CONFIG_GPC_SET_WAKE, d->hwirq, on, 0, 0, 0, 0, &res);
++
+ raw_spin_unlock_irqrestore(&cd->rlock, flags);
+
+ /*
+@@ -97,6 +110,7 @@ static void imx_gpcv2_irq_unmask(struct irq_data *d)
+ struct gpcv2_irqchip_data *cd = d->chip_data;
+ void __iomem *reg;
+ u32 val;
++ struct arm_smccc_res res;
+
+ raw_spin_lock(&cd->rlock);
+ reg = gpcv2_idx_to_reg(cd, d->hwirq / 32);
+@@ -105,6 +119,10 @@ static void imx_gpcv2_irq_unmask(struct irq_data *d)
+ writel_relaxed(val, reg);
+ raw_spin_unlock(&cd->rlock);
+
++ // call into vendor tf-a
++ //arm_smccc_smc(FSL_SIP_GPC, FSL_SIP_CONFIG_GPC_UNMASK,
++ // d->hwirq, 0, 0, 0, 0, 0, &res);
++
+ irq_chip_unmask_parent(d);
+ }
+
+@@ -113,12 +131,18 @@ static void imx_gpcv2_irq_mask(struct irq_data *d)
+ struct gpcv2_irqchip_data *cd = d->chip_data;
+ void __iomem *reg;
+ u32 val;
++ struct arm_smccc_res res;
+
+ raw_spin_lock(&cd->rlock);
+ reg = gpcv2_idx_to_reg(cd, d->hwirq / 32);
+ val = readl_relaxed(reg);
+ val |= BIT(d->hwirq % 32);
+ writel_relaxed(val, reg);
++
++ // call into vendor tf-a
++ //arm_smccc_smc(FSL_SIP_GPC, FSL_SIP_CONFIG_GPC_MASK,
++ // d->hwirq, 0, 0, 0, 0, 0, &res);
++
+ raw_spin_unlock(&cd->rlock);
+
+ irq_chip_mask_parent(d);
+--
+2.37.2
+
diff --git a/gnu/packages/patches/linux-libre-mnt-reform-0006-drm-bridge-ti-sn65dsi86-fetch-bpc-using-drm_atomic_s.patch b/gnu/packages/patches/linux-libre-mnt-reform-0006-drm-bridge-ti-sn65dsi86-fetch-bpc-using-drm_atomic_s.patch
new file mode 100644
index 0000000000..667e67c178
--- /dev/null
+++ b/gnu/packages/patches/linux-libre-mnt-reform-0006-drm-bridge-ti-sn65dsi86-fetch-bpc-using-drm_atomic_s.patch
@@ -0,0 +1,96 @@
+From 330e2f7b2653315d48729200004f15df5948ec76 Mon Sep 17 00:00:00 2001
+From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Date: Mon, 11 Jul 2022 12:21:16 +0300
+Subject: [PATCH 6/7] drm/bridge: ti-sn65dsi86: fetch bpc using
+ drm_atomic_state
+
+Rather than reading the pdata->connector directly, fetch the connector
+using drm_atomic_state. This allows us to make pdata->connector optional
+(and thus supporting DRM_BRIDGE_ATTACH_NO_CONNECTOR).
+
+Reviewed-by: Sam Ravnborg <sam@ravnborg.org>
+Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+---
+ drivers/gpu/drm/bridge/ti-sn65dsi86.c | 22 ++++++++++++++++------
+ 1 file changed, 16 insertions(+), 6 deletions(-)
+
+diff --git a/drivers/gpu/drm/bridge/ti-sn65dsi86.c b/drivers/gpu/drm/bridge/ti-sn65dsi86.c
+index d6dd4d9..b362a7b 100644
+--- a/drivers/gpu/drm/bridge/ti-sn65dsi86.c
++++ b/drivers/gpu/drm/bridge/ti-sn65dsi86.c
+@@ -779,9 +779,9 @@ static void ti_sn_bridge_set_dsi_rate(struct ti_sn65dsi86 *pdata)
+ regmap_write(pdata->regmap, SN_DSIA_CLK_FREQ_REG, val);
+ }
+
+-static unsigned int ti_sn_bridge_get_bpp(struct ti_sn65dsi86 *pdata)
++static unsigned int ti_sn_bridge_get_bpp(struct drm_connector *connector)
+ {
+- if (pdata->connector->display_info.bpc <= 6)
++ if (connector->display_info.bpc <= 6)
+ return 18;
+ else
+ return 24;
+@@ -796,7 +796,7 @@ static const unsigned int ti_sn_bridge_dp_rate_lut[] = {
+ 0, 1620, 2160, 2430, 2700, 3240, 4320, 5400
+ };
+
+-static int ti_sn_bridge_calc_min_dp_rate_idx(struct ti_sn65dsi86 *pdata)
++static int ti_sn_bridge_calc_min_dp_rate_idx(struct ti_sn65dsi86 *pdata, unsigned int bpp)
+ {
+ unsigned int bit_rate_khz, dp_rate_mhz;
+ unsigned int i;
+@@ -804,7 +804,7 @@ static int ti_sn_bridge_calc_min_dp_rate_idx(struct ti_sn65dsi86 *pdata)
+ &pdata->bridge.encoder->crtc->state->adjusted_mode;
+
+ /* Calculate minimum bit rate based on our pixel clock. */
+- bit_rate_khz = mode->clock * ti_sn_bridge_get_bpp(pdata);
++ bit_rate_khz = mode->clock * bpp;
+
+ /* Calculate minimum DP data rate, taking 80% as per DP spec */
+ dp_rate_mhz = DIV_ROUND_UP(bit_rate_khz * DP_CLK_FUDGE_NUM,
+@@ -1016,12 +1016,21 @@ static void ti_sn_bridge_atomic_enable(struct drm_bridge *bridge,
+ struct drm_bridge_state *old_bridge_state)
+ {
+ struct ti_sn65dsi86 *pdata = bridge_to_ti_sn65dsi86(bridge);
++ struct drm_connector *connector;
+ const char *last_err_str = "No supported DP rate";
+ unsigned int valid_rates;
+ int dp_rate_idx;
+ unsigned int val;
+ int ret = -EINVAL;
+ int max_dp_lanes;
++ unsigned int bpp;
++
++ connector = drm_atomic_get_new_connector_for_encoder(old_bridge_state->base.state,
++ bridge->encoder);
++ if (!connector) {
++ dev_err_ratelimited(pdata->dev, "Could not get the connector\n");
++ return;
++ }
+
+ max_dp_lanes = ti_sn_get_max_lanes(pdata);
+ pdata->dp_lanes = min(pdata->dp_lanes, max_dp_lanes);
+@@ -1047,8 +1056,9 @@ static void ti_sn_bridge_atomic_enable(struct drm_bridge *bridge,
+ drm_dp_dpcd_writeb(&pdata->aux, DP_EDP_CONFIGURATION_SET,
+ DP_ALTERNATE_SCRAMBLER_RESET_ENABLE);
+
++ bpp = ti_sn_bridge_get_bpp(connector);
+ /* Set the DP output format (18 bpp or 24 bpp) */
+- val = (ti_sn_bridge_get_bpp(pdata) == 18) ? BPP_18_RGB : 0;
++ val = bpp == 18 ? BPP_18_RGB : 0;
+ regmap_update_bits(pdata->regmap, SN_DATA_FORMAT_REG, BPP_18_RGB, val);
+
+ /* DP lane config */
+@@ -1059,7 +1069,7 @@ static void ti_sn_bridge_atomic_enable(struct drm_bridge *bridge,
+ valid_rates = ti_sn_bridge_read_valid_rates(pdata);
+
+ /* Train until we run out of rates */
+- for (dp_rate_idx = ti_sn_bridge_calc_min_dp_rate_idx(pdata);
++ for (dp_rate_idx = ti_sn_bridge_calc_min_dp_rate_idx(pdata, bpp);
+ dp_rate_idx < ARRAY_SIZE(ti_sn_bridge_dp_rate_lut);
+ dp_rate_idx++) {
+ if (!(valid_rates & BIT(dp_rate_idx)))
+--
+2.37.2
+
diff --git a/gnu/packages/patches/linux-libre-mnt-reform-0007-drm-bridge-ti-sn65dsi86-support-DRM_BRIDGE_ATTACH_NO.patch b/gnu/packages/patches/linux-libre-mnt-reform-0007-drm-bridge-ti-sn65dsi86-support-DRM_BRIDGE_ATTACH_NO.patch
new file mode 100644
index 0000000000..60e73e01d3
--- /dev/null
+++ b/gnu/packages/patches/linux-libre-mnt-reform-0007-drm-bridge-ti-sn65dsi86-support-DRM_BRIDGE_ATTACH_NO.patch
@@ -0,0 +1,59 @@
+From 3b8da4be82c0ce989303d7bc2077a85a7fd5674a Mon Sep 17 00:00:00 2001
+From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Date: Mon, 11 Jul 2022 12:21:17 +0300
+Subject: [PATCH 7/7] drm/bridge: ti-sn65dsi86: support
+ DRM_BRIDGE_ATTACH_NO_CONNECTOR
+
+Now as the driver does not depend on pdata->connector, add support for
+attaching the bridge with DRM_BRIDGE_ATTACH_NO_CONNECTOR.
+
+Reviewed-by: Sam Ravnborg <sam@ravnborg.org>
+Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+---
+ drivers/gpu/drm/bridge/ti-sn65dsi86.c | 18 ++++++++----------
+ 1 file changed, 8 insertions(+), 10 deletions(-)
+
+diff --git a/drivers/gpu/drm/bridge/ti-sn65dsi86.c b/drivers/gpu/drm/bridge/ti-sn65dsi86.c
+index b362a7b..369bf72 100644
+--- a/drivers/gpu/drm/bridge/ti-sn65dsi86.c
++++ b/drivers/gpu/drm/bridge/ti-sn65dsi86.c
+@@ -698,11 +698,6 @@ static int ti_sn_bridge_attach(struct drm_bridge *bridge,
+ struct ti_sn65dsi86 *pdata = bridge_to_ti_sn65dsi86(bridge);
+ int ret;
+
+- if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR) {
+- DRM_ERROR("Fix bridge driver to make connector optional!");
+- return -EINVAL;
+- }
+-
+ pdata->aux.drm_dev = bridge->dev;
+ ret = drm_dp_aux_register(&pdata->aux);
+ if (ret < 0) {
+@@ -710,15 +705,18 @@ static int ti_sn_bridge_attach(struct drm_bridge *bridge,
+ return ret;
+ }
+
+- /* We never want the next bridge to *also* create a connector: */
+- flags |= DRM_BRIDGE_ATTACH_NO_CONNECTOR;
+-
+- /* Attach the next bridge */
++ /*
++ * Attach the next bridge.
++ * We never want the next bridge to *also* create a connector.
++ */
+ ret = drm_bridge_attach(bridge->encoder, pdata->next_bridge,
+- &pdata->bridge, flags);
++ &pdata->bridge, flags | DRM_BRIDGE_ATTACH_NO_CONNECTOR);
+ if (ret < 0)
+ goto err_initted_aux;
+
++ if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR)
++ return 0;
++
+ pdata->connector = drm_bridge_connector_init(pdata->bridge.dev,
+ pdata->bridge.encoder);
+ if (IS_ERR(pdata->connector)) {
+--
+2.37.2
+