summary refs log tree commit diff
diff options
context:
space:
mode:
-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
+