mirror of
https://github.com/LibreELEC/LibreELEC.tv.git
synced 2025-07-29 13:46:49 +00:00
Merge pull request #7011 from jernejsk/iommu
[LE11] Allwinner: H6: Enable IOMMU
This commit is contained in:
commit
63521869df
@ -37,4 +37,4 @@
|
|||||||
ADDON_PROJECT="ARMv8"
|
ADDON_PROJECT="ARMv8"
|
||||||
|
|
||||||
# additional kernel parameters
|
# additional kernel parameters
|
||||||
EXTRA_CMDLINE="$EXTRA_CMDLINE deferred_probe_timeout=0"
|
EXTRA_CMDLINE="$EXTRA_CMDLINE"
|
||||||
|
@ -4168,7 +4168,7 @@ CONFIG_DRM_PANEL_BRIDGE=y
|
|||||||
# CONFIG_DRM_CDNS_DSI is not set
|
# CONFIG_DRM_CDNS_DSI is not set
|
||||||
# CONFIG_DRM_CHIPONE_ICN6211 is not set
|
# CONFIG_DRM_CHIPONE_ICN6211 is not set
|
||||||
# CONFIG_DRM_CHRONTEL_CH7033 is not set
|
# CONFIG_DRM_CHRONTEL_CH7033 is not set
|
||||||
CONFIG_DRM_DISPLAY_CONNECTOR=y
|
# CONFIG_DRM_DISPLAY_CONNECTOR is not set
|
||||||
# CONFIG_DRM_ITE_IT6505 is not set
|
# CONFIG_DRM_ITE_IT6505 is not set
|
||||||
# CONFIG_DRM_LONTIUM_LT8912B is not set
|
# CONFIG_DRM_LONTIUM_LT8912B is not set
|
||||||
# CONFIG_DRM_LONTIUM_LT9211 is not set
|
# CONFIG_DRM_LONTIUM_LT9211 is not set
|
||||||
@ -5474,7 +5474,7 @@ CONFIG_IOMMU_DEFAULT_DMA_STRICT=y
|
|||||||
# CONFIG_IOMMU_DEFAULT_PASSTHROUGH is not set
|
# CONFIG_IOMMU_DEFAULT_PASSTHROUGH is not set
|
||||||
CONFIG_OF_IOMMU=y
|
CONFIG_OF_IOMMU=y
|
||||||
CONFIG_IOMMU_DMA=y
|
CONFIG_IOMMU_DMA=y
|
||||||
# CONFIG_SUN50I_IOMMU is not set
|
CONFIG_SUN50I_IOMMU=y
|
||||||
# CONFIG_ARM_SMMU is not set
|
# CONFIG_ARM_SMMU is not set
|
||||||
# CONFIG_ARM_SMMU_V3 is not set
|
# CONFIG_ARM_SMMU_V3 is not set
|
||||||
|
|
||||||
|
@ -47,7 +47,7 @@ Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
|
|||||||
+obj-$(CONFIG_VIDEO_SUN50I_DEINTERLACE) += sun50i-di.o
|
+obj-$(CONFIG_VIDEO_SUN50I_DEINTERLACE) += sun50i-di.o
|
||||||
--- /dev/null
|
--- /dev/null
|
||||||
+++ b/drivers/media/platform/sunxi/sun50i-di/sun50i-di.c
|
+++ b/drivers/media/platform/sunxi/sun50i-di/sun50i-di.c
|
||||||
@@ -0,0 +1,1134 @@
|
@@ -0,0 +1,1137 @@
|
||||||
+// SPDX-License-Identifier: GPL-2.0
|
+// SPDX-License-Identifier: GPL-2.0
|
||||||
+/*
|
+/*
|
||||||
+ * Allwinner sun50i deinterlacer driver
|
+ * Allwinner sun50i deinterlacer driver
|
||||||
@ -137,6 +137,9 @@ Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
|
|||||||
+ deinterlace_write(dev, DEINTERLACE_OUT_FLAG_ADDR, ctx->flag2_buf_dma);
|
+ deinterlace_write(dev, DEINTERLACE_OUT_FLAG_ADDR, ctx->flag2_buf_dma);
|
||||||
+ deinterlace_write(dev, DEINTERLACE_FLAG_ADDRH, 0);
|
+ deinterlace_write(dev, DEINTERLACE_FLAG_ADDRH, 0);
|
||||||
+ deinterlace_write(dev, DEINTERLACE_FLAG_PITCH, 0x200);
|
+ deinterlace_write(dev, DEINTERLACE_FLAG_PITCH, 0x200);
|
||||||
|
+ if (device_iommu_mapped(dev->dev))
|
||||||
|
+ deinterlace_set_bits(dev, DEINTERLACE_CTRL,
|
||||||
|
+ DEINTERLACE_CTRL_IOMMU_EN);
|
||||||
+
|
+
|
||||||
+ width = ctx->src_fmt.width;
|
+ width = ctx->src_fmt.width;
|
||||||
+ height = ctx->src_fmt.height;
|
+ height = ctx->src_fmt.height;
|
||||||
|
@ -10,10 +10,10 @@ Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
|
|||||||
|
|
||||||
--- a/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi
|
--- a/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi
|
||||||
+++ b/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi
|
+++ b/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi
|
||||||
@@ -160,6 +160,17 @@
|
@@ -160,6 +160,18 @@
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
+ deinterlace: deinterlace@1420000 {
|
+ deinterlace: deinterlace@1420000 {
|
||||||
+ compatible = "allwinner,sun50i-h6-deinterlace";
|
+ compatible = "allwinner,sun50i-h6-deinterlace";
|
||||||
+ reg = <0x01420000 0x2000>;
|
+ reg = <0x01420000 0x2000>;
|
||||||
@ -23,6 +23,7 @@ Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
|
|||||||
+ clock-names = "bus", "mod", "ram";
|
+ clock-names = "bus", "mod", "ram";
|
||||||
+ resets = <&ccu RST_BUS_DEINTERLACE>;
|
+ resets = <&ccu RST_BUS_DEINTERLACE>;
|
||||||
+ interrupts = <GIC_SPI 79 IRQ_TYPE_LEVEL_HIGH>;
|
+ interrupts = <GIC_SPI 79 IRQ_TYPE_LEVEL_HIGH>;
|
||||||
|
+ iommus = <&iommu 2>;
|
||||||
+ };
|
+ };
|
||||||
+
|
+
|
||||||
video-codec@1c0e000 {
|
video-codec@1c0e000 {
|
||||||
|
@ -0,0 +1,26 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Jernej Skrabec <jernej.skrabec@gmail.com>
|
||||||
|
Date: Wed, 12 Oct 2022 23:01:04 +0200
|
||||||
|
Subject: [PATCH] arm64: dts: allwinner: h6: Fix Cedrus IOMMU, again
|
||||||
|
|
||||||
|
Cedrus actually uses two IOMMU channels. Add the second one.
|
||||||
|
|
||||||
|
Fixes: 62a8ccf3a248 ("arm64: dts: allwinner: h6: Fix Cedrus IOMMU usage")
|
||||||
|
Signed-off-by: Jernej Skrabec <jernej.skrabec@gmail.com>
|
||||||
|
---
|
||||||
|
arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi | 2 +-
|
||||||
|
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi
|
||||||
|
index e897559d9a89..436cc2a02d1a 100644
|
||||||
|
--- a/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi
|
||||||
|
+++ b/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi
|
||||||
|
@@ -172,7 +172,7 @@ video-codec@1c0e000 {
|
||||||
|
resets = <&ccu RST_BUS_VE>;
|
||||||
|
interrupts = <GIC_SPI 89 IRQ_TYPE_LEVEL_HIGH>;
|
||||||
|
allwinner,sram = <&ve_sram 1>;
|
||||||
|
- iommus = <&iommu 3>;
|
||||||
|
+ iommus = <&iommu 1>, <&iommu 3>;
|
||||||
|
};
|
||||||
|
|
||||||
|
gpu: gpu@1800000 {
|
@ -0,0 +1,24 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Jernej Skrabec <jernej.skrabec@gmail.com>
|
||||||
|
Date: Wed, 12 Oct 2022 22:59:29 +0200
|
||||||
|
Subject: [PATCH] arm64: dts: allwinner: h6: Add Hantro G2 IOMMU phandle
|
||||||
|
|
||||||
|
Hantro G2 is connected to IOMMU. Add a phandle to it.
|
||||||
|
|
||||||
|
Signed-off-by: Jernej Skrabec <jernej.skrabec@gmail.com>
|
||||||
|
---
|
||||||
|
arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi | 1 +
|
||||||
|
1 file changed, 1 insertion(+)
|
||||||
|
|
||||||
|
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi
|
||||||
|
index 436cc2a02d1a..d189ce4ebe37 100644
|
||||||
|
--- a/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi
|
||||||
|
+++ b/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi
|
||||||
|
@@ -161,6 +161,7 @@ video-codec-g2@1c00000 {
|
||||||
|
clocks = <&ccu CLK_BUS_VP9>, <&ccu CLK_VP9>;
|
||||||
|
clock-names = "bus", "mod";
|
||||||
|
resets = <&ccu RST_BUS_VP9>;
|
||||||
|
+ iommus = <&iommu 5>;
|
||||||
|
};
|
||||||
|
|
||||||
|
video-codec@1c0e000 {
|
@ -0,0 +1,44 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Jernej Skrabec <jernej.skrabec@gmail.com>
|
||||||
|
Date: Wed, 12 Oct 2022 21:10:47 +0200
|
||||||
|
Subject: [PATCH] iommu/sun50i: Fix reset release
|
||||||
|
|
||||||
|
Reset signal is asserted by writing 0 to the corresponding locations of
|
||||||
|
masters we want to reset. So in order to deassert all reset signals, we
|
||||||
|
should write 1's to all locations.
|
||||||
|
|
||||||
|
Current code writes 1's to locations of masters which were just reset
|
||||||
|
which is good. However, at the same time it also writes 0's to other
|
||||||
|
locations and thus asserts reset signals of remaining masters. Fix code
|
||||||
|
by writing all 1's when we want to deassert all reset signals.
|
||||||
|
|
||||||
|
This bug was discovered when working with Cedrus (video decoder). When
|
||||||
|
it faulted, display went blank due to reset signal assertion.
|
||||||
|
|
||||||
|
Fixes: 4100b8c229b3 ("iommu: Add Allwinner H6 IOMMU driver")
|
||||||
|
Signed-off-by: Jernej Skrabec <jernej.skrabec@gmail.com>
|
||||||
|
---
|
||||||
|
drivers/iommu/sun50i-iommu.c | 3 ++-
|
||||||
|
1 file changed, 2 insertions(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/drivers/iommu/sun50i-iommu.c b/drivers/iommu/sun50i-iommu.c
|
||||||
|
index a84c63518773..c777882d0ec2 100644
|
||||||
|
--- a/drivers/iommu/sun50i-iommu.c
|
||||||
|
+++ b/drivers/iommu/sun50i-iommu.c
|
||||||
|
@@ -27,6 +27,7 @@
|
||||||
|
#include <linux/types.h>
|
||||||
|
|
||||||
|
#define IOMMU_RESET_REG 0x010
|
||||||
|
+#define IOMMU_RESET_RELEASE_ALL 0xffffffff
|
||||||
|
#define IOMMU_ENABLE_REG 0x020
|
||||||
|
#define IOMMU_ENABLE_ENABLE BIT(0)
|
||||||
|
|
||||||
|
@@ -893,7 +894,7 @@ static irqreturn_t sun50i_iommu_irq(int irq, void *dev_id)
|
||||||
|
iommu_write(iommu, IOMMU_INT_CLR_REG, status);
|
||||||
|
|
||||||
|
iommu_write(iommu, IOMMU_RESET_REG, ~status);
|
||||||
|
- iommu_write(iommu, IOMMU_RESET_REG, status);
|
||||||
|
+ iommu_write(iommu, IOMMU_RESET_REG, IOMMU_RESET_RELEASE_ALL);
|
||||||
|
|
||||||
|
spin_unlock(&iommu->iommu_lock);
|
||||||
|
|
@ -0,0 +1,50 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Jernej Skrabec <jernej.skrabec@gmail.com>
|
||||||
|
Date: Wed, 12 Oct 2022 22:46:32 +0200
|
||||||
|
Subject: [PATCH] iommu/sun50i: Consider all fault sources for reset
|
||||||
|
|
||||||
|
We have to reset masters for all faults - permissions, L1 fault or L2
|
||||||
|
fault. Currently it's done only for permissions. If other type of fault
|
||||||
|
happens, master is in locked up state. Fix that by really considering
|
||||||
|
all fault sources.
|
||||||
|
|
||||||
|
Fixes: 4100b8c229b3 ("iommu: Add Allwinner H6 IOMMU driver")
|
||||||
|
Signed-off-by: Jernej Skrabec <jernej.skrabec@gmail.com>
|
||||||
|
---
|
||||||
|
drivers/iommu/sun50i-iommu.c | 8 ++++++--
|
||||||
|
1 file changed, 6 insertions(+), 2 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/drivers/iommu/sun50i-iommu.c b/drivers/iommu/sun50i-iommu.c
|
||||||
|
index c777882d0ec2..38d1069cf383 100644
|
||||||
|
--- a/drivers/iommu/sun50i-iommu.c
|
||||||
|
+++ b/drivers/iommu/sun50i-iommu.c
|
||||||
|
@@ -869,8 +869,8 @@ static phys_addr_t sun50i_iommu_handle_perm_irq(struct sun50i_iommu *iommu)
|
||||||
|
|
||||||
|
static irqreturn_t sun50i_iommu_irq(int irq, void *dev_id)
|
||||||
|
{
|
||||||
|
+ u32 status, l1_status, l2_status, resets;
|
||||||
|
struct sun50i_iommu *iommu = dev_id;
|
||||||
|
- u32 status;
|
||||||
|
|
||||||
|
spin_lock(&iommu->iommu_lock);
|
||||||
|
|
||||||
|
@@ -880,6 +880,9 @@ static irqreturn_t sun50i_iommu_irq(int irq, void *dev_id)
|
||||||
|
return IRQ_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ l1_status = iommu_read(iommu, IOMMU_L1PG_INT_REG);
|
||||||
|
+ l2_status = iommu_read(iommu, IOMMU_L2PG_INT_REG);
|
||||||
|
+
|
||||||
|
if (status & IOMMU_INT_INVALID_L2PG)
|
||||||
|
sun50i_iommu_handle_pt_irq(iommu,
|
||||||
|
IOMMU_INT_ERR_ADDR_L2_REG,
|
||||||
|
@@ -893,7 +896,8 @@ static irqreturn_t sun50i_iommu_irq(int irq, void *dev_id)
|
||||||
|
|
||||||
|
iommu_write(iommu, IOMMU_INT_CLR_REG, status);
|
||||||
|
|
||||||
|
- iommu_write(iommu, IOMMU_RESET_REG, ~status);
|
||||||
|
+ resets = (status | l1_status | l2_status) & IOMMU_INT_MASTER_MASK;
|
||||||
|
+ iommu_write(iommu, IOMMU_RESET_REG, ~resets);
|
||||||
|
iommu_write(iommu, IOMMU_RESET_REG, IOMMU_RESET_RELEASE_ALL);
|
||||||
|
|
||||||
|
spin_unlock(&iommu->iommu_lock);
|
@ -0,0 +1,33 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Jernej Skrabec <jernej.skrabec@gmail.com>
|
||||||
|
Date: Wed, 12 Oct 2022 21:24:03 +0200
|
||||||
|
Subject: [PATCH] iommu/sun50i: Fix R/W permission check
|
||||||
|
|
||||||
|
Because driver has enum type permissions and iommu subsystem has bitmap
|
||||||
|
type, we have to be careful how check for combined read and write
|
||||||
|
permissions is done. In such case, we have to mask both permissions and
|
||||||
|
check that both are set at the same time.
|
||||||
|
|
||||||
|
Current code just masks both flags but doesn't check that both are set.
|
||||||
|
In short, it always sets R/W permission, regardles if requested
|
||||||
|
permissions were RO, WO or RW. Fix that.
|
||||||
|
|
||||||
|
Fixes: 4100b8c229b3 ("iommu: Add Allwinner H6 IOMMU driver")
|
||||||
|
Signed-off-by: Jernej Skrabec <jernej.skrabec@gmail.com>
|
||||||
|
---
|
||||||
|
drivers/iommu/sun50i-iommu.c | 2 +-
|
||||||
|
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/drivers/iommu/sun50i-iommu.c b/drivers/iommu/sun50i-iommu.c
|
||||||
|
index 38d1069cf383..135df6934a9e 100644
|
||||||
|
--- a/drivers/iommu/sun50i-iommu.c
|
||||||
|
+++ b/drivers/iommu/sun50i-iommu.c
|
||||||
|
@@ -271,7 +271,7 @@ static u32 sun50i_mk_pte(phys_addr_t page, int prot)
|
||||||
|
enum sun50i_iommu_aci aci;
|
||||||
|
u32 flags = 0;
|
||||||
|
|
||||||
|
- if (prot & (IOMMU_READ | IOMMU_WRITE))
|
||||||
|
+ if ((prot & (IOMMU_READ | IOMMU_WRITE)) == (IOMMU_READ | IOMMU_WRITE))
|
||||||
|
aci = SUN50I_IOMMU_ACI_RD_WR;
|
||||||
|
else if (prot & IOMMU_READ)
|
||||||
|
aci = SUN50I_IOMMU_ACI_RD;
|
@ -0,0 +1,27 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Jernej Skrabec <jernej.skrabec@gmail.com>
|
||||||
|
Date: Wed, 12 Oct 2022 21:35:53 +0200
|
||||||
|
Subject: [PATCH] iommu/sun50i: Fix flush size
|
||||||
|
|
||||||
|
Function sun50i_table_flush() takes number of entries as an argument,
|
||||||
|
not number of bytes. Fix that mistake in sun50i_dte_get_page_table().
|
||||||
|
|
||||||
|
Fixes: 4100b8c229b3 ("iommu: Add Allwinner H6 IOMMU driver")
|
||||||
|
Signed-off-by: Jernej Skrabec <jernej.skrabec@gmail.com>
|
||||||
|
---
|
||||||
|
drivers/iommu/sun50i-iommu.c | 2 +-
|
||||||
|
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/drivers/iommu/sun50i-iommu.c b/drivers/iommu/sun50i-iommu.c
|
||||||
|
index 135df6934a9e..7c3b2ac552da 100644
|
||||||
|
--- a/drivers/iommu/sun50i-iommu.c
|
||||||
|
+++ b/drivers/iommu/sun50i-iommu.c
|
||||||
|
@@ -512,7 +512,7 @@ static u32 *sun50i_dte_get_page_table(struct sun50i_iommu_domain *sun50i_domain,
|
||||||
|
sun50i_iommu_free_page_table(iommu, drop_pt);
|
||||||
|
}
|
||||||
|
|
||||||
|
- sun50i_table_flush(sun50i_domain, page_table, PT_SIZE);
|
||||||
|
+ sun50i_table_flush(sun50i_domain, page_table, NUM_PT_ENTRIES);
|
||||||
|
sun50i_table_flush(sun50i_domain, dte_addr, 1);
|
||||||
|
|
||||||
|
return page_table;
|
@ -0,0 +1,133 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Jernej Skrabec <jernej.skrabec@gmail.com>
|
||||||
|
Date: Wed, 12 Oct 2022 21:55:27 +0200
|
||||||
|
Subject: [PATCH] iommu/sun50i: Implement .iotlb_sync_map
|
||||||
|
|
||||||
|
Allocated iova ranges need to be invalidated immediately or otherwise
|
||||||
|
they might or might not work when used by master or CPU. This was
|
||||||
|
discovered when running video decoder conformity test with Cedrus. Some
|
||||||
|
videos were now and then decoded incorrectly and generated page faults.
|
||||||
|
|
||||||
|
According to vendor driver, it's enough to invalidate just start and end
|
||||||
|
TLB and PTW cache lines. Documentation says that neighbouring lines must
|
||||||
|
be invalidated too. Finally, when page fault occurs, that iova must be
|
||||||
|
invalidated the same way, according to documentation.
|
||||||
|
|
||||||
|
Fixes: 4100b8c229b3 ("iommu: Add Allwinner H6 IOMMU driver")
|
||||||
|
Signed-off-by: Jernej Skrabec <jernej.skrabec@gmail.com>
|
||||||
|
---
|
||||||
|
drivers/iommu/sun50i-iommu.c | 73 ++++++++++++++++++++++++++++++++++++
|
||||||
|
1 file changed, 73 insertions(+)
|
||||||
|
|
||||||
|
diff --git a/drivers/iommu/sun50i-iommu.c b/drivers/iommu/sun50i-iommu.c
|
||||||
|
index 7c3b2ac552da..d7c5e9b1a087 100644
|
||||||
|
--- a/drivers/iommu/sun50i-iommu.c
|
||||||
|
+++ b/drivers/iommu/sun50i-iommu.c
|
||||||
|
@@ -93,6 +93,8 @@
|
||||||
|
#define NUM_PT_ENTRIES 256
|
||||||
|
#define PT_SIZE (NUM_PT_ENTRIES * PT_ENTRY_SIZE)
|
||||||
|
|
||||||
|
+#define SPAGE_SIZE 4096
|
||||||
|
+
|
||||||
|
struct sun50i_iommu {
|
||||||
|
struct iommu_device iommu;
|
||||||
|
|
||||||
|
@@ -295,6 +297,62 @@ static void sun50i_table_flush(struct sun50i_iommu_domain *sun50i_domain,
|
||||||
|
dma_sync_single_for_device(iommu->dev, dma, size, DMA_TO_DEVICE);
|
||||||
|
}
|
||||||
|
|
||||||
|
+static void sun50i_iommu_zap_iova(struct sun50i_iommu *iommu,
|
||||||
|
+ unsigned long iova)
|
||||||
|
+{
|
||||||
|
+ u32 reg;
|
||||||
|
+ int ret;
|
||||||
|
+
|
||||||
|
+ iommu_write(iommu, IOMMU_TLB_IVLD_ADDR_REG, iova);
|
||||||
|
+ iommu_write(iommu, IOMMU_TLB_IVLD_ADDR_MASK_REG, GENMASK(31, 12));
|
||||||
|
+ iommu_write(iommu, IOMMU_TLB_IVLD_ENABLE_REG,
|
||||||
|
+ IOMMU_TLB_IVLD_ENABLE_ENABLE);
|
||||||
|
+
|
||||||
|
+ ret = readl_poll_timeout_atomic(iommu->base + IOMMU_TLB_IVLD_ENABLE_REG,
|
||||||
|
+ reg, !reg, 1, 2000);
|
||||||
|
+ if (ret)
|
||||||
|
+ dev_warn(iommu->dev, "TLB invalidation timed out!\n");
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void sun50i_iommu_zap_ptw_cache(struct sun50i_iommu *iommu,
|
||||||
|
+ unsigned long iova)
|
||||||
|
+{
|
||||||
|
+ u32 reg;
|
||||||
|
+ int ret;
|
||||||
|
+
|
||||||
|
+ iommu_write(iommu, IOMMU_PC_IVLD_ADDR_REG, iova);
|
||||||
|
+ iommu_write(iommu, IOMMU_PC_IVLD_ENABLE_REG,
|
||||||
|
+ IOMMU_PC_IVLD_ENABLE_ENABLE);
|
||||||
|
+
|
||||||
|
+ ret = readl_poll_timeout_atomic(iommu->base + IOMMU_PC_IVLD_ENABLE_REG,
|
||||||
|
+ reg, !reg, 1, 2000);
|
||||||
|
+ if (ret)
|
||||||
|
+ dev_warn(iommu->dev, "PTW cache invalidation timed out!\n");
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void sun50i_iommu_zap_range(struct sun50i_iommu *iommu,
|
||||||
|
+ unsigned long iova, size_t size)
|
||||||
|
+{
|
||||||
|
+ assert_spin_locked(&iommu->iommu_lock);
|
||||||
|
+
|
||||||
|
+ iommu_write(iommu, IOMMU_AUTO_GATING_REG, 0);
|
||||||
|
+
|
||||||
|
+ sun50i_iommu_zap_iova(iommu, iova);
|
||||||
|
+ sun50i_iommu_zap_iova(iommu, iova + SPAGE_SIZE);
|
||||||
|
+ if (size > SPAGE_SIZE) {
|
||||||
|
+ sun50i_iommu_zap_iova(iommu, iova + size);
|
||||||
|
+ sun50i_iommu_zap_iova(iommu, iova + size + SPAGE_SIZE);
|
||||||
|
+ }
|
||||||
|
+ sun50i_iommu_zap_ptw_cache(iommu, iova);
|
||||||
|
+ sun50i_iommu_zap_ptw_cache(iommu, iova + SZ_1M);
|
||||||
|
+ if (size > SZ_1M) {
|
||||||
|
+ sun50i_iommu_zap_ptw_cache(iommu, iova + size);
|
||||||
|
+ sun50i_iommu_zap_ptw_cache(iommu, iova + size + SZ_1M);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ iommu_write(iommu, IOMMU_AUTO_GATING_REG, IOMMU_AUTO_GATING_ENABLE);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
static int sun50i_iommu_flush_all_tlb(struct sun50i_iommu *iommu)
|
||||||
|
{
|
||||||
|
u32 reg;
|
||||||
|
@@ -344,6 +402,18 @@ static void sun50i_iommu_flush_iotlb_all(struct iommu_domain *domain)
|
||||||
|
spin_unlock_irqrestore(&iommu->iommu_lock, flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
+static void sun50i_iommu_iotlb_sync_map(struct iommu_domain *domain,
|
||||||
|
+ unsigned long iova, size_t size)
|
||||||
|
+{
|
||||||
|
+ struct sun50i_iommu_domain *sun50i_domain = to_sun50i_domain(domain);
|
||||||
|
+ struct sun50i_iommu *iommu = sun50i_domain->iommu;
|
||||||
|
+ unsigned long flags;
|
||||||
|
+
|
||||||
|
+ spin_lock_irqsave(&iommu->iommu_lock, flags);
|
||||||
|
+ sun50i_iommu_zap_range(iommu, iova, size);
|
||||||
|
+ spin_unlock_irqrestore(&iommu->iommu_lock, flags);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
static void sun50i_iommu_iotlb_sync(struct iommu_domain *domain,
|
||||||
|
struct iommu_iotlb_gather *gather)
|
||||||
|
{
|
||||||
|
@@ -767,6 +837,7 @@ static const struct iommu_ops sun50i_iommu_ops = {
|
||||||
|
.attach_dev = sun50i_iommu_attach_device,
|
||||||
|
.detach_dev = sun50i_iommu_detach_device,
|
||||||
|
.flush_iotlb_all = sun50i_iommu_flush_iotlb_all,
|
||||||
|
+ .iotlb_sync_map = sun50i_iommu_iotlb_sync_map,
|
||||||
|
.iotlb_sync = sun50i_iommu_iotlb_sync,
|
||||||
|
.iova_to_phys = sun50i_iommu_iova_to_phys,
|
||||||
|
.map = sun50i_iommu_map,
|
||||||
|
@@ -786,6 +857,8 @@ static void sun50i_iommu_report_fault(struct sun50i_iommu *iommu,
|
||||||
|
report_iommu_fault(iommu->domain, iommu->dev, iova, prot);
|
||||||
|
else
|
||||||
|
dev_err(iommu->dev, "Page fault while iommu not attached to any domain?\n");
|
||||||
|
+
|
||||||
|
+ sun50i_iommu_zap_range(iommu, iova, SPAGE_SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
static phys_addr_t sun50i_iommu_handle_pt_irq(struct sun50i_iommu *iommu,
|
@ -0,0 +1,107 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Jernej Skrabec <jernej.skrabec@gmail.com>
|
||||||
|
Date: Fri, 14 Oct 2022 20:15:43 +0200
|
||||||
|
Subject: [PATCH] iommu/sun50i: Allow page sizes multiple of 4096
|
||||||
|
|
||||||
|
While peripheral supports only 4K page sizes, we can easily emulate
|
||||||
|
support for bigger page sizes, up to 1M. This is done by making multiple
|
||||||
|
entries in map function or clearing multiple entries in unmap.
|
||||||
|
|
||||||
|
This considerably lowers overhead.
|
||||||
|
|
||||||
|
Signed-off-by: Jernej Skrabec <jernej.skrabec@gmail.com>
|
||||||
|
---
|
||||||
|
drivers/iommu/sun50i-iommu.c | 44 +++++++++++++++++++++---------------
|
||||||
|
1 file changed, 26 insertions(+), 18 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/drivers/iommu/sun50i-iommu.c b/drivers/iommu/sun50i-iommu.c
|
||||||
|
index d7c5e9b1a087..9944266c4f58 100644
|
||||||
|
--- a/drivers/iommu/sun50i-iommu.c
|
||||||
|
+++ b/drivers/iommu/sun50i-iommu.c
|
||||||
|
@@ -593,10 +593,12 @@ static int sun50i_iommu_map(struct iommu_domain *domain, unsigned long iova,
|
||||||
|
{
|
||||||
|
struct sun50i_iommu_domain *sun50i_domain = to_sun50i_domain(domain);
|
||||||
|
struct sun50i_iommu *iommu = sun50i_domain->iommu;
|
||||||
|
- u32 pte_index;
|
||||||
|
+ u32 pte_index, pages, i;
|
||||||
|
u32 *page_table, *pte_addr;
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
+ pages = size / SPAGE_SIZE;
|
||||||
|
+
|
||||||
|
page_table = sun50i_dte_get_page_table(sun50i_domain, iova, gfp);
|
||||||
|
if (IS_ERR(page_table)) {
|
||||||
|
ret = PTR_ERR(page_table);
|
||||||
|
@@ -604,18 +606,21 @@ static int sun50i_iommu_map(struct iommu_domain *domain, unsigned long iova,
|
||||||
|
}
|
||||||
|
|
||||||
|
pte_index = sun50i_iova_get_pte_index(iova);
|
||||||
|
- pte_addr = &page_table[pte_index];
|
||||||
|
- if (unlikely(sun50i_pte_is_page_valid(*pte_addr))) {
|
||||||
|
- phys_addr_t page_phys = sun50i_pte_get_page_address(*pte_addr);
|
||||||
|
- dev_err(iommu->dev,
|
||||||
|
- "iova %pad already mapped to %pa cannot remap to %pa prot: %#x\n",
|
||||||
|
- &iova, &page_phys, &paddr, prot);
|
||||||
|
- ret = -EBUSY;
|
||||||
|
- goto out;
|
||||||
|
+ for (i = 0; i < pages; i++) {
|
||||||
|
+ pte_addr = &page_table[pte_index + i];
|
||||||
|
+ if (unlikely(sun50i_pte_is_page_valid(*pte_addr))) {
|
||||||
|
+ phys_addr_t page_phys = sun50i_pte_get_page_address(*pte_addr);
|
||||||
|
+ dev_err(iommu->dev,
|
||||||
|
+ "iova %pad already mapped to %pa cannot remap to %pa prot: %#x\n",
|
||||||
|
+ &iova, &page_phys, &paddr, prot);
|
||||||
|
+ ret = -EBUSY;
|
||||||
|
+ goto out;
|
||||||
|
+ }
|
||||||
|
+ *pte_addr = sun50i_mk_pte(paddr, prot);
|
||||||
|
+ paddr += SPAGE_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
- *pte_addr = sun50i_mk_pte(paddr, prot);
|
||||||
|
- sun50i_table_flush(sun50i_domain, pte_addr, 1);
|
||||||
|
+ sun50i_table_flush(sun50i_domain, &page_table[pte_index], pages);
|
||||||
|
|
||||||
|
out:
|
||||||
|
return ret;
|
||||||
|
@@ -626,8 +631,10 @@ static size_t sun50i_iommu_unmap(struct iommu_domain *domain, unsigned long iova
|
||||||
|
{
|
||||||
|
struct sun50i_iommu_domain *sun50i_domain = to_sun50i_domain(domain);
|
||||||
|
phys_addr_t pt_phys;
|
||||||
|
+ u32 dte, pages, i;
|
||||||
|
u32 *pte_addr;
|
||||||
|
- u32 dte;
|
||||||
|
+
|
||||||
|
+ pages = size / SPAGE_SIZE;
|
||||||
|
|
||||||
|
dte = sun50i_domain->dt[sun50i_iova_get_dte_index(iova)];
|
||||||
|
if (!sun50i_dte_is_pt_valid(dte))
|
||||||
|
@@ -636,13 +643,14 @@ static size_t sun50i_iommu_unmap(struct iommu_domain *domain, unsigned long iova
|
||||||
|
pt_phys = sun50i_dte_get_pt_address(dte);
|
||||||
|
pte_addr = (u32 *)phys_to_virt(pt_phys) + sun50i_iova_get_pte_index(iova);
|
||||||
|
|
||||||
|
- if (!sun50i_pte_is_page_valid(*pte_addr))
|
||||||
|
- return 0;
|
||||||
|
+ for (i = 0; i < pages; i++)
|
||||||
|
+ if (!sun50i_pte_is_page_valid(pte_addr[i]))
|
||||||
|
+ return 0;
|
||||||
|
|
||||||
|
- memset(pte_addr, 0, sizeof(*pte_addr));
|
||||||
|
- sun50i_table_flush(sun50i_domain, pte_addr, 1);
|
||||||
|
+ memset(pte_addr, 0, sizeof(*pte_addr) * pages);
|
||||||
|
+ sun50i_table_flush(sun50i_domain, pte_addr, pages);
|
||||||
|
|
||||||
|
- return SZ_4K;
|
||||||
|
+ return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
static phys_addr_t sun50i_iommu_iova_to_phys(struct iommu_domain *domain,
|
||||||
|
@@ -828,7 +836,7 @@ static int sun50i_iommu_of_xlate(struct device *dev,
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct iommu_ops sun50i_iommu_ops = {
|
||||||
|
- .pgsize_bitmap = SZ_4K,
|
||||||
|
+ .pgsize_bitmap = 0x1ff000,
|
||||||
|
.device_group = sun50i_iommu_device_group,
|
||||||
|
.domain_alloc = sun50i_iommu_domain_alloc,
|
||||||
|
.of_xlate = sun50i_iommu_of_xlate,
|
@ -0,0 +1,61 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Jernej Skrabec <jernej.skrabec@gmail.com>
|
||||||
|
Date: Sat, 15 Oct 2022 10:43:41 +0200
|
||||||
|
Subject: [PATCH] media: Unify YCbCr/YUV terms in format descriptions
|
||||||
|
|
||||||
|
Format descriptions use YCbCr and YUV terms interchangeably. Let's unify
|
||||||
|
them so they all use YUV. While YCbCr is actually correct term here, YUV
|
||||||
|
is shorter and thus it also fixes too long description of P010 tiled
|
||||||
|
format.
|
||||||
|
|
||||||
|
Fixes: 3c8e19d3d3f9 ("media: Add P010 tiled format")
|
||||||
|
Signed-off-by: Jernej Skrabec <jernej.skrabec@gmail.com>
|
||||||
|
---
|
||||||
|
drivers/media/v4l2-core/v4l2-ioctl.c | 34 ++++++++++++++--------------
|
||||||
|
1 file changed, 17 insertions(+), 17 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c b/drivers/media/v4l2-core/v4l2-ioctl.c
|
||||||
|
index e6fd355a2e92..de83714f0d40 100644
|
||||||
|
--- a/drivers/media/v4l2-core/v4l2-ioctl.c
|
||||||
|
+++ b/drivers/media/v4l2-core/v4l2-ioctl.c
|
||||||
|
@@ -1347,23 +1347,23 @@ static void v4l_fill_fmtdesc(struct v4l2_fmtdesc *fmt)
|
||||||
|
case V4L2_PIX_FMT_YUV420: descr = "Planar YUV 4:2:0"; break;
|
||||||
|
case V4L2_PIX_FMT_HI240: descr = "8-bit Dithered RGB (BTTV)"; break;
|
||||||
|
case V4L2_PIX_FMT_M420: descr = "YUV 4:2:0 (M420)"; break;
|
||||||
|
- case V4L2_PIX_FMT_NV12: descr = "Y/CbCr 4:2:0"; break;
|
||||||
|
- case V4L2_PIX_FMT_NV21: descr = "Y/CrCb 4:2:0"; break;
|
||||||
|
- case V4L2_PIX_FMT_NV16: descr = "Y/CbCr 4:2:2"; break;
|
||||||
|
- case V4L2_PIX_FMT_NV61: descr = "Y/CrCb 4:2:2"; break;
|
||||||
|
- case V4L2_PIX_FMT_NV24: descr = "Y/CbCr 4:4:4"; break;
|
||||||
|
- case V4L2_PIX_FMT_NV42: descr = "Y/CrCb 4:4:4"; break;
|
||||||
|
- case V4L2_PIX_FMT_P010: descr = "10-bit Y/CbCr 4:2:0"; break;
|
||||||
|
- case V4L2_PIX_FMT_NV12_4L4: descr = "Y/CbCr 4:2:0 (4x4 Linear)"; break;
|
||||||
|
- case V4L2_PIX_FMT_NV12_16L16: descr = "Y/CbCr 4:2:0 (16x16 Linear)"; break;
|
||||||
|
- case V4L2_PIX_FMT_NV12_32L32: descr = "Y/CbCr 4:2:0 (32x32 Linear)"; break;
|
||||||
|
- case V4L2_PIX_FMT_P010_4L4: descr = "10-bit Y/CbCr 4:2:0 (4x4 Linear)"; break;
|
||||||
|
- case V4L2_PIX_FMT_NV12M: descr = "Y/CbCr 4:2:0 (N-C)"; break;
|
||||||
|
- case V4L2_PIX_FMT_NV21M: descr = "Y/CrCb 4:2:0 (N-C)"; break;
|
||||||
|
- case V4L2_PIX_FMT_NV16M: descr = "Y/CbCr 4:2:2 (N-C)"; break;
|
||||||
|
- case V4L2_PIX_FMT_NV61M: descr = "Y/CrCb 4:2:2 (N-C)"; break;
|
||||||
|
- case V4L2_PIX_FMT_NV12MT: descr = "Y/CbCr 4:2:0 (64x32 MB, N-C)"; break;
|
||||||
|
- case V4L2_PIX_FMT_NV12MT_16X16: descr = "Y/CbCr 4:2:0 (16x16 MB, N-C)"; break;
|
||||||
|
+ case V4L2_PIX_FMT_NV12: descr = "Y/UV 4:2:0"; break;
|
||||||
|
+ case V4L2_PIX_FMT_NV21: descr = "Y/VU 4:2:0"; break;
|
||||||
|
+ case V4L2_PIX_FMT_NV16: descr = "Y/UV 4:2:2"; break;
|
||||||
|
+ case V4L2_PIX_FMT_NV61: descr = "Y/VU 4:2:2"; break;
|
||||||
|
+ case V4L2_PIX_FMT_NV24: descr = "Y/UV 4:4:4"; break;
|
||||||
|
+ case V4L2_PIX_FMT_NV42: descr = "Y/VU 4:4:4"; break;
|
||||||
|
+ case V4L2_PIX_FMT_P010: descr = "10-bit Y/UV 4:2:0"; break;
|
||||||
|
+ case V4L2_PIX_FMT_NV12_4L4: descr = "Y/UV 4:2:0 (4x4 Linear)"; break;
|
||||||
|
+ case V4L2_PIX_FMT_NV12_16L16: descr = "Y/UV 4:2:0 (16x16 Linear)"; break;
|
||||||
|
+ case V4L2_PIX_FMT_NV12_32L32: descr = "Y/UV 4:2:0 (32x32 Linear)"; break;
|
||||||
|
+ case V4L2_PIX_FMT_P010_4L4: descr = "10-bit Y/UV 4:2:0 (4x4 Linear)"; break;
|
||||||
|
+ case V4L2_PIX_FMT_NV12M: descr = "Y/UV 4:2:0 (N-C)"; break;
|
||||||
|
+ case V4L2_PIX_FMT_NV21M: descr = "Y/VU 4:2:0 (N-C)"; break;
|
||||||
|
+ case V4L2_PIX_FMT_NV16M: descr = "Y/UV 4:2:2 (N-C)"; break;
|
||||||
|
+ case V4L2_PIX_FMT_NV61M: descr = "Y/VU 4:2:2 (N-C)"; break;
|
||||||
|
+ case V4L2_PIX_FMT_NV12MT: descr = "Y/UV 4:2:0 (64x32 MB, N-C)"; break;
|
||||||
|
+ case V4L2_PIX_FMT_NV12MT_16X16: descr = "Y/UV 4:2:0 (16x16 MB, N-C)"; break;
|
||||||
|
case V4L2_PIX_FMT_YUV420M: descr = "Planar YUV 4:2:0 (N-C)"; break;
|
||||||
|
case V4L2_PIX_FMT_YVU420M: descr = "Planar YVU 4:2:0 (N-C)"; break;
|
||||||
|
case V4L2_PIX_FMT_YUV422M: descr = "Planar YUV 4:2:2 (N-C)"; break;
|
@ -0,0 +1,131 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Jernej Skrabec <jernej.skrabec@gmail.com>
|
||||||
|
Date: Fri, 14 Oct 2022 23:35:13 +0200
|
||||||
|
Subject: [PATCH] Revert "drm/sun4i: dw-hdmi: Fix ddc-en GPIO consumer
|
||||||
|
conflict"
|
||||||
|
|
||||||
|
This reverts commit 920169041baa0a7497ed702aa97d6a2d6285efd3.
|
||||||
|
---
|
||||||
|
drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c | 54 +++++++++++++++++++++++++--
|
||||||
|
drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h | 2 +
|
||||||
|
2 files changed, 52 insertions(+), 4 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c
|
||||||
|
index 477cb6985b4d..a8d75fd7e9f4 100644
|
||||||
|
--- a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c
|
||||||
|
+++ b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c
|
||||||
|
@@ -93,10 +93,34 @@ static u32 sun8i_dw_hdmi_find_possible_crtcs(struct drm_device *drm,
|
||||||
|
return crtcs;
|
||||||
|
}
|
||||||
|
|
||||||
|
+static int sun8i_dw_hdmi_find_connector_pdev(struct device *dev,
|
||||||
|
+ struct platform_device **pdev_out)
|
||||||
|
+{
|
||||||
|
+ struct platform_device *pdev;
|
||||||
|
+ struct device_node *remote;
|
||||||
|
+
|
||||||
|
+ remote = of_graph_get_remote_node(dev->of_node, 1, -1);
|
||||||
|
+ if (!remote)
|
||||||
|
+ return -ENODEV;
|
||||||
|
+
|
||||||
|
+ if (!of_device_is_compatible(remote, "hdmi-connector")) {
|
||||||
|
+ of_node_put(remote);
|
||||||
|
+ return -ENODEV;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ pdev = of_find_device_by_node(remote);
|
||||||
|
+ of_node_put(remote);
|
||||||
|
+ if (!pdev)
|
||||||
|
+ return -ENODEV;
|
||||||
|
+
|
||||||
|
+ *pdev_out = pdev;
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
static int sun8i_dw_hdmi_bind(struct device *dev, struct device *master,
|
||||||
|
void *data)
|
||||||
|
{
|
||||||
|
- struct platform_device *pdev = to_platform_device(dev);
|
||||||
|
+ struct platform_device *pdev = to_platform_device(dev), *connector_pdev;
|
||||||
|
struct dw_hdmi_plat_data *plat_data;
|
||||||
|
struct drm_device *drm = data;
|
||||||
|
struct device_node *phy_node;
|
||||||
|
@@ -143,16 +167,30 @@ static int sun8i_dw_hdmi_bind(struct device *dev, struct device *master,
|
||||||
|
return dev_err_probe(dev, PTR_ERR(hdmi->regulator),
|
||||||
|
"Couldn't get regulator\n");
|
||||||
|
|
||||||
|
+ ret = sun8i_dw_hdmi_find_connector_pdev(dev, &connector_pdev);
|
||||||
|
+ if (!ret) {
|
||||||
|
+ hdmi->ddc_en = gpiod_get_optional(&connector_pdev->dev,
|
||||||
|
+ "ddc-en", GPIOD_OUT_HIGH);
|
||||||
|
+ platform_device_put(connector_pdev);
|
||||||
|
+
|
||||||
|
+ if (IS_ERR(hdmi->ddc_en)) {
|
||||||
|
+ dev_err(dev, "Couldn't get ddc-en gpio\n");
|
||||||
|
+ return PTR_ERR(hdmi->ddc_en);
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
ret = regulator_enable(hdmi->regulator);
|
||||||
|
if (ret) {
|
||||||
|
dev_err(dev, "Failed to enable regulator\n");
|
||||||
|
- return ret;
|
||||||
|
+ goto err_unref_ddc_en;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ gpiod_set_value(hdmi->ddc_en, 1);
|
||||||
|
+
|
||||||
|
ret = reset_control_deassert(hdmi->rst_ctrl);
|
||||||
|
if (ret) {
|
||||||
|
dev_err(dev, "Could not deassert ctrl reset control\n");
|
||||||
|
- goto err_disable_regulator;
|
||||||
|
+ goto err_disable_ddc_en;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = clk_prepare_enable(hdmi->clk_tmds);
|
||||||
|
@@ -207,8 +245,12 @@ static int sun8i_dw_hdmi_bind(struct device *dev, struct device *master,
|
||||||
|
clk_disable_unprepare(hdmi->clk_tmds);
|
||||||
|
err_assert_ctrl_reset:
|
||||||
|
reset_control_assert(hdmi->rst_ctrl);
|
||||||
|
-err_disable_regulator:
|
||||||
|
+err_disable_ddc_en:
|
||||||
|
+ gpiod_set_value(hdmi->ddc_en, 0);
|
||||||
|
regulator_disable(hdmi->regulator);
|
||||||
|
+err_unref_ddc_en:
|
||||||
|
+ if (hdmi->ddc_en)
|
||||||
|
+ gpiod_put(hdmi->ddc_en);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
@@ -222,7 +264,11 @@ static void sun8i_dw_hdmi_unbind(struct device *dev, struct device *master,
|
||||||
|
sun8i_hdmi_phy_deinit(hdmi->phy);
|
||||||
|
clk_disable_unprepare(hdmi->clk_tmds);
|
||||||
|
reset_control_assert(hdmi->rst_ctrl);
|
||||||
|
+ gpiod_set_value(hdmi->ddc_en, 0);
|
||||||
|
regulator_disable(hdmi->regulator);
|
||||||
|
+
|
||||||
|
+ if (hdmi->ddc_en)
|
||||||
|
+ gpiod_put(hdmi->ddc_en);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct component_ops sun8i_dw_hdmi_ops = {
|
||||||
|
diff --git a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h
|
||||||
|
index ab80d52a70bb..f082b8ecfe2c 100644
|
||||||
|
--- a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h
|
||||||
|
+++ b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h
|
||||||
|
@@ -9,6 +9,7 @@
|
||||||
|
#include <drm/bridge/dw_hdmi.h>
|
||||||
|
#include <drm/drm_encoder.h>
|
||||||
|
#include <linux/clk.h>
|
||||||
|
+#include <linux/gpio/consumer.h>
|
||||||
|
#include <linux/regmap.h>
|
||||||
|
#include <linux/regulator/consumer.h>
|
||||||
|
#include <linux/reset.h>
|
||||||
|
@@ -187,6 +188,7 @@ struct sun8i_dw_hdmi {
|
||||||
|
struct regulator *regulator;
|
||||||
|
const struct sun8i_dw_hdmi_quirks *quirks;
|
||||||
|
struct reset_control *rst_ctrl;
|
||||||
|
+ struct gpio_desc *ddc_en;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern struct platform_driver sun8i_hdmi_phy_driver;
|
Loading…
x
Reference in New Issue
Block a user