mirror of https://github.com/armbian/build.git
sunxi-6.14: Add drm patches
This commit is contained in:
parent
468871e561
commit
fb4b91a169
|
|
@ -0,0 +1,41 @@
|
|||
From 86ef31fcb116682d399b9723a7ab66c87e6f2cc5 Mon Sep 17 00:00:00 2001
|
||||
From: Stephen Graf <stephen.graf@gmail.com>
|
||||
Date: Tue, 18 Feb 2025 05:12:44 +0000
|
||||
Subject: add TCON global control reg for pad selection
|
||||
|
||||
Signed-off-by: Stephen Graf <stephen.graf@gmail.com>
|
||||
---
|
||||
drivers/gpu/drm/sun4i/sun4i_tcon.c | 4 ++++
|
||||
drivers/gpu/drm/sun4i/sun4i_tcon.h | 1 +
|
||||
2 files changed, 5 insertions(+)
|
||||
|
||||
diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c b/drivers/gpu/drm/sun4i/sun4i_tcon.c
|
||||
index af67bf2e6e09..88984572f5c5 100644
|
||||
--- a/drivers/gpu/drm/sun4i/sun4i_tcon.c
|
||||
+++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c
|
||||
@@ -1308,6 +1308,10 @@ static int sun4i_tcon_bind(struct device *dev, struct device *master,
|
||||
goto err_free_dclk;
|
||||
}
|
||||
|
||||
+ regmap_update_bits(tcon->regs, SUN4I_TCON_GCTL_REG,
|
||||
+ SUN4I_TCON_GCTL_PAD_SEL,
|
||||
+ SUN4I_TCON_GCTL_PAD_SEL);
|
||||
+
|
||||
if (tcon->quirks->has_channel_0) {
|
||||
/*
|
||||
* If we have an LVDS panel connected to the TCON, we should
|
||||
diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.h b/drivers/gpu/drm/sun4i/sun4i_tcon.h
|
||||
index bd4abc90062b..e8d28bad4060 100644
|
||||
--- a/drivers/gpu/drm/sun4i/sun4i_tcon.h
|
||||
+++ b/drivers/gpu/drm/sun4i/sun4i_tcon.h
|
||||
@@ -19,6 +19,7 @@
|
||||
|
||||
#define SUN4I_TCON_GCTL_REG 0x0
|
||||
#define SUN4I_TCON_GCTL_TCON_ENABLE BIT(31)
|
||||
+#define SUN4I_TCON_GCTL_PAD_SEL BIT(1)
|
||||
#define SUN4I_TCON_GCTL_IOMAP_MASK BIT(0)
|
||||
#define SUN4I_TCON_GCTL_IOMAP_TCON1 (1 << 0)
|
||||
#define SUN4I_TCON_GCTL_IOMAP_TCON0 (0 << 0)
|
||||
--
|
||||
2.35.3
|
||||
|
||||
|
|
@ -0,0 +1,61 @@
|
|||
From 02dc976a5f62b393f378c056888f121ba1880fc5 Mon Sep 17 00:00:00 2001
|
||||
From: Andre Przywara <andre.przywara@arm.com>
|
||||
Date: Fri, 21 Feb 2025 00:58:01 +0000
|
||||
Subject: arm64: dts: allwinner: h616: Add Mali GPU node
|
||||
|
||||
The Allwinner H616 SoC contains a Mali-G31 MP2 GPU, which is of the Mali
|
||||
Bifrost family. There is a power domain specifically for that GPU, which
|
||||
needs to be enabled to make use of the it.
|
||||
|
||||
Add the DT nodes for those two devices, and link them together through
|
||||
the "power-domains" property.
|
||||
Any board wishing to use the GPU would need to enable the GPU node and
|
||||
specify the "mali-supply" regulator.
|
||||
|
||||
Signed-off-by: Andre Przywara <andre.przywara@arm.com>
|
||||
---
|
||||
.../arm64/boot/dts/allwinner/sun50i-h616.dtsi | 21 +++++++++++++++++++
|
||||
1 file changed, 21 insertions(+)
|
||||
|
||||
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h616.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-h616.dtsi
|
||||
index cdce3dcb8ec0..ceedae9e399b 100644
|
||||
--- a/arch/arm64/boot/dts/allwinner/sun50i-h616.dtsi
|
||||
+++ b/arch/arm64/boot/dts/allwinner/sun50i-h616.dtsi
|
||||
@@ -150,6 +150,21 @@ soc {
|
||||
#size-cells = <1>;
|
||||
ranges = <0x0 0x0 0x0 0x40000000>;
|
||||
|
||||
+ gpu: gpu@1800000 {
|
||||
+ compatible = "allwinner,sun50i-h616-mali",
|
||||
+ "arm,mali-bifrost";
|
||||
+ reg = <0x1800000 0x40000>;
|
||||
+ interrupts = <GIC_SPI 95 IRQ_TYPE_LEVEL_HIGH>,
|
||||
+ <GIC_SPI 96 IRQ_TYPE_LEVEL_HIGH>,
|
||||
+ <GIC_SPI 97 IRQ_TYPE_LEVEL_HIGH>;
|
||||
+ interrupt-names = "job", "mmu", "gpu";
|
||||
+ clocks = <&ccu CLK_GPU0>, <&ccu CLK_BUS_GPU>;
|
||||
+ clock-names = "core", "bus";
|
||||
+ power-domains = <&prcm_ppu 2>;
|
||||
+ resets = <&ccu RST_BUS_GPU>;
|
||||
+ status = "disabled";
|
||||
+ };
|
||||
+
|
||||
crypto: crypto@1904000 {
|
||||
compatible = "allwinner,sun50i-h616-crypto";
|
||||
reg = <0x01904000 0x800>;
|
||||
@@ -874,6 +889,12 @@ r_ccu: clock@7010000 {
|
||||
#reset-cells = <1>;
|
||||
};
|
||||
|
||||
+ prcm_ppu: power-controller@7010250 {
|
||||
+ compatible = "allwinner,sun50i-h616-prcm-ppu";
|
||||
+ reg = <0x07010250 0x10>;
|
||||
+ #power-domain-cells = <1>;
|
||||
+ };
|
||||
+
|
||||
nmi_intc: interrupt-controller@7010320 {
|
||||
compatible = "allwinner,sun50i-h616-nmi",
|
||||
"allwinner,sun9i-a80-nmi";
|
||||
--
|
||||
2.35.3
|
||||
|
||||
|
|
@ -0,0 +1,86 @@
|
|||
From b41f5a9ec8841c0342f101585c64c292019543d2 Mon Sep 17 00:00:00 2001
|
||||
From: Ryan Walklin <ryan@testtoast.com>
|
||||
Date: Sun, 29 Sep 2024 22:04:54 +1300
|
||||
Subject: clk: sunxi-ng: ccu: add Display Engine 3.3 (DE33) support
|
||||
|
||||
The DE33 is a newer version of the Allwinner Display Engine IP block,
|
||||
found in the H616, H618, H700 and T507 SoCs. DE2 and DE3 are already
|
||||
supported by the mainline driver.
|
||||
|
||||
The DE33 in the H616 has mixer0 and writeback units. The clocks
|
||||
and resets required are identical to the H3 and H5 respectively, so use
|
||||
those existing structs for the H616 description.
|
||||
|
||||
There are two additional 32-bit registers (at offsets 0x24 and 0x28)
|
||||
which require clearing and setting respectively to bring up the
|
||||
hardware. The function of these registers is currently unknown, and the
|
||||
values are taken from the out-of-tree driver.
|
||||
|
||||
Add the required clock description struct and compatible string to the
|
||||
DE2 driver.
|
||||
|
||||
Signed-off-by: Ryan Walklin <ryan@testtoast.com>
|
||||
---
|
||||
drivers/clk/sunxi-ng/ccu-sun8i-de2.c | 25 +++++++++++++++++++++++++
|
||||
1 file changed, 25 insertions(+)
|
||||
|
||||
diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-de2.c b/drivers/clk/sunxi-ng/ccu-sun8i-de2.c
|
||||
index 7683ea08d8e3..83eab6f132aa 100644
|
||||
--- a/drivers/clk/sunxi-ng/ccu-sun8i-de2.c
|
||||
+++ b/drivers/clk/sunxi-ng/ccu-sun8i-de2.c
|
||||
@@ -5,6 +5,7 @@
|
||||
|
||||
#include <linux/clk.h>
|
||||
#include <linux/clk-provider.h>
|
||||
+#include <linux/io.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/platform_device.h>
|
||||
@@ -239,6 +240,16 @@ static const struct sunxi_ccu_desc sun50i_h5_de2_clk_desc = {
|
||||
.num_resets = ARRAY_SIZE(sun50i_h5_de2_resets),
|
||||
};
|
||||
|
||||
+static const struct sunxi_ccu_desc sun50i_h616_de33_clk_desc = {
|
||||
+ .ccu_clks = sun8i_de2_ccu_clks,
|
||||
+ .num_ccu_clks = ARRAY_SIZE(sun8i_de2_ccu_clks),
|
||||
+
|
||||
+ .hw_clks = &sun8i_h3_de2_hw_clks,
|
||||
+
|
||||
+ .resets = sun50i_h5_de2_resets,
|
||||
+ .num_resets = ARRAY_SIZE(sun50i_h5_de2_resets),
|
||||
+};
|
||||
+
|
||||
static int sunxi_de2_clk_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct clk *bus_clk, *mod_clk;
|
||||
@@ -291,6 +302,16 @@ static int sunxi_de2_clk_probe(struct platform_device *pdev)
|
||||
goto err_disable_mod_clk;
|
||||
}
|
||||
|
||||
+ /*
|
||||
+ * The DE33 requires these additional (unknown) registers set
|
||||
+ * during initialisation.
|
||||
+ */
|
||||
+ if (of_device_is_compatible(pdev->dev.of_node,
|
||||
+ "allwinner,sun50i-h616-de33-clk")) {
|
||||
+ writel(0, reg + 0x24);
|
||||
+ writel(0x0000a980, reg + 0x28);
|
||||
+ }
|
||||
+
|
||||
ret = devm_sunxi_ccu_probe(&pdev->dev, reg, ccu_desc);
|
||||
if (ret)
|
||||
goto err_assert_reset;
|
||||
@@ -335,6 +356,10 @@ static const struct of_device_id sunxi_de2_clk_ids[] = {
|
||||
.compatible = "allwinner,sun50i-h6-de3-clk",
|
||||
.data = &sun50i_h5_de2_clk_desc,
|
||||
},
|
||||
+ {
|
||||
+ .compatible = "allwinner,sun50i-h616-de33-clk",
|
||||
+ .data = &sun50i_h616_de33_clk_desc,
|
||||
+ },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, sunxi_de2_clk_ids);
|
||||
--
|
||||
2.35.3
|
||||
|
||||
|
|
@ -0,0 +1,111 @@
|
|||
From ce56f3f385e0830a1e242f9fca9a82c3067ba03f Mon Sep 17 00:00:00 2001
|
||||
From: Philippe Simons <simons.philippe@gmail.com>
|
||||
Date: Thu, 13 Mar 2025 00:23:18 +0100
|
||||
Subject: drm/panfrost: Add PM runtime flags
|
||||
|
||||
Allwinner H616 has a dedicated power domain for its Mali G31.
|
||||
|
||||
Currently after probe, the GPU is put in runtime suspend which
|
||||
disable the power domain.
|
||||
On first usage of GPU, the power domain enable hangs the system.
|
||||
|
||||
This series adds the necessary calls to enable the clocks and
|
||||
deasserting the reset line after the power domain enabling and
|
||||
asserting the reset line and disabling the clocks prior to the
|
||||
power domain disabling.
|
||||
|
||||
This allows to use the Mali GPU on all Allwinner H616
|
||||
boards and devices.
|
||||
|
||||
When the GPU is the only device attached to a single power domain,
|
||||
core genpd disable and enable it when gpu enter and leave runtime suspend.
|
||||
|
||||
Some power-domain requires a sequence before disabled,
|
||||
and the reverse when enabled.
|
||||
|
||||
Add GPU_PM_RT flag, and implement in
|
||||
panfrost_device_runtime_suspend/resume.
|
||||
|
||||
Signed-off-by: Philippe Simons <simons.philippe@gmail.com>
|
||||
---
|
||||
drivers/gpu/drm/panfrost/panfrost_device.c | 33 ++++++++++++++++++++++
|
||||
drivers/gpu/drm/panfrost/panfrost_device.h | 3 ++
|
||||
2 files changed, 36 insertions(+)
|
||||
|
||||
diff --git a/drivers/gpu/drm/panfrost/panfrost_device.c b/drivers/gpu/drm/panfrost/panfrost_device.c
|
||||
index a45e4addcc19..93d48e97ce10 100644
|
||||
--- a/drivers/gpu/drm/panfrost/panfrost_device.c
|
||||
+++ b/drivers/gpu/drm/panfrost/panfrost_device.c
|
||||
@@ -406,11 +406,36 @@ void panfrost_device_reset(struct panfrost_device *pfdev)
|
||||
static int panfrost_device_runtime_resume(struct device *dev)
|
||||
{
|
||||
struct panfrost_device *pfdev = dev_get_drvdata(dev);
|
||||
+ int ret;
|
||||
+
|
||||
+ if (pfdev->comp->pm_features & BIT(GPU_PM_RT)) {
|
||||
+ ret = reset_control_deassert(pfdev->rstc);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ ret = clk_enable(pfdev->clock);
|
||||
+ if (ret)
|
||||
+ goto err_clk;
|
||||
+
|
||||
+ if (pfdev->bus_clock) {
|
||||
+ ret = clk_enable(pfdev->bus_clock);
|
||||
+ if (ret)
|
||||
+ goto err_bus_clk;
|
||||
+ }
|
||||
+ }
|
||||
|
||||
panfrost_device_reset(pfdev);
|
||||
panfrost_devfreq_resume(pfdev);
|
||||
|
||||
return 0;
|
||||
+
|
||||
+err_bus_clk:
|
||||
+ if (pfdev->comp->pm_features & BIT(GPU_PM_RT))
|
||||
+ clk_disable(pfdev->clock);
|
||||
+err_clk:
|
||||
+ if (pfdev->comp->pm_features & BIT(GPU_PM_RT))
|
||||
+ reset_control_assert(pfdev->rstc);
|
||||
+ return ret;
|
||||
}
|
||||
|
||||
static int panfrost_device_runtime_suspend(struct device *dev)
|
||||
@@ -426,6 +451,14 @@ static int panfrost_device_runtime_suspend(struct device *dev)
|
||||
panfrost_gpu_suspend_irq(pfdev);
|
||||
panfrost_gpu_power_off(pfdev);
|
||||
|
||||
+ if (pfdev->comp->pm_features & BIT(GPU_PM_RT)) {
|
||||
+ if (pfdev->bus_clock)
|
||||
+ clk_disable(pfdev->bus_clock);
|
||||
+
|
||||
+ clk_disable(pfdev->clock);
|
||||
+ reset_control_assert(pfdev->rstc);
|
||||
+ }
|
||||
+
|
||||
return 0;
|
||||
}
|
||||
|
||||
diff --git a/drivers/gpu/drm/panfrost/panfrost_device.h b/drivers/gpu/drm/panfrost/panfrost_device.h
|
||||
index cffcb0ac7c11..861555ceea65 100644
|
||||
--- a/drivers/gpu/drm/panfrost/panfrost_device.h
|
||||
+++ b/drivers/gpu/drm/panfrost/panfrost_device.h
|
||||
@@ -36,10 +36,13 @@ enum panfrost_drv_comp_bits {
|
||||
* enum panfrost_gpu_pm - Supported kernel power management features
|
||||
* @GPU_PM_CLK_DIS: Allow disabling clocks during system suspend
|
||||
* @GPU_PM_VREG_OFF: Allow turning off regulators during system suspend
|
||||
+ * @GPU_PM_RT: Allow disabling clocks and asserting the reset control during
|
||||
+ * system runtime suspend
|
||||
*/
|
||||
enum panfrost_gpu_pm {
|
||||
GPU_PM_CLK_DIS,
|
||||
GPU_PM_VREG_OFF,
|
||||
+ GPU_PM_RT
|
||||
};
|
||||
|
||||
struct panfrost_features {
|
||||
--
|
||||
2.35.3
|
||||
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
From 16e3a927918e0c6349c2bfcbe468ee1690eaaaca Mon Sep 17 00:00:00 2001
|
||||
From: Philippe Simons <simons.philippe@gmail.com>
|
||||
Date: Thu, 13 Mar 2025 00:23:19 +0100
|
||||
Subject: drm/panfrost: add h616 compatible string
|
||||
|
||||
Tie the Allwinner compatible string to the GPU_PM_RT feature bits that will
|
||||
toggle the clocks and the reset line whenever the power domain is changing
|
||||
state.
|
||||
|
||||
Signed-off-by: Philippe Simons <simons.philippe@gmail.com>
|
||||
---
|
||||
drivers/gpu/drm/panfrost/panfrost_drv.c | 8 ++++++++
|
||||
1 file changed, 8 insertions(+)
|
||||
|
||||
diff --git a/drivers/gpu/drm/panfrost/panfrost_drv.c b/drivers/gpu/drm/panfrost/panfrost_drv.c
|
||||
index 0f3935556ac7..9470c04c5487 100644
|
||||
--- a/drivers/gpu/drm/panfrost/panfrost_drv.c
|
||||
+++ b/drivers/gpu/drm/panfrost/panfrost_drv.c
|
||||
@@ -776,6 +776,13 @@ static const struct panfrost_compatible default_data = {
|
||||
.pm_domain_names = NULL,
|
||||
};
|
||||
|
||||
+static const struct panfrost_compatible allwinner_h616_data = {
|
||||
+ .num_supplies = ARRAY_SIZE(default_supplies) - 1,
|
||||
+ .supply_names = default_supplies,
|
||||
+ .num_pm_domains = 1,
|
||||
+ .pm_features = BIT(GPU_PM_RT),
|
||||
+};
|
||||
+
|
||||
static const struct panfrost_compatible amlogic_data = {
|
||||
.num_supplies = ARRAY_SIZE(default_supplies) - 1,
|
||||
.supply_names = default_supplies,
|
||||
@@ -859,6 +866,7 @@ static const struct of_device_id dt_match[] = {
|
||||
{ .compatible = "mediatek,mt8186-mali", .data = &mediatek_mt8186_data },
|
||||
{ .compatible = "mediatek,mt8188-mali", .data = &mediatek_mt8188_data },
|
||||
{ .compatible = "mediatek,mt8192-mali", .data = &mediatek_mt8192_data },
|
||||
+ { .compatible = "allwinner,sun50i-h616-mali", .data = &allwinner_h616_data },
|
||||
{}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, dt_match);
|
||||
--
|
||||
2.35.3
|
||||
|
||||
|
|
@ -0,0 +1,106 @@
|
|||
From 37f8be7eaca786f85cf2a17dfd33227e2ff45780 Mon Sep 17 00:00:00 2001
|
||||
From: Philippe Simons <simons.philippe@gmail.com>
|
||||
Date: Thu, 3 Apr 2025 07:52:10 +0200
|
||||
Subject: drm/panfrost: reorder pd/clk/rst sequence
|
||||
|
||||
According to Mali manuals, the powerup sequence should be
|
||||
enable pd, asserting the reset then enabling the clock and
|
||||
the reverse for powerdown.
|
||||
|
||||
Signed-off-by: Philippe Simons <simons.philippe@gmail.com>
|
||||
---
|
||||
drivers/gpu/drm/panfrost/panfrost_device.c | 38 +++++++++++-----------
|
||||
1 file changed, 19 insertions(+), 19 deletions(-)
|
||||
|
||||
diff --git a/drivers/gpu/drm/panfrost/panfrost_device.c b/drivers/gpu/drm/panfrost/panfrost_device.c
|
||||
index 93d48e97ce10..5d35076b2e6d 100644
|
||||
--- a/drivers/gpu/drm/panfrost/panfrost_device.c
|
||||
+++ b/drivers/gpu/drm/panfrost/panfrost_device.c
|
||||
@@ -209,10 +209,20 @@ int panfrost_device_init(struct panfrost_device *pfdev)
|
||||
|
||||
spin_lock_init(&pfdev->cycle_counter.lock);
|
||||
|
||||
+ err = panfrost_pm_domain_init(pfdev);
|
||||
+ if (err)
|
||||
+ return err;
|
||||
+
|
||||
+ err = panfrost_reset_init(pfdev);
|
||||
+ if (err) {
|
||||
+ dev_err(pfdev->dev, "reset init failed %d\n", err);
|
||||
+ goto out_pm_domain;
|
||||
+ }
|
||||
+
|
||||
err = panfrost_clk_init(pfdev);
|
||||
if (err) {
|
||||
dev_err(pfdev->dev, "clk init failed %d\n", err);
|
||||
- return err;
|
||||
+ goto out_reset;
|
||||
}
|
||||
|
||||
err = panfrost_devfreq_init(pfdev);
|
||||
@@ -229,25 +239,15 @@ int panfrost_device_init(struct panfrost_device *pfdev)
|
||||
goto out_devfreq;
|
||||
}
|
||||
|
||||
- err = panfrost_reset_init(pfdev);
|
||||
- if (err) {
|
||||
- dev_err(pfdev->dev, "reset init failed %d\n", err);
|
||||
- goto out_regulator;
|
||||
- }
|
||||
-
|
||||
- err = panfrost_pm_domain_init(pfdev);
|
||||
- if (err)
|
||||
- goto out_reset;
|
||||
-
|
||||
pfdev->iomem = devm_platform_ioremap_resource(pfdev->pdev, 0);
|
||||
if (IS_ERR(pfdev->iomem)) {
|
||||
err = PTR_ERR(pfdev->iomem);
|
||||
- goto out_pm_domain;
|
||||
+ goto out_regulator;
|
||||
}
|
||||
|
||||
err = panfrost_gpu_init(pfdev);
|
||||
if (err)
|
||||
- goto out_pm_domain;
|
||||
+ goto out_regulator;
|
||||
|
||||
err = panfrost_mmu_init(pfdev);
|
||||
if (err)
|
||||
@@ -268,16 +268,16 @@ int panfrost_device_init(struct panfrost_device *pfdev)
|
||||
panfrost_mmu_fini(pfdev);
|
||||
out_gpu:
|
||||
panfrost_gpu_fini(pfdev);
|
||||
-out_pm_domain:
|
||||
- panfrost_pm_domain_fini(pfdev);
|
||||
-out_reset:
|
||||
- panfrost_reset_fini(pfdev);
|
||||
out_regulator:
|
||||
panfrost_regulator_fini(pfdev);
|
||||
out_devfreq:
|
||||
panfrost_devfreq_fini(pfdev);
|
||||
out_clk:
|
||||
panfrost_clk_fini(pfdev);
|
||||
+out_reset:
|
||||
+ panfrost_reset_fini(pfdev);
|
||||
+out_pm_domain:
|
||||
+ panfrost_pm_domain_fini(pfdev);
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -287,11 +287,11 @@ void panfrost_device_fini(struct panfrost_device *pfdev)
|
||||
panfrost_job_fini(pfdev);
|
||||
panfrost_mmu_fini(pfdev);
|
||||
panfrost_gpu_fini(pfdev);
|
||||
- panfrost_pm_domain_fini(pfdev);
|
||||
- panfrost_reset_fini(pfdev);
|
||||
panfrost_devfreq_fini(pfdev);
|
||||
panfrost_regulator_fini(pfdev);
|
||||
panfrost_clk_fini(pfdev);
|
||||
+ panfrost_reset_fini(pfdev);
|
||||
+ panfrost_pm_domain_fini(pfdev);
|
||||
}
|
||||
|
||||
#define PANFROST_EXCEPTION(id) \
|
||||
--
|
||||
2.35.3
|
||||
|
||||
|
|
@ -0,0 +1,108 @@
|
|||
From 6c8bbaf43b8eaf62d4682ce66a35fc7f341f4a13 Mon Sep 17 00:00:00 2001
|
||||
From: The-going <48602507+The-going@users.noreply.github.com>
|
||||
Date: Mon, 10 Feb 2025 15:45:13 +0300
|
||||
Subject: [PATCH] drm: sun4i: add sun50i-h616-hdmi-phy support
|
||||
|
||||
---
|
||||
drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c | 71 ++++++++++++++++++++++++++
|
||||
1 file changed, 71 insertions(+)
|
||||
|
||||
diff --git a/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c b/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c
|
||||
index 4fa69c463dc4..8a07052037c3 100644
|
||||
--- a/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c
|
||||
+++ b/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c
|
||||
@@ -124,6 +124,66 @@ static const struct dw_hdmi_phy_config sun50i_h6_phy_config[] = {
|
||||
{ ~0UL, 0x0000, 0x0000, 0x0000}
|
||||
};
|
||||
|
||||
+static const struct dw_hdmi_mpll_config sun50i_h616_mpll_cfg[] = {
|
||||
+ {
|
||||
+ 27000000, {
|
||||
+ {0x00b3, 0x0003},
|
||||
+ {0x2153, 0x0003},
|
||||
+ {0x40f3, 0x0003},
|
||||
+ },
|
||||
+ }, {
|
||||
+ 74250000, {
|
||||
+ {0x0072, 0x0003},
|
||||
+ {0x2145, 0x0003},
|
||||
+ {0x4061, 0x0003},
|
||||
+ },
|
||||
+ }, {
|
||||
+ 148500000, {
|
||||
+ {0x0051, 0x0003},
|
||||
+ {0x214c, 0x0003},
|
||||
+ {0x4064, 0x0003},
|
||||
+ },
|
||||
+ }, {
|
||||
+ 297000000, {
|
||||
+ {0x0040, 0x0003},
|
||||
+ {0x3b4c, 0x0003},
|
||||
+ {0x5a64, 0x0003},
|
||||
+ },
|
||||
+ }, {
|
||||
+ 594000000, {
|
||||
+ {0x1a40, 0x0003},
|
||||
+ {0x3b4c, 0x0003},
|
||||
+ {0x5a64, 0x0003},
|
||||
+ },
|
||||
+ }, {
|
||||
+ ~0UL, {
|
||||
+ {0x0000, 0x0000},
|
||||
+ {0x0000, 0x0000},
|
||||
+ {0x0000, 0x0000},
|
||||
+ },
|
||||
+ }
|
||||
+};
|
||||
+
|
||||
+static const struct dw_hdmi_curr_ctrl sun50i_h616_cur_ctr[] = {
|
||||
+ /* pixelclk bpp8 bpp10 bpp12 */
|
||||
+ { 27000000, { 0x0012, 0x0000, 0x0000 }, },
|
||||
+ { 74250000, { 0x0013, 0x0013, 0x0013 }, },
|
||||
+ { 148500000, { 0x0019, 0x0019, 0x0019 }, },
|
||||
+ { 297000000, { 0x0019, 0x001b, 0x0019 }, },
|
||||
+ { 594000000, { 0x0010, 0x0010, 0x0010 }, },
|
||||
+ { ~0UL, { 0x0000, 0x0000, 0x0000 }, }
|
||||
+};
|
||||
+
|
||||
+static const struct dw_hdmi_phy_config sun50i_h616_phy_config[] = {
|
||||
+ /*pixelclk symbol term vlev*/
|
||||
+ {27000000, 0x8009, 0x0007, 0x02b0},
|
||||
+ {74250000, 0x8019, 0x0004, 0x0290},
|
||||
+ {148500000, 0x8019, 0x0004, 0x0290},
|
||||
+ {297000000, 0x8039, 0x0004, 0x022b},
|
||||
+ {594000000, 0x8029, 0x0000, 0x008a},
|
||||
+ {~0UL, 0x0000, 0x0000, 0x0000}
|
||||
+};
|
||||
+
|
||||
static void sun8i_hdmi_phy_set_polarity(struct sun8i_hdmi_phy *phy,
|
||||
const struct drm_display_mode *mode)
|
||||
{
|
||||
@@ -626,6 +686,13 @@ static const struct sun8i_hdmi_phy_variant sun50i_h6_hdmi_phy = {
|
||||
.phy_init = &sun50i_hdmi_phy_init_h6,
|
||||
};
|
||||
|
||||
+static const struct sun8i_hdmi_phy_variant sun50i_h616_hdmi_phy = {
|
||||
+ .cur_ctr = sun50i_h616_cur_ctr,
|
||||
+ .mpll_cfg = sun50i_h616_mpll_cfg,
|
||||
+ .phy_cfg = sun50i_h616_phy_config,
|
||||
+ .phy_init = &sun50i_hdmi_phy_init_h6,
|
||||
+};
|
||||
+
|
||||
static const struct of_device_id sun8i_hdmi_phy_of_table[] = {
|
||||
{
|
||||
.compatible = "allwinner,sun8i-a83t-hdmi-phy",
|
||||
@@ -647,6 +714,10 @@ static const struct of_device_id sun8i_hdmi_phy_of_table[] = {
|
||||
.compatible = "allwinner,sun50i-h6-hdmi-phy",
|
||||
.data = &sun50i_h6_hdmi_phy,
|
||||
},
|
||||
+ {
|
||||
+ .compatible = "allwinner,sun50i-h616-hdmi-phy",
|
||||
+ .data = &sun50i_h616_hdmi_phy,
|
||||
+ },
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
|
||||
--
|
||||
2.35.3
|
||||
|
||||
|
|
@ -0,0 +1,75 @@
|
|||
From 5c2859b3cccd1b1b3f1700fd70c06770f418247a Mon Sep 17 00:00:00 2001
|
||||
From: Jernej Skrabec <jernej.skrabec@gmail.com>
|
||||
Date: Sun, 29 Sep 2024 22:04:36 +1300
|
||||
Subject: drm: sun4i: de2: Initialize layer fields earlier
|
||||
|
||||
drm_universal_plane_init() can already call some callbacks, like
|
||||
format_mod_supported, during initialization. Because of that, fields
|
||||
should be initialized beforehand.
|
||||
|
||||
Signed-off-by: Jernej Skrabec <jernej.skrabec@gmail.com>
|
||||
Co-developed-by: Ryan Walklin <ryan@testtoast.com>
|
||||
Signed-off-by: Ryan Walklin <ryan@testtoast.com>
|
||||
Reviewed-by: Chen-Yu Tsai <wens@csie.org>
|
||||
---
|
||||
drivers/gpu/drm/sun4i/sun8i_ui_layer.c | 9 +++++----
|
||||
drivers/gpu/drm/sun4i/sun8i_vi_layer.c | 9 +++++----
|
||||
2 files changed, 10 insertions(+), 8 deletions(-)
|
||||
|
||||
diff --git a/drivers/gpu/drm/sun4i/sun8i_ui_layer.c b/drivers/gpu/drm/sun4i/sun8i_ui_layer.c
|
||||
index aa987bca1dbb..cb9b694fef10 100644
|
||||
--- a/drivers/gpu/drm/sun4i/sun8i_ui_layer.c
|
||||
+++ b/drivers/gpu/drm/sun4i/sun8i_ui_layer.c
|
||||
@@ -295,6 +295,11 @@ struct sun8i_layer *sun8i_ui_layer_init_one(struct drm_device *drm,
|
||||
if (!layer)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
+ layer->mixer = mixer;
|
||||
+ layer->type = SUN8I_LAYER_TYPE_UI;
|
||||
+ layer->channel = channel;
|
||||
+ layer->overlay = 0;
|
||||
+
|
||||
if (index == 0)
|
||||
type = DRM_PLANE_TYPE_PRIMARY;
|
||||
|
||||
@@ -325,10 +330,6 @@ struct sun8i_layer *sun8i_ui_layer_init_one(struct drm_device *drm,
|
||||
}
|
||||
|
||||
drm_plane_helper_add(&layer->plane, &sun8i_ui_layer_helper_funcs);
|
||||
- layer->mixer = mixer;
|
||||
- layer->type = SUN8I_LAYER_TYPE_UI;
|
||||
- layer->channel = channel;
|
||||
- layer->overlay = 0;
|
||||
|
||||
return layer;
|
||||
}
|
||||
diff --git a/drivers/gpu/drm/sun4i/sun8i_vi_layer.c b/drivers/gpu/drm/sun4i/sun8i_vi_layer.c
|
||||
index f3a5329351ca..3c657b069d1f 100644
|
||||
--- a/drivers/gpu/drm/sun4i/sun8i_vi_layer.c
|
||||
+++ b/drivers/gpu/drm/sun4i/sun8i_vi_layer.c
|
||||
@@ -478,6 +478,11 @@ struct sun8i_layer *sun8i_vi_layer_init_one(struct drm_device *drm,
|
||||
if (!layer)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
+ layer->mixer = mixer;
|
||||
+ layer->type = SUN8I_LAYER_TYPE_VI;
|
||||
+ layer->channel = index;
|
||||
+ layer->overlay = 0;
|
||||
+
|
||||
if (mixer->cfg->is_de3) {
|
||||
formats = sun8i_vi_layer_de3_formats;
|
||||
format_count = ARRAY_SIZE(sun8i_vi_layer_de3_formats);
|
||||
@@ -536,10 +541,6 @@ struct sun8i_layer *sun8i_vi_layer_init_one(struct drm_device *drm,
|
||||
}
|
||||
|
||||
drm_plane_helper_add(&layer->plane, &sun8i_vi_layer_helper_funcs);
|
||||
- layer->mixer = mixer;
|
||||
- layer->type = SUN8I_LAYER_TYPE_VI;
|
||||
- layer->channel = index;
|
||||
- layer->overlay = 0;
|
||||
|
||||
return layer;
|
||||
}
|
||||
--
|
||||
2.35.3
|
||||
|
||||
|
|
@ -0,0 +1,178 @@
|
|||
From 54669ac67e47835b8cc3eea215026385a0050567 Mon Sep 17 00:00:00 2001
|
||||
From: Jernej Skrabec <jernej.skrabec@gmail.com>
|
||||
Date: Sun, 29 Sep 2024 22:04:33 +1300
|
||||
Subject: drm: sun4i: de2/de3: Change CSC argument
|
||||
|
||||
Currently, CSC module takes care only for converting YUV to RGB.
|
||||
However, DE3 is more suited to work in YUV color space. Change CSC mode
|
||||
argument to format type to be more neutral. New argument only tells
|
||||
layer format type and doesn't imply output type.
|
||||
|
||||
This commit doesn't make any functional change.
|
||||
|
||||
Signed-off-by: Jernej Skrabec <jernej.skrabec@gmail.com>
|
||||
Signed-off-by: Ryan Walklin <ryan@testtoast.com>
|
||||
Reviewed-by: Andre Przywara <andre.przywara@arm.com>
|
||||
---
|
||||
drivers/gpu/drm/sun4i/sun8i_csc.c | 22 +++++++++++-----------
|
||||
drivers/gpu/drm/sun4i/sun8i_csc.h | 10 +++++-----
|
||||
drivers/gpu/drm/sun4i/sun8i_vi_layer.c | 16 ++++++++--------
|
||||
3 files changed, 24 insertions(+), 24 deletions(-)
|
||||
|
||||
diff --git a/drivers/gpu/drm/sun4i/sun8i_csc.c b/drivers/gpu/drm/sun4i/sun8i_csc.c
|
||||
index 58480d8e4f70..6ebd1c3aa3ab 100644
|
||||
--- a/drivers/gpu/drm/sun4i/sun8i_csc.c
|
||||
+++ b/drivers/gpu/drm/sun4i/sun8i_csc.c
|
||||
@@ -108,7 +108,7 @@ static const u32 yuv2rgb_de3[2][3][12] = {
|
||||
};
|
||||
|
||||
static void sun8i_csc_set_coefficients(struct regmap *map, u32 base,
|
||||
- enum sun8i_csc_mode mode,
|
||||
+ enum format_type fmt_type,
|
||||
enum drm_color_encoding encoding,
|
||||
enum drm_color_range range)
|
||||
{
|
||||
@@ -118,12 +118,12 @@ static void sun8i_csc_set_coefficients(struct regmap *map, u32 base,
|
||||
|
||||
table = yuv2rgb[range][encoding];
|
||||
|
||||
- switch (mode) {
|
||||
- case SUN8I_CSC_MODE_YUV2RGB:
|
||||
+ switch (fmt_type) {
|
||||
+ case FORMAT_TYPE_YUV:
|
||||
base_reg = SUN8I_CSC_COEFF(base, 0);
|
||||
regmap_bulk_write(map, base_reg, table, 12);
|
||||
break;
|
||||
- case SUN8I_CSC_MODE_YVU2RGB:
|
||||
+ case FORMAT_TYPE_YVU:
|
||||
for (i = 0; i < 12; i++) {
|
||||
if ((i & 3) == 1)
|
||||
base_reg = SUN8I_CSC_COEFF(base, i + 1);
|
||||
@@ -141,7 +141,7 @@ static void sun8i_csc_set_coefficients(struct regmap *map, u32 base,
|
||||
}
|
||||
|
||||
static void sun8i_de3_ccsc_set_coefficients(struct regmap *map, int layer,
|
||||
- enum sun8i_csc_mode mode,
|
||||
+ enum format_type fmt_type,
|
||||
enum drm_color_encoding encoding,
|
||||
enum drm_color_range range)
|
||||
{
|
||||
@@ -151,12 +151,12 @@ static void sun8i_de3_ccsc_set_coefficients(struct regmap *map, int layer,
|
||||
|
||||
table = yuv2rgb_de3[range][encoding];
|
||||
|
||||
- switch (mode) {
|
||||
- case SUN8I_CSC_MODE_YUV2RGB:
|
||||
+ switch (fmt_type) {
|
||||
+ case FORMAT_TYPE_YUV:
|
||||
addr = SUN50I_MIXER_BLEND_CSC_COEFF(DE3_BLD_BASE, layer, 0);
|
||||
regmap_bulk_write(map, addr, table, 12);
|
||||
break;
|
||||
- case SUN8I_CSC_MODE_YVU2RGB:
|
||||
+ case FORMAT_TYPE_YVU:
|
||||
for (i = 0; i < 12; i++) {
|
||||
if ((i & 3) == 1)
|
||||
addr = SUN50I_MIXER_BLEND_CSC_COEFF(DE3_BLD_BASE,
|
||||
@@ -206,7 +206,7 @@ static void sun8i_de3_ccsc_enable(struct regmap *map, int layer, bool enable)
|
||||
}
|
||||
|
||||
void sun8i_csc_set_ccsc_coefficients(struct sun8i_mixer *mixer, int layer,
|
||||
- enum sun8i_csc_mode mode,
|
||||
+ enum format_type fmt_type,
|
||||
enum drm_color_encoding encoding,
|
||||
enum drm_color_range range)
|
||||
{
|
||||
@@ -214,14 +214,14 @@ void sun8i_csc_set_ccsc_coefficients(struct sun8i_mixer *mixer, int layer,
|
||||
|
||||
if (mixer->cfg->is_de3) {
|
||||
sun8i_de3_ccsc_set_coefficients(mixer->engine.regs, layer,
|
||||
- mode, encoding, range);
|
||||
+ fmt_type, encoding, range);
|
||||
return;
|
||||
}
|
||||
|
||||
base = ccsc_base[mixer->cfg->ccsc][layer];
|
||||
|
||||
sun8i_csc_set_coefficients(mixer->engine.regs, base,
|
||||
- mode, encoding, range);
|
||||
+ fmt_type, encoding, range);
|
||||
}
|
||||
|
||||
void sun8i_csc_enable_ccsc(struct sun8i_mixer *mixer, int layer, bool enable)
|
||||
diff --git a/drivers/gpu/drm/sun4i/sun8i_csc.h b/drivers/gpu/drm/sun4i/sun8i_csc.h
|
||||
index 828b86fd0cab..7322770f39f0 100644
|
||||
--- a/drivers/gpu/drm/sun4i/sun8i_csc.h
|
||||
+++ b/drivers/gpu/drm/sun4i/sun8i_csc.h
|
||||
@@ -22,14 +22,14 @@ struct sun8i_mixer;
|
||||
|
||||
#define SUN8I_CSC_CTRL_EN BIT(0)
|
||||
|
||||
-enum sun8i_csc_mode {
|
||||
- SUN8I_CSC_MODE_OFF,
|
||||
- SUN8I_CSC_MODE_YUV2RGB,
|
||||
- SUN8I_CSC_MODE_YVU2RGB,
|
||||
+enum format_type {
|
||||
+ FORMAT_TYPE_RGB,
|
||||
+ FORMAT_TYPE_YUV,
|
||||
+ FORMAT_TYPE_YVU,
|
||||
};
|
||||
|
||||
void sun8i_csc_set_ccsc_coefficients(struct sun8i_mixer *mixer, int layer,
|
||||
- enum sun8i_csc_mode mode,
|
||||
+ enum format_type fmt_type,
|
||||
enum drm_color_encoding encoding,
|
||||
enum drm_color_range range);
|
||||
void sun8i_csc_enable_ccsc(struct sun8i_mixer *mixer, int layer, bool enable);
|
||||
diff --git a/drivers/gpu/drm/sun4i/sun8i_vi_layer.c b/drivers/gpu/drm/sun4i/sun8i_vi_layer.c
|
||||
index 9c09d9c08496..8a80934e928f 100644
|
||||
--- a/drivers/gpu/drm/sun4i/sun8i_vi_layer.c
|
||||
+++ b/drivers/gpu/drm/sun4i/sun8i_vi_layer.c
|
||||
@@ -193,19 +193,19 @@ static int sun8i_vi_layer_update_coord(struct sun8i_mixer *mixer, int channel,
|
||||
return 0;
|
||||
}
|
||||
|
||||
-static u32 sun8i_vi_layer_get_csc_mode(const struct drm_format_info *format)
|
||||
+static u32 sun8i_vi_layer_get_format_type(const struct drm_format_info *format)
|
||||
{
|
||||
if (!format->is_yuv)
|
||||
- return SUN8I_CSC_MODE_OFF;
|
||||
+ return FORMAT_TYPE_RGB;
|
||||
|
||||
switch (format->format) {
|
||||
case DRM_FORMAT_YVU411:
|
||||
case DRM_FORMAT_YVU420:
|
||||
case DRM_FORMAT_YVU422:
|
||||
case DRM_FORMAT_YVU444:
|
||||
- return SUN8I_CSC_MODE_YVU2RGB;
|
||||
+ return FORMAT_TYPE_YVU;
|
||||
default:
|
||||
- return SUN8I_CSC_MODE_YUV2RGB;
|
||||
+ return FORMAT_TYPE_YUV;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -213,7 +213,7 @@ static int sun8i_vi_layer_update_formats(struct sun8i_mixer *mixer, int channel,
|
||||
int overlay, struct drm_plane *plane)
|
||||
{
|
||||
struct drm_plane_state *state = plane->state;
|
||||
- u32 val, ch_base, csc_mode, hw_fmt;
|
||||
+ u32 val, ch_base, fmt_type, hw_fmt;
|
||||
const struct drm_format_info *fmt;
|
||||
int ret;
|
||||
|
||||
@@ -231,9 +231,9 @@ static int sun8i_vi_layer_update_formats(struct sun8i_mixer *mixer, int channel,
|
||||
SUN8I_MIXER_CHAN_VI_LAYER_ATTR(ch_base, overlay),
|
||||
SUN8I_MIXER_CHAN_VI_LAYER_ATTR_FBFMT_MASK, val);
|
||||
|
||||
- csc_mode = sun8i_vi_layer_get_csc_mode(fmt);
|
||||
- if (csc_mode != SUN8I_CSC_MODE_OFF) {
|
||||
- sun8i_csc_set_ccsc_coefficients(mixer, channel, csc_mode,
|
||||
+ fmt_type = sun8i_vi_layer_get_format_type(fmt);
|
||||
+ if (fmt_type != FORMAT_TYPE_RGB) {
|
||||
+ sun8i_csc_set_ccsc_coefficients(mixer, channel, fmt_type,
|
||||
state->color_encoding,
|
||||
state->color_range);
|
||||
sun8i_csc_enable_ccsc(mixer, channel, true);
|
||||
--
|
||||
2.35.3
|
||||
|
||||
|
|
@ -0,0 +1,221 @@
|
|||
From 09744193cdcf400e5a4c54d9309acf5aea3a591c Mon Sep 17 00:00:00 2001
|
||||
From: Jernej Skrabec <jernej.skrabec@gmail.com>
|
||||
Date: Sun, 29 Sep 2024 22:04:34 +1300
|
||||
Subject: drm: sun4i: de2/de3: Merge CSC functions into one
|
||||
|
||||
At the moment the colour space conversion is handled by two functions:
|
||||
one to setup the conversion parameters, and another one to enable the
|
||||
conversion. Merging both into one gives more flexibility for upcoming
|
||||
extensions to support whole YUV pipelines, in the DE33.
|
||||
|
||||
Signed-off-by: Jernej Skrabec <jernej.skrabec@gmail.com>
|
||||
Signed-off-by: Ryan Walklin <ryan@testtoast.com>
|
||||
Reviewed-by: Andre Przywara <andre.przywara@arm.com>
|
||||
---
|
||||
drivers/gpu/drm/sun4i/sun8i_csc.c | 89 ++++++++++----------------
|
||||
drivers/gpu/drm/sun4i/sun8i_csc.h | 9 ++-
|
||||
drivers/gpu/drm/sun4i/sun8i_vi_layer.c | 11 +---
|
||||
3 files changed, 40 insertions(+), 69 deletions(-)
|
||||
|
||||
diff --git a/drivers/gpu/drm/sun4i/sun8i_csc.c b/drivers/gpu/drm/sun4i/sun8i_csc.c
|
||||
index 6ebd1c3aa3ab..0dcbc0866ae8 100644
|
||||
--- a/drivers/gpu/drm/sun4i/sun8i_csc.c
|
||||
+++ b/drivers/gpu/drm/sun4i/sun8i_csc.c
|
||||
@@ -107,23 +107,28 @@ static const u32 yuv2rgb_de3[2][3][12] = {
|
||||
},
|
||||
};
|
||||
|
||||
-static void sun8i_csc_set_coefficients(struct regmap *map, u32 base,
|
||||
- enum format_type fmt_type,
|
||||
- enum drm_color_encoding encoding,
|
||||
- enum drm_color_range range)
|
||||
+static void sun8i_csc_setup(struct regmap *map, u32 base,
|
||||
+ enum format_type fmt_type,
|
||||
+ enum drm_color_encoding encoding,
|
||||
+ enum drm_color_range range)
|
||||
{
|
||||
+ u32 base_reg, val;
|
||||
const u32 *table;
|
||||
- u32 base_reg;
|
||||
int i;
|
||||
|
||||
table = yuv2rgb[range][encoding];
|
||||
|
||||
switch (fmt_type) {
|
||||
+ case FORMAT_TYPE_RGB:
|
||||
+ val = 0;
|
||||
+ break;
|
||||
case FORMAT_TYPE_YUV:
|
||||
+ val = SUN8I_CSC_CTRL_EN;
|
||||
base_reg = SUN8I_CSC_COEFF(base, 0);
|
||||
regmap_bulk_write(map, base_reg, table, 12);
|
||||
break;
|
||||
case FORMAT_TYPE_YVU:
|
||||
+ val = SUN8I_CSC_CTRL_EN;
|
||||
for (i = 0; i < 12; i++) {
|
||||
if ((i & 3) == 1)
|
||||
base_reg = SUN8I_CSC_COEFF(base, i + 1);
|
||||
@@ -135,28 +140,37 @@ static void sun8i_csc_set_coefficients(struct regmap *map, u32 base,
|
||||
}
|
||||
break;
|
||||
default:
|
||||
+ val = 0;
|
||||
DRM_WARN("Wrong CSC mode specified.\n");
|
||||
return;
|
||||
}
|
||||
+
|
||||
+ regmap_write(map, SUN8I_CSC_CTRL(base), val);
|
||||
}
|
||||
|
||||
-static void sun8i_de3_ccsc_set_coefficients(struct regmap *map, int layer,
|
||||
- enum format_type fmt_type,
|
||||
- enum drm_color_encoding encoding,
|
||||
- enum drm_color_range range)
|
||||
+static void sun8i_de3_ccsc_setup(struct regmap *map, int layer,
|
||||
+ enum format_type fmt_type,
|
||||
+ enum drm_color_encoding encoding,
|
||||
+ enum drm_color_range range)
|
||||
{
|
||||
+ u32 addr, val, mask;
|
||||
const u32 *table;
|
||||
- u32 addr;
|
||||
int i;
|
||||
|
||||
+ mask = SUN50I_MIXER_BLEND_CSC_CTL_EN(layer);
|
||||
table = yuv2rgb_de3[range][encoding];
|
||||
|
||||
switch (fmt_type) {
|
||||
+ case FORMAT_TYPE_RGB:
|
||||
+ val = 0;
|
||||
+ break;
|
||||
case FORMAT_TYPE_YUV:
|
||||
+ val = mask;
|
||||
addr = SUN50I_MIXER_BLEND_CSC_COEFF(DE3_BLD_BASE, layer, 0);
|
||||
regmap_bulk_write(map, addr, table, 12);
|
||||
break;
|
||||
case FORMAT_TYPE_YVU:
|
||||
+ val = mask;
|
||||
for (i = 0; i < 12; i++) {
|
||||
if ((i & 3) == 1)
|
||||
addr = SUN50I_MIXER_BLEND_CSC_COEFF(DE3_BLD_BASE,
|
||||
@@ -173,67 +187,30 @@ static void sun8i_de3_ccsc_set_coefficients(struct regmap *map, int layer,
|
||||
}
|
||||
break;
|
||||
default:
|
||||
+ val = 0;
|
||||
DRM_WARN("Wrong CSC mode specified.\n");
|
||||
return;
|
||||
}
|
||||
-}
|
||||
-
|
||||
-static void sun8i_csc_enable(struct regmap *map, u32 base, bool enable)
|
||||
-{
|
||||
- u32 val;
|
||||
-
|
||||
- if (enable)
|
||||
- val = SUN8I_CSC_CTRL_EN;
|
||||
- else
|
||||
- val = 0;
|
||||
-
|
||||
- regmap_update_bits(map, SUN8I_CSC_CTRL(base), SUN8I_CSC_CTRL_EN, val);
|
||||
-}
|
||||
-
|
||||
-static void sun8i_de3_ccsc_enable(struct regmap *map, int layer, bool enable)
|
||||
-{
|
||||
- u32 val, mask;
|
||||
-
|
||||
- mask = SUN50I_MIXER_BLEND_CSC_CTL_EN(layer);
|
||||
-
|
||||
- if (enable)
|
||||
- val = mask;
|
||||
- else
|
||||
- val = 0;
|
||||
|
||||
regmap_update_bits(map, SUN50I_MIXER_BLEND_CSC_CTL(DE3_BLD_BASE),
|
||||
mask, val);
|
||||
}
|
||||
|
||||
-void sun8i_csc_set_ccsc_coefficients(struct sun8i_mixer *mixer, int layer,
|
||||
- enum format_type fmt_type,
|
||||
- enum drm_color_encoding encoding,
|
||||
- enum drm_color_range range)
|
||||
-{
|
||||
- u32 base;
|
||||
-
|
||||
- if (mixer->cfg->is_de3) {
|
||||
- sun8i_de3_ccsc_set_coefficients(mixer->engine.regs, layer,
|
||||
- fmt_type, encoding, range);
|
||||
- return;
|
||||
- }
|
||||
-
|
||||
- base = ccsc_base[mixer->cfg->ccsc][layer];
|
||||
-
|
||||
- sun8i_csc_set_coefficients(mixer->engine.regs, base,
|
||||
- fmt_type, encoding, range);
|
||||
-}
|
||||
-
|
||||
-void sun8i_csc_enable_ccsc(struct sun8i_mixer *mixer, int layer, bool enable)
|
||||
+void sun8i_csc_set_ccsc(struct sun8i_mixer *mixer, int layer,
|
||||
+ enum format_type fmt_type,
|
||||
+ enum drm_color_encoding encoding,
|
||||
+ enum drm_color_range range)
|
||||
{
|
||||
u32 base;
|
||||
|
||||
if (mixer->cfg->is_de3) {
|
||||
- sun8i_de3_ccsc_enable(mixer->engine.regs, layer, enable);
|
||||
+ sun8i_de3_ccsc_setup(mixer->engine.regs, layer,
|
||||
+ fmt_type, encoding, range);
|
||||
return;
|
||||
}
|
||||
|
||||
base = ccsc_base[mixer->cfg->ccsc][layer];
|
||||
|
||||
- sun8i_csc_enable(mixer->engine.regs, base, enable);
|
||||
+ sun8i_csc_setup(mixer->engine.regs, base,
|
||||
+ fmt_type, encoding, range);
|
||||
}
|
||||
diff --git a/drivers/gpu/drm/sun4i/sun8i_csc.h b/drivers/gpu/drm/sun4i/sun8i_csc.h
|
||||
index 7322770f39f0..b7546e06e315 100644
|
||||
--- a/drivers/gpu/drm/sun4i/sun8i_csc.h
|
||||
+++ b/drivers/gpu/drm/sun4i/sun8i_csc.h
|
||||
@@ -28,10 +28,9 @@ enum format_type {
|
||||
FORMAT_TYPE_YVU,
|
||||
};
|
||||
|
||||
-void sun8i_csc_set_ccsc_coefficients(struct sun8i_mixer *mixer, int layer,
|
||||
- enum format_type fmt_type,
|
||||
- enum drm_color_encoding encoding,
|
||||
- enum drm_color_range range);
|
||||
-void sun8i_csc_enable_ccsc(struct sun8i_mixer *mixer, int layer, bool enable);
|
||||
+void sun8i_csc_set_ccsc(struct sun8i_mixer *mixer, int layer,
|
||||
+ enum format_type fmt_type,
|
||||
+ enum drm_color_encoding encoding,
|
||||
+ enum drm_color_range range);
|
||||
|
||||
#endif
|
||||
diff --git a/drivers/gpu/drm/sun4i/sun8i_vi_layer.c b/drivers/gpu/drm/sun4i/sun8i_vi_layer.c
|
||||
index 8a80934e928f..f3a5329351ca 100644
|
||||
--- a/drivers/gpu/drm/sun4i/sun8i_vi_layer.c
|
||||
+++ b/drivers/gpu/drm/sun4i/sun8i_vi_layer.c
|
||||
@@ -232,14 +232,9 @@ static int sun8i_vi_layer_update_formats(struct sun8i_mixer *mixer, int channel,
|
||||
SUN8I_MIXER_CHAN_VI_LAYER_ATTR_FBFMT_MASK, val);
|
||||
|
||||
fmt_type = sun8i_vi_layer_get_format_type(fmt);
|
||||
- if (fmt_type != FORMAT_TYPE_RGB) {
|
||||
- sun8i_csc_set_ccsc_coefficients(mixer, channel, fmt_type,
|
||||
- state->color_encoding,
|
||||
- state->color_range);
|
||||
- sun8i_csc_enable_ccsc(mixer, channel, true);
|
||||
- } else {
|
||||
- sun8i_csc_enable_ccsc(mixer, channel, false);
|
||||
- }
|
||||
+ sun8i_csc_set_ccsc(mixer, channel, fmt_type,
|
||||
+ state->color_encoding,
|
||||
+ state->color_range);
|
||||
|
||||
if (!fmt->is_yuv)
|
||||
val = SUN8I_MIXER_CHAN_VI_LAYER_ATTR_RGB_MODE;
|
||||
--
|
||||
2.35.3
|
||||
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
From 45d06599927825fe1fa3c374508d6d0c8c9f9f52 Mon Sep 17 00:00:00 2001
|
||||
From: Jernej Skrabec <jernej.skrabec@gmail.com>
|
||||
Date: Sun, 29 Sep 2024 22:04:48 +1300
|
||||
Subject: drm: sun4i: de2/de3: add generic blender register reference function
|
||||
|
||||
The DE2 and DE3 engines have a blender register range within the
|
||||
mixer engine register map, whereas the DE33 separates this out into
|
||||
a separate display group.
|
||||
|
||||
Prepare for this by adding a function to look the blender reference up,
|
||||
with a subsequent patch to add a conditional based on the DE type.
|
||||
|
||||
Signed-off-by: Jernej Skrabec <jernej.skrabec@gmail.com>
|
||||
Signed-off-by: Ryan Walklin <ryan@testtoast.com>
|
||||
---
|
||||
drivers/gpu/drm/sun4i/sun8i_mixer.h | 6 ++++++
|
||||
1 file changed, 6 insertions(+)
|
||||
|
||||
diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.h b/drivers/gpu/drm/sun4i/sun8i_mixer.h
|
||||
index 82956cb97cfd..75facc7d1fa6 100644
|
||||
--- a/drivers/gpu/drm/sun4i/sun8i_mixer.h
|
||||
+++ b/drivers/gpu/drm/sun4i/sun8i_mixer.h
|
||||
@@ -224,6 +224,12 @@ sun8i_blender_base(struct sun8i_mixer *mixer)
|
||||
return mixer->cfg->de_type == sun8i_mixer_de3 ? DE3_BLD_BASE : DE2_BLD_BASE;
|
||||
}
|
||||
|
||||
+static inline struct regmap *
|
||||
+sun8i_blender_regmap(struct sun8i_mixer *mixer)
|
||||
+{
|
||||
+ return mixer->engine.regs;
|
||||
+}
|
||||
+
|
||||
static inline u32
|
||||
sun8i_channel_base(struct sun8i_mixer *mixer, int channel)
|
||||
{
|
||||
--
|
||||
2.35.3
|
||||
|
||||
|
|
@ -0,0 +1,257 @@
|
|||
From b49e4fb3439c50eb6effc559366b3e88e2ac2f27 Mon Sep 17 00:00:00 2001
|
||||
From: Jernej Skrabec <jernej.skrabec@gmail.com>
|
||||
Date: Sun, 29 Sep 2024 22:04:45 +1300
|
||||
Subject: drm: sun4i: de2/de3: add mixer version enum
|
||||
|
||||
The Allwinner DE2 and DE3 display engine mixers are currently identified
|
||||
by a simple boolean flag. This will not scale to support additional DE
|
||||
variants.
|
||||
|
||||
Convert the boolean flag to an enum.
|
||||
|
||||
Signed-off-by: Jernej Skrabec <jernej.skrabec@gmail.com>
|
||||
Signed-off-by: Ryan Walklin <ryan@testtoast.com>
|
||||
Reviewed-by: Andre Przywara <andre.przywara@arm.com>
|
||||
---
|
||||
drivers/gpu/drm/sun4i/sun8i_csc.c | 2 +-
|
||||
drivers/gpu/drm/sun4i/sun8i_mixer.c | 14 ++++++++++++--
|
||||
drivers/gpu/drm/sun4i/sun8i_mixer.h | 11 ++++++++---
|
||||
drivers/gpu/drm/sun4i/sun8i_ui_scaler.c | 2 +-
|
||||
drivers/gpu/drm/sun4i/sun8i_vi_layer.c | 8 ++++----
|
||||
drivers/gpu/drm/sun4i/sun8i_vi_scaler.c | 4 ++--
|
||||
6 files changed, 28 insertions(+), 13 deletions(-)
|
||||
|
||||
diff --git a/drivers/gpu/drm/sun4i/sun8i_csc.c b/drivers/gpu/drm/sun4i/sun8i_csc.c
|
||||
index e12a81fa9108..2d5a2cf7cba2 100644
|
||||
--- a/drivers/gpu/drm/sun4i/sun8i_csc.c
|
||||
+++ b/drivers/gpu/drm/sun4i/sun8i_csc.c
|
||||
@@ -365,7 +365,7 @@ void sun8i_csc_set_ccsc(struct sun8i_mixer *mixer, int layer,
|
||||
{
|
||||
u32 base;
|
||||
|
||||
- if (mixer->cfg->is_de3) {
|
||||
+ if (mixer->cfg->de_type == sun8i_mixer_de3) {
|
||||
sun8i_de3_ccsc_setup(&mixer->engine, layer,
|
||||
fmt_type, encoding, range);
|
||||
return;
|
||||
diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.c b/drivers/gpu/drm/sun4i/sun8i_mixer.c
|
||||
index a50c583852ed..16e018aa4aae 100644
|
||||
--- a/drivers/gpu/drm/sun4i/sun8i_mixer.c
|
||||
+++ b/drivers/gpu/drm/sun4i/sun8i_mixer.c
|
||||
@@ -584,7 +584,7 @@ static int sun8i_mixer_bind(struct device *dev, struct device *master,
|
||||
base = sun8i_blender_base(mixer);
|
||||
|
||||
/* Reset registers and disable unused sub-engines */
|
||||
- if (mixer->cfg->is_de3) {
|
||||
+ if (mixer->cfg->de_type == sun8i_mixer_de3) {
|
||||
for (i = 0; i < DE3_MIXER_UNIT_SIZE; i += 4)
|
||||
regmap_write(mixer->engine.regs, i, 0);
|
||||
|
||||
@@ -675,6 +675,7 @@ static void sun8i_mixer_remove(struct platform_device *pdev)
|
||||
|
||||
static const struct sun8i_mixer_cfg sun8i_a83t_mixer0_cfg = {
|
||||
.ccsc = CCSC_MIXER0_LAYOUT,
|
||||
+ .de_type = sun8i_mixer_de2,
|
||||
.scaler_mask = 0xf,
|
||||
.scanline_yuv = 2048,
|
||||
.ui_num = 3,
|
||||
@@ -683,6 +684,7 @@ static const struct sun8i_mixer_cfg sun8i_a83t_mixer0_cfg = {
|
||||
|
||||
static const struct sun8i_mixer_cfg sun8i_a83t_mixer1_cfg = {
|
||||
.ccsc = CCSC_MIXER1_LAYOUT,
|
||||
+ .de_type = sun8i_mixer_de2,
|
||||
.scaler_mask = 0x3,
|
||||
.scanline_yuv = 2048,
|
||||
.ui_num = 1,
|
||||
@@ -691,6 +693,7 @@ static const struct sun8i_mixer_cfg sun8i_a83t_mixer1_cfg = {
|
||||
|
||||
static const struct sun8i_mixer_cfg sun8i_h3_mixer0_cfg = {
|
||||
.ccsc = CCSC_MIXER0_LAYOUT,
|
||||
+ .de_type = sun8i_mixer_de2,
|
||||
.mod_rate = 432000000,
|
||||
.scaler_mask = 0xf,
|
||||
.scanline_yuv = 2048,
|
||||
@@ -700,6 +703,7 @@ static const struct sun8i_mixer_cfg sun8i_h3_mixer0_cfg = {
|
||||
|
||||
static const struct sun8i_mixer_cfg sun8i_r40_mixer0_cfg = {
|
||||
.ccsc = CCSC_MIXER0_LAYOUT,
|
||||
+ .de_type = sun8i_mixer_de2,
|
||||
.mod_rate = 297000000,
|
||||
.scaler_mask = 0xf,
|
||||
.scanline_yuv = 2048,
|
||||
@@ -709,6 +713,7 @@ static const struct sun8i_mixer_cfg sun8i_r40_mixer0_cfg = {
|
||||
|
||||
static const struct sun8i_mixer_cfg sun8i_r40_mixer1_cfg = {
|
||||
.ccsc = CCSC_MIXER1_LAYOUT,
|
||||
+ .de_type = sun8i_mixer_de2,
|
||||
.mod_rate = 297000000,
|
||||
.scaler_mask = 0x3,
|
||||
.scanline_yuv = 2048,
|
||||
@@ -717,6 +722,7 @@ static const struct sun8i_mixer_cfg sun8i_r40_mixer1_cfg = {
|
||||
};
|
||||
|
||||
static const struct sun8i_mixer_cfg sun8i_v3s_mixer_cfg = {
|
||||
+ .de_type = sun8i_mixer_de2,
|
||||
.vi_num = 2,
|
||||
.ui_num = 1,
|
||||
.scaler_mask = 0x3,
|
||||
@@ -727,6 +733,7 @@ static const struct sun8i_mixer_cfg sun8i_v3s_mixer_cfg = {
|
||||
|
||||
static const struct sun8i_mixer_cfg sun20i_d1_mixer0_cfg = {
|
||||
.ccsc = CCSC_D1_MIXER0_LAYOUT,
|
||||
+ .de_type = sun8i_mixer_de2,
|
||||
.mod_rate = 297000000,
|
||||
.scaler_mask = 0x3,
|
||||
.scanline_yuv = 2048,
|
||||
@@ -736,6 +743,7 @@ static const struct sun8i_mixer_cfg sun20i_d1_mixer0_cfg = {
|
||||
|
||||
static const struct sun8i_mixer_cfg sun20i_d1_mixer1_cfg = {
|
||||
.ccsc = CCSC_MIXER1_LAYOUT,
|
||||
+ .de_type = sun8i_mixer_de2,
|
||||
.mod_rate = 297000000,
|
||||
.scaler_mask = 0x1,
|
||||
.scanline_yuv = 1024,
|
||||
@@ -745,6 +753,7 @@ static const struct sun8i_mixer_cfg sun20i_d1_mixer1_cfg = {
|
||||
|
||||
static const struct sun8i_mixer_cfg sun50i_a64_mixer0_cfg = {
|
||||
.ccsc = CCSC_MIXER0_LAYOUT,
|
||||
+ .de_type = sun8i_mixer_de2,
|
||||
.mod_rate = 297000000,
|
||||
.scaler_mask = 0xf,
|
||||
.scanline_yuv = 4096,
|
||||
@@ -754,6 +763,7 @@ static const struct sun8i_mixer_cfg sun50i_a64_mixer0_cfg = {
|
||||
|
||||
static const struct sun8i_mixer_cfg sun50i_a64_mixer1_cfg = {
|
||||
.ccsc = CCSC_MIXER1_LAYOUT,
|
||||
+ .de_type = sun8i_mixer_de2,
|
||||
.mod_rate = 297000000,
|
||||
.scaler_mask = 0x3,
|
||||
.scanline_yuv = 2048,
|
||||
@@ -763,7 +773,7 @@ static const struct sun8i_mixer_cfg sun50i_a64_mixer1_cfg = {
|
||||
|
||||
static const struct sun8i_mixer_cfg sun50i_h6_mixer0_cfg = {
|
||||
.ccsc = CCSC_MIXER0_LAYOUT,
|
||||
- .is_de3 = true,
|
||||
+ .de_type = sun8i_mixer_de3,
|
||||
.has_formatter = 1,
|
||||
.mod_rate = 600000000,
|
||||
.scaler_mask = 0xf,
|
||||
diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.h b/drivers/gpu/drm/sun4i/sun8i_mixer.h
|
||||
index 8417b8fef2e1..82956cb97cfd 100644
|
||||
--- a/drivers/gpu/drm/sun4i/sun8i_mixer.h
|
||||
+++ b/drivers/gpu/drm/sun4i/sun8i_mixer.h
|
||||
@@ -151,6 +151,11 @@ enum {
|
||||
CCSC_D1_MIXER0_LAYOUT,
|
||||
};
|
||||
|
||||
+enum sun8i_mixer_type {
|
||||
+ sun8i_mixer_de2,
|
||||
+ sun8i_mixer_de3,
|
||||
+};
|
||||
+
|
||||
/**
|
||||
* struct sun8i_mixer_cfg - mixer HW configuration
|
||||
* @vi_num: number of VI channels
|
||||
@@ -172,7 +177,7 @@ struct sun8i_mixer_cfg {
|
||||
int scaler_mask;
|
||||
int ccsc;
|
||||
unsigned long mod_rate;
|
||||
- unsigned int is_de3 : 1;
|
||||
+ unsigned int de_type;
|
||||
unsigned int has_formatter : 1;
|
||||
unsigned int scanline_yuv;
|
||||
};
|
||||
@@ -216,13 +221,13 @@ engine_to_sun8i_mixer(struct sunxi_engine *engine)
|
||||
static inline u32
|
||||
sun8i_blender_base(struct sun8i_mixer *mixer)
|
||||
{
|
||||
- return mixer->cfg->is_de3 ? DE3_BLD_BASE : DE2_BLD_BASE;
|
||||
+ return mixer->cfg->de_type == sun8i_mixer_de3 ? DE3_BLD_BASE : DE2_BLD_BASE;
|
||||
}
|
||||
|
||||
static inline u32
|
||||
sun8i_channel_base(struct sun8i_mixer *mixer, int channel)
|
||||
{
|
||||
- if (mixer->cfg->is_de3)
|
||||
+ if (mixer->cfg->de_type == sun8i_mixer_de3)
|
||||
return DE3_CH_BASE + channel * DE3_CH_SIZE;
|
||||
else
|
||||
return DE2_CH_BASE + channel * DE2_CH_SIZE;
|
||||
diff --git a/drivers/gpu/drm/sun4i/sun8i_ui_scaler.c b/drivers/gpu/drm/sun4i/sun8i_ui_scaler.c
|
||||
index ae0806bccac7..504ffa0971a4 100644
|
||||
--- a/drivers/gpu/drm/sun4i/sun8i_ui_scaler.c
|
||||
+++ b/drivers/gpu/drm/sun4i/sun8i_ui_scaler.c
|
||||
@@ -93,7 +93,7 @@ static u32 sun8i_ui_scaler_base(struct sun8i_mixer *mixer, int channel)
|
||||
{
|
||||
int vi_num = mixer->cfg->vi_num;
|
||||
|
||||
- if (mixer->cfg->is_de3)
|
||||
+ if (mixer->cfg->de_type == sun8i_mixer_de3)
|
||||
return DE3_VI_SCALER_UNIT_BASE +
|
||||
DE3_VI_SCALER_UNIT_SIZE * vi_num +
|
||||
DE3_UI_SCALER_UNIT_SIZE * (channel - vi_num);
|
||||
diff --git a/drivers/gpu/drm/sun4i/sun8i_vi_layer.c b/drivers/gpu/drm/sun4i/sun8i_vi_layer.c
|
||||
index 3c657b069d1f..4647e9bcccaa 100644
|
||||
--- a/drivers/gpu/drm/sun4i/sun8i_vi_layer.c
|
||||
+++ b/drivers/gpu/drm/sun4i/sun8i_vi_layer.c
|
||||
@@ -25,7 +25,7 @@ static void sun8i_vi_layer_update_alpha(struct sun8i_mixer *mixer, int channel,
|
||||
|
||||
ch_base = sun8i_channel_base(mixer, channel);
|
||||
|
||||
- if (mixer->cfg->is_de3) {
|
||||
+ if (mixer->cfg->de_type >= sun8i_mixer_de3) {
|
||||
mask = SUN50I_MIXER_CHAN_VI_LAYER_ATTR_ALPHA_MASK |
|
||||
SUN50I_MIXER_CHAN_VI_LAYER_ATTR_ALPHA_MODE_MASK;
|
||||
val = SUN50I_MIXER_CHAN_VI_LAYER_ATTR_ALPHA
|
||||
@@ -483,7 +483,7 @@ struct sun8i_layer *sun8i_vi_layer_init_one(struct drm_device *drm,
|
||||
layer->channel = index;
|
||||
layer->overlay = 0;
|
||||
|
||||
- if (mixer->cfg->is_de3) {
|
||||
+ if (mixer->cfg->de_type >= sun8i_mixer_de3) {
|
||||
formats = sun8i_vi_layer_de3_formats;
|
||||
format_count = ARRAY_SIZE(sun8i_vi_layer_de3_formats);
|
||||
} else {
|
||||
@@ -507,7 +507,7 @@ struct sun8i_layer *sun8i_vi_layer_init_one(struct drm_device *drm,
|
||||
|
||||
plane_cnt = mixer->cfg->ui_num + mixer->cfg->vi_num;
|
||||
|
||||
- if (mixer->cfg->vi_num == 1 || mixer->cfg->is_de3) {
|
||||
+ if (mixer->cfg->vi_num == 1 || mixer->cfg->de_type >= sun8i_mixer_de3) {
|
||||
ret = drm_plane_create_alpha_property(&layer->plane);
|
||||
if (ret) {
|
||||
dev_err(drm->dev, "Couldn't add alpha property\n");
|
||||
@@ -524,7 +524,7 @@ struct sun8i_layer *sun8i_vi_layer_init_one(struct drm_device *drm,
|
||||
|
||||
supported_encodings = BIT(DRM_COLOR_YCBCR_BT601) |
|
||||
BIT(DRM_COLOR_YCBCR_BT709);
|
||||
- if (mixer->cfg->is_de3)
|
||||
+ if (mixer->cfg->de_type >= sun8i_mixer_de3)
|
||||
supported_encodings |= BIT(DRM_COLOR_YCBCR_BT2020);
|
||||
|
||||
supported_ranges = BIT(DRM_COLOR_YCBCR_LIMITED_RANGE) |
|
||||
diff --git a/drivers/gpu/drm/sun4i/sun8i_vi_scaler.c b/drivers/gpu/drm/sun4i/sun8i_vi_scaler.c
|
||||
index 2e49a6e5f1f1..aa346c3beb30 100644
|
||||
--- a/drivers/gpu/drm/sun4i/sun8i_vi_scaler.c
|
||||
+++ b/drivers/gpu/drm/sun4i/sun8i_vi_scaler.c
|
||||
@@ -835,7 +835,7 @@ static const u32 bicubic4coefftab32[480] = {
|
||||
|
||||
static u32 sun8i_vi_scaler_base(struct sun8i_mixer *mixer, int channel)
|
||||
{
|
||||
- if (mixer->cfg->is_de3)
|
||||
+ if (mixer->cfg->de_type == sun8i_mixer_de3)
|
||||
return DE3_VI_SCALER_UNIT_BASE +
|
||||
DE3_VI_SCALER_UNIT_SIZE * channel;
|
||||
else
|
||||
@@ -982,7 +982,7 @@ void sun8i_vi_scaler_setup(struct sun8i_mixer *mixer, int layer,
|
||||
cvphase = vphase;
|
||||
}
|
||||
|
||||
- if (mixer->cfg->is_de3) {
|
||||
+ if (mixer->cfg->de_type >= sun8i_mixer_de3) {
|
||||
u32 val;
|
||||
|
||||
if (format->hsub == 1 && format->vsub == 1)
|
||||
--
|
||||
2.35.3
|
||||
|
||||
|
|
@ -0,0 +1,64 @@
|
|||
From 000c586a34ad82e4673e6dfda5457147b0d85606 Mon Sep 17 00:00:00 2001
|
||||
From: Jernej Skrabec <jernej.skrabec@gmail.com>
|
||||
Date: Sun, 29 Sep 2024 22:04:35 +1300
|
||||
Subject: drm: sun4i: de2/de3: call csc setup also for UI layer
|
||||
|
||||
Currently, only VI layer calls CSC setup function. This comes from DE2
|
||||
limitation, which doesn't have CSC unit for UI layers. However, DE3 has
|
||||
separate CSC units for each layer. This allows display pipeline to make
|
||||
output signal in different color spaces. To support both use cases, add
|
||||
a call to CSC setup function also in UI layer code. For DE2, this will
|
||||
be a no-op, but it will allow DE3 to output signal in multiple formats.
|
||||
|
||||
Signed-off-by: Jernej Skrabec <jernej.skrabec@gmail.com>
|
||||
Signed-off-by: Ryan Walklin <ryan@testtoast.com>
|
||||
---
|
||||
drivers/gpu/drm/sun4i/sun8i_csc.c | 8 +++++---
|
||||
drivers/gpu/drm/sun4i/sun8i_ui_layer.c | 6 ++++++
|
||||
2 files changed, 11 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/drivers/gpu/drm/sun4i/sun8i_csc.c b/drivers/gpu/drm/sun4i/sun8i_csc.c
|
||||
index 0dcbc0866ae8..68d955c63b05 100644
|
||||
--- a/drivers/gpu/drm/sun4i/sun8i_csc.c
|
||||
+++ b/drivers/gpu/drm/sun4i/sun8i_csc.c
|
||||
@@ -209,8 +209,10 @@ void sun8i_csc_set_ccsc(struct sun8i_mixer *mixer, int layer,
|
||||
return;
|
||||
}
|
||||
|
||||
- base = ccsc_base[mixer->cfg->ccsc][layer];
|
||||
+ if (layer < mixer->cfg->vi_num) {
|
||||
+ base = ccsc_base[mixer->cfg->ccsc][layer];
|
||||
|
||||
- sun8i_csc_setup(mixer->engine.regs, base,
|
||||
- fmt_type, encoding, range);
|
||||
+ sun8i_csc_setup(mixer->engine.regs, base,
|
||||
+ fmt_type, encoding, range);
|
||||
+ }
|
||||
}
|
||||
diff --git a/drivers/gpu/drm/sun4i/sun8i_ui_layer.c b/drivers/gpu/drm/sun4i/sun8i_ui_layer.c
|
||||
index b90e5edef4e8..aa987bca1dbb 100644
|
||||
--- a/drivers/gpu/drm/sun4i/sun8i_ui_layer.c
|
||||
+++ b/drivers/gpu/drm/sun4i/sun8i_ui_layer.c
|
||||
@@ -20,6 +20,7 @@
|
||||
#include <drm/drm_gem_dma_helper.h>
|
||||
#include <drm/drm_probe_helper.h>
|
||||
|
||||
+#include "sun8i_csc.h"
|
||||
#include "sun8i_mixer.h"
|
||||
#include "sun8i_ui_layer.h"
|
||||
#include "sun8i_ui_scaler.h"
|
||||
@@ -135,6 +136,11 @@ static int sun8i_ui_layer_update_formats(struct sun8i_mixer *mixer, int channel,
|
||||
SUN8I_MIXER_CHAN_UI_LAYER_ATTR(ch_base, overlay),
|
||||
SUN8I_MIXER_CHAN_UI_LAYER_ATTR_FBFMT_MASK, val);
|
||||
|
||||
+ /* Note: encoding and range arguments are ignored for RGB */
|
||||
+ sun8i_csc_set_ccsc(mixer, channel, FORMAT_TYPE_RGB,
|
||||
+ DRM_COLOR_YCBCR_BT601,
|
||||
+ DRM_COLOR_YCBCR_FULL_RANGE);
|
||||
+
|
||||
return 0;
|
||||
}
|
||||
|
||||
--
|
||||
2.35.3
|
||||
|
||||
|
|
@ -0,0 +1,121 @@
|
|||
From 18890b5c9dbf9270b7f0e42875d6b8bd14ee6624 Mon Sep 17 00:00:00 2001
|
||||
From: Jernej Skrabec <jernej.skrabec@gmail.com>
|
||||
Date: Sun, 29 Sep 2024 22:04:46 +1300
|
||||
Subject: drm: sun4i: de2/de3: refactor mixer initialisation
|
||||
|
||||
Now that the DE variant can be selected by enum, take the oppportunity
|
||||
to factor out some common initialisation code to a separate function.
|
||||
|
||||
Signed-off-by: Jernej Skrabec <jernej.skrabec@gmail.com>
|
||||
Signed-off-by: Ryan Walklin <ryan@testtoast.com>
|
||||
Reviewed-by: Andre Przywara <andre.przywara@arm.com>
|
||||
---
|
||||
drivers/gpu/drm/sun4i/sun8i_mixer.c | 64 +++++++++++++++--------------
|
||||
1 file changed, 34 insertions(+), 30 deletions(-)
|
||||
|
||||
diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.c b/drivers/gpu/drm/sun4i/sun8i_mixer.c
|
||||
index 16e018aa4aae..18745af08954 100644
|
||||
--- a/drivers/gpu/drm/sun4i/sun8i_mixer.c
|
||||
+++ b/drivers/gpu/drm/sun4i/sun8i_mixer.c
|
||||
@@ -468,6 +468,38 @@ static int sun8i_mixer_of_get_id(struct device_node *node)
|
||||
return of_ep.id;
|
||||
}
|
||||
|
||||
+static void sun8i_mixer_init(struct sun8i_mixer *mixer)
|
||||
+{
|
||||
+ unsigned int base = sun8i_blender_base(mixer);
|
||||
+ int plane_cnt, i;
|
||||
+
|
||||
+ /* Enable the mixer */
|
||||
+ regmap_write(mixer->engine.regs, SUN8I_MIXER_GLOBAL_CTL,
|
||||
+ SUN8I_MIXER_GLOBAL_CTL_RT_EN);
|
||||
+
|
||||
+ /* Set background color to black */
|
||||
+ regmap_write(mixer->engine.regs, SUN8I_MIXER_BLEND_BKCOLOR(base),
|
||||
+ SUN8I_MIXER_BLEND_COLOR_BLACK);
|
||||
+
|
||||
+ /*
|
||||
+ * Set fill color of bottom plane to black. Generally not needed
|
||||
+ * except when VI plane is at bottom (zpos = 0) and enabled.
|
||||
+ */
|
||||
+ regmap_write(mixer->engine.regs, SUN8I_MIXER_BLEND_PIPE_CTL(base),
|
||||
+ SUN8I_MIXER_BLEND_PIPE_CTL_FC_EN(0));
|
||||
+ regmap_write(mixer->engine.regs, SUN8I_MIXER_BLEND_ATTR_FCOLOR(base, 0),
|
||||
+ SUN8I_MIXER_BLEND_COLOR_BLACK);
|
||||
+
|
||||
+ plane_cnt = mixer->cfg->vi_num + mixer->cfg->ui_num;
|
||||
+ for (i = 0; i < plane_cnt; i++)
|
||||
+ regmap_write(mixer->engine.regs,
|
||||
+ SUN8I_MIXER_BLEND_MODE(base, i),
|
||||
+ SUN8I_MIXER_BLEND_MODE_DEF);
|
||||
+
|
||||
+ regmap_update_bits(mixer->engine.regs, SUN8I_MIXER_BLEND_PIPE_CTL(base),
|
||||
+ SUN8I_MIXER_BLEND_PIPE_CTL_EN_MSK, 0);
|
||||
+}
|
||||
+
|
||||
static int sun8i_mixer_bind(struct device *dev, struct device *master,
|
||||
void *data)
|
||||
{
|
||||
@@ -476,8 +508,6 @@ static int sun8i_mixer_bind(struct device *dev, struct device *master,
|
||||
struct sun4i_drv *drv = drm->dev_private;
|
||||
struct sun8i_mixer *mixer;
|
||||
void __iomem *regs;
|
||||
- unsigned int base;
|
||||
- int plane_cnt;
|
||||
int i, ret;
|
||||
|
||||
/*
|
||||
@@ -581,8 +611,6 @@ static int sun8i_mixer_bind(struct device *dev, struct device *master,
|
||||
|
||||
list_add_tail(&mixer->engine.list, &drv->engine_list);
|
||||
|
||||
- base = sun8i_blender_base(mixer);
|
||||
-
|
||||
/* Reset registers and disable unused sub-engines */
|
||||
if (mixer->cfg->de_type == sun8i_mixer_de3) {
|
||||
for (i = 0; i < DE3_MIXER_UNIT_SIZE; i += 4)
|
||||
@@ -598,7 +626,7 @@ static int sun8i_mixer_bind(struct device *dev, struct device *master,
|
||||
regmap_write(mixer->engine.regs, SUN50I_MIXER_FMT_EN, 0);
|
||||
regmap_write(mixer->engine.regs, SUN50I_MIXER_CDC0_EN, 0);
|
||||
regmap_write(mixer->engine.regs, SUN50I_MIXER_CDC1_EN, 0);
|
||||
- } else {
|
||||
+ } else if (mixer->cfg->de_type == sun8i_mixer_de2) {
|
||||
for (i = 0; i < DE2_MIXER_UNIT_SIZE; i += 4)
|
||||
regmap_write(mixer->engine.regs, i, 0);
|
||||
|
||||
@@ -611,31 +639,7 @@ static int sun8i_mixer_bind(struct device *dev, struct device *master,
|
||||
regmap_write(mixer->engine.regs, SUN8I_MIXER_DCSC_EN, 0);
|
||||
}
|
||||
|
||||
- /* Enable the mixer */
|
||||
- regmap_write(mixer->engine.regs, SUN8I_MIXER_GLOBAL_CTL,
|
||||
- SUN8I_MIXER_GLOBAL_CTL_RT_EN);
|
||||
-
|
||||
- /* Set background color to black */
|
||||
- regmap_write(mixer->engine.regs, SUN8I_MIXER_BLEND_BKCOLOR(base),
|
||||
- SUN8I_MIXER_BLEND_COLOR_BLACK);
|
||||
-
|
||||
- /*
|
||||
- * Set fill color of bottom plane to black. Generally not needed
|
||||
- * except when VI plane is at bottom (zpos = 0) and enabled.
|
||||
- */
|
||||
- regmap_write(mixer->engine.regs, SUN8I_MIXER_BLEND_PIPE_CTL(base),
|
||||
- SUN8I_MIXER_BLEND_PIPE_CTL_FC_EN(0));
|
||||
- regmap_write(mixer->engine.regs, SUN8I_MIXER_BLEND_ATTR_FCOLOR(base, 0),
|
||||
- SUN8I_MIXER_BLEND_COLOR_BLACK);
|
||||
-
|
||||
- plane_cnt = mixer->cfg->vi_num + mixer->cfg->ui_num;
|
||||
- for (i = 0; i < plane_cnt; i++)
|
||||
- regmap_write(mixer->engine.regs,
|
||||
- SUN8I_MIXER_BLEND_MODE(base, i),
|
||||
- SUN8I_MIXER_BLEND_MODE_DEF);
|
||||
-
|
||||
- regmap_update_bits(mixer->engine.regs, SUN8I_MIXER_BLEND_PIPE_CTL(base),
|
||||
- SUN8I_MIXER_BLEND_PIPE_CTL_EN_MSK, 0);
|
||||
+ sun8i_mixer_init(mixer);
|
||||
|
||||
return 0;
|
||||
|
||||
--
|
||||
2.35.3
|
||||
|
||||
|
|
@ -0,0 +1,117 @@
|
|||
From a756d6b4ac645ac3c18d5758faec068b3c8819a6 Mon Sep 17 00:00:00 2001
|
||||
From: Jernej Skrabec <jernej.skrabec@gmail.com>
|
||||
Date: Sun, 29 Sep 2024 22:04:49 +1300
|
||||
Subject: drm: sun4i: de2/de3: use generic register reference function for
|
||||
layer configuration
|
||||
|
||||
Use the new blender register lookup function where required in the layer
|
||||
commit and update code.
|
||||
|
||||
Signed-off-by: Jernej Skrabec <jernej.skrabec@gmail.com>
|
||||
Signed-off-by: Ryan Walklin <ryan@testtoast.com>
|
||||
---
|
||||
drivers/gpu/drm/sun4i/sun8i_mixer.c | 5 +++--
|
||||
drivers/gpu/drm/sun4i/sun8i_ui_layer.c | 7 +++++--
|
||||
drivers/gpu/drm/sun4i/sun8i_vi_layer.c | 6 ++++--
|
||||
3 files changed, 12 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.c b/drivers/gpu/drm/sun4i/sun8i_mixer.c
|
||||
index 18745af08954..600084286b39 100644
|
||||
--- a/drivers/gpu/drm/sun4i/sun8i_mixer.c
|
||||
+++ b/drivers/gpu/drm/sun4i/sun8i_mixer.c
|
||||
@@ -277,6 +277,7 @@ static void sun8i_mixer_commit(struct sunxi_engine *engine,
|
||||
{
|
||||
struct sun8i_mixer *mixer = engine_to_sun8i_mixer(engine);
|
||||
u32 bld_base = sun8i_blender_base(mixer);
|
||||
+ struct regmap *bld_regs = sun8i_blender_regmap(mixer);
|
||||
struct drm_plane_state *plane_state;
|
||||
struct drm_plane *plane;
|
||||
u32 route = 0, pipe_en = 0;
|
||||
@@ -316,8 +317,8 @@ static void sun8i_mixer_commit(struct sunxi_engine *engine,
|
||||
pipe_en |= SUN8I_MIXER_BLEND_PIPE_CTL_EN(zpos);
|
||||
}
|
||||
|
||||
- regmap_write(mixer->engine.regs, SUN8I_MIXER_BLEND_ROUTE(bld_base), route);
|
||||
- regmap_write(mixer->engine.regs, SUN8I_MIXER_BLEND_PIPE_CTL(bld_base),
|
||||
+ regmap_write(bld_regs, SUN8I_MIXER_BLEND_ROUTE(bld_base), route);
|
||||
+ regmap_write(bld_regs, SUN8I_MIXER_BLEND_PIPE_CTL(bld_base),
|
||||
pipe_en | SUN8I_MIXER_BLEND_PIPE_CTL_FC_EN(0));
|
||||
|
||||
regmap_write(engine->regs, SUN8I_MIXER_GLOBAL_DBUFF,
|
||||
diff --git a/drivers/gpu/drm/sun4i/sun8i_ui_layer.c b/drivers/gpu/drm/sun4i/sun8i_ui_layer.c
|
||||
index cb9b694fef10..7f1231cf0f01 100644
|
||||
--- a/drivers/gpu/drm/sun4i/sun8i_ui_layer.c
|
||||
+++ b/drivers/gpu/drm/sun4i/sun8i_ui_layer.c
|
||||
@@ -24,6 +24,7 @@
|
||||
#include "sun8i_mixer.h"
|
||||
#include "sun8i_ui_layer.h"
|
||||
#include "sun8i_ui_scaler.h"
|
||||
+#include "sun8i_vi_scaler.h"
|
||||
|
||||
static void sun8i_ui_layer_update_alpha(struct sun8i_mixer *mixer, int channel,
|
||||
int overlay, struct drm_plane *plane)
|
||||
@@ -52,6 +53,7 @@ static int sun8i_ui_layer_update_coord(struct sun8i_mixer *mixer, int channel,
|
||||
{
|
||||
struct drm_plane_state *state = plane->state;
|
||||
u32 src_w, src_h, dst_w, dst_h;
|
||||
+ struct regmap *bld_regs;
|
||||
u32 bld_base, ch_base;
|
||||
u32 outsize, insize;
|
||||
u32 hphase, vphase;
|
||||
@@ -60,6 +62,7 @@ static int sun8i_ui_layer_update_coord(struct sun8i_mixer *mixer, int channel,
|
||||
channel, overlay);
|
||||
|
||||
bld_base = sun8i_blender_base(mixer);
|
||||
+ bld_regs = sun8i_blender_regmap(mixer);
|
||||
ch_base = sun8i_channel_base(mixer, channel);
|
||||
|
||||
src_w = drm_rect_width(&state->src) >> 16;
|
||||
@@ -104,10 +107,10 @@ static int sun8i_ui_layer_update_coord(struct sun8i_mixer *mixer, int channel,
|
||||
DRM_DEBUG_DRIVER("Layer destination coordinates X: %d Y: %d\n",
|
||||
state->dst.x1, state->dst.y1);
|
||||
DRM_DEBUG_DRIVER("Layer destination size W: %d H: %d\n", dst_w, dst_h);
|
||||
- regmap_write(mixer->engine.regs,
|
||||
+ regmap_write(bld_regs,
|
||||
SUN8I_MIXER_BLEND_ATTR_COORD(bld_base, zpos),
|
||||
SUN8I_MIXER_COORD(state->dst.x1, state->dst.y1));
|
||||
- regmap_write(mixer->engine.regs,
|
||||
+ regmap_write(bld_regs,
|
||||
SUN8I_MIXER_BLEND_ATTR_INSIZE(bld_base, zpos),
|
||||
outsize);
|
||||
|
||||
diff --git a/drivers/gpu/drm/sun4i/sun8i_vi_layer.c b/drivers/gpu/drm/sun4i/sun8i_vi_layer.c
|
||||
index e348fd0a3d81..d19349eecc9d 100644
|
||||
--- a/drivers/gpu/drm/sun4i/sun8i_vi_layer.c
|
||||
+++ b/drivers/gpu/drm/sun4i/sun8i_vi_layer.c
|
||||
@@ -55,6 +55,7 @@ static int sun8i_vi_layer_update_coord(struct sun8i_mixer *mixer, int channel,
|
||||
struct drm_plane_state *state = plane->state;
|
||||
const struct drm_format_info *format = state->fb->format;
|
||||
u32 src_w, src_h, dst_w, dst_h;
|
||||
+ struct regmap *bld_regs;
|
||||
u32 bld_base, ch_base;
|
||||
u32 outsize, insize;
|
||||
u32 hphase, vphase;
|
||||
@@ -66,6 +67,7 @@ static int sun8i_vi_layer_update_coord(struct sun8i_mixer *mixer, int channel,
|
||||
channel, overlay);
|
||||
|
||||
bld_base = sun8i_blender_base(mixer);
|
||||
+ bld_regs = sun8i_blender_regmap(mixer);
|
||||
ch_base = sun8i_channel_base(mixer, channel);
|
||||
|
||||
src_w = drm_rect_width(&state->src) >> 16;
|
||||
@@ -182,10 +184,10 @@ static int sun8i_vi_layer_update_coord(struct sun8i_mixer *mixer, int channel,
|
||||
DRM_DEBUG_DRIVER("Layer destination coordinates X: %d Y: %d\n",
|
||||
state->dst.x1, state->dst.y1);
|
||||
DRM_DEBUG_DRIVER("Layer destination size W: %d H: %d\n", dst_w, dst_h);
|
||||
- regmap_write(mixer->engine.regs,
|
||||
+ regmap_write(bld_regs,
|
||||
SUN8I_MIXER_BLEND_ATTR_COORD(bld_base, zpos),
|
||||
SUN8I_MIXER_COORD(state->dst.x1, state->dst.y1));
|
||||
- regmap_write(mixer->engine.regs,
|
||||
+ regmap_write(bld_regs,
|
||||
SUN8I_MIXER_BLEND_ATTR_INSIZE(bld_base, zpos),
|
||||
outsize);
|
||||
|
||||
--
|
||||
2.35.3
|
||||
|
||||
|
|
@ -0,0 +1,164 @@
|
|||
From 8bdcc131fedb576a8db65bb6e87ca8742660add0 Mon Sep 17 00:00:00 2001
|
||||
From: Jernej Skrabec <jernej.skrabec@gmail.com>
|
||||
Date: Sun, 29 Sep 2024 22:04:37 +1300
|
||||
Subject: drm: sun4i: de3: Add YUV formatter module
|
||||
|
||||
The display engine formatter (FMT) module is present in the DE3 engine
|
||||
and provides YUV444 to YUV422/YUV420 conversion, format re-mapping and
|
||||
color depth conversion.
|
||||
|
||||
Add support for this module.
|
||||
|
||||
Signed-off-by: Jernej Skrabec <jernej.skrabec@gmail.com>
|
||||
Signed-off-by: Ryan Walklin <ryan@testtoast.com>
|
||||
---
|
||||
drivers/gpu/drm/sun4i/Makefile | 3 +-
|
||||
drivers/gpu/drm/sun4i/sun50i_fmt.c | 82 ++++++++++++++++++++++++++++++
|
||||
drivers/gpu/drm/sun4i/sun50i_fmt.h | 32 ++++++++++++
|
||||
3 files changed, 116 insertions(+), 1 deletion(-)
|
||||
create mode 100644 drivers/gpu/drm/sun4i/sun50i_fmt.c
|
||||
create mode 100644 drivers/gpu/drm/sun4i/sun50i_fmt.h
|
||||
|
||||
diff --git a/drivers/gpu/drm/sun4i/Makefile b/drivers/gpu/drm/sun4i/Makefile
|
||||
index bad7497a0d11..3f516329f51e 100644
|
||||
--- a/drivers/gpu/drm/sun4i/Makefile
|
||||
+++ b/drivers/gpu/drm/sun4i/Makefile
|
||||
@@ -16,7 +16,8 @@ sun8i-drm-hdmi-y += sun8i_hdmi_phy_clk.o
|
||||
|
||||
sun8i-mixer-y += sun8i_mixer.o sun8i_ui_layer.o \
|
||||
sun8i_vi_layer.o sun8i_ui_scaler.o \
|
||||
- sun8i_vi_scaler.o sun8i_csc.o
|
||||
+ sun8i_vi_scaler.o sun8i_csc.o \
|
||||
+ sun50i_fmt.o
|
||||
|
||||
sun4i-tcon-y += sun4i_crtc.o
|
||||
sun4i-tcon-y += sun4i_tcon_dclk.o
|
||||
diff --git a/drivers/gpu/drm/sun4i/sun50i_fmt.c b/drivers/gpu/drm/sun4i/sun50i_fmt.c
|
||||
new file mode 100644
|
||||
index 000000000000..050a8716ae86
|
||||
--- /dev/null
|
||||
+++ b/drivers/gpu/drm/sun4i/sun50i_fmt.c
|
||||
@@ -0,0 +1,82 @@
|
||||
+// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
+/*
|
||||
+ * Copyright (C) Jernej Skrabec <jernej.skrabec@gmail.com>
|
||||
+ */
|
||||
+
|
||||
+#include <uapi/linux/media-bus-format.h>
|
||||
+
|
||||
+#include "sun50i_fmt.h"
|
||||
+
|
||||
+static bool sun50i_fmt_is_10bit(u32 format)
|
||||
+{
|
||||
+ switch (format) {
|
||||
+ case MEDIA_BUS_FMT_RGB101010_1X30:
|
||||
+ case MEDIA_BUS_FMT_YUV10_1X30:
|
||||
+ case MEDIA_BUS_FMT_UYYVYY10_0_5X30:
|
||||
+ case MEDIA_BUS_FMT_UYVY10_1X20:
|
||||
+ return true;
|
||||
+ default:
|
||||
+ return false;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static u32 sun50i_fmt_get_colorspace(u32 format)
|
||||
+{
|
||||
+ switch (format) {
|
||||
+ case MEDIA_BUS_FMT_UYYVYY8_0_5X24:
|
||||
+ case MEDIA_BUS_FMT_UYYVYY10_0_5X30:
|
||||
+ return SUN50I_FMT_CS_YUV420;
|
||||
+ case MEDIA_BUS_FMT_UYVY8_1X16:
|
||||
+ case MEDIA_BUS_FMT_UYVY10_1X20:
|
||||
+ return SUN50I_FMT_CS_YUV422;
|
||||
+ default:
|
||||
+ return SUN50I_FMT_CS_YUV444RGB;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static void sun50i_fmt_de3_limits(u32 *limits, u32 colorspace, bool bit10)
|
||||
+{
|
||||
+ if (colorspace != SUN50I_FMT_CS_YUV444RGB) {
|
||||
+ limits[0] = SUN50I_FMT_LIMIT(64, 940);
|
||||
+ limits[1] = SUN50I_FMT_LIMIT(64, 960);
|
||||
+ limits[2] = SUN50I_FMT_LIMIT(64, 960);
|
||||
+ } else if (bit10) {
|
||||
+ limits[0] = SUN50I_FMT_LIMIT(0, 1023);
|
||||
+ limits[1] = SUN50I_FMT_LIMIT(0, 1023);
|
||||
+ limits[2] = SUN50I_FMT_LIMIT(0, 1023);
|
||||
+ } else {
|
||||
+ limits[0] = SUN50I_FMT_LIMIT(0, 1021);
|
||||
+ limits[1] = SUN50I_FMT_LIMIT(0, 1021);
|
||||
+ limits[2] = SUN50I_FMT_LIMIT(0, 1021);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+void sun50i_fmt_setup(struct sun8i_mixer *mixer, u16 width,
|
||||
+ u16 height, u32 format)
|
||||
+{
|
||||
+ u32 colorspace, limit[3], base;
|
||||
+ struct regmap *regs;
|
||||
+ bool bit10;
|
||||
+
|
||||
+ colorspace = sun50i_fmt_get_colorspace(format);
|
||||
+ bit10 = sun50i_fmt_is_10bit(format);
|
||||
+ base = SUN50I_FMT_DE3;
|
||||
+ regs = sun8i_blender_regmap(mixer);
|
||||
+
|
||||
+ sun50i_fmt_de3_limits(limit, colorspace, bit10);
|
||||
+
|
||||
+ regmap_write(regs, SUN50I_FMT_CTRL(base), 0);
|
||||
+
|
||||
+ regmap_write(regs, SUN50I_FMT_SIZE(base),
|
||||
+ SUN8I_MIXER_SIZE(width, height));
|
||||
+ regmap_write(regs, SUN50I_FMT_SWAP(base), 0);
|
||||
+ regmap_write(regs, SUN50I_FMT_DEPTH(base), bit10);
|
||||
+ regmap_write(regs, SUN50I_FMT_FORMAT(base), colorspace);
|
||||
+ regmap_write(regs, SUN50I_FMT_COEF(base), 0);
|
||||
+
|
||||
+ regmap_write(regs, SUN50I_FMT_LMT_Y(base), limit[0]);
|
||||
+ regmap_write(regs, SUN50I_FMT_LMT_C0(base), limit[1]);
|
||||
+ regmap_write(regs, SUN50I_FMT_LMT_C1(base), limit[2]);
|
||||
+
|
||||
+ regmap_write(regs, SUN50I_FMT_CTRL(base), 1);
|
||||
+}
|
||||
diff --git a/drivers/gpu/drm/sun4i/sun50i_fmt.h b/drivers/gpu/drm/sun4i/sun50i_fmt.h
|
||||
new file mode 100644
|
||||
index 000000000000..4127f7206aad
|
||||
--- /dev/null
|
||||
+++ b/drivers/gpu/drm/sun4i/sun50i_fmt.h
|
||||
@@ -0,0 +1,32 @@
|
||||
+/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
+/*
|
||||
+ * Copyright (C) Jernej Skrabec <jernej.skrabec@gmail.com>
|
||||
+ */
|
||||
+
|
||||
+#ifndef _SUN50I_FMT_H_
|
||||
+#define _SUN50I_FMT_H_
|
||||
+
|
||||
+#include "sun8i_mixer.h"
|
||||
+
|
||||
+#define SUN50I_FMT_DE3 0xa8000
|
||||
+
|
||||
+#define SUN50I_FMT_CTRL(base) ((base) + 0x00)
|
||||
+#define SUN50I_FMT_SIZE(base) ((base) + 0x04)
|
||||
+#define SUN50I_FMT_SWAP(base) ((base) + 0x08)
|
||||
+#define SUN50I_FMT_DEPTH(base) ((base) + 0x0c)
|
||||
+#define SUN50I_FMT_FORMAT(base) ((base) + 0x10)
|
||||
+#define SUN50I_FMT_COEF(base) ((base) + 0x14)
|
||||
+#define SUN50I_FMT_LMT_Y(base) ((base) + 0x20)
|
||||
+#define SUN50I_FMT_LMT_C0(base) ((base) + 0x24)
|
||||
+#define SUN50I_FMT_LMT_C1(base) ((base) + 0x28)
|
||||
+
|
||||
+#define SUN50I_FMT_LIMIT(low, high) (((high) << 16) | (low))
|
||||
+
|
||||
+#define SUN50I_FMT_CS_YUV444RGB 0
|
||||
+#define SUN50I_FMT_CS_YUV422 1
|
||||
+#define SUN50I_FMT_CS_YUV420 2
|
||||
+
|
||||
+void sun50i_fmt_setup(struct sun8i_mixer *mixer, u16 width,
|
||||
+ u16 height, u32 format);
|
||||
+
|
||||
+#endif
|
||||
--
|
||||
2.35.3
|
||||
|
||||
|
|
@ -0,0 +1,569 @@
|
|||
From 0788787d1240dba85ecbbdb559cb46d413975656 Mon Sep 17 00:00:00 2001
|
||||
From: Jernej Skrabec <jernej.skrabec@gmail.com>
|
||||
Date: Sun, 29 Sep 2024 22:04:50 +1300
|
||||
Subject: drm: sun4i: de3: Implement AFBC support
|
||||
|
||||
Buffers, compressed with AFBC, are supported by the DE3 and above, and
|
||||
are generally more efficient for memory transfers. Add support for them.
|
||||
|
||||
Currently it's implemented only for VI layers, but vendor code and
|
||||
documentation suggest UI layers can have them too. However, I haven't
|
||||
observed any SoC with such feature.
|
||||
|
||||
Signed-off-by: Jernej Skrabec <jernej.skrabec@gmail.com>
|
||||
Signed-off-by: Ryan Walklin <ryan@testtoast.com>
|
||||
---
|
||||
drivers/gpu/drm/sun4i/Makefile | 2 +-
|
||||
drivers/gpu/drm/sun4i/sun50i_afbc.c | 250 +++++++++++++++++++++++++
|
||||
drivers/gpu/drm/sun4i/sun50i_afbc.h | 87 +++++++++
|
||||
drivers/gpu/drm/sun4i/sun8i_vi_layer.c | 84 +++++++--
|
||||
4 files changed, 409 insertions(+), 14 deletions(-)
|
||||
create mode 100644 drivers/gpu/drm/sun4i/sun50i_afbc.c
|
||||
create mode 100644 drivers/gpu/drm/sun4i/sun50i_afbc.h
|
||||
|
||||
diff --git a/drivers/gpu/drm/sun4i/Makefile b/drivers/gpu/drm/sun4i/Makefile
|
||||
index 3f516329f51e..78290f1660fb 100644
|
||||
--- a/drivers/gpu/drm/sun4i/Makefile
|
||||
+++ b/drivers/gpu/drm/sun4i/Makefile
|
||||
@@ -17,7 +17,7 @@ sun8i-drm-hdmi-y += sun8i_hdmi_phy_clk.o
|
||||
sun8i-mixer-y += sun8i_mixer.o sun8i_ui_layer.o \
|
||||
sun8i_vi_layer.o sun8i_ui_scaler.o \
|
||||
sun8i_vi_scaler.o sun8i_csc.o \
|
||||
- sun50i_fmt.o
|
||||
+ sun50i_fmt.o sun50i_afbc.o
|
||||
|
||||
sun4i-tcon-y += sun4i_crtc.o
|
||||
sun4i-tcon-y += sun4i_tcon_dclk.o
|
||||
diff --git a/drivers/gpu/drm/sun4i/sun50i_afbc.c b/drivers/gpu/drm/sun4i/sun50i_afbc.c
|
||||
new file mode 100644
|
||||
index 000000000000..b55e1c553371
|
||||
--- /dev/null
|
||||
+++ b/drivers/gpu/drm/sun4i/sun50i_afbc.c
|
||||
@@ -0,0 +1,250 @@
|
||||
+// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
+/*
|
||||
+ * Copyright (C) Jernej Skrabec <jernej.skrabec@gmail.com>
|
||||
+ */
|
||||
+
|
||||
+#include <drm/drm_blend.h>
|
||||
+#include <drm/drm_fb_dma_helper.h>
|
||||
+#include <drm/drm_framebuffer.h>
|
||||
+#include <drm/drm_gem_dma_helper.h>
|
||||
+#include <drm/drm_plane.h>
|
||||
+#include <uapi/drm/drm_fourcc.h>
|
||||
+
|
||||
+#include "sun50i_afbc.h"
|
||||
+#include "sun8i_mixer.h"
|
||||
+
|
||||
+static u32 sun50i_afbc_get_base(struct sun8i_mixer *mixer, unsigned int channel)
|
||||
+{
|
||||
+ u32 base = sun8i_channel_base(mixer, channel);
|
||||
+
|
||||
+ if (mixer->cfg->de_type == sun8i_mixer_de3)
|
||||
+ return base + SUN50I_AFBC_CH_OFFSET;
|
||||
+
|
||||
+ return base + 0x4000;
|
||||
+}
|
||||
+
|
||||
+bool sun50i_afbc_format_mod_supported(struct sun8i_mixer *mixer,
|
||||
+ u32 format, u64 modifier)
|
||||
+{
|
||||
+ u64 mode;
|
||||
+
|
||||
+ if (modifier == DRM_FORMAT_MOD_INVALID)
|
||||
+ return false;
|
||||
+
|
||||
+ if (modifier == DRM_FORMAT_MOD_LINEAR) {
|
||||
+ if (format == DRM_FORMAT_YUV420_8BIT ||
|
||||
+ format == DRM_FORMAT_YUV420_10BIT ||
|
||||
+ format == DRM_FORMAT_Y210)
|
||||
+ return false;
|
||||
+ return true;
|
||||
+ }
|
||||
+
|
||||
+ if (mixer->cfg->de_type == sun8i_mixer_de2)
|
||||
+ return false;
|
||||
+
|
||||
+ mode = AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 |
|
||||
+ AFBC_FORMAT_MOD_SPARSE |
|
||||
+ AFBC_FORMAT_MOD_SPLIT;
|
||||
+
|
||||
+ switch (format) {
|
||||
+ case DRM_FORMAT_RGBA8888:
|
||||
+ case DRM_FORMAT_RGB888:
|
||||
+ case DRM_FORMAT_RGB565:
|
||||
+ case DRM_FORMAT_RGBA4444:
|
||||
+ case DRM_FORMAT_RGBA5551:
|
||||
+ case DRM_FORMAT_RGBA1010102:
|
||||
+ mode |= AFBC_FORMAT_MOD_YTR;
|
||||
+ break;
|
||||
+ case DRM_FORMAT_YUYV:
|
||||
+ case DRM_FORMAT_Y210:
|
||||
+ case DRM_FORMAT_YUV420_8BIT:
|
||||
+ case DRM_FORMAT_YUV420_10BIT:
|
||||
+ break;
|
||||
+ default:
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ return modifier == DRM_FORMAT_MOD_ARM_AFBC(mode);
|
||||
+}
|
||||
+
|
||||
+void sun50i_afbc_atomic_update(struct sun8i_mixer *mixer, unsigned int channel,
|
||||
+ struct drm_plane *plane)
|
||||
+{
|
||||
+ struct drm_plane_state *state = plane->state;
|
||||
+ struct drm_framebuffer *fb = state->fb;
|
||||
+ const struct drm_format_info *format = fb->format;
|
||||
+ struct drm_gem_dma_object *gem;
|
||||
+ u32 base, val, src_w, src_h;
|
||||
+ u32 def_color0, def_color1;
|
||||
+ struct regmap *regs;
|
||||
+ dma_addr_t dma_addr;
|
||||
+
|
||||
+ base = sun50i_afbc_get_base(mixer, channel);
|
||||
+ regs = mixer->engine.regs;
|
||||
+
|
||||
+ src_w = drm_rect_width(&state->src) >> 16;
|
||||
+ src_h = drm_rect_height(&state->src) >> 16;
|
||||
+
|
||||
+ val = SUN50I_FBD_SIZE_HEIGHT(src_h);
|
||||
+ val |= SUN50I_FBD_SIZE_WIDTH(src_w);
|
||||
+ regmap_write(regs, SUN50I_FBD_SIZE(base), val);
|
||||
+
|
||||
+ val = SUN50I_FBD_BLK_SIZE_HEIGHT(DIV_ROUND_UP(src_h, 16));
|
||||
+ val = SUN50I_FBD_BLK_SIZE_WIDTH(DIV_ROUND_UP(src_w, 16));
|
||||
+ regmap_write(regs, SUN50I_FBD_BLK_SIZE(base), val);
|
||||
+
|
||||
+ val = SUN50I_FBD_SRC_CROP_TOP(0);
|
||||
+ val |= SUN50I_FBD_SRC_CROP_LEFT(0);
|
||||
+ regmap_write(regs, SUN50I_FBD_SRC_CROP(base), val);
|
||||
+
|
||||
+ val = SUN50I_FBD_LAY_CROP_TOP(state->src.y1 >> 16);
|
||||
+ val |= SUN50I_FBD_LAY_CROP_LEFT(state->src.x1 >> 16);
|
||||
+ regmap_write(regs, SUN50I_FBD_LAY_CROP(base), val);
|
||||
+
|
||||
+ /*
|
||||
+ * Default color is always set to white, in colorspace and bitness
|
||||
+ * that coresponds to used format. If it is actually used or not
|
||||
+ * depends on AFBC buffer. At least in Cedrus it can be turned on
|
||||
+ * or off.
|
||||
+ * NOTE: G and B channels are off by 1 (up). It's unclear if this
|
||||
+ * is because HW need such value or it is due to good enough code
|
||||
+ * in vendor driver and HW clips the value anyway.
|
||||
+ */
|
||||
+ def_color0 = 0;
|
||||
+ def_color1 = 0;
|
||||
+
|
||||
+ val = 0;
|
||||
+ switch (format->format) {
|
||||
+ case DRM_FORMAT_YUYV:
|
||||
+ case DRM_FORMAT_YUV420_10BIT:
|
||||
+ val |= SUN50I_FBD_FMT_SBS1(2);
|
||||
+ val |= SUN50I_FBD_FMT_SBS0(1);
|
||||
+ break;
|
||||
+ case DRM_FORMAT_Y210:
|
||||
+ val |= SUN50I_FBD_FMT_SBS1(3);
|
||||
+ val |= SUN50I_FBD_FMT_SBS0(2);
|
||||
+ break;
|
||||
+ default:
|
||||
+ val |= SUN50I_FBD_FMT_SBS1(1);
|
||||
+ val |= SUN50I_FBD_FMT_SBS0(1);
|
||||
+ break;
|
||||
+ }
|
||||
+ switch (format->format) {
|
||||
+ case DRM_FORMAT_RGBA8888:
|
||||
+ val |= SUN50I_FBD_FMT_YUV_TRAN;
|
||||
+ val |= SUN50I_FBD_FMT_IN_FMT(SUN50I_AFBC_RGBA_8888);
|
||||
+ def_color0 = SUN50I_FBD_DEFAULT_COLOR0_ALPHA(255) |
|
||||
+ SUN50I_FBD_DEFAULT_COLOR0_YR(255);
|
||||
+ def_color1 = SUN50I_FBD_DEFAULT_COLOR1_UG(256) |
|
||||
+ SUN50I_FBD_DEFAULT_COLOR1_VB(256);
|
||||
+ break;
|
||||
+ case DRM_FORMAT_RGB888:
|
||||
+ val |= SUN50I_FBD_FMT_YUV_TRAN;
|
||||
+ val |= SUN50I_FBD_FMT_IN_FMT(SUN50I_AFBC_RGB_888);
|
||||
+ def_color0 = SUN50I_FBD_DEFAULT_COLOR0_ALPHA(0) |
|
||||
+ SUN50I_FBD_DEFAULT_COLOR0_YR(255);
|
||||
+ def_color1 = SUN50I_FBD_DEFAULT_COLOR1_UG(256) |
|
||||
+ SUN50I_FBD_DEFAULT_COLOR1_VB(256);
|
||||
+ break;
|
||||
+ case DRM_FORMAT_RGB565:
|
||||
+ val |= SUN50I_FBD_FMT_YUV_TRAN;
|
||||
+ val |= SUN50I_FBD_FMT_IN_FMT(SUN50I_AFBC_RGB_565);
|
||||
+ def_color0 = SUN50I_FBD_DEFAULT_COLOR0_ALPHA(0) |
|
||||
+ SUN50I_FBD_DEFAULT_COLOR0_YR(31);
|
||||
+ def_color1 = SUN50I_FBD_DEFAULT_COLOR1_UG(64) |
|
||||
+ SUN50I_FBD_DEFAULT_COLOR1_VB(32);
|
||||
+ break;
|
||||
+ case DRM_FORMAT_RGBA4444:
|
||||
+ val |= SUN50I_FBD_FMT_YUV_TRAN;
|
||||
+ val |= SUN50I_FBD_FMT_IN_FMT(SUN50I_AFBC_RGBA_4444);
|
||||
+ def_color0 = SUN50I_FBD_DEFAULT_COLOR0_ALPHA(15) |
|
||||
+ SUN50I_FBD_DEFAULT_COLOR0_YR(15);
|
||||
+ def_color1 = SUN50I_FBD_DEFAULT_COLOR1_UG(16) |
|
||||
+ SUN50I_FBD_DEFAULT_COLOR1_VB(16);
|
||||
+ break;
|
||||
+ case DRM_FORMAT_RGBA5551:
|
||||
+ val |= SUN50I_FBD_FMT_YUV_TRAN;
|
||||
+ val |= SUN50I_FBD_FMT_IN_FMT(SUN50I_AFBC_RGBA_5551);
|
||||
+ def_color0 = SUN50I_FBD_DEFAULT_COLOR0_ALPHA(1) |
|
||||
+ SUN50I_FBD_DEFAULT_COLOR0_YR(31);
|
||||
+ def_color1 = SUN50I_FBD_DEFAULT_COLOR1_UG(32) |
|
||||
+ SUN50I_FBD_DEFAULT_COLOR1_VB(32);
|
||||
+ break;
|
||||
+ case DRM_FORMAT_RGBA1010102:
|
||||
+ val |= SUN50I_FBD_FMT_YUV_TRAN;
|
||||
+ val |= SUN50I_FBD_FMT_IN_FMT(SUN50I_AFBC_RGBA1010102);
|
||||
+ def_color0 = SUN50I_FBD_DEFAULT_COLOR0_ALPHA(3) |
|
||||
+ SUN50I_FBD_DEFAULT_COLOR0_YR(1023);
|
||||
+ def_color1 = SUN50I_FBD_DEFAULT_COLOR1_UG(1024) |
|
||||
+ SUN50I_FBD_DEFAULT_COLOR1_VB(1024);
|
||||
+ break;
|
||||
+ case DRM_FORMAT_YUV420_8BIT:
|
||||
+ val |= SUN50I_FBD_FMT_IN_FMT(SUN50I_AFBC_YUV420);
|
||||
+ def_color0 = SUN50I_FBD_DEFAULT_COLOR0_ALPHA(0) |
|
||||
+ SUN50I_FBD_DEFAULT_COLOR0_YR(255);
|
||||
+ def_color1 = SUN50I_FBD_DEFAULT_COLOR1_UG(128) |
|
||||
+ SUN50I_FBD_DEFAULT_COLOR1_VB(128);
|
||||
+ break;
|
||||
+ case DRM_FORMAT_YUYV:
|
||||
+ val |= SUN50I_FBD_FMT_IN_FMT(SUN50I_AFBC_YUV422);
|
||||
+ def_color0 = SUN50I_FBD_DEFAULT_COLOR0_ALPHA(0) |
|
||||
+ SUN50I_FBD_DEFAULT_COLOR0_YR(255);
|
||||
+ def_color1 = SUN50I_FBD_DEFAULT_COLOR1_UG(128) |
|
||||
+ SUN50I_FBD_DEFAULT_COLOR1_VB(128);
|
||||
+ break;
|
||||
+ case DRM_FORMAT_YUV420_10BIT:
|
||||
+ val |= SUN50I_FBD_FMT_IN_FMT(SUN50I_AFBC_P010);
|
||||
+ def_color0 = SUN50I_FBD_DEFAULT_COLOR0_ALPHA(0) |
|
||||
+ SUN50I_FBD_DEFAULT_COLOR0_YR(1023);
|
||||
+ def_color1 = SUN50I_FBD_DEFAULT_COLOR1_UG(512) |
|
||||
+ SUN50I_FBD_DEFAULT_COLOR1_VB(512);
|
||||
+ break;
|
||||
+ case DRM_FORMAT_Y210:
|
||||
+ val |= SUN50I_FBD_FMT_IN_FMT(SUN50I_AFBC_P210);
|
||||
+ def_color0 = SUN50I_FBD_DEFAULT_COLOR0_ALPHA(0) |
|
||||
+ SUN50I_FBD_DEFAULT_COLOR0_YR(1023);
|
||||
+ def_color1 = SUN50I_FBD_DEFAULT_COLOR1_UG(512) |
|
||||
+ SUN50I_FBD_DEFAULT_COLOR1_VB(512);
|
||||
+ break;
|
||||
+ }
|
||||
+ regmap_write(regs, SUN50I_FBD_FMT(base), val);
|
||||
+
|
||||
+ /* Get the physical address of the buffer in memory */
|
||||
+ gem = drm_fb_dma_get_gem_obj(fb, 0);
|
||||
+
|
||||
+ DRM_DEBUG_DRIVER("Using GEM @ %pad\n", &gem->dma_addr);
|
||||
+
|
||||
+ /* Compute the start of the displayed memory */
|
||||
+ dma_addr = gem->dma_addr + fb->offsets[0];
|
||||
+
|
||||
+ regmap_write(regs, SUN50I_FBD_LADDR(base), lower_32_bits(dma_addr));
|
||||
+ regmap_write(regs, SUN50I_FBD_HADDR(base), upper_32_bits(dma_addr));
|
||||
+
|
||||
+ val = SUN50I_FBD_OVL_SIZE_HEIGHT(src_h);
|
||||
+ val |= SUN50I_FBD_OVL_SIZE_WIDTH(src_w);
|
||||
+ regmap_write(regs, SUN50I_FBD_OVL_SIZE(base), val);
|
||||
+
|
||||
+ val = SUN50I_FBD_OVL_COOR_Y(0);
|
||||
+ val |= SUN50I_FBD_OVL_COOR_X(0);
|
||||
+ regmap_write(regs, SUN50I_FBD_OVL_COOR(base), val);
|
||||
+
|
||||
+ regmap_write(regs, SUN50I_FBD_OVL_BG_COLOR(base),
|
||||
+ SUN8I_MIXER_BLEND_COLOR_BLACK);
|
||||
+ regmap_write(regs, SUN50I_FBD_DEFAULT_COLOR0(base), def_color0);
|
||||
+ regmap_write(regs, SUN50I_FBD_DEFAULT_COLOR1(base), def_color1);
|
||||
+
|
||||
+ val = SUN50I_FBD_CTL_GLB_ALPHA(state->alpha >> 16);
|
||||
+ val |= SUN50I_FBD_CTL_CLK_GATE;
|
||||
+ val |= (state->alpha == DRM_BLEND_ALPHA_OPAQUE) ?
|
||||
+ SUN50I_FBD_CTL_ALPHA_MODE_PIXEL :
|
||||
+ SUN50I_FBD_CTL_ALPHA_MODE_COMBINED;
|
||||
+ val |= SUN50I_FBD_CTL_FBD_EN;
|
||||
+ regmap_write(regs, SUN50I_FBD_CTL(base), val);
|
||||
+}
|
||||
+
|
||||
+void sun50i_afbc_disable(struct sun8i_mixer *mixer, unsigned int channel)
|
||||
+{
|
||||
+ u32 base = sun50i_afbc_get_base(mixer, channel);
|
||||
+
|
||||
+ regmap_write(mixer->engine.regs, SUN50I_FBD_CTL(base), 0);
|
||||
+}
|
||||
diff --git a/drivers/gpu/drm/sun4i/sun50i_afbc.h b/drivers/gpu/drm/sun4i/sun50i_afbc.h
|
||||
new file mode 100644
|
||||
index 000000000000..cea685c86855
|
||||
--- /dev/null
|
||||
+++ b/drivers/gpu/drm/sun4i/sun50i_afbc.h
|
||||
@@ -0,0 +1,87 @@
|
||||
+/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
+/*
|
||||
+ * Copyright (C) Jernej Skrabec <jernej.skrabec@gmail.com>
|
||||
+ */
|
||||
+
|
||||
+#ifndef _SUN50I_AFBC_H_
|
||||
+#define _SUN50I_AFBC_H_
|
||||
+
|
||||
+#include <linux/types.h>
|
||||
+
|
||||
+#define SUN50I_AFBC_CH_OFFSET 0x300
|
||||
+
|
||||
+#define SUN50I_AFBC_RGBA_8888 0x02
|
||||
+#define SUN50I_AFBC_RGB_888 0x08
|
||||
+#define SUN50I_AFBC_RGB_565 0x0a
|
||||
+#define SUN50I_AFBC_RGBA_4444 0x0e
|
||||
+#define SUN50I_AFBC_RGBA_5551 0x12
|
||||
+#define SUN50I_AFBC_RGBA1010102 0x16
|
||||
+#define SUN50I_AFBC_YUV422 0x26
|
||||
+#define SUN50I_AFBC_YUV420 0x2a
|
||||
+#define SUN50I_AFBC_P010 0x30
|
||||
+#define SUN50I_AFBC_P210 0x32
|
||||
+
|
||||
+#define SUN50I_FBD_CTL(base) ((base) + 0x00)
|
||||
+#define SUN50I_FBD_CTL_GLB_ALPHA(v) ((v) << 24)
|
||||
+#define SUN50I_FBD_CTL_CLK_GATE BIT(4)
|
||||
+#define SUN50I_FBD_CTL_ALPHA_MODE_PIXEL ((0) << 2)
|
||||
+#define SUN50I_FBD_CTL_ALPHA_MODE_LAYER ((1) << 2)
|
||||
+#define SUN50I_FBD_CTL_ALPHA_MODE_COMBINED ((2) << 2)
|
||||
+#define SUN50I_FBD_CTL_FBD_FCEN BIT(1)
|
||||
+#define SUN50I_FBD_CTL_FBD_EN BIT(0)
|
||||
+
|
||||
+#define SUN50I_FBD_SIZE(base) ((base) + 0x08)
|
||||
+#define SUN50I_FBD_SIZE_HEIGHT(v) (((v) - 1) << 16)
|
||||
+#define SUN50I_FBD_SIZE_WIDTH(v) (((v) - 1) << 0)
|
||||
+
|
||||
+#define SUN50I_FBD_BLK_SIZE(base) ((base) + 0x0c)
|
||||
+#define SUN50I_FBD_BLK_SIZE_HEIGHT(v) ((v) << 16)
|
||||
+#define SUN50I_FBD_BLK_SIZE_WIDTH(v) ((v) << 0)
|
||||
+
|
||||
+#define SUN50I_FBD_SRC_CROP(base) ((base) + 0x10)
|
||||
+#define SUN50I_FBD_SRC_CROP_TOP(v) ((v) << 16)
|
||||
+#define SUN50I_FBD_SRC_CROP_LEFT(v) ((v) << 0)
|
||||
+
|
||||
+#define SUN50I_FBD_LAY_CROP(base) ((base) + 0x14)
|
||||
+#define SUN50I_FBD_LAY_CROP_TOP(v) ((v) << 16)
|
||||
+#define SUN50I_FBD_LAY_CROP_LEFT(v) ((v) << 0)
|
||||
+
|
||||
+#define SUN50I_FBD_FMT(base) ((base) + 0x18)
|
||||
+#define SUN50I_FBD_FMT_SBS1(v) ((v) << 18)
|
||||
+#define SUN50I_FBD_FMT_SBS0(v) ((v) << 16)
|
||||
+#define SUN50I_FBD_FMT_YUV_TRAN BIT(7)
|
||||
+#define SUN50I_FBD_FMT_IN_FMT(v) ((v) << 0)
|
||||
+
|
||||
+#define SUN50I_FBD_LADDR(base) ((base) + 0x20)
|
||||
+#define SUN50I_FBD_HADDR(base) ((base) + 0x24)
|
||||
+
|
||||
+#define SUN50I_FBD_OVL_SIZE(base) ((base) + 0x30)
|
||||
+#define SUN50I_FBD_OVL_SIZE_HEIGHT(v) (((v) - 1) << 16)
|
||||
+#define SUN50I_FBD_OVL_SIZE_WIDTH(v) (((v) - 1) << 0)
|
||||
+
|
||||
+#define SUN50I_FBD_OVL_COOR(base) ((base) + 0x34)
|
||||
+#define SUN50I_FBD_OVL_COOR_Y(v) ((v) << 16)
|
||||
+#define SUN50I_FBD_OVL_COOR_X(v) ((v) << 0)
|
||||
+
|
||||
+#define SUN50I_FBD_OVL_BG_COLOR(base) ((base) + 0x38)
|
||||
+#define SUN50I_FBD_OVL_FILL_COLOR(base) ((base) + 0x3c)
|
||||
+
|
||||
+#define SUN50I_FBD_DEFAULT_COLOR0(base) ((base) + 0x50)
|
||||
+#define SUN50I_FBD_DEFAULT_COLOR0_ALPHA(v) ((v) << 16)
|
||||
+#define SUN50I_FBD_DEFAULT_COLOR0_YR(v) ((v) << 0)
|
||||
+
|
||||
+#define SUN50I_FBD_DEFAULT_COLOR1(base) ((base) + 0x54)
|
||||
+#define SUN50I_FBD_DEFAULT_COLOR1_VB(v) ((v) << 16)
|
||||
+#define SUN50I_FBD_DEFAULT_COLOR1_UG(v) ((v) << 0)
|
||||
+
|
||||
+struct sun8i_mixer;
|
||||
+struct drm_plane;
|
||||
+
|
||||
+bool sun50i_afbc_format_mod_supported(struct sun8i_mixer *mixer,
|
||||
+ u32 format, u64 modifier);
|
||||
+
|
||||
+void sun50i_afbc_atomic_update(struct sun8i_mixer *mixer, unsigned int channel,
|
||||
+ struct drm_plane *plane);
|
||||
+void sun50i_afbc_disable(struct sun8i_mixer *mixer, unsigned int channel);
|
||||
+
|
||||
+#endif
|
||||
diff --git a/drivers/gpu/drm/sun4i/sun8i_vi_layer.c b/drivers/gpu/drm/sun4i/sun8i_vi_layer.c
|
||||
index d19349eecc9d..84f8917e2dd8 100644
|
||||
--- a/drivers/gpu/drm/sun4i/sun8i_vi_layer.c
|
||||
+++ b/drivers/gpu/drm/sun4i/sun8i_vi_layer.c
|
||||
@@ -11,8 +11,10 @@
|
||||
#include <drm/drm_framebuffer.h>
|
||||
#include <drm/drm_gem_atomic_helper.h>
|
||||
#include <drm/drm_gem_dma_helper.h>
|
||||
+#include <drm/drm_gem_framebuffer_helper.h>
|
||||
#include <drm/drm_probe_helper.h>
|
||||
|
||||
+#include "sun50i_afbc.h"
|
||||
#include "sun8i_csc.h"
|
||||
#include "sun8i_mixer.h"
|
||||
#include "sun8i_vi_layer.h"
|
||||
@@ -50,7 +52,7 @@ static void sun8i_vi_layer_update_alpha(struct sun8i_mixer *mixer, int channel,
|
||||
|
||||
static int sun8i_vi_layer_update_coord(struct sun8i_mixer *mixer, int channel,
|
||||
int overlay, struct drm_plane *plane,
|
||||
- unsigned int zpos)
|
||||
+ unsigned int zpos, bool afbc)
|
||||
{
|
||||
struct drm_plane_state *state = plane->state;
|
||||
const struct drm_format_info *format = state->fb->format;
|
||||
@@ -135,7 +137,7 @@ static int sun8i_vi_layer_update_coord(struct sun8i_mixer *mixer, int channel,
|
||||
|
||||
required = src_h * 100 / dst_h;
|
||||
|
||||
- if (ability < required) {
|
||||
+ if (!afbc && ability < required) {
|
||||
DRM_DEBUG_DRIVER("Using vertical coarse scaling\n");
|
||||
vm = src_h;
|
||||
vn = (u32)ability * dst_h / 100;
|
||||
@@ -145,7 +147,7 @@ static int sun8i_vi_layer_update_coord(struct sun8i_mixer *mixer, int channel,
|
||||
/* it seems that every RGB scaler has buffer for 2048 pixels */
|
||||
scanline = subsampled ? mixer->cfg->scanline_yuv : 2048;
|
||||
|
||||
- if (src_w > scanline) {
|
||||
+ if (!afbc && src_w > scanline) {
|
||||
DRM_DEBUG_DRIVER("Using horizontal coarse scaling\n");
|
||||
hm = src_w;
|
||||
hn = scanline;
|
||||
@@ -308,6 +310,15 @@ static int sun8i_vi_layer_update_buffer(struct sun8i_mixer *mixer, int channel,
|
||||
return 0;
|
||||
}
|
||||
|
||||
+static void sun8i_vi_layer_prepare_non_linear(struct sun8i_mixer *mixer,
|
||||
+ int channel, int overlay)
|
||||
+{
|
||||
+ u32 base = sun8i_channel_base(mixer, channel);
|
||||
+
|
||||
+ regmap_write(mixer->engine.regs,
|
||||
+ SUN8I_MIXER_CHAN_VI_LAYER_ATTR(base, overlay), 0);
|
||||
+}
|
||||
+
|
||||
static int sun8i_vi_layer_atomic_check(struct drm_plane *plane,
|
||||
struct drm_atomic_state *state)
|
||||
{
|
||||
@@ -348,18 +359,45 @@ static void sun8i_vi_layer_atomic_update(struct drm_plane *plane,
|
||||
struct sun8i_layer *layer = plane_to_sun8i_layer(plane);
|
||||
unsigned int zpos = new_state->normalized_zpos;
|
||||
struct sun8i_mixer *mixer = layer->mixer;
|
||||
+ struct drm_framebuffer *fb = plane->state->fb;
|
||||
+ bool afbc = drm_is_afbc(fb->modifier);
|
||||
|
||||
- if (!new_state->crtc || !new_state->visible)
|
||||
+ if (!new_state->crtc || !new_state->visible) {
|
||||
+ if (mixer->cfg->de_type >= sun8i_mixer_de3)
|
||||
+ sun50i_afbc_disable(mixer, layer->channel);
|
||||
return;
|
||||
+ }
|
||||
|
||||
sun8i_vi_layer_update_coord(mixer, layer->channel,
|
||||
- layer->overlay, plane, zpos);
|
||||
- sun8i_vi_layer_update_alpha(mixer, layer->channel,
|
||||
- layer->overlay, plane);
|
||||
- sun8i_vi_layer_update_formats(mixer, layer->channel,
|
||||
- layer->overlay, plane);
|
||||
- sun8i_vi_layer_update_buffer(mixer, layer->channel,
|
||||
- layer->overlay, plane);
|
||||
+ layer->overlay, plane, zpos, afbc);
|
||||
+
|
||||
+ if (afbc) {
|
||||
+ u32 fmt_type;
|
||||
+
|
||||
+ sun8i_vi_layer_prepare_non_linear(mixer, layer->channel,
|
||||
+ layer->overlay);
|
||||
+ sun50i_afbc_atomic_update(mixer, layer->channel, plane);
|
||||
+
|
||||
+ fmt_type = sun8i_vi_layer_get_format_type(fb->format);
|
||||
+ sun8i_csc_set_ccsc(mixer, layer->channel, fmt_type,
|
||||
+ plane->state->color_encoding,
|
||||
+ plane->state->color_range);
|
||||
+ } else {
|
||||
+ sun8i_vi_layer_update_alpha(mixer, layer->channel,
|
||||
+ layer->overlay, plane);
|
||||
+ sun8i_vi_layer_update_formats(mixer, layer->channel,
|
||||
+ layer->overlay, plane);
|
||||
+ sun8i_vi_layer_update_buffer(mixer, layer->channel,
|
||||
+ layer->overlay, plane);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static bool sun8i_vi_layer_format_mod_supported(struct drm_plane *plane,
|
||||
+ u32 format, u64 modifier)
|
||||
+{
|
||||
+ struct sun8i_layer *layer = plane_to_sun8i_layer(plane);
|
||||
+
|
||||
+ return sun50i_afbc_format_mod_supported(layer->mixer, format, modifier);
|
||||
}
|
||||
|
||||
static const struct drm_plane_helper_funcs sun8i_vi_layer_helper_funcs = {
|
||||
@@ -374,6 +412,7 @@ static const struct drm_plane_funcs sun8i_vi_layer_funcs = {
|
||||
.disable_plane = drm_atomic_helper_disable_plane,
|
||||
.reset = drm_atomic_helper_plane_reset,
|
||||
.update_plane = drm_atomic_helper_update_plane,
|
||||
+ .format_mod_supported = sun8i_vi_layer_format_mod_supported,
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -457,6 +496,11 @@ static const u32 sun8i_vi_layer_de3_formats[] = {
|
||||
DRM_FORMAT_YVU411,
|
||||
DRM_FORMAT_YVU420,
|
||||
DRM_FORMAT_YVU422,
|
||||
+
|
||||
+ /* AFBC only formats */
|
||||
+ DRM_FORMAT_YUV420_8BIT,
|
||||
+ DRM_FORMAT_YUV420_10BIT,
|
||||
+ DRM_FORMAT_Y210,
|
||||
};
|
||||
|
||||
static const uint64_t sun8i_layer_modifiers[] = {
|
||||
@@ -464,6 +508,18 @@ static const uint64_t sun8i_layer_modifiers[] = {
|
||||
DRM_FORMAT_MOD_INVALID
|
||||
};
|
||||
|
||||
+static const uint64_t sun50i_layer_de3_modifiers[] = {
|
||||
+ DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 |
|
||||
+ AFBC_FORMAT_MOD_SPARSE |
|
||||
+ AFBC_FORMAT_MOD_SPLIT),
|
||||
+ DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 |
|
||||
+ AFBC_FORMAT_MOD_YTR |
|
||||
+ AFBC_FORMAT_MOD_SPARSE |
|
||||
+ AFBC_FORMAT_MOD_SPLIT),
|
||||
+ DRM_FORMAT_MOD_LINEAR,
|
||||
+ DRM_FORMAT_MOD_INVALID
|
||||
+};
|
||||
+
|
||||
struct sun8i_layer *sun8i_vi_layer_init_one(struct drm_device *drm,
|
||||
struct sun8i_mixer *mixer,
|
||||
int index)
|
||||
@@ -472,6 +528,7 @@ struct sun8i_layer *sun8i_vi_layer_init_one(struct drm_device *drm,
|
||||
u32 supported_encodings, supported_ranges;
|
||||
unsigned int plane_cnt, format_count;
|
||||
struct sun8i_layer *layer;
|
||||
+ const uint64_t *modifiers;
|
||||
const u32 *formats;
|
||||
int ret;
|
||||
|
||||
@@ -487,9 +544,11 @@ struct sun8i_layer *sun8i_vi_layer_init_one(struct drm_device *drm,
|
||||
if (mixer->cfg->de_type >= sun8i_mixer_de3) {
|
||||
formats = sun8i_vi_layer_de3_formats;
|
||||
format_count = ARRAY_SIZE(sun8i_vi_layer_de3_formats);
|
||||
+ modifiers = sun50i_layer_de3_modifiers;
|
||||
} else {
|
||||
formats = sun8i_vi_layer_formats;
|
||||
format_count = ARRAY_SIZE(sun8i_vi_layer_formats);
|
||||
+ modifiers = sun8i_layer_modifiers;
|
||||
}
|
||||
|
||||
if (!mixer->cfg->ui_num && index == 0)
|
||||
@@ -499,8 +558,7 @@ struct sun8i_layer *sun8i_vi_layer_init_one(struct drm_device *drm,
|
||||
ret = drm_universal_plane_init(drm, &layer->plane, 0,
|
||||
&sun8i_vi_layer_funcs,
|
||||
formats, format_count,
|
||||
- sun8i_layer_modifiers,
|
||||
- type, NULL);
|
||||
+ modifiers, type, NULL);
|
||||
if (ret) {
|
||||
dev_err(drm->dev, "Couldn't initialize layer\n");
|
||||
return ERR_PTR(ret);
|
||||
--
|
||||
2.35.3
|
||||
|
||||
|
|
@ -0,0 +1,126 @@
|
|||
From 3b6462ebad249f4762acfd8e262442bb0cda95b4 Mon Sep 17 00:00:00 2001
|
||||
From: Jernej Skrabec <jernej.skrabec@gmail.com>
|
||||
Date: Sun, 29 Sep 2024 22:04:40 +1300
|
||||
Subject: drm: sun4i: de3: add YUV support to the DE3 mixer
|
||||
|
||||
The mixer in the DE3 display engine supports YUV 8 and 10 bit
|
||||
formats in addition to 8-bit RGB. Add the required register
|
||||
configuration and format enumeration callback functions to the mixer,
|
||||
and store the in-use output format (defaulting to RGB) and color
|
||||
encoding in engine variables.
|
||||
|
||||
Signed-off-by: Jernej Skrabec <jernej.skrabec@gmail.com>
|
||||
Signed-off-by: Ryan Walklin <ryan@testtoast.com>
|
||||
---
|
||||
drivers/gpu/drm/sun4i/sun8i_mixer.c | 53 ++++++++++++++++++++++++++--
|
||||
drivers/gpu/drm/sun4i/sunxi_engine.h | 5 +++
|
||||
2 files changed, 55 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.c b/drivers/gpu/drm/sun4i/sun8i_mixer.c
|
||||
index 252827715de1..a50c583852ed 100644
|
||||
--- a/drivers/gpu/drm/sun4i/sun8i_mixer.c
|
||||
+++ b/drivers/gpu/drm/sun4i/sun8i_mixer.c
|
||||
@@ -23,7 +23,10 @@
|
||||
#include <drm/drm_gem_dma_helper.h>
|
||||
#include <drm/drm_probe_helper.h>
|
||||
|
||||
+#include <uapi/linux/media-bus-format.h>
|
||||
+
|
||||
#include "sun4i_drv.h"
|
||||
+#include "sun50i_fmt.h"
|
||||
#include "sun8i_mixer.h"
|
||||
#include "sun8i_ui_layer.h"
|
||||
#include "sun8i_vi_layer.h"
|
||||
@@ -390,12 +393,52 @@ static void sun8i_mixer_mode_set(struct sunxi_engine *engine,
|
||||
|
||||
DRM_DEBUG_DRIVER("Switching display mixer interlaced mode %s\n",
|
||||
interlaced ? "on" : "off");
|
||||
+
|
||||
+ if (engine->format == MEDIA_BUS_FMT_RGB888_1X24)
|
||||
+ val = SUN8I_MIXER_BLEND_COLOR_BLACK;
|
||||
+ else
|
||||
+ val = 0xff108080;
|
||||
+
|
||||
+ regmap_write(mixer->engine.regs,
|
||||
+ SUN8I_MIXER_BLEND_BKCOLOR(bld_base), val);
|
||||
+ regmap_write(mixer->engine.regs,
|
||||
+ SUN8I_MIXER_BLEND_ATTR_FCOLOR(bld_base, 0), val);
|
||||
+
|
||||
+ if (mixer->cfg->has_formatter)
|
||||
+ sun50i_fmt_setup(mixer, mode->hdisplay,
|
||||
+ mode->vdisplay, mixer->engine.format);
|
||||
+}
|
||||
+
|
||||
+static u32 *sun8i_mixer_get_supported_fmts(struct sunxi_engine *engine, u32 *num)
|
||||
+{
|
||||
+ struct sun8i_mixer *mixer = engine_to_sun8i_mixer(engine);
|
||||
+ u32 *formats, count;
|
||||
+
|
||||
+ count = 0;
|
||||
+
|
||||
+ formats = kcalloc(5, sizeof(*formats), GFP_KERNEL);
|
||||
+ if (!formats)
|
||||
+ return NULL;
|
||||
+
|
||||
+ if (mixer->cfg->has_formatter) {
|
||||
+ formats[count++] = MEDIA_BUS_FMT_UYYVYY10_0_5X30;
|
||||
+ formats[count++] = MEDIA_BUS_FMT_YUV8_1X24;
|
||||
+ formats[count++] = MEDIA_BUS_FMT_UYVY8_1X16;
|
||||
+ formats[count++] = MEDIA_BUS_FMT_UYYVYY8_0_5X24;
|
||||
+ }
|
||||
+
|
||||
+ formats[count++] = MEDIA_BUS_FMT_RGB888_1X24;
|
||||
+
|
||||
+ *num = count;
|
||||
+
|
||||
+ return formats;
|
||||
}
|
||||
|
||||
static const struct sunxi_engine_ops sun8i_engine_ops = {
|
||||
- .commit = sun8i_mixer_commit,
|
||||
- .layers_init = sun8i_layers_init,
|
||||
- .mode_set = sun8i_mixer_mode_set,
|
||||
+ .commit = sun8i_mixer_commit,
|
||||
+ .layers_init = sun8i_layers_init,
|
||||
+ .mode_set = sun8i_mixer_mode_set,
|
||||
+ .get_supported_fmts = sun8i_mixer_get_supported_fmts,
|
||||
};
|
||||
|
||||
static const struct regmap_config sun8i_mixer_regmap_config = {
|
||||
@@ -456,6 +499,10 @@ static int sun8i_mixer_bind(struct device *dev, struct device *master,
|
||||
dev_set_drvdata(dev, mixer);
|
||||
mixer->engine.ops = &sun8i_engine_ops;
|
||||
mixer->engine.node = dev->of_node;
|
||||
+ /* default output format, supported by all mixers */
|
||||
+ mixer->engine.format = MEDIA_BUS_FMT_RGB888_1X24;
|
||||
+ /* default color encoding, ignored with RGB I/O */
|
||||
+ mixer->engine.encoding = DRM_COLOR_YCBCR_BT601;
|
||||
|
||||
if (of_property_present(dev->of_node, "iommus")) {
|
||||
/*
|
||||
diff --git a/drivers/gpu/drm/sun4i/sunxi_engine.h b/drivers/gpu/drm/sun4i/sunxi_engine.h
|
||||
index c48cbc1aceb8..ffafc29b3a0c 100644
|
||||
--- a/drivers/gpu/drm/sun4i/sunxi_engine.h
|
||||
+++ b/drivers/gpu/drm/sun4i/sunxi_engine.h
|
||||
@@ -6,6 +6,8 @@
|
||||
#ifndef _SUNXI_ENGINE_H_
|
||||
#define _SUNXI_ENGINE_H_
|
||||
|
||||
+#include <drm/drm_color_mgmt.h>
|
||||
+
|
||||
struct drm_plane;
|
||||
struct drm_crtc;
|
||||
struct drm_device;
|
||||
@@ -151,6 +153,9 @@ struct sunxi_engine {
|
||||
|
||||
int id;
|
||||
|
||||
+ u32 format;
|
||||
+ enum drm_color_encoding encoding;
|
||||
+
|
||||
/* Engine list management */
|
||||
struct list_head list;
|
||||
};
|
||||
--
|
||||
2.35.3
|
||||
|
||||
|
|
@ -0,0 +1,83 @@
|
|||
From ff794822d56721795fec59dea66164cc19ba792c Mon Sep 17 00:00:00 2001
|
||||
From: Jernej Skrabec <jernej.skrabec@gmail.com>
|
||||
Date: Sun, 29 Sep 2024 22:04:43 +1300
|
||||
Subject: drm: sun4i: de3: add YUV support to the TCON
|
||||
|
||||
Account for U/V channel subsampling by reducing the dot clock and
|
||||
resolution with a divider in the DE3 timing controller if a YUV format
|
||||
is selected.
|
||||
|
||||
Signed-off-by: Jernej Skrabec <jernej.skrabec@gmail.com>
|
||||
Signed-off-by: Ryan Walklin <ryan@testtoast.com>
|
||||
---
|
||||
drivers/gpu/drm/sun4i/sun4i_tcon.c | 26 +++++++++++++++++++-------
|
||||
1 file changed, 19 insertions(+), 7 deletions(-)
|
||||
|
||||
diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c b/drivers/gpu/drm/sun4i/sun4i_tcon.c
|
||||
index 3675c87461e9..af67bf2e6e09 100644
|
||||
--- a/drivers/gpu/drm/sun4i/sun4i_tcon.c
|
||||
+++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c
|
||||
@@ -649,14 +649,26 @@ static void sun4i_tcon0_mode_set_rgb(struct sun4i_tcon *tcon,
|
||||
static void sun4i_tcon1_mode_set(struct sun4i_tcon *tcon,
|
||||
const struct drm_display_mode *mode)
|
||||
{
|
||||
- unsigned int bp, hsync, vsync, vtotal;
|
||||
+ unsigned int bp, hsync, vsync, vtotal, div;
|
||||
+ struct sun4i_crtc *scrtc = tcon->crtc;
|
||||
+ struct sunxi_engine *engine = scrtc->engine;
|
||||
u8 clk_delay;
|
||||
u32 val;
|
||||
|
||||
WARN_ON(!tcon->quirks->has_channel_1);
|
||||
|
||||
+ switch (engine->format) {
|
||||
+ case MEDIA_BUS_FMT_UYYVYY8_0_5X24:
|
||||
+ case MEDIA_BUS_FMT_UYYVYY10_0_5X30:
|
||||
+ div = 2;
|
||||
+ break;
|
||||
+ default:
|
||||
+ div = 1;
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
/* Configure the dot clock */
|
||||
- clk_set_rate(tcon->sclk1, mode->crtc_clock * 1000);
|
||||
+ clk_set_rate(tcon->sclk1, mode->crtc_clock * 1000 / div);
|
||||
|
||||
/* Adjust clock delay */
|
||||
clk_delay = sun4i_tcon_get_clk_delay(mode, 1);
|
||||
@@ -675,17 +687,17 @@ static void sun4i_tcon1_mode_set(struct sun4i_tcon *tcon,
|
||||
|
||||
/* Set the input resolution */
|
||||
regmap_write(tcon->regs, SUN4I_TCON1_BASIC0_REG,
|
||||
- SUN4I_TCON1_BASIC0_X(mode->crtc_hdisplay) |
|
||||
+ SUN4I_TCON1_BASIC0_X(mode->crtc_hdisplay / div) |
|
||||
SUN4I_TCON1_BASIC0_Y(mode->crtc_vdisplay));
|
||||
|
||||
/* Set the upscaling resolution */
|
||||
regmap_write(tcon->regs, SUN4I_TCON1_BASIC1_REG,
|
||||
- SUN4I_TCON1_BASIC1_X(mode->crtc_hdisplay) |
|
||||
+ SUN4I_TCON1_BASIC1_X(mode->crtc_hdisplay / div) |
|
||||
SUN4I_TCON1_BASIC1_Y(mode->crtc_vdisplay));
|
||||
|
||||
/* Set the output resolution */
|
||||
regmap_write(tcon->regs, SUN4I_TCON1_BASIC2_REG,
|
||||
- SUN4I_TCON1_BASIC2_X(mode->crtc_hdisplay) |
|
||||
+ SUN4I_TCON1_BASIC2_X(mode->crtc_hdisplay / div) |
|
||||
SUN4I_TCON1_BASIC2_Y(mode->crtc_vdisplay));
|
||||
|
||||
/* Set horizontal display timings */
|
||||
@@ -693,8 +705,8 @@ static void sun4i_tcon1_mode_set(struct sun4i_tcon *tcon,
|
||||
DRM_DEBUG_DRIVER("Setting horizontal total %d, backporch %d\n",
|
||||
mode->htotal, bp);
|
||||
regmap_write(tcon->regs, SUN4I_TCON1_BASIC3_REG,
|
||||
- SUN4I_TCON1_BASIC3_H_TOTAL(mode->crtc_htotal) |
|
||||
- SUN4I_TCON1_BASIC3_H_BACKPORCH(bp));
|
||||
+ SUN4I_TCON1_BASIC3_H_TOTAL(mode->crtc_htotal / div) |
|
||||
+ SUN4I_TCON1_BASIC3_H_BACKPORCH(bp / div));
|
||||
|
||||
bp = mode->crtc_vtotal - mode->crtc_vsync_start;
|
||||
DRM_DEBUG_DRIVER("Setting vertical total %d, backporch %d\n",
|
||||
--
|
||||
2.35.3
|
||||
|
||||
|
|
@ -0,0 +1,225 @@
|
|||
From a23ed976ee720c2445791716d975f040ef576c2b Mon Sep 17 00:00:00 2001
|
||||
From: Jernej Skrabec <jernej.skrabec@gmail.com>
|
||||
Date: Sun, 29 Sep 2024 22:04:42 +1300
|
||||
Subject: drm: sun4i: de3: add YUV support to the color space correction module
|
||||
|
||||
Add coefficients and support for YUV formats to the display engine
|
||||
colorspace and dynamic range correction submodule.
|
||||
|
||||
Signed-off-by: Jernej Skrabec <jernej.skrabec@gmail.com>
|
||||
Signed-off-by: Ryan Walklin <ryan@testtoast.com>
|
||||
---
|
||||
drivers/gpu/drm/sun4i/sun8i_csc.c | 164 +++++++++++++++++++++++++++++-
|
||||
1 file changed, 162 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/drivers/gpu/drm/sun4i/sun8i_csc.c b/drivers/gpu/drm/sun4i/sun8i_csc.c
|
||||
index 8a336ccb27d3..e12a81fa9108 100644
|
||||
--- a/drivers/gpu/drm/sun4i/sun8i_csc.c
|
||||
+++ b/drivers/gpu/drm/sun4i/sun8i_csc.c
|
||||
@@ -5,6 +5,8 @@
|
||||
|
||||
#include <drm/drm_print.h>
|
||||
|
||||
+#include <uapi/linux/media-bus-format.h>
|
||||
+
|
||||
#include "sun8i_csc.h"
|
||||
#include "sun8i_mixer.h"
|
||||
|
||||
@@ -107,6 +109,135 @@ static const u32 yuv2rgb_de3[2][3][12] = {
|
||||
},
|
||||
};
|
||||
|
||||
+/* always convert to limited mode */
|
||||
+static const u32 rgb2yuv_de3[3][12] = {
|
||||
+ [DRM_COLOR_YCBCR_BT601] = {
|
||||
+ 0x0000837A, 0x0001021D, 0x00003221, 0x00000040,
|
||||
+ 0xFFFFB41C, 0xFFFF6B03, 0x0000E0E1, 0x00000200,
|
||||
+ 0x0000E0E1, 0xFFFF43B1, 0xFFFFDB6E, 0x00000200,
|
||||
+ },
|
||||
+ [DRM_COLOR_YCBCR_BT709] = {
|
||||
+ 0x00005D7C, 0x00013A7C, 0x00001FBF, 0x00000040,
|
||||
+ 0xFFFFCC78, 0xFFFF52A7, 0x0000E0E1, 0x00000200,
|
||||
+ 0x0000E0E1, 0xFFFF33BE, 0xFFFFEB61, 0x00000200,
|
||||
+ },
|
||||
+ [DRM_COLOR_YCBCR_BT2020] = {
|
||||
+ 0x00007384, 0x00012A21, 0x00001A13, 0x00000040,
|
||||
+ 0xFFFFC133, 0xFFFF5DEC, 0x0000E0E1, 0x00000200,
|
||||
+ 0x0000E0E1, 0xFFFF3135, 0xFFFFEDEA, 0x00000200,
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
+/* always convert to limited mode */
|
||||
+static const u32 yuv2yuv_de3[2][3][3][12] = {
|
||||
+ [DRM_COLOR_YCBCR_LIMITED_RANGE] = {
|
||||
+ [DRM_COLOR_YCBCR_BT601] = {
|
||||
+ [DRM_COLOR_YCBCR_BT601] = {
|
||||
+ 0x00020000, 0x00000000, 0x00000000, 0x00000000,
|
||||
+ 0x00000000, 0x00020000, 0x00000000, 0x00000000,
|
||||
+ 0x00000000, 0x00000000, 0x00020000, 0x00000000,
|
||||
+ },
|
||||
+ [DRM_COLOR_YCBCR_BT709] = {
|
||||
+ 0x00020000, 0xFFFFC4D7, 0xFFFF9589, 0xFFC00040,
|
||||
+ 0x00000000, 0x0002098B, 0x00003AAF, 0xFE000200,
|
||||
+ 0x00000000, 0x0000266D, 0x00020CF8, 0xFE000200,
|
||||
+ },
|
||||
+ [DRM_COLOR_YCBCR_BT2020] = {
|
||||
+ 0x00020000, 0xFFFFBFCE, 0xFFFFC5FF, 0xFFC00040,
|
||||
+ 0x00000000, 0x00020521, 0x00001F89, 0xFE000200,
|
||||
+ 0x00000000, 0x00002C87, 0x00020F07, 0xFE000200,
|
||||
+ },
|
||||
+ },
|
||||
+ [DRM_COLOR_YCBCR_BT709] = {
|
||||
+ [DRM_COLOR_YCBCR_BT601] = {
|
||||
+ 0x00020000, 0x000032D9, 0x00006226, 0xFFC00040,
|
||||
+ 0x00000000, 0x0001FACE, 0xFFFFC759, 0xFE000200,
|
||||
+ 0x00000000, 0xFFFFDAE7, 0x0001F780, 0xFE000200,
|
||||
+ },
|
||||
+ [DRM_COLOR_YCBCR_BT709] = {
|
||||
+ 0x00020000, 0x00000000, 0x00000000, 0x00000000,
|
||||
+ 0x00000000, 0x00020000, 0x00000000, 0x00000000,
|
||||
+ 0x00000000, 0x00000000, 0x00020000, 0x00000000,
|
||||
+ },
|
||||
+ [DRM_COLOR_YCBCR_BT2020] = {
|
||||
+ 0x00020000, 0xFFFFF782, 0x00003036, 0xFFC00040,
|
||||
+ 0x00000000, 0x0001FD99, 0xFFFFE5CA, 0xFE000200,
|
||||
+ 0x00000000, 0x000005E4, 0x0002015A, 0xFE000200,
|
||||
+ },
|
||||
+ },
|
||||
+ [DRM_COLOR_YCBCR_BT2020] = {
|
||||
+ [DRM_COLOR_YCBCR_BT601] = {
|
||||
+ 0x00020000, 0x00003B03, 0x000034D2, 0xFFC00040,
|
||||
+ 0x00000000, 0x0001FD8C, 0xFFFFE183, 0xFE000200,
|
||||
+ 0x00000000, 0xFFFFD4F3, 0x0001F3FA, 0xFE000200,
|
||||
+ },
|
||||
+ [DRM_COLOR_YCBCR_BT709] = {
|
||||
+ 0x00020000, 0x00000916, 0xFFFFD061, 0xFFC00040,
|
||||
+ 0x00000000, 0x0002021C, 0x00001A40, 0xFE000200,
|
||||
+ 0x00000000, 0xFFFFFA19, 0x0001FE5A, 0xFE000200,
|
||||
+ },
|
||||
+ [DRM_COLOR_YCBCR_BT2020] = {
|
||||
+ 0x00020000, 0x00000000, 0x00000000, 0x00000000,
|
||||
+ 0x00000000, 0x00020000, 0x00000000, 0x00000000,
|
||||
+ 0x00000000, 0x00000000, 0x00020000, 0x00000000,
|
||||
+ },
|
||||
+ },
|
||||
+ },
|
||||
+ [DRM_COLOR_YCBCR_FULL_RANGE] = {
|
||||
+ [DRM_COLOR_YCBCR_BT601] = {
|
||||
+ [DRM_COLOR_YCBCR_BT601] = {
|
||||
+ 0x0001B7B8, 0x00000000, 0x00000000, 0x00000040,
|
||||
+ 0x00000000, 0x0001C1C2, 0x00000000, 0xFE000200,
|
||||
+ 0x00000000, 0x00000000, 0x0001C1C2, 0xFE000200,
|
||||
+ },
|
||||
+ [DRM_COLOR_YCBCR_BT709] = {
|
||||
+ 0x0001B7B8, 0xFFFFCC08, 0xFFFFA27B, 0x00000040,
|
||||
+ 0x00000000, 0x0001CA24, 0x0000338D, 0xFE000200,
|
||||
+ 0x00000000, 0x000021C1, 0x0001CD26, 0xFE000200,
|
||||
+ },
|
||||
+ [DRM_COLOR_YCBCR_BT2020] = {
|
||||
+ 0x0001B7B8, 0xFFFFC79C, 0xFFFFCD0C, 0x00000040,
|
||||
+ 0x00000000, 0x0001C643, 0x00001BB4, 0xFE000200,
|
||||
+ 0x00000000, 0x0000271D, 0x0001CEF5, 0xFE000200,
|
||||
+ },
|
||||
+ },
|
||||
+ [DRM_COLOR_YCBCR_BT709] = {
|
||||
+ [DRM_COLOR_YCBCR_BT601] = {
|
||||
+ 0x0001B7B8, 0x00002CAB, 0x00005638, 0x00000040,
|
||||
+ 0x00000000, 0x0001BD32, 0xFFFFCE3C, 0xFE000200,
|
||||
+ 0x00000000, 0xFFFFDF6A, 0x0001BA4A, 0xFE000200,
|
||||
+ },
|
||||
+ [DRM_COLOR_YCBCR_BT709] = {
|
||||
+ 0x0001B7B8, 0x00000000, 0x00000000, 0x00000040,
|
||||
+ 0x00000000, 0x0001C1C2, 0x00000000, 0xFE000200,
|
||||
+ 0x00000000, 0x00000000, 0x0001C1C2, 0xFE000200,
|
||||
+ },
|
||||
+ [DRM_COLOR_YCBCR_BT2020] = {
|
||||
+ 0x0001B7B8, 0xFFFFF88A, 0x00002A5A, 0x00000040,
|
||||
+ 0x00000000, 0x0001BFA5, 0xFFFFE8FA, 0xFE000200,
|
||||
+ 0x00000000, 0x0000052D, 0x0001C2F1, 0xFE000200,
|
||||
+ },
|
||||
+ },
|
||||
+ [DRM_COLOR_YCBCR_BT2020] = {
|
||||
+ [DRM_COLOR_YCBCR_BT601] = {
|
||||
+ 0x0001B7B8, 0x000033D6, 0x00002E66, 0x00000040,
|
||||
+ 0x00000000, 0x0001BF9A, 0xFFFFE538, 0xFE000200,
|
||||
+ 0x00000000, 0xFFFFDA2F, 0x0001B732, 0xFE000200,
|
||||
+ },
|
||||
+ [DRM_COLOR_YCBCR_BT709] = {
|
||||
+ 0x0001B7B8, 0x000007FB, 0xFFFFD62B, 0x00000040,
|
||||
+ 0x00000000, 0x0001C39D, 0x0000170F, 0xFE000200,
|
||||
+ 0x00000000, 0xFFFFFAD1, 0x0001C04F, 0xFE000200,
|
||||
+ },
|
||||
+ [DRM_COLOR_YCBCR_BT2020] = {
|
||||
+ 0x0001B7B8, 0x00000000, 0x00000000, 0x00000040,
|
||||
+ 0x00000000, 0x0001C1C2, 0x00000000, 0xFE000200,
|
||||
+ 0x00000000, 0x00000000, 0x0001C1C2, 0xFE000200,
|
||||
+ },
|
||||
+ },
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
static void sun8i_csc_setup(struct regmap *map, u32 base,
|
||||
enum format_type fmt_type,
|
||||
enum drm_color_encoding encoding,
|
||||
@@ -148,12 +279,27 @@ static void sun8i_csc_setup(struct regmap *map, u32 base,
|
||||
regmap_write(map, SUN8I_CSC_CTRL(base), val);
|
||||
}
|
||||
|
||||
+static const u32 *sun8i_csc_get_de3_yuv_table(enum drm_color_encoding in_enc,
|
||||
+ enum drm_color_range in_range,
|
||||
+ u32 out_format,
|
||||
+ enum drm_color_encoding out_enc)
|
||||
+{
|
||||
+ if (out_format == MEDIA_BUS_FMT_RGB888_1X24)
|
||||
+ return yuv2rgb_de3[in_range][in_enc];
|
||||
+
|
||||
+ /* check for identity transformation */
|
||||
+ if (in_range == DRM_COLOR_YCBCR_LIMITED_RANGE && out_enc == in_enc)
|
||||
+ return NULL;
|
||||
+
|
||||
+ return yuv2yuv_de3[in_range][in_enc][out_enc];
|
||||
+}
|
||||
+
|
||||
static void sun8i_de3_ccsc_setup(struct sunxi_engine *engine, int layer,
|
||||
enum format_type fmt_type,
|
||||
enum drm_color_encoding encoding,
|
||||
enum drm_color_range range)
|
||||
{
|
||||
- u32 addr, val, mask;
|
||||
+ u32 addr, val = 0, mask;
|
||||
struct regmap *map;
|
||||
const u32 *table;
|
||||
int i;
|
||||
@@ -164,14 +310,28 @@ static void sun8i_de3_ccsc_setup(struct sunxi_engine *engine, int layer,
|
||||
|
||||
switch (fmt_type) {
|
||||
case FORMAT_TYPE_RGB:
|
||||
- val = 0;
|
||||
+ if (engine->format == MEDIA_BUS_FMT_RGB888_1X24)
|
||||
+ break;
|
||||
+ val = mask;
|
||||
+ addr = SUN50I_MIXER_BLEND_CSC_COEFF(DE3_BLD_BASE, layer, 0);
|
||||
+ regmap_bulk_write(map, addr, rgb2yuv_de3[engine->encoding], 12);
|
||||
break;
|
||||
case FORMAT_TYPE_YUV:
|
||||
+ table = sun8i_csc_get_de3_yuv_table(encoding, range,
|
||||
+ engine->format,
|
||||
+ engine->encoding);
|
||||
+ if (!table)
|
||||
+ break;
|
||||
val = mask;
|
||||
addr = SUN50I_MIXER_BLEND_CSC_COEFF(DE3_BLD_BASE, layer, 0);
|
||||
regmap_bulk_write(map, addr, table, 12);
|
||||
break;
|
||||
case FORMAT_TYPE_YVU:
|
||||
+ table = sun8i_csc_get_de3_yuv_table(encoding, range,
|
||||
+ engine->format,
|
||||
+ engine->encoding);
|
||||
+ if (!table)
|
||||
+ table = yuv2yuv_de3[range][encoding][encoding];
|
||||
val = mask;
|
||||
for (i = 0; i < 12; i++) {
|
||||
if ((i & 3) == 1)
|
||||
--
|
||||
2.35.3
|
||||
|
||||
|
|
@ -0,0 +1,63 @@
|
|||
From 99d327853acbc5d6c6d4140f004f82fcd5c40ea1 Mon Sep 17 00:00:00 2001
|
||||
From: Jernej Skrabec <jernej.skrabec@gmail.com>
|
||||
Date: Sun, 29 Sep 2024 22:04:38 +1300
|
||||
Subject: drm: sun4i: de3: add format enumeration function to engine
|
||||
|
||||
The DE3 display engine supports YUV formats in addition to RGB.
|
||||
|
||||
Add an optional format enumeration function to the engine.
|
||||
|
||||
Signed-off-by: Jernej Skrabec <jernej.skrabec@gmail.com>
|
||||
Signed-off-by: Ryan Walklin <ryan@testtoast.com>
|
||||
---
|
||||
drivers/gpu/drm/sun4i/sunxi_engine.h | 29 ++++++++++++++++++++++++++++
|
||||
1 file changed, 29 insertions(+)
|
||||
|
||||
diff --git a/drivers/gpu/drm/sun4i/sunxi_engine.h b/drivers/gpu/drm/sun4i/sunxi_engine.h
|
||||
index ec0c4932f15c..c48cbc1aceb8 100644
|
||||
--- a/drivers/gpu/drm/sun4i/sunxi_engine.h
|
||||
+++ b/drivers/gpu/drm/sun4i/sunxi_engine.h
|
||||
@@ -123,6 +123,17 @@ struct sunxi_engine_ops {
|
||||
*/
|
||||
void (*mode_set)(struct sunxi_engine *engine,
|
||||
const struct drm_display_mode *mode);
|
||||
+
|
||||
+ /**
|
||||
+ * @get_supported_fmts
|
||||
+ *
|
||||
+ * This callback is used to enumerate all supported output
|
||||
+ * formats by the engine. They are used for bridge format
|
||||
+ * negotiation.
|
||||
+ *
|
||||
+ * This function is optional.
|
||||
+ */
|
||||
+ u32 *(*get_supported_fmts)(struct sunxi_engine *engine, u32 *num);
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -215,4 +226,22 @@ sunxi_engine_mode_set(struct sunxi_engine *engine,
|
||||
if (engine->ops && engine->ops->mode_set)
|
||||
engine->ops->mode_set(engine, mode);
|
||||
}
|
||||
+
|
||||
+/**
|
||||
+ * sunxi_engine_get_supported_formats - Provide array of supported formats
|
||||
+ * @engine: pointer to the engine
|
||||
+ * @num: pointer to variable, which will hold number of formats
|
||||
+ *
|
||||
+ * This list can be used for format negotiation by bridge.
|
||||
+ */
|
||||
+static inline u32 *
|
||||
+sunxi_engine_get_supported_formats(struct sunxi_engine *engine, u32 *num)
|
||||
+{
|
||||
+ if (engine->ops && engine->ops->get_supported_fmts)
|
||||
+ return engine->ops->get_supported_fmts(engine, num);
|
||||
+
|
||||
+ *num = 0;
|
||||
+
|
||||
+ return NULL;
|
||||
+}
|
||||
#endif /* _SUNXI_ENGINE_H_ */
|
||||
--
|
||||
2.35.3
|
||||
|
||||
|
|
@ -0,0 +1,53 @@
|
|||
From f9a39553dcf5e87eba968d2aac4f5acf52baa392 Mon Sep 17 00:00:00 2001
|
||||
From: Jernej Skrabec <jernej.skrabec@gmail.com>
|
||||
Date: Sun, 29 Sep 2024 22:04:39 +1300
|
||||
Subject: drm: sun4i: de3: add formatter flag to mixer config
|
||||
|
||||
Only the DE3 (and newer) display engines have a formatter module. This
|
||||
could be inferred from the is_de3 flag alone, however this will not
|
||||
scale with addition of future DE versions in subsequent patches.
|
||||
|
||||
Add a separate flag to signal this in the mixer configuration.
|
||||
|
||||
Signed-off-by: Jernej Skrabec <jernej.skrabec@gmail.com>
|
||||
Signed-off-by: Ryan Walklin <ryan@testtoast.com>
|
||||
---
|
||||
drivers/gpu/drm/sun4i/sun8i_mixer.c | 1 +
|
||||
drivers/gpu/drm/sun4i/sun8i_mixer.h | 2 ++
|
||||
2 files changed, 3 insertions(+)
|
||||
|
||||
diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.c b/drivers/gpu/drm/sun4i/sun8i_mixer.c
|
||||
index bd0fe2c6624e..252827715de1 100644
|
||||
--- a/drivers/gpu/drm/sun4i/sun8i_mixer.c
|
||||
+++ b/drivers/gpu/drm/sun4i/sun8i_mixer.c
|
||||
@@ -717,6 +717,7 @@ static const struct sun8i_mixer_cfg sun50i_a64_mixer1_cfg = {
|
||||
static const struct sun8i_mixer_cfg sun50i_h6_mixer0_cfg = {
|
||||
.ccsc = CCSC_MIXER0_LAYOUT,
|
||||
.is_de3 = true,
|
||||
+ .has_formatter = 1,
|
||||
.mod_rate = 600000000,
|
||||
.scaler_mask = 0xf,
|
||||
.scanline_yuv = 4096,
|
||||
diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.h b/drivers/gpu/drm/sun4i/sun8i_mixer.h
|
||||
index d7898c9c9cc0..8417b8fef2e1 100644
|
||||
--- a/drivers/gpu/drm/sun4i/sun8i_mixer.h
|
||||
+++ b/drivers/gpu/drm/sun4i/sun8i_mixer.h
|
||||
@@ -163,6 +163,7 @@ enum {
|
||||
* @mod_rate: module clock rate that needs to be set in order to have
|
||||
* a functional block.
|
||||
* @is_de3: true, if this is next gen display engine 3.0, false otherwise.
|
||||
+ * @has_formatter: true, if mixer has formatter core, for 10-bit and YUV handling
|
||||
* @scaline_yuv: size of a scanline for VI scaler for YUV formats.
|
||||
*/
|
||||
struct sun8i_mixer_cfg {
|
||||
@@ -172,6 +173,7 @@ struct sun8i_mixer_cfg {
|
||||
int ccsc;
|
||||
unsigned long mod_rate;
|
||||
unsigned int is_de3 : 1;
|
||||
+ unsigned int has_formatter : 1;
|
||||
unsigned int scanline_yuv;
|
||||
};
|
||||
|
||||
--
|
||||
2.35.3
|
||||
|
||||
|
|
@ -0,0 +1,54 @@
|
|||
From 2d7c88fc2af6d07ccadc99b157753638b4940293 Mon Sep 17 00:00:00 2001
|
||||
From: Jernej Skrabec <jernej.skrabec@gmail.com>
|
||||
Date: Sun, 29 Sep 2024 22:04:41 +1300
|
||||
Subject: drm: sun4i: de3: pass engine reference to ccsc setup function
|
||||
|
||||
Configuration of the DE3 colorspace and dynamic range correction module
|
||||
requires knowledge of the current video format and encoding.
|
||||
|
||||
Pass the display engine by reference to the csc setup function, rather
|
||||
than the register map alone, to allow access to this information.
|
||||
|
||||
Signed-off-by: Jernej Skrabec <jernej.skrabec@gmail.com>
|
||||
Signed-off-by: Ryan Walklin <ryan@testtoast.com>
|
||||
---
|
||||
drivers/gpu/drm/sun4i/sun8i_csc.c | 6 ++++--
|
||||
1 file changed, 4 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/drivers/gpu/drm/sun4i/sun8i_csc.c b/drivers/gpu/drm/sun4i/sun8i_csc.c
|
||||
index 68d955c63b05..8a336ccb27d3 100644
|
||||
--- a/drivers/gpu/drm/sun4i/sun8i_csc.c
|
||||
+++ b/drivers/gpu/drm/sun4i/sun8i_csc.c
|
||||
@@ -148,17 +148,19 @@ static void sun8i_csc_setup(struct regmap *map, u32 base,
|
||||
regmap_write(map, SUN8I_CSC_CTRL(base), val);
|
||||
}
|
||||
|
||||
-static void sun8i_de3_ccsc_setup(struct regmap *map, int layer,
|
||||
+static void sun8i_de3_ccsc_setup(struct sunxi_engine *engine, int layer,
|
||||
enum format_type fmt_type,
|
||||
enum drm_color_encoding encoding,
|
||||
enum drm_color_range range)
|
||||
{
|
||||
u32 addr, val, mask;
|
||||
+ struct regmap *map;
|
||||
const u32 *table;
|
||||
int i;
|
||||
|
||||
mask = SUN50I_MIXER_BLEND_CSC_CTL_EN(layer);
|
||||
table = yuv2rgb_de3[range][encoding];
|
||||
+ map = engine->regs;
|
||||
|
||||
switch (fmt_type) {
|
||||
case FORMAT_TYPE_RGB:
|
||||
@@ -204,7 +206,7 @@ void sun8i_csc_set_ccsc(struct sun8i_mixer *mixer, int layer,
|
||||
u32 base;
|
||||
|
||||
if (mixer->cfg->is_de3) {
|
||||
- sun8i_de3_ccsc_setup(mixer->engine.regs, layer,
|
||||
+ sun8i_de3_ccsc_setup(&mixer->engine, layer,
|
||||
fmt_type, encoding, range);
|
||||
return;
|
||||
}
|
||||
--
|
||||
2.35.3
|
||||
|
||||
|
|
@ -0,0 +1,156 @@
|
|||
From 0d003a88bcacf5f405f3922b0c56b7eecdb68386 Mon Sep 17 00:00:00 2001
|
||||
From: Jernej Skrabec <jernej.skrabec@gmail.com>
|
||||
Date: Sun, 29 Sep 2024 22:04:58 +1300
|
||||
Subject: drm: sun4i: de33: csc: add Display Engine 3.3 (DE33) support
|
||||
|
||||
Like earlier DE versions, the DE33 has a CSC (Color Space Correction)
|
||||
module. which provides color space conversion between BT2020/BT709, and
|
||||
dynamic range conversion between SDR/ST2084/HLG.
|
||||
|
||||
Add support for the DE33.
|
||||
|
||||
Signed-off-by: Jernej Skrabec <jernej.skrabec@gmail.com>
|
||||
Signed-off-by: Ryan Walklin <ryan@testtoast.com>
|
||||
---
|
||||
drivers/gpu/drm/sun4i/sun8i_csc.c | 96 +++++++++++++++++++++++++++++++
|
||||
drivers/gpu/drm/sun4i/sun8i_csc.h | 3 +
|
||||
2 files changed, 99 insertions(+)
|
||||
|
||||
diff --git a/drivers/gpu/drm/sun4i/sun8i_csc.c b/drivers/gpu/drm/sun4i/sun8i_csc.c
|
||||
index 2d5a2cf7cba2..45bd1ca06400 100644
|
||||
--- a/drivers/gpu/drm/sun4i/sun8i_csc.c
|
||||
+++ b/drivers/gpu/drm/sun4i/sun8i_csc.c
|
||||
@@ -238,6 +238,14 @@ static const u32 yuv2yuv_de3[2][3][3][12] = {
|
||||
},
|
||||
};
|
||||
|
||||
+static u32 sun8i_csc_base(struct sun8i_mixer *mixer, int layer)
|
||||
+{
|
||||
+ if (mixer->cfg->de_type == sun8i_mixer_de33)
|
||||
+ return sun8i_channel_base(mixer, layer) - 0x800;
|
||||
+ else
|
||||
+ return ccsc_base[mixer->cfg->ccsc][layer];
|
||||
+}
|
||||
+
|
||||
static void sun8i_csc_setup(struct regmap *map, u32 base,
|
||||
enum format_type fmt_type,
|
||||
enum drm_color_encoding encoding,
|
||||
@@ -358,6 +366,90 @@ static void sun8i_de3_ccsc_setup(struct sunxi_engine *engine, int layer,
|
||||
mask, val);
|
||||
}
|
||||
|
||||
+/* extract constant from high word and invert sign if necessary */
|
||||
+static u32 sun8i_de33_ccsc_get_constant(u32 value)
|
||||
+{
|
||||
+ value >>= 16;
|
||||
+
|
||||
+ if (value & BIT(15))
|
||||
+ return 0x400 - (value & 0x3ff);
|
||||
+
|
||||
+ return value;
|
||||
+}
|
||||
+
|
||||
+static void sun8i_de33_convert_table(const u32 *src, u32 *dst)
|
||||
+{
|
||||
+ dst[0] = sun8i_de33_ccsc_get_constant(src[3]);
|
||||
+ dst[1] = sun8i_de33_ccsc_get_constant(src[7]);
|
||||
+ dst[2] = sun8i_de33_ccsc_get_constant(src[11]);
|
||||
+ memcpy(&dst[3], src, sizeof(u32) * 12);
|
||||
+ dst[6] &= 0xffff;
|
||||
+ dst[10] &= 0xffff;
|
||||
+ dst[14] &= 0xffff;
|
||||
+}
|
||||
+
|
||||
+static void sun8i_de33_ccsc_setup(struct sun8i_mixer *mixer, int layer,
|
||||
+ enum format_type fmt_type,
|
||||
+ enum drm_color_encoding encoding,
|
||||
+ enum drm_color_range range)
|
||||
+{
|
||||
+ u32 addr, val = 0, base, csc[15];
|
||||
+ struct sunxi_engine *engine;
|
||||
+ struct regmap *map;
|
||||
+ const u32 *table;
|
||||
+ int i;
|
||||
+
|
||||
+ table = yuv2rgb_de3[range][encoding];
|
||||
+ base = sun8i_csc_base(mixer, layer);
|
||||
+ engine = &mixer->engine;
|
||||
+ map = engine->regs;
|
||||
+
|
||||
+ switch (fmt_type) {
|
||||
+ case FORMAT_TYPE_RGB:
|
||||
+ if (engine->format == MEDIA_BUS_FMT_RGB888_1X24)
|
||||
+ break;
|
||||
+ val = SUN8I_CSC_CTRL_EN;
|
||||
+ sun8i_de33_convert_table(rgb2yuv_de3[engine->encoding], csc);
|
||||
+ regmap_bulk_write(map, SUN50I_CSC_COEFF(base, 0), csc, 15);
|
||||
+ break;
|
||||
+ case FORMAT_TYPE_YUV:
|
||||
+ table = sun8i_csc_get_de3_yuv_table(encoding, range,
|
||||
+ engine->format,
|
||||
+ engine->encoding);
|
||||
+ if (!table)
|
||||
+ break;
|
||||
+ val = SUN8I_CSC_CTRL_EN;
|
||||
+ sun8i_de33_convert_table(table, csc);
|
||||
+ regmap_bulk_write(map, SUN50I_CSC_COEFF(base, 0), csc, 15);
|
||||
+ break;
|
||||
+ case FORMAT_TYPE_YVU:
|
||||
+ table = sun8i_csc_get_de3_yuv_table(encoding, range,
|
||||
+ engine->format,
|
||||
+ engine->encoding);
|
||||
+ if (!table)
|
||||
+ table = yuv2yuv_de3[range][encoding][encoding];
|
||||
+ val = SUN8I_CSC_CTRL_EN;
|
||||
+ sun8i_de33_convert_table(table, csc);
|
||||
+ for (i = 0; i < 15; i++) {
|
||||
+ addr = SUN50I_CSC_COEFF(base, i);
|
||||
+ if (i > 3) {
|
||||
+ if (((i - 3) & 3) == 1)
|
||||
+ addr = SUN50I_CSC_COEFF(base, i + 1);
|
||||
+ else if (((i - 3) & 3) == 2)
|
||||
+ addr = SUN50I_CSC_COEFF(base, i - 1);
|
||||
+ }
|
||||
+ regmap_write(map, addr, csc[i]);
|
||||
+ }
|
||||
+ break;
|
||||
+ default:
|
||||
+ val = 0;
|
||||
+ DRM_WARN("Wrong CSC mode specified.\n");
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ regmap_write(map, SUN8I_CSC_CTRL(base), val);
|
||||
+}
|
||||
+
|
||||
void sun8i_csc_set_ccsc(struct sun8i_mixer *mixer, int layer,
|
||||
enum format_type fmt_type,
|
||||
enum drm_color_encoding encoding,
|
||||
@@ -369,6 +461,10 @@ void sun8i_csc_set_ccsc(struct sun8i_mixer *mixer, int layer,
|
||||
sun8i_de3_ccsc_setup(&mixer->engine, layer,
|
||||
fmt_type, encoding, range);
|
||||
return;
|
||||
+ } else if (mixer->cfg->de_type == sun8i_mixer_de33) {
|
||||
+ sun8i_de33_ccsc_setup(mixer, layer, fmt_type,
|
||||
+ encoding, range);
|
||||
+ return;
|
||||
}
|
||||
|
||||
if (layer < mixer->cfg->vi_num) {
|
||||
diff --git a/drivers/gpu/drm/sun4i/sun8i_csc.h b/drivers/gpu/drm/sun4i/sun8i_csc.h
|
||||
index b7546e06e315..2b762cb79f02 100644
|
||||
--- a/drivers/gpu/drm/sun4i/sun8i_csc.h
|
||||
+++ b/drivers/gpu/drm/sun4i/sun8i_csc.h
|
||||
@@ -20,6 +20,9 @@ struct sun8i_mixer;
|
||||
#define SUN8I_CSC_CTRL(base) ((base) + 0x0)
|
||||
#define SUN8I_CSC_COEFF(base, i) ((base) + 0x10 + 4 * (i))
|
||||
|
||||
+#define SUN50I_CSC_COEFF(base, i) ((base) + 0x04 + 4 * (i))
|
||||
+#define SUN50I_CSC_ALPHA(base) ((base) + 0x40)
|
||||
+
|
||||
#define SUN8I_CSC_CTRL_EN BIT(0)
|
||||
|
||||
enum format_type {
|
||||
--
|
||||
2.35.3
|
||||
|
||||
|
|
@ -0,0 +1,75 @@
|
|||
From 792b816c952bcf5dbf7c3ac7d90937bc71f0a7cd Mon Sep 17 00:00:00 2001
|
||||
From: Jernej Skrabec <jernej.skrabec@gmail.com>
|
||||
Date: Sun, 29 Sep 2024 22:04:57 +1300
|
||||
Subject: drm: sun4i: de33: fmt: add Display Engine 3.3 (DE33) support
|
||||
|
||||
Like the DE3, the DE33 has a FMT (formatter) module, which
|
||||
provides YUV444 to YUV422/YUV420 conversion, format re-mapping and color
|
||||
depth conversion, although the DE33 module appears significantly more
|
||||
capable, including up to 4K video support.
|
||||
|
||||
Add support for the DE33.
|
||||
|
||||
Signed-off-by: Jernej Skrabec <jernej.skrabec@gmail.com>
|
||||
Signed-off-by: Ryan Walklin <ryan@testtoast.com>
|
||||
---
|
||||
drivers/gpu/drm/sun4i/sun50i_fmt.c | 21 +++++++++++++++++++--
|
||||
drivers/gpu/drm/sun4i/sun50i_fmt.h | 1 +
|
||||
2 files changed, 20 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/drivers/gpu/drm/sun4i/sun50i_fmt.c b/drivers/gpu/drm/sun4i/sun50i_fmt.c
|
||||
index 050a8716ae86..39682d4e6d20 100644
|
||||
--- a/drivers/gpu/drm/sun4i/sun50i_fmt.c
|
||||
+++ b/drivers/gpu/drm/sun4i/sun50i_fmt.c
|
||||
@@ -51,6 +51,19 @@ static void sun50i_fmt_de3_limits(u32 *limits, u32 colorspace, bool bit10)
|
||||
}
|
||||
}
|
||||
|
||||
+static void sun50i_fmt_de33_limits(u32 *limits, u32 colorspace)
|
||||
+{
|
||||
+ if (colorspace == SUN50I_FMT_CS_YUV444RGB) {
|
||||
+ limits[0] = SUN50I_FMT_LIMIT(0, 4095);
|
||||
+ limits[1] = SUN50I_FMT_LIMIT(0, 4095);
|
||||
+ limits[2] = SUN50I_FMT_LIMIT(0, 4095);
|
||||
+ } else {
|
||||
+ limits[0] = SUN50I_FMT_LIMIT(256, 3840);
|
||||
+ limits[1] = SUN50I_FMT_LIMIT(256, 3840);
|
||||
+ limits[2] = SUN50I_FMT_LIMIT(256, 3840);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
void sun50i_fmt_setup(struct sun8i_mixer *mixer, u16 width,
|
||||
u16 height, u32 format)
|
||||
{
|
||||
@@ -60,10 +73,14 @@ void sun50i_fmt_setup(struct sun8i_mixer *mixer, u16 width,
|
||||
|
||||
colorspace = sun50i_fmt_get_colorspace(format);
|
||||
bit10 = sun50i_fmt_is_10bit(format);
|
||||
- base = SUN50I_FMT_DE3;
|
||||
+ base = mixer->cfg->de_type == sun8i_mixer_de3 ?
|
||||
+ SUN50I_FMT_DE3 : SUN50I_FMT_DE33;
|
||||
regs = sun8i_blender_regmap(mixer);
|
||||
|
||||
- sun50i_fmt_de3_limits(limit, colorspace, bit10);
|
||||
+ if (mixer->cfg->de_type == sun8i_mixer_de3)
|
||||
+ sun50i_fmt_de3_limits(limit, colorspace, bit10);
|
||||
+ else
|
||||
+ sun50i_fmt_de33_limits(limit, colorspace);
|
||||
|
||||
regmap_write(regs, SUN50I_FMT_CTRL(base), 0);
|
||||
|
||||
diff --git a/drivers/gpu/drm/sun4i/sun50i_fmt.h b/drivers/gpu/drm/sun4i/sun50i_fmt.h
|
||||
index 4127f7206aad..3e60d5c788b3 100644
|
||||
--- a/drivers/gpu/drm/sun4i/sun50i_fmt.h
|
||||
+++ b/drivers/gpu/drm/sun4i/sun50i_fmt.h
|
||||
@@ -9,6 +9,7 @@
|
||||
#include "sun8i_mixer.h"
|
||||
|
||||
#define SUN50I_FMT_DE3 0xa8000
|
||||
+#define SUN50I_FMT_DE33 0x5000
|
||||
|
||||
#define SUN50I_FMT_CTRL(base) ((base) + 0x00)
|
||||
#define SUN50I_FMT_SIZE(base) ((base) + 0x04)
|
||||
--
|
||||
2.35.3
|
||||
|
||||
|
|
@ -0,0 +1,302 @@
|
|||
From 66c111f3315d2c34c2f9bfb39de61bf3ec46a5f6 Mon Sep 17 00:00:00 2001
|
||||
From: Jernej Skrabec <jernej.skrabec@gmail.com>
|
||||
Date: Sun, 29 Sep 2024 22:04:55 +1300
|
||||
Subject: drm: sun4i: de33: mixer: add Display Engine 3.3 (DE33) support
|
||||
|
||||
The DE33 is a newer version of the Allwinner Display Engine IP block,
|
||||
found in the H616, H618, H700 and T507 SoCs. DE2 and DE3 are already
|
||||
supported by the mainline driver.
|
||||
|
||||
Notable features (from the H616 datasheet and implemented):
|
||||
- 4096 x 2048 (4K) output support
|
||||
- AFBC ARM Frame Buffer Compression support
|
||||
- YUV420 input support
|
||||
|
||||
The DE2 and DE3 engines have a blender register range within the
|
||||
mixer engine register map, whereas the DE33 separates this out into
|
||||
a separate display group, and adds a top register map.
|
||||
|
||||
Extend the mixer to support the DE33.
|
||||
|
||||
Signed-off-by: Jernej Skrabec <jernej.skrabec@gmail.com>
|
||||
Signed-off-by: Ryan Walklin <ryan@testtoast.com>
|
||||
---
|
||||
drivers/gpu/drm/sun4i/sun8i_mixer.c | 109 ++++++++++++++++++++++++----
|
||||
drivers/gpu/drm/sun4i/sun8i_mixer.h | 16 +++-
|
||||
2 files changed, 108 insertions(+), 17 deletions(-)
|
||||
|
||||
diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.c b/drivers/gpu/drm/sun4i/sun8i_mixer.c
|
||||
index 600084286b39..204fc8055b32 100644
|
||||
--- a/drivers/gpu/drm/sun4i/sun8i_mixer.c
|
||||
+++ b/drivers/gpu/drm/sun4i/sun8i_mixer.c
|
||||
@@ -321,8 +321,12 @@ static void sun8i_mixer_commit(struct sunxi_engine *engine,
|
||||
regmap_write(bld_regs, SUN8I_MIXER_BLEND_PIPE_CTL(bld_base),
|
||||
pipe_en | SUN8I_MIXER_BLEND_PIPE_CTL_FC_EN(0));
|
||||
|
||||
- regmap_write(engine->regs, SUN8I_MIXER_GLOBAL_DBUFF,
|
||||
- SUN8I_MIXER_GLOBAL_DBUFF_ENABLE);
|
||||
+ if (mixer->cfg->de_type == sun8i_mixer_de33)
|
||||
+ regmap_write(mixer->top_regs, SUN50I_MIXER_GLOBAL_DBUFF,
|
||||
+ SUN8I_MIXER_GLOBAL_DBUFF_ENABLE);
|
||||
+ else
|
||||
+ regmap_write(engine->regs, SUN8I_MIXER_GLOBAL_DBUFF,
|
||||
+ SUN8I_MIXER_GLOBAL_DBUFF_ENABLE);
|
||||
}
|
||||
|
||||
static struct drm_plane **sun8i_layers_init(struct drm_device *drm,
|
||||
@@ -371,25 +375,33 @@ static void sun8i_mixer_mode_set(struct sunxi_engine *engine,
|
||||
const struct drm_display_mode *mode)
|
||||
{
|
||||
struct sun8i_mixer *mixer = engine_to_sun8i_mixer(engine);
|
||||
+ struct regmap *bld_regs, *disp_regs;
|
||||
u32 bld_base, size, val;
|
||||
bool interlaced;
|
||||
|
||||
bld_base = sun8i_blender_base(mixer);
|
||||
+ bld_regs = sun8i_blender_regmap(mixer);
|
||||
interlaced = !!(mode->flags & DRM_MODE_FLAG_INTERLACE);
|
||||
size = SUN8I_MIXER_SIZE(mode->hdisplay, mode->vdisplay);
|
||||
|
||||
DRM_DEBUG_DRIVER("Updating global size W: %u H: %u\n",
|
||||
mode->hdisplay, mode->vdisplay);
|
||||
|
||||
- regmap_write(engine->regs, SUN8I_MIXER_GLOBAL_SIZE, size);
|
||||
- regmap_write(engine->regs, SUN8I_MIXER_BLEND_OUTSIZE(bld_base), size);
|
||||
+ if (mixer->cfg->de_type == sun8i_mixer_de33) {
|
||||
+ disp_regs = mixer->disp_regs;
|
||||
+ regmap_write(mixer->top_regs, SUN50I_MIXER_GLOBAL_SIZE, size);
|
||||
+ } else {
|
||||
+ disp_regs = mixer->engine.regs;
|
||||
+ regmap_write(mixer->engine.regs, SUN8I_MIXER_GLOBAL_SIZE, size);
|
||||
+ }
|
||||
+ regmap_write(bld_regs, SUN8I_MIXER_BLEND_OUTSIZE(bld_base), size);
|
||||
|
||||
if (interlaced)
|
||||
val = SUN8I_MIXER_BLEND_OUTCTL_INTERLACED;
|
||||
else
|
||||
val = 0;
|
||||
|
||||
- regmap_update_bits(engine->regs, SUN8I_MIXER_BLEND_OUTCTL(bld_base),
|
||||
+ regmap_update_bits(bld_regs, SUN8I_MIXER_BLEND_OUTCTL(bld_base),
|
||||
SUN8I_MIXER_BLEND_OUTCTL_INTERLACED, val);
|
||||
|
||||
DRM_DEBUG_DRIVER("Switching display mixer interlaced mode %s\n",
|
||||
@@ -400,10 +412,8 @@ static void sun8i_mixer_mode_set(struct sunxi_engine *engine,
|
||||
else
|
||||
val = 0xff108080;
|
||||
|
||||
- regmap_write(mixer->engine.regs,
|
||||
- SUN8I_MIXER_BLEND_BKCOLOR(bld_base), val);
|
||||
- regmap_write(mixer->engine.regs,
|
||||
- SUN8I_MIXER_BLEND_ATTR_FCOLOR(bld_base, 0), val);
|
||||
+ regmap_write(disp_regs, SUN8I_MIXER_BLEND_BKCOLOR(bld_base), val);
|
||||
+ regmap_write(disp_regs, SUN8I_MIXER_BLEND_ATTR_FCOLOR(bld_base, 0), val);
|
||||
|
||||
if (mixer->cfg->has_formatter)
|
||||
sun50i_fmt_setup(mixer, mode->hdisplay,
|
||||
@@ -443,12 +453,29 @@ static const struct sunxi_engine_ops sun8i_engine_ops = {
|
||||
};
|
||||
|
||||
static const struct regmap_config sun8i_mixer_regmap_config = {
|
||||
+ .name = "layers",
|
||||
.reg_bits = 32,
|
||||
.val_bits = 32,
|
||||
.reg_stride = 4,
|
||||
.max_register = 0xffffc, /* guessed */
|
||||
};
|
||||
|
||||
+static const struct regmap_config sun8i_top_regmap_config = {
|
||||
+ .name = "top",
|
||||
+ .reg_bits = 32,
|
||||
+ .val_bits = 32,
|
||||
+ .reg_stride = 4,
|
||||
+ .max_register = 0x3c,
|
||||
+};
|
||||
+
|
||||
+static const struct regmap_config sun8i_disp_regmap_config = {
|
||||
+ .name = "display",
|
||||
+ .reg_bits = 32,
|
||||
+ .val_bits = 32,
|
||||
+ .reg_stride = 4,
|
||||
+ .max_register = 0x20000,
|
||||
+};
|
||||
+
|
||||
static int sun8i_mixer_of_get_id(struct device_node *node)
|
||||
{
|
||||
struct device_node *ep, *remote;
|
||||
@@ -471,33 +498,45 @@ static int sun8i_mixer_of_get_id(struct device_node *node)
|
||||
|
||||
static void sun8i_mixer_init(struct sun8i_mixer *mixer)
|
||||
{
|
||||
+ struct regmap *top_regs, *disp_regs;
|
||||
unsigned int base = sun8i_blender_base(mixer);
|
||||
int plane_cnt, i;
|
||||
|
||||
+ if (mixer->cfg->de_type == sun8i_mixer_de33) {
|
||||
+ top_regs = mixer->top_regs;
|
||||
+ disp_regs = mixer->disp_regs;
|
||||
+ } else {
|
||||
+ top_regs = mixer->engine.regs;
|
||||
+ disp_regs = mixer->engine.regs;
|
||||
+ }
|
||||
+
|
||||
/* Enable the mixer */
|
||||
- regmap_write(mixer->engine.regs, SUN8I_MIXER_GLOBAL_CTL,
|
||||
+ regmap_write(top_regs, SUN8I_MIXER_GLOBAL_CTL,
|
||||
SUN8I_MIXER_GLOBAL_CTL_RT_EN);
|
||||
|
||||
+ if (mixer->cfg->de_type == sun8i_mixer_de33)
|
||||
+ regmap_write(top_regs, SUN50I_MIXER_GLOBAL_CLK, 1);
|
||||
+
|
||||
/* Set background color to black */
|
||||
- regmap_write(mixer->engine.regs, SUN8I_MIXER_BLEND_BKCOLOR(base),
|
||||
+ regmap_write(disp_regs, SUN8I_MIXER_BLEND_BKCOLOR(base),
|
||||
SUN8I_MIXER_BLEND_COLOR_BLACK);
|
||||
|
||||
/*
|
||||
* Set fill color of bottom plane to black. Generally not needed
|
||||
* except when VI plane is at bottom (zpos = 0) and enabled.
|
||||
*/
|
||||
- regmap_write(mixer->engine.regs, SUN8I_MIXER_BLEND_PIPE_CTL(base),
|
||||
+ regmap_write(disp_regs, SUN8I_MIXER_BLEND_PIPE_CTL(base),
|
||||
SUN8I_MIXER_BLEND_PIPE_CTL_FC_EN(0));
|
||||
- regmap_write(mixer->engine.regs, SUN8I_MIXER_BLEND_ATTR_FCOLOR(base, 0),
|
||||
+ regmap_write(disp_regs, SUN8I_MIXER_BLEND_ATTR_FCOLOR(base, 0),
|
||||
SUN8I_MIXER_BLEND_COLOR_BLACK);
|
||||
|
||||
plane_cnt = mixer->cfg->vi_num + mixer->cfg->ui_num;
|
||||
for (i = 0; i < plane_cnt; i++)
|
||||
- regmap_write(mixer->engine.regs,
|
||||
+ regmap_write(disp_regs,
|
||||
SUN8I_MIXER_BLEND_MODE(base, i),
|
||||
SUN8I_MIXER_BLEND_MODE_DEF);
|
||||
|
||||
- regmap_update_bits(mixer->engine.regs, SUN8I_MIXER_BLEND_PIPE_CTL(base),
|
||||
+ regmap_update_bits(disp_regs, SUN8I_MIXER_BLEND_PIPE_CTL(base),
|
||||
SUN8I_MIXER_BLEND_PIPE_CTL_EN_MSK, 0);
|
||||
}
|
||||
|
||||
@@ -573,6 +612,30 @@ static int sun8i_mixer_bind(struct device *dev, struct device *master,
|
||||
return PTR_ERR(mixer->engine.regs);
|
||||
}
|
||||
|
||||
+ if (mixer->cfg->de_type == sun8i_mixer_de33) {
|
||||
+ regs = devm_platform_ioremap_resource(pdev, 1);
|
||||
+ if (IS_ERR(regs))
|
||||
+ return PTR_ERR(regs);
|
||||
+
|
||||
+ mixer->top_regs = devm_regmap_init_mmio(dev, regs,
|
||||
+ &sun8i_top_regmap_config);
|
||||
+ if (IS_ERR(mixer->top_regs)) {
|
||||
+ dev_err(dev, "Couldn't create the top regmap\n");
|
||||
+ return PTR_ERR(mixer->top_regs);
|
||||
+ }
|
||||
+
|
||||
+ regs = devm_platform_ioremap_resource(pdev, 2);
|
||||
+ if (IS_ERR(regs))
|
||||
+ return PTR_ERR(regs);
|
||||
+
|
||||
+ mixer->disp_regs = devm_regmap_init_mmio(dev, regs,
|
||||
+ &sun8i_disp_regmap_config);
|
||||
+ if (IS_ERR(mixer->disp_regs)) {
|
||||
+ dev_err(dev, "Couldn't create the disp regmap\n");
|
||||
+ return PTR_ERR(mixer->disp_regs);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
mixer->reset = devm_reset_control_get(dev, NULL);
|
||||
if (IS_ERR(mixer->reset)) {
|
||||
dev_err(dev, "Couldn't get our reset line\n");
|
||||
@@ -787,6 +850,18 @@ static const struct sun8i_mixer_cfg sun50i_h6_mixer0_cfg = {
|
||||
.vi_num = 1,
|
||||
};
|
||||
|
||||
+static const struct sun8i_mixer_cfg sun50i_h616_mixer0_cfg = {
|
||||
+ .ccsc = CCSC_MIXER0_LAYOUT,
|
||||
+ .de_type = sun8i_mixer_de33,
|
||||
+ .has_formatter = 1,
|
||||
+ .mod_rate = 600000000,
|
||||
+ .scaler_mask = 0xf,
|
||||
+ .scanline_yuv = 4096,
|
||||
+ .ui_num = 3,
|
||||
+ .vi_num = 1,
|
||||
+ .map = {0, 6, 7, 8},
|
||||
+};
|
||||
+
|
||||
static const struct of_device_id sun8i_mixer_of_table[] = {
|
||||
{
|
||||
.compatible = "allwinner,sun8i-a83t-de2-mixer-0",
|
||||
@@ -832,6 +907,10 @@ static const struct of_device_id sun8i_mixer_of_table[] = {
|
||||
.compatible = "allwinner,sun50i-h6-de3-mixer-0",
|
||||
.data = &sun50i_h6_mixer0_cfg,
|
||||
},
|
||||
+ {
|
||||
+ .compatible = "allwinner,sun50i-h616-de33-mixer-0",
|
||||
+ .data = &sun50i_h616_mixer0_cfg,
|
||||
+ },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, sun8i_mixer_of_table);
|
||||
diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.h b/drivers/gpu/drm/sun4i/sun8i_mixer.h
|
||||
index 75facc7d1fa6..26b001164647 100644
|
||||
--- a/drivers/gpu/drm/sun4i/sun8i_mixer.h
|
||||
+++ b/drivers/gpu/drm/sun4i/sun8i_mixer.h
|
||||
@@ -21,6 +21,10 @@
|
||||
#define SUN8I_MIXER_GLOBAL_DBUFF 0x8
|
||||
#define SUN8I_MIXER_GLOBAL_SIZE 0xc
|
||||
|
||||
+#define SUN50I_MIXER_GLOBAL_SIZE 0x8
|
||||
+#define SUN50I_MIXER_GLOBAL_CLK 0xc
|
||||
+#define SUN50I_MIXER_GLOBAL_DBUFF 0x10
|
||||
+
|
||||
#define SUN8I_MIXER_GLOBAL_CTL_RT_EN BIT(0)
|
||||
|
||||
#define SUN8I_MIXER_GLOBAL_DBUFF_ENABLE BIT(0)
|
||||
@@ -154,6 +158,7 @@ enum {
|
||||
enum sun8i_mixer_type {
|
||||
sun8i_mixer_de2,
|
||||
sun8i_mixer_de3,
|
||||
+ sun8i_mixer_de33,
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -180,6 +185,7 @@ struct sun8i_mixer_cfg {
|
||||
unsigned int de_type;
|
||||
unsigned int has_formatter : 1;
|
||||
unsigned int scanline_yuv;
|
||||
+ unsigned int map[6];
|
||||
};
|
||||
|
||||
struct sun8i_mixer {
|
||||
@@ -191,6 +197,9 @@ struct sun8i_mixer {
|
||||
|
||||
struct clk *bus_clk;
|
||||
struct clk *mod_clk;
|
||||
+
|
||||
+ struct regmap *top_regs;
|
||||
+ struct regmap *disp_regs;
|
||||
};
|
||||
|
||||
enum {
|
||||
@@ -227,13 +236,16 @@ sun8i_blender_base(struct sun8i_mixer *mixer)
|
||||
static inline struct regmap *
|
||||
sun8i_blender_regmap(struct sun8i_mixer *mixer)
|
||||
{
|
||||
- return mixer->engine.regs;
|
||||
+ return mixer->cfg->de_type == sun8i_mixer_de33 ?
|
||||
+ mixer->disp_regs : mixer->engine.regs;
|
||||
}
|
||||
|
||||
static inline u32
|
||||
sun8i_channel_base(struct sun8i_mixer *mixer, int channel)
|
||||
{
|
||||
- if (mixer->cfg->de_type == sun8i_mixer_de3)
|
||||
+ if (mixer->cfg->de_type == sun8i_mixer_de33)
|
||||
+ return mixer->cfg->map[channel] * 0x20000 + DE2_CH_SIZE;
|
||||
+ else if (mixer->cfg->de_type == sun8i_mixer_de3)
|
||||
return DE3_CH_BASE + channel * DE3_CH_SIZE;
|
||||
else
|
||||
return DE2_CH_BASE + channel * DE2_CH_SIZE;
|
||||
--
|
||||
2.35.3
|
||||
|
||||
|
|
@ -0,0 +1,77 @@
|
|||
From 412294545ec91452cc3eccff746a4243879b4cde Mon Sep 17 00:00:00 2001
|
||||
From: Jernej Skrabec <jernej.skrabec@gmail.com>
|
||||
Date: Sun, 29 Sep 2024 22:04:56 +1300
|
||||
Subject: drm: sun4i: de33: vi_scaler: add Display Engine 3.3 (DE33) support
|
||||
|
||||
The vi_scaler appears to be used in preference to the ui_scaler module
|
||||
for hardware video scaling in the DE33.
|
||||
|
||||
Enable support for this scaler.
|
||||
|
||||
Signed-off-by: Jernej Skrabec <jernej.skrabec@gmail.com>
|
||||
Signed-off-by: Ryan Walklin <ryan@testtoast.com>
|
||||
---
|
||||
drivers/gpu/drm/sun4i/sun8i_ui_layer.c | 19 +++++++++++++++----
|
||||
drivers/gpu/drm/sun4i/sun8i_vi_scaler.c | 7 ++++++-
|
||||
2 files changed, 21 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/drivers/gpu/drm/sun4i/sun8i_ui_layer.c b/drivers/gpu/drm/sun4i/sun8i_ui_layer.c
|
||||
index 7f1231cf0f01..180be9d67d9c 100644
|
||||
--- a/drivers/gpu/drm/sun4i/sun8i_ui_layer.c
|
||||
+++ b/drivers/gpu/drm/sun4i/sun8i_ui_layer.c
|
||||
@@ -95,12 +95,23 @@ static int sun8i_ui_layer_update_coord(struct sun8i_mixer *mixer, int channel,
|
||||
hscale = state->src_w / state->crtc_w;
|
||||
vscale = state->src_h / state->crtc_h;
|
||||
|
||||
- sun8i_ui_scaler_setup(mixer, channel, src_w, src_h, dst_w,
|
||||
- dst_h, hscale, vscale, hphase, vphase);
|
||||
- sun8i_ui_scaler_enable(mixer, channel, true);
|
||||
+ if (mixer->cfg->de_type == sun8i_mixer_de33) {
|
||||
+ sun8i_vi_scaler_setup(mixer, channel, src_w, src_h,
|
||||
+ dst_w, dst_h, hscale, vscale,
|
||||
+ hphase, vphase,
|
||||
+ state->fb->format);
|
||||
+ } else {
|
||||
+ sun8i_ui_scaler_setup(mixer, channel, src_w, src_h,
|
||||
+ dst_w, dst_h, hscale, vscale,
|
||||
+ hphase, vphase);
|
||||
+ sun8i_ui_scaler_enable(mixer, channel, true);
|
||||
+ }
|
||||
} else {
|
||||
DRM_DEBUG_DRIVER("HW scaling is not needed\n");
|
||||
- sun8i_ui_scaler_enable(mixer, channel, false);
|
||||
+ if (mixer->cfg->de_type == sun8i_mixer_de33)
|
||||
+ sun8i_vi_scaler_disable(mixer, channel);
|
||||
+ else
|
||||
+ sun8i_ui_scaler_enable(mixer, channel, false);
|
||||
}
|
||||
|
||||
/* Set base coordinates */
|
||||
diff --git a/drivers/gpu/drm/sun4i/sun8i_vi_scaler.c b/drivers/gpu/drm/sun4i/sun8i_vi_scaler.c
|
||||
index e7242301b312..9c7f6e7d71d5 100644
|
||||
--- a/drivers/gpu/drm/sun4i/sun8i_vi_scaler.c
|
||||
+++ b/drivers/gpu/drm/sun4i/sun8i_vi_scaler.c
|
||||
@@ -835,7 +835,9 @@ static const u32 bicubic4coefftab32[480] = {
|
||||
|
||||
static u32 sun8i_vi_scaler_base(struct sun8i_mixer *mixer, int channel)
|
||||
{
|
||||
- if (mixer->cfg->de_type == sun8i_mixer_de3)
|
||||
+ if (mixer->cfg->de_type == sun8i_mixer_de33)
|
||||
+ return sun8i_channel_base(mixer, channel) + 0x3000;
|
||||
+ else if (mixer->cfg->de_type == sun8i_mixer_de3)
|
||||
return DE3_VI_SCALER_UNIT_BASE +
|
||||
DE3_VI_SCALER_UNIT_SIZE * channel;
|
||||
else
|
||||
@@ -845,6 +847,9 @@ static u32 sun8i_vi_scaler_base(struct sun8i_mixer *mixer, int channel)
|
||||
|
||||
static bool sun8i_vi_scaler_is_vi_plane(struct sun8i_mixer *mixer, int channel)
|
||||
{
|
||||
+ if (mixer->cfg->de_type == sun8i_mixer_de33)
|
||||
+ return mixer->cfg->map[channel] < mixer->cfg->vi_num;
|
||||
+
|
||||
return true;
|
||||
}
|
||||
|
||||
--
|
||||
2.35.3
|
||||
|
||||
|
|
@ -0,0 +1,140 @@
|
|||
From e0de25f60a3535d345b33dcc541c814499151788 Mon Sep 17 00:00:00 2001
|
||||
From: Jernej Skrabec <jernej.skrabec@gmail.com>
|
||||
Date: Sun, 29 Sep 2024 22:04:44 +1300
|
||||
Subject: drm: sun4i: support YUV formats in VI scaler
|
||||
|
||||
Now that YUV formats are available, enable support in the VI scaler.
|
||||
|
||||
Signed-off-by: Jernej Skrabec <jernej.skrabec@gmail.com>
|
||||
Signed-off-by: Ryan Walklin <ryan@testtoast.com>
|
||||
|
||||
Changelog v4..v5:
|
||||
- Add commit description
|
||||
---
|
||||
drivers/gpu/drm/sun4i/sun8i_vi_scaler.c | 85 +++++++++++++++++--------
|
||||
1 file changed, 58 insertions(+), 27 deletions(-)
|
||||
|
||||
diff --git a/drivers/gpu/drm/sun4i/sun8i_vi_scaler.c b/drivers/gpu/drm/sun4i/sun8i_vi_scaler.c
|
||||
index 7ba75011adf9..2e49a6e5f1f1 100644
|
||||
--- a/drivers/gpu/drm/sun4i/sun8i_vi_scaler.c
|
||||
+++ b/drivers/gpu/drm/sun4i/sun8i_vi_scaler.c
|
||||
@@ -843,6 +843,11 @@ static u32 sun8i_vi_scaler_base(struct sun8i_mixer *mixer, int channel)
|
||||
DE2_VI_SCALER_UNIT_SIZE * channel;
|
||||
}
|
||||
|
||||
+static bool sun8i_vi_scaler_is_vi_plane(struct sun8i_mixer *mixer, int channel)
|
||||
+{
|
||||
+ return true;
|
||||
+}
|
||||
+
|
||||
static int sun8i_vi_scaler_coef_index(unsigned int step)
|
||||
{
|
||||
unsigned int scale, int_part, float_part;
|
||||
@@ -867,44 +872,65 @@ static int sun8i_vi_scaler_coef_index(unsigned int step)
|
||||
}
|
||||
}
|
||||
|
||||
-static void sun8i_vi_scaler_set_coeff(struct regmap *map, u32 base,
|
||||
- u32 hstep, u32 vstep,
|
||||
- const struct drm_format_info *format)
|
||||
+static void sun8i_vi_scaler_set_coeff_vi(struct regmap *map, u32 base,
|
||||
+ u32 hstep, u32 vstep,
|
||||
+ const struct drm_format_info *format)
|
||||
{
|
||||
const u32 *ch_left, *ch_right, *cy;
|
||||
- int offset, i;
|
||||
+ int offset;
|
||||
|
||||
- if (format->hsub == 1 && format->vsub == 1) {
|
||||
- ch_left = lan3coefftab32_left;
|
||||
- ch_right = lan3coefftab32_right;
|
||||
- cy = lan2coefftab32;
|
||||
- } else {
|
||||
+ if (format->is_yuv) {
|
||||
ch_left = bicubic8coefftab32_left;
|
||||
ch_right = bicubic8coefftab32_right;
|
||||
cy = bicubic4coefftab32;
|
||||
+ } else {
|
||||
+ ch_left = lan3coefftab32_left;
|
||||
+ ch_right = lan3coefftab32_right;
|
||||
+ cy = lan2coefftab32;
|
||||
}
|
||||
|
||||
offset = sun8i_vi_scaler_coef_index(hstep) *
|
||||
SUN8I_VI_SCALER_COEFF_COUNT;
|
||||
- for (i = 0; i < SUN8I_VI_SCALER_COEFF_COUNT; i++) {
|
||||
- regmap_write(map, SUN8I_SCALER_VSU_YHCOEFF0(base, i),
|
||||
- lan3coefftab32_left[offset + i]);
|
||||
- regmap_write(map, SUN8I_SCALER_VSU_YHCOEFF1(base, i),
|
||||
- lan3coefftab32_right[offset + i]);
|
||||
- regmap_write(map, SUN8I_SCALER_VSU_CHCOEFF0(base, i),
|
||||
- ch_left[offset + i]);
|
||||
- regmap_write(map, SUN8I_SCALER_VSU_CHCOEFF1(base, i),
|
||||
- ch_right[offset + i]);
|
||||
- }
|
||||
+ regmap_bulk_write(map, SUN8I_SCALER_VSU_YHCOEFF0(base, 0),
|
||||
+ &lan3coefftab32_left[offset],
|
||||
+ SUN8I_VI_SCALER_COEFF_COUNT);
|
||||
+ regmap_bulk_write(map, SUN8I_SCALER_VSU_YHCOEFF1(base, 0),
|
||||
+ &lan3coefftab32_right[offset],
|
||||
+ SUN8I_VI_SCALER_COEFF_COUNT);
|
||||
+ regmap_bulk_write(map, SUN8I_SCALER_VSU_CHCOEFF0(base, 0),
|
||||
+ &ch_left[offset], SUN8I_VI_SCALER_COEFF_COUNT);
|
||||
+ regmap_bulk_write(map, SUN8I_SCALER_VSU_CHCOEFF1(base, 0),
|
||||
+ &ch_right[offset], SUN8I_VI_SCALER_COEFF_COUNT);
|
||||
|
||||
offset = sun8i_vi_scaler_coef_index(hstep) *
|
||||
SUN8I_VI_SCALER_COEFF_COUNT;
|
||||
- for (i = 0; i < SUN8I_VI_SCALER_COEFF_COUNT; i++) {
|
||||
- regmap_write(map, SUN8I_SCALER_VSU_YVCOEFF(base, i),
|
||||
- lan2coefftab32[offset + i]);
|
||||
- regmap_write(map, SUN8I_SCALER_VSU_CVCOEFF(base, i),
|
||||
- cy[offset + i]);
|
||||
- }
|
||||
+ regmap_bulk_write(map, SUN8I_SCALER_VSU_YVCOEFF(base, 0),
|
||||
+ &lan2coefftab32[offset], SUN8I_VI_SCALER_COEFF_COUNT);
|
||||
+ regmap_bulk_write(map, SUN8I_SCALER_VSU_CVCOEFF(base, 0),
|
||||
+ &cy[offset], SUN8I_VI_SCALER_COEFF_COUNT);
|
||||
+}
|
||||
+
|
||||
+static void sun8i_vi_scaler_set_coeff_ui(struct regmap *map, u32 base,
|
||||
+ u32 hstep, u32 vstep,
|
||||
+ const struct drm_format_info *format)
|
||||
+{
|
||||
+ const u32 *table;
|
||||
+ int offset;
|
||||
+
|
||||
+ offset = sun8i_vi_scaler_coef_index(hstep) *
|
||||
+ SUN8I_VI_SCALER_COEFF_COUNT;
|
||||
+ regmap_bulk_write(map, SUN8I_SCALER_VSU_YHCOEFF0(base, 0),
|
||||
+ &lan2coefftab32[offset], SUN8I_VI_SCALER_COEFF_COUNT);
|
||||
+ offset = sun8i_vi_scaler_coef_index(vstep) *
|
||||
+ SUN8I_VI_SCALER_COEFF_COUNT;
|
||||
+ regmap_bulk_write(map, SUN8I_SCALER_VSU_YVCOEFF(base, 0),
|
||||
+ &lan2coefftab32[offset], SUN8I_VI_SCALER_COEFF_COUNT);
|
||||
+
|
||||
+ table = format->is_yuv ? bicubic4coefftab32 : lan2coefftab32;
|
||||
+ offset = sun8i_vi_scaler_coef_index(hstep) *
|
||||
+ SUN8I_VI_SCALER_COEFF_COUNT;
|
||||
+ regmap_bulk_write(map, SUN8I_SCALER_VSU_CHCOEFF0(base, 0),
|
||||
+ &table[offset], SUN8I_VI_SCALER_COEFF_COUNT);
|
||||
}
|
||||
|
||||
void sun8i_vi_scaler_enable(struct sun8i_mixer *mixer, int layer, bool enable)
|
||||
@@ -994,6 +1020,11 @@ void sun8i_vi_scaler_setup(struct sun8i_mixer *mixer, int layer,
|
||||
SUN8I_SCALER_VSU_CHPHASE(base), chphase);
|
||||
regmap_write(mixer->engine.regs,
|
||||
SUN8I_SCALER_VSU_CVPHASE(base), cvphase);
|
||||
- sun8i_vi_scaler_set_coeff(mixer->engine.regs, base,
|
||||
- hscale, vscale, format);
|
||||
+
|
||||
+ if (sun8i_vi_scaler_is_vi_plane(mixer, layer))
|
||||
+ sun8i_vi_scaler_set_coeff_vi(mixer->engine.regs, base,
|
||||
+ hscale, vscale, format);
|
||||
+ else
|
||||
+ sun8i_vi_scaler_set_coeff_ui(mixer->engine.regs, base,
|
||||
+ hscale, vscale, format);
|
||||
}
|
||||
--
|
||||
2.35.3
|
||||
|
||||
|
|
@ -0,0 +1,100 @@
|
|||
From 0c10a80b8e37d9a7fc57d8bf968c70419423065a Mon Sep 17 00:00:00 2001
|
||||
From: Jernej Skrabec <jernej.skrabec@gmail.com>
|
||||
Date: Sun, 29 Sep 2024 22:04:47 +1300
|
||||
Subject: drm: sun4i: vi_scaler refactor vi_scaler enablement
|
||||
|
||||
If the video scaler is required, then it is obligatory to set the
|
||||
relevant register to enable it, so move this to the
|
||||
sun8i_vi_scaler_setup() function.
|
||||
|
||||
This simplifies the alternate case (scaler not required) so replace the
|
||||
vi_scaler_enable() function with a vi_scaler_disable() function.
|
||||
|
||||
Signed-off-by: Jernej Skrabec <jernej.skrabec@gmail.com>
|
||||
Signed-off-by: Ryan Walklin <ryan@testtoast.com>
|
||||
---
|
||||
drivers/gpu/drm/sun4i/sun8i_vi_layer.c | 3 +--
|
||||
drivers/gpu/drm/sun4i/sun8i_vi_scaler.c | 21 +++++++++++----------
|
||||
drivers/gpu/drm/sun4i/sun8i_vi_scaler.h | 2 +-
|
||||
3 files changed, 13 insertions(+), 13 deletions(-)
|
||||
|
||||
diff --git a/drivers/gpu/drm/sun4i/sun8i_vi_layer.c b/drivers/gpu/drm/sun4i/sun8i_vi_layer.c
|
||||
index 4647e9bcccaa..e348fd0a3d81 100644
|
||||
--- a/drivers/gpu/drm/sun4i/sun8i_vi_layer.c
|
||||
+++ b/drivers/gpu/drm/sun4i/sun8i_vi_layer.c
|
||||
@@ -156,10 +156,9 @@ static int sun8i_vi_layer_update_coord(struct sun8i_mixer *mixer, int channel,
|
||||
sun8i_vi_scaler_setup(mixer, channel, src_w, src_h, dst_w,
|
||||
dst_h, hscale, vscale, hphase, vphase,
|
||||
format);
|
||||
- sun8i_vi_scaler_enable(mixer, channel, true);
|
||||
} else {
|
||||
DRM_DEBUG_DRIVER("HW scaling is not needed\n");
|
||||
- sun8i_vi_scaler_enable(mixer, channel, false);
|
||||
+ sun8i_vi_scaler_disable(mixer, channel);
|
||||
}
|
||||
|
||||
regmap_write(mixer->engine.regs,
|
||||
diff --git a/drivers/gpu/drm/sun4i/sun8i_vi_scaler.c b/drivers/gpu/drm/sun4i/sun8i_vi_scaler.c
|
||||
index aa346c3beb30..e7242301b312 100644
|
||||
--- a/drivers/gpu/drm/sun4i/sun8i_vi_scaler.c
|
||||
+++ b/drivers/gpu/drm/sun4i/sun8i_vi_scaler.c
|
||||
@@ -933,20 +933,13 @@ static void sun8i_vi_scaler_set_coeff_ui(struct regmap *map, u32 base,
|
||||
&table[offset], SUN8I_VI_SCALER_COEFF_COUNT);
|
||||
}
|
||||
|
||||
-void sun8i_vi_scaler_enable(struct sun8i_mixer *mixer, int layer, bool enable)
|
||||
+void sun8i_vi_scaler_disable(struct sun8i_mixer *mixer, int layer)
|
||||
{
|
||||
- u32 val, base;
|
||||
+ u32 base;
|
||||
|
||||
base = sun8i_vi_scaler_base(mixer, layer);
|
||||
|
||||
- if (enable)
|
||||
- val = SUN8I_SCALER_VSU_CTRL_EN |
|
||||
- SUN8I_SCALER_VSU_CTRL_COEFF_RDY;
|
||||
- else
|
||||
- val = 0;
|
||||
-
|
||||
- regmap_write(mixer->engine.regs,
|
||||
- SUN8I_SCALER_VSU_CTRL(base), val);
|
||||
+ regmap_write(mixer->engine.regs, SUN8I_SCALER_VSU_CTRL(base), 0);
|
||||
}
|
||||
|
||||
void sun8i_vi_scaler_setup(struct sun8i_mixer *mixer, int layer,
|
||||
@@ -982,6 +975,9 @@ void sun8i_vi_scaler_setup(struct sun8i_mixer *mixer, int layer,
|
||||
cvphase = vphase;
|
||||
}
|
||||
|
||||
+ regmap_write(mixer->engine.regs, SUN8I_SCALER_VSU_CTRL(base),
|
||||
+ SUN8I_SCALER_VSU_CTRL_EN);
|
||||
+
|
||||
if (mixer->cfg->de_type >= sun8i_mixer_de3) {
|
||||
u32 val;
|
||||
|
||||
@@ -1027,4 +1023,9 @@ void sun8i_vi_scaler_setup(struct sun8i_mixer *mixer, int layer,
|
||||
else
|
||||
sun8i_vi_scaler_set_coeff_ui(mixer->engine.regs, base,
|
||||
hscale, vscale, format);
|
||||
+
|
||||
+ if (mixer->cfg->de_type <= sun8i_mixer_de3)
|
||||
+ regmap_write(mixer->engine.regs, SUN8I_SCALER_VSU_CTRL(base),
|
||||
+ SUN8I_SCALER_VSU_CTRL_EN |
|
||||
+ SUN8I_SCALER_VSU_CTRL_COEFF_RDY);
|
||||
}
|
||||
diff --git a/drivers/gpu/drm/sun4i/sun8i_vi_scaler.h b/drivers/gpu/drm/sun4i/sun8i_vi_scaler.h
|
||||
index 68f6593b369a..e801bc7a4189 100644
|
||||
--- a/drivers/gpu/drm/sun4i/sun8i_vi_scaler.h
|
||||
+++ b/drivers/gpu/drm/sun4i/sun8i_vi_scaler.h
|
||||
@@ -69,7 +69,7 @@
|
||||
#define SUN50I_SCALER_VSU_ANGLE_SHIFT(x) (((x) << 16) & 0xF)
|
||||
#define SUN50I_SCALER_VSU_ANGLE_OFFSET(x) ((x) & 0xFF)
|
||||
|
||||
-void sun8i_vi_scaler_enable(struct sun8i_mixer *mixer, int layer, bool enable);
|
||||
+void sun8i_vi_scaler_disable(struct sun8i_mixer *mixer, int layer);
|
||||
void sun8i_vi_scaler_setup(struct sun8i_mixer *mixer, int layer,
|
||||
u32 src_w, u32 src_h, u32 dst_w, u32 dst_h,
|
||||
u32 hscale, u32 vscale, u32 hphase, u32 vphase,
|
||||
--
|
||||
2.35.3
|
||||
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
From b8344d8eb9d000bc2984a5fcafc25b527f361b5b Mon Sep 17 00:00:00 2001
|
||||
From: Ryan Walklin <ryan@testtoast.com>
|
||||
Date: Sun, 29 Sep 2024 22:04:51 +1300
|
||||
Subject: dt-bindings: allwinner: add H616 DE33 bus binding
|
||||
|
||||
The Allwinner H616 and variants have a new display engine revision
|
||||
(DE33).
|
||||
|
||||
Add a display engine bus binding for the DE33.
|
||||
|
||||
Signed-off-by: Ryan Walklin <ryan@testtoast.com>
|
||||
Acked-by: Conor Dooley <conor.dooley@microchip.com>
|
||||
Reviewed-by: Chen-Yu Tsai <wens@csie.org>
|
||||
---
|
||||
.../devicetree/bindings/bus/allwinner,sun50i-a64-de2.yaml | 4 +++-
|
||||
1 file changed, 3 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/Documentation/devicetree/bindings/bus/allwinner,sun50i-a64-de2.yaml b/Documentation/devicetree/bindings/bus/allwinner,sun50i-a64-de2.yaml
|
||||
index 9845a187bdf6..ea7ee89158c6 100644
|
||||
--- a/Documentation/devicetree/bindings/bus/allwinner,sun50i-a64-de2.yaml
|
||||
+++ b/Documentation/devicetree/bindings/bus/allwinner,sun50i-a64-de2.yaml
|
||||
@@ -24,7 +24,9 @@ properties:
|
||||
oneOf:
|
||||
- const: allwinner,sun50i-a64-de2
|
||||
- items:
|
||||
- - const: allwinner,sun50i-h6-de3
|
||||
+ - enum:
|
||||
+ - allwinner,sun50i-h6-de3
|
||||
+ - allwinner,sun50i-h616-de33
|
||||
- const: allwinner,sun50i-a64-de2
|
||||
|
||||
reg:
|
||||
--
|
||||
2.35.3
|
||||
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
From 58a606c8136c57d23b4e35f0f50cb140f1d65d9b Mon Sep 17 00:00:00 2001
|
||||
From: Ryan Walklin <ryan@testtoast.com>
|
||||
Date: Sun, 29 Sep 2024 22:04:52 +1300
|
||||
Subject: dt-bindings: allwinner: add H616 DE33 clock binding
|
||||
|
||||
The Allwinner H616 and variants have a new display engine revision
|
||||
(DE33).
|
||||
|
||||
Add a clock binding for the DE33.
|
||||
|
||||
Signed-off-by: Ryan Walklin <ryan@testtoast.com>
|
||||
Acked-by: Conor Dooley <conor.dooley@microchip.com>
|
||||
Reviewed-by: Chen-Yu Tsai <wens@csie.org>
|
||||
---
|
||||
.../devicetree/bindings/clock/allwinner,sun8i-a83t-de2-clk.yaml | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
diff --git a/Documentation/devicetree/bindings/clock/allwinner,sun8i-a83t-de2-clk.yaml b/Documentation/devicetree/bindings/clock/allwinner,sun8i-a83t-de2-clk.yaml
|
||||
index 70369bd633e4..7fcd55d468d4 100644
|
||||
--- a/Documentation/devicetree/bindings/clock/allwinner,sun8i-a83t-de2-clk.yaml
|
||||
+++ b/Documentation/devicetree/bindings/clock/allwinner,sun8i-a83t-de2-clk.yaml
|
||||
@@ -25,6 +25,7 @@ properties:
|
||||
- const: allwinner,sun50i-a64-de2-clk
|
||||
- const: allwinner,sun50i-h5-de2-clk
|
||||
- const: allwinner,sun50i-h6-de3-clk
|
||||
+ - const: allwinner,sun50i-h616-de33-clk
|
||||
- items:
|
||||
- const: allwinner,sun8i-r40-de2-clk
|
||||
- const: allwinner,sun8i-h3-de2-clk
|
||||
--
|
||||
2.35.3
|
||||
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
From 12d7983166ed867dd72c023af036b1397aec66ba Mon Sep 17 00:00:00 2001
|
||||
From: Ryan Walklin <ryan@testtoast.com>
|
||||
Date: Sun, 29 Sep 2024 22:04:53 +1300
|
||||
Subject: dt-bindings: allwinner: add H616 DE33 mixer binding
|
||||
|
||||
The Allwinner H616 and variants have a new display engine revision
|
||||
(DE33).
|
||||
|
||||
The mixer configuration registers are significantly different to the DE3
|
||||
and DE2 revisions, being split into separate top and display blocks,
|
||||
therefore a fallback for the mixer compatible is not provided.
|
||||
|
||||
Add a display engine mixer binding for the DE33.
|
||||
|
||||
Signed-off-by: Ryan Walklin <ryan@testtoast.com>
|
||||
Acked-by: Conor Dooley <conor.dooley@microchip.com>
|
||||
Reviewed-by: Chen-Yu Tsai <wens@csie.org>
|
||||
---
|
||||
.../bindings/display/allwinner,sun8i-a83t-de2-mixer.yaml | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
diff --git a/Documentation/devicetree/bindings/display/allwinner,sun8i-a83t-de2-mixer.yaml b/Documentation/devicetree/bindings/display/allwinner,sun8i-a83t-de2-mixer.yaml
|
||||
index b75c1ec686ad..c37eb8ae1b8e 100644
|
||||
--- a/Documentation/devicetree/bindings/display/allwinner,sun8i-a83t-de2-mixer.yaml
|
||||
+++ b/Documentation/devicetree/bindings/display/allwinner,sun8i-a83t-de2-mixer.yaml
|
||||
@@ -24,6 +24,7 @@ properties:
|
||||
- allwinner,sun50i-a64-de2-mixer-0
|
||||
- allwinner,sun50i-a64-de2-mixer-1
|
||||
- allwinner,sun50i-h6-de3-mixer-0
|
||||
+ - allwinner,sun50i-h616-de33-mixer-0
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
--
|
||||
2.35.3
|
||||
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
From 7f350d05012873c129458241792d005ef1344d9a Mon Sep 17 00:00:00 2001
|
||||
From: Andre Przywara <andre.przywara@arm.com>
|
||||
Date: Fri, 21 Feb 2025 00:58:00 +0000
|
||||
Subject: dt-bindings: gpu: mali-bifrost: Add Allwinner H616 compatible
|
||||
|
||||
The Allwinner H616 SoC has a Mali-G31 MP2 GPU, which is of the Mali
|
||||
Bifrost family.
|
||||
Add the SoC specific compatible string and pair it with the bifrost
|
||||
fallback compatible.
|
||||
|
||||
Signed-off-by: Andre Przywara <andre.przywara@arm.com>
|
||||
---
|
||||
Documentation/devicetree/bindings/gpu/arm,mali-bifrost.yaml | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
diff --git a/Documentation/devicetree/bindings/gpu/arm,mali-bifrost.yaml b/Documentation/devicetree/bindings/gpu/arm,mali-bifrost.yaml
|
||||
index 735c7f06c24e..439d5c59daa2 100644
|
||||
--- a/Documentation/devicetree/bindings/gpu/arm,mali-bifrost.yaml
|
||||
+++ b/Documentation/devicetree/bindings/gpu/arm,mali-bifrost.yaml
|
||||
@@ -17,6 +17,7 @@ properties:
|
||||
oneOf:
|
||||
- items:
|
||||
- enum:
|
||||
+ - allwinner,sun50i-h616-mali
|
||||
- amlogic,meson-g12a-mali
|
||||
- mediatek,mt8183-mali
|
||||
- mediatek,mt8183b-mali
|
||||
--
|
||||
2.35.3
|
||||
|
||||
|
|
@ -0,0 +1,67 @@
|
|||
From af0be61ac5ff0f86567ddbf3924c46eaa211e07f Mon Sep 17 00:00:00 2001
|
||||
From: Andre Przywara <andre.przywara@arm.com>
|
||||
Date: Fri, 21 Feb 2025 00:57:58 +0000
|
||||
Subject: dt-bindings: power: Add Allwinner H6/H616 PRCM PPU
|
||||
|
||||
The Allwinner H6 and some later SoCs contain some bits in the PRCM (Power
|
||||
Reset Clock Management) block that control some power domains.
|
||||
Those power domains include the one for the GPU, the PLLs and some
|
||||
analogue circuits.
|
||||
|
||||
Signed-off-by: Andre Przywara <andre.przywara@arm.com>
|
||||
---
|
||||
.../power/allwinner,sun50i-h6-prcm-ppu.yaml | 42 +++++++++++++++++++
|
||||
1 file changed, 42 insertions(+)
|
||||
create mode 100644 Documentation/devicetree/bindings/power/allwinner,sun50i-h6-prcm-ppu.yaml
|
||||
|
||||
diff --git a/Documentation/devicetree/bindings/power/allwinner,sun50i-h6-prcm-ppu.yaml b/Documentation/devicetree/bindings/power/allwinner,sun50i-h6-prcm-ppu.yaml
|
||||
new file mode 100644
|
||||
index 000000000000..7eaff9baf726
|
||||
--- /dev/null
|
||||
+++ b/Documentation/devicetree/bindings/power/allwinner,sun50i-h6-prcm-ppu.yaml
|
||||
@@ -0,0 +1,42 @@
|
||||
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
+%YAML 1.2
|
||||
+---
|
||||
+$id: http://devicetree.org/schemas/power/allwinner,sun50i-h6-prcm-ppu.yaml#
|
||||
+$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
+
|
||||
+title: Allwinner SoCs PRCM power domain controller
|
||||
+
|
||||
+maintainers:
|
||||
+ - Andre Przywara <andre.przywara@arm.com>
|
||||
+
|
||||
+description:
|
||||
+ The Allwinner Power Reset Clock Management (PRCM) unit contains bits to
|
||||
+ control a few power domains.
|
||||
+
|
||||
+properties:
|
||||
+ compatible:
|
||||
+ enum:
|
||||
+ - allwinner,sun50i-h6-prcm-ppu
|
||||
+ - allwinner,sun50i-h616-prcm-ppu
|
||||
+ - allwinner,sun55i-a523-prcm-ppu
|
||||
+
|
||||
+ reg:
|
||||
+ maxItems: 1
|
||||
+
|
||||
+ '#power-domain-cells':
|
||||
+ const: 1
|
||||
+
|
||||
+required:
|
||||
+ - compatible
|
||||
+ - reg
|
||||
+ - '#power-domain-cells'
|
||||
+
|
||||
+additionalProperties: false
|
||||
+
|
||||
+examples:
|
||||
+ - |
|
||||
+ prcm_ppu: power-controller@7010210 {
|
||||
+ compatible = "allwinner,sun50i-h616-prcm-ppu";
|
||||
+ reg = <0x07010250 0x10>;
|
||||
+ #power-domain-cells = <1>;
|
||||
+ };
|
||||
--
|
||||
2.35.3
|
||||
|
||||
|
|
@ -0,0 +1,249 @@
|
|||
From 9fb1314045a676823428efa503b581c2910169d7 Mon Sep 17 00:00:00 2001
|
||||
From: Andre Przywara <andre.przywara@arm.com>
|
||||
Date: Fri, 21 Feb 2025 00:57:59 +0000
|
||||
Subject: pmdomain: sunxi: add H6 PRCM PPU driver
|
||||
|
||||
The Allwinner Power Reset Clock Management (RPCM) block contains a few
|
||||
bits that control some power domains. The most prominent one is the one
|
||||
for the Mali GPU. On the Allwinner H6 this domain is enabled at reset, so
|
||||
we didn't care about it so far, but the H616 defaults to it being disabled.
|
||||
|
||||
Add a power domain driver for those bits. Some BSP code snippets and
|
||||
some spare documentation describe three bits, slightly different between
|
||||
the H6 and H616, so add three power domains for each SoC, connected to
|
||||
their compatible string.
|
||||
|
||||
Signed-off-by: Andre Przywara <andre.przywara@arm.com>
|
||||
---
|
||||
drivers/pmdomain/sunxi/Kconfig | 10 +
|
||||
drivers/pmdomain/sunxi/Makefile | 1 +
|
||||
drivers/pmdomain/sunxi/sun50i-h6-prcm-ppu.c | 191 ++++++++++++++++++++
|
||||
3 files changed, 202 insertions(+)
|
||||
create mode 100644 drivers/pmdomain/sunxi/sun50i-h6-prcm-ppu.c
|
||||
|
||||
diff --git a/drivers/pmdomain/sunxi/Kconfig b/drivers/pmdomain/sunxi/Kconfig
|
||||
index 17781bf8d86d..43eecb3ea981 100644
|
||||
--- a/drivers/pmdomain/sunxi/Kconfig
|
||||
+++ b/drivers/pmdomain/sunxi/Kconfig
|
||||
@@ -8,3 +8,13 @@ config SUN20I_PPU
|
||||
help
|
||||
Say y to enable the PPU power domain driver. This saves power
|
||||
when certain peripherals, such as the video engine, are idle.
|
||||
+
|
||||
+config SUN50I_H6_PRCM_PPU
|
||||
+ tristate "Allwinner H6 PRCM power domain driver"
|
||||
+ depends on ARCH_SUNXI || COMPILE_TEST
|
||||
+ depends on PM
|
||||
+ select PM_GENERIC_DOMAINS
|
||||
+ help
|
||||
+ Say y to enable the Allwinner H6/H616 PRCM power domain driver.
|
||||
+ This is required to enable the Mali GPU in the H616 SoC, it is
|
||||
+ optional for the H6.
|
||||
diff --git a/drivers/pmdomain/sunxi/Makefile b/drivers/pmdomain/sunxi/Makefile
|
||||
index ec1d7a2fb21d..c1343e123759 100644
|
||||
--- a/drivers/pmdomain/sunxi/Makefile
|
||||
+++ b/drivers/pmdomain/sunxi/Makefile
|
||||
@@ -1,2 +1,3 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
obj-$(CONFIG_SUN20I_PPU) += sun20i-ppu.o
|
||||
+obj-$(CONFIG_SUN50I_H6_PRCM_PPU) += sun50i-h6-prcm-ppu.o
|
||||
diff --git a/drivers/pmdomain/sunxi/sun50i-h6-prcm-ppu.c b/drivers/pmdomain/sunxi/sun50i-h6-prcm-ppu.c
|
||||
new file mode 100644
|
||||
index 000000000000..1c6b0c78b222
|
||||
--- /dev/null
|
||||
+++ b/drivers/pmdomain/sunxi/sun50i-h6-prcm-ppu.c
|
||||
@@ -0,0 +1,191 @@
|
||||
+// SPDX-License-Identifier: GPL-2.0-only
|
||||
+/*
|
||||
+ * Copyright (C) Arm Ltd. 2024
|
||||
+ *
|
||||
+ * Allwinner H6/H616 PRCM power domain driver.
|
||||
+ * This covers a few registers inside the PRCM (Power Reset Clock Management)
|
||||
+ * block that control some power rails, most prominently for the Mali GPU.
|
||||
+ */
|
||||
+
|
||||
+#include <linux/bitfield.h>
|
||||
+#include <linux/clk.h>
|
||||
+#include <linux/io.h>
|
||||
+#include <linux/iopoll.h>
|
||||
+#include <linux/module.h>
|
||||
+#include <linux/of.h>
|
||||
+#include <linux/platform_device.h>
|
||||
+#include <linux/pm_domain.h>
|
||||
+#include <linux/reset.h>
|
||||
+
|
||||
+/*
|
||||
+ * The PRCM block covers multiple devices, starting with some clocks,
|
||||
+ * then followed by the power rails.
|
||||
+ * The clocks are covered by a different driver, so this driver's MMIO range
|
||||
+ * starts later in the PRCM MMIO frame, not at the beginning of it.
|
||||
+ * To keep the register offsets consistent with other PRCM documentation,
|
||||
+ * express the registers relative to the beginning of the whole PRCM, and
|
||||
+ * subtract the PPU offset this driver is bound to.
|
||||
+ */
|
||||
+#define PD_H6_PPU_OFFSET 0x250
|
||||
+#define PD_H6_VDD_SYS_REG 0x250
|
||||
+#define PD_H616_ANA_VDD_GATE BIT(4)
|
||||
+#define PD_H6_CPUS_VDD_GATE BIT(3)
|
||||
+#define PD_H6_AVCC_VDD_GATE BIT(2)
|
||||
+#define PD_H6_GPU_REG 0x254
|
||||
+#define PD_H6_GPU_GATE BIT(0)
|
||||
+
|
||||
+struct sun50i_h6_ppu_pd {
|
||||
+ struct generic_pm_domain genpd;
|
||||
+ void __iomem *reg;
|
||||
+ u32 gate_mask;
|
||||
+ bool negated;
|
||||
+};
|
||||
+
|
||||
+#define FLAG_PPU_ALWAYS_ON BIT(0)
|
||||
+#define FLAG_PPU_NEGATED BIT(1)
|
||||
+
|
||||
+struct sun50i_h6_ppu_desc {
|
||||
+ const char *name;
|
||||
+ u32 offset;
|
||||
+ u32 mask;
|
||||
+ unsigned int flags;
|
||||
+};
|
||||
+
|
||||
+struct sun50i_h6_ppu_desc sun50i_h6_ppus[] = {
|
||||
+ { "AVCC", PD_H6_VDD_SYS_REG, PD_H6_AVCC_VDD_GATE },
|
||||
+ { "CPUS", PD_H6_VDD_SYS_REG, PD_H6_CPUS_VDD_GATE },
|
||||
+ { "GPU", PD_H6_GPU_REG, PD_H6_GPU_GATE },
|
||||
+ {}
|
||||
+};
|
||||
+
|
||||
+struct sun50i_h6_ppu_desc sun50i_h616_ppus[] = {
|
||||
+ { "PLL", PD_H6_VDD_SYS_REG, PD_H6_AVCC_VDD_GATE,
|
||||
+ FLAG_PPU_ALWAYS_ON | FLAG_PPU_NEGATED },
|
||||
+ { "ANA", PD_H6_VDD_SYS_REG, PD_H616_ANA_VDD_GATE, FLAG_PPU_ALWAYS_ON },
|
||||
+ { "GPU", PD_H6_GPU_REG, PD_H6_GPU_GATE, FLAG_PPU_NEGATED },
|
||||
+ {}
|
||||
+};
|
||||
+#define to_sun50i_h6_ppu_pd(_genpd) \
|
||||
+ container_of(_genpd, struct sun50i_h6_ppu_pd, genpd)
|
||||
+
|
||||
+static bool sun50i_h6_ppu_power_status(const struct sun50i_h6_ppu_pd *pd)
|
||||
+{
|
||||
+ bool bit = readl(pd->reg) & pd->gate_mask;
|
||||
+
|
||||
+ return bit ^ pd->negated;
|
||||
+}
|
||||
+
|
||||
+static int sun50i_h6_ppu_pd_set_power(const struct sun50i_h6_ppu_pd *pd,
|
||||
+ bool set_bit)
|
||||
+{
|
||||
+ u32 reg = readl(pd->reg);
|
||||
+
|
||||
+ if (set_bit)
|
||||
+ writel(reg | pd->gate_mask, pd->reg);
|
||||
+ else
|
||||
+ writel(reg & ~pd->gate_mask, pd->reg);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int sun50i_h6_ppu_pd_power_on(struct generic_pm_domain *genpd)
|
||||
+{
|
||||
+ const struct sun50i_h6_ppu_pd *pd = to_sun50i_h6_ppu_pd(genpd);
|
||||
+
|
||||
+ return sun50i_h6_ppu_pd_set_power(pd, !pd->negated);
|
||||
+}
|
||||
+
|
||||
+static int sun50i_h6_ppu_pd_power_off(struct generic_pm_domain *genpd)
|
||||
+{
|
||||
+ const struct sun50i_h6_ppu_pd *pd = to_sun50i_h6_ppu_pd(genpd);
|
||||
+
|
||||
+ return sun50i_h6_ppu_pd_set_power(pd, pd->negated);
|
||||
+}
|
||||
+
|
||||
+static int sun50i_h6_ppu_probe(struct platform_device *pdev)
|
||||
+{
|
||||
+ struct device *dev = &pdev->dev;
|
||||
+ struct genpd_onecell_data *ppu;
|
||||
+ struct sun50i_h6_ppu_pd *pds;
|
||||
+ const struct sun50i_h6_ppu_desc *desc;
|
||||
+ void __iomem *base;
|
||||
+ int ret, i, count;
|
||||
+
|
||||
+ desc = of_device_get_match_data(dev);
|
||||
+ if (!desc)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ for (count = 0; desc[count].name; count++)
|
||||
+ ;
|
||||
+
|
||||
+ pds = devm_kcalloc(dev, count, sizeof(*pds), GFP_KERNEL);
|
||||
+ if (!pds)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ ppu = devm_kzalloc(dev, sizeof(*ppu), GFP_KERNEL);
|
||||
+ if (!ppu)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ ppu->num_domains = count;
|
||||
+ ppu->domains = devm_kcalloc(dev, count, sizeof(*ppu->domains),
|
||||
+ GFP_KERNEL);
|
||||
+ if (!ppu->domains)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ platform_set_drvdata(pdev, ppu);
|
||||
+
|
||||
+ base = devm_platform_ioremap_resource(pdev, 0);
|
||||
+ if (IS_ERR(base))
|
||||
+ return PTR_ERR(base);
|
||||
+
|
||||
+ for (i = 0; i < count; i++) {
|
||||
+ struct sun50i_h6_ppu_pd *pd = &pds[i];
|
||||
+
|
||||
+ pd->genpd.name = desc[i].name;
|
||||
+ pd->genpd.power_off = sun50i_h6_ppu_pd_power_off;
|
||||
+ pd->genpd.power_on = sun50i_h6_ppu_pd_power_on;
|
||||
+ if (desc[i].flags & FLAG_PPU_ALWAYS_ON)
|
||||
+ pd->genpd.flags = GENPD_FLAG_ALWAYS_ON;
|
||||
+ pd->negated = !!(desc[i].flags & FLAG_PPU_NEGATED);
|
||||
+ pd->reg = base + desc[i].offset - PD_H6_PPU_OFFSET;
|
||||
+ pd->gate_mask = desc[i].mask;
|
||||
+
|
||||
+ ret = pm_genpd_init(&pd->genpd, NULL,
|
||||
+ !sun50i_h6_ppu_power_status(pd));
|
||||
+ if (ret) {
|
||||
+ dev_warn(dev, "Failed to add GPU power domain: %d\n", ret);
|
||||
+ return ret;
|
||||
+ }
|
||||
+ ppu->domains[i] = &pd->genpd;
|
||||
+ }
|
||||
+
|
||||
+ ret = of_genpd_add_provider_onecell(dev->of_node, ppu);
|
||||
+ if (ret)
|
||||
+ dev_warn(dev, "Failed to add provider: %d\n", ret);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static const struct of_device_id sun50i_h6_ppu_of_match[] = {
|
||||
+ { .compatible = "allwinner,sun50i-h6-prcm-ppu",
|
||||
+ .data = &sun50i_h6_ppus },
|
||||
+ { .compatible = "allwinner,sun50i-h616-prcm-ppu",
|
||||
+ .data = &sun50i_h616_ppus },
|
||||
+ { }
|
||||
+};
|
||||
+MODULE_DEVICE_TABLE(of, sun50i_h6_ppu_of_match);
|
||||
+
|
||||
+static struct platform_driver sun50i_h6_ppu_driver = {
|
||||
+ .probe = sun50i_h6_ppu_probe,
|
||||
+ .driver = {
|
||||
+ .name = "sun50i-h6-prcm-ppu",
|
||||
+ .of_match_table = sun50i_h6_ppu_of_match,
|
||||
+ /* Power domains cannot be removed while they are in use. */
|
||||
+ .suppress_bind_attrs = true,
|
||||
+ },
|
||||
+};
|
||||
+module_platform_driver(sun50i_h6_ppu_driver);
|
||||
+
|
||||
+MODULE_AUTHOR("Andre Przywara <andre.przywara@arm.com>");
|
||||
+MODULE_DESCRIPTION("Allwinner H6 PRCM power domain driver");
|
||||
+MODULE_LICENSE("GPL");
|
||||
--
|
||||
2.35.3
|
||||
|
||||
|
|
@ -13,7 +13,7 @@ Signed-off-by: Ondrej Jirman <megi@xff.cz>
|
|||
1 file changed, 10 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-a64.c b/drivers/clk/sunxi-ng/ccu-sun50i-a64.c
|
||||
index c8cdb342b1a0..e76a1c10f390 100644
|
||||
index 4b3068bdfdf2..e76a1c10f390 100644
|
||||
--- a/drivers/clk/sunxi-ng/ccu-sun50i-a64.c
|
||||
+++ b/drivers/clk/sunxi-ng/ccu-sun50i-a64.c
|
||||
@@ -962,6 +962,8 @@ static struct ccu_mux_nb sun50i_a64_cpu_nb = {
|
||||
|
|
@ -25,24 +25,24 @@ index c8cdb342b1a0..e76a1c10f390 100644
|
|||
static int sun50i_a64_ccu_probe(struct platform_device *pdev)
|
||||
{
|
||||
void __iomem *reg;
|
||||
@@ -981,9 +983,16 @@ static int sun50i_a64_ccu_probe(struct platform_device *pdev)
|
||||
@@ -980,7 +982,16 @@ static int sun50i_a64_ccu_probe(struct platform_device *pdev)
|
||||
/* Decrease the PLL AUDIO bias current to reduce noise. */
|
||||
writel(0x10040000, reg + SUN50I_A64_PLL_AUDIO_BIAS_REG);
|
||||
|
||||
ret = of_property_read_u32_index(of_chosen, "p-boot,framebuffer-start", 0, &val);
|
||||
- if (ret)
|
||||
- writel(0x515, reg + SUN50I_A64_PLL_MIPI_REG);
|
||||
+ ret = of_property_read_u32_index(of_chosen, "p-boot,framebuffer-start", 0, &val);
|
||||
+ if (ret) {
|
||||
writel(0x515, reg + SUN50I_A64_PLL_MIPI_REG);
|
||||
|
||||
+ writel(0x515, reg + SUN50I_A64_PLL_MIPI_REG);
|
||||
+
|
||||
+ /* Set MIPI-DSI clock parent to periph0(1x), so that video0(1x) is free to change. */
|
||||
+ val = readl(reg + CCU_MIPI_DSI_CLK);
|
||||
+ val &= 0x30f;
|
||||
+ val |= (2 << 8) | ((4 - 1) << 0); /* M-1 */
|
||||
+ writel(val, reg + CCU_MIPI_DSI_CLK);
|
||||
+ }
|
||||
+
|
||||
|
||||
ret = devm_sunxi_ccu_probe(&pdev->dev, reg, &sun50i_a64_ccu_desc);
|
||||
if (ret)
|
||||
return ret;
|
||||
--
|
||||
2.35.3
|
||||
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ Signed-off-by: Ondrej Jirman <megi@xff.cz>
|
|||
1 file changed, 70 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/drivers/video/backlight/pwm_bl.c b/drivers/video/backlight/pwm_bl.c
|
||||
index f7d9d8813d92..8a7a158dc1f6 100644
|
||||
index 237d3d3f3bb1..9f96bdd82a87 100644
|
||||
--- a/drivers/video/backlight/pwm_bl.c
|
||||
+++ b/drivers/video/backlight/pwm_bl.c
|
||||
@@ -437,6 +437,61 @@ static int pwm_backlight_initial_power_state(const struct pwm_bl_data *pb)
|
||||
|
|
@ -90,15 +90,29 @@ index f7d9d8813d92..8a7a158dc1f6 100644
|
|||
static int pwm_backlight_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct platform_pwm_backlight_data *data = dev_get_platdata(&pdev->dev);
|
||||
@@ -445,6 +500,7 @@ static int pwm_backlight_probe(struct platform_device *pdev)
|
||||
@@ -444,7 +499,8 @@ static int pwm_backlight_probe(struct platform_device *pdev)
|
||||
struct backlight_properties props;
|
||||
struct backlight_device *bl;
|
||||
struct pwm_bl_data *pb;
|
||||
struct pwm_state state, state_real;
|
||||
- struct pwm_state state;
|
||||
+ struct pwm_state state, state_real;
|
||||
+ u32 lth_brightness;
|
||||
unsigned int i;
|
||||
int ret;
|
||||
|
||||
@@ -584,8 +640,20 @@ static int pwm_backlight_probe(struct platform_device *pdev)
|
||||
@@ -509,6 +565,11 @@ static int pwm_backlight_probe(struct platform_device *pdev)
|
||||
/* Sync up PWM state. */
|
||||
pwm_init_state(pb->pwm, &state);
|
||||
|
||||
+ /* Read real state, but only if the PWM is enabled. */
|
||||
+ pwm_get_state(pb->pwm, &state_real);
|
||||
+ if (state_real.enabled)
|
||||
+ state = state_real;
|
||||
+
|
||||
/*
|
||||
* The DT case will set the pwm_period_ns field to 0 and store the
|
||||
* period, parsed from the DT, in the PWM device. For the non-DT case,
|
||||
@@ -579,8 +640,20 @@ static int pwm_backlight_probe(struct platform_device *pdev)
|
||||
pb->scale = data->max_brightness;
|
||||
}
|
||||
|
||||
|
|
@ -121,6 +135,31 @@ index f7d9d8813d92..8a7a158dc1f6 100644
|
|||
|
||||
props.type = BACKLIGHT_RAW;
|
||||
props.max_brightness = data->max_brightness;
|
||||
@@ -601,6 +674,24 @@ static int pwm_backlight_probe(struct platform_device *pdev)
|
||||
|
||||
bl->props.brightness = data->dft_brightness;
|
||||
bl->props.power = pwm_backlight_initial_power_state(pb);
|
||||
+ if (bl->props.power == FB_BLANK_UNBLANK && pb->levels) {
|
||||
+ u64 level;
|
||||
+
|
||||
+ /* If the backlight is already on, determine the default
|
||||
+ * brightness from PWM duty cycle instead of forcing
|
||||
+ * the brightness determined by the driver
|
||||
+ */
|
||||
+ pwm_get_state(pb->pwm, &state);
|
||||
+ level = (u64)state.duty_cycle * pb->scale;
|
||||
+ do_div(level, (u64)state.period);
|
||||
+
|
||||
+ for (i = 0; i <= data->max_brightness; i++) {
|
||||
+ if (data->levels[i] > level) {
|
||||
+ bl->props.brightness = i;
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
backlight_update_status(bl);
|
||||
|
||||
platform_set_drvdata(pdev, bl);
|
||||
--
|
||||
2.35.3
|
||||
|
||||
|
|
|
|||
|
|
@ -180,10 +180,10 @@
|
|||
patches.megous/arm64-dts-rk3399-Add-dmc_opp_table.patch
|
||||
patches.megous/arm64-dts-rockchip-rk3399-s-Add-DMC-table.patch
|
||||
patches.megous/bluetooth-h5-Don-t-re-initialize-rtl8723cs-on-resume.patch
|
||||
patches.megous/drm-sun4i-Mark-one-of-the-UI-planes-as-a-cursor-one.patch
|
||||
patches.megous/drm-sun4i-Implement-gamma-correction.patch
|
||||
- patches.megous/drm-sun4i-Mark-one-of-the-UI-planes-as-a-cursor-one.patch
|
||||
- patches.megous/drm-sun4i-Implement-gamma-correction.patch
|
||||
patches.megous/drm-panel-st7703-Fix-xbd599-timings-to-make-refresh-rate-exactl.patch
|
||||
patches.megous/drm-sun4i-Support-taking-over-display-pipeline-state-from-p-boo.patch
|
||||
- patches.megous/drm-sun4i-Support-taking-over-display-pipeline-state-from-p-boo.patch
|
||||
patches.megous/video-pwm_bl-Allow-to-change-lth_brightness-via-sysfs.patch
|
||||
patches.megous/clk-sunxi-ng-sun50i-a64-Switch-parent-of-MIPI-DSI-to-periph0-1x.patch
|
||||
patches.megous/drm-sun4i-tcon-Support-keeping-dclk-rate-upon-ancestor-clock-ch.patch
|
||||
|
|
@ -245,5 +245,46 @@
|
|||
patches.megous/Add-support-for-my-private-Sapomat-device.patch
|
||||
patches.megous/ARM-dts-sun8i-h3-orange-pi-one-Enable-all-gpio-header-UARTs.patch
|
||||
patches.megous/mtd-spi-nor-Add-Alliance-memory-support.patch
|
||||
patches.megous/Add-README.md-with-information-and-u-boot-patches.patch
|
||||
- patches.megous/Add-README.md-with-information-and-u-boot-patches.patch
|
||||
patches.megous/Defconfigs-for-all-my-devices.patch
|
||||
|
||||
################################################################################
|
||||
#
|
||||
# drivers/gpu/drm/sun4i/
|
||||
#
|
||||
################################################################################
|
||||
patches.drm/drm-sun4i-de2-de3-Change-CSC-argument.patch
|
||||
patches.drm/drm-sun4i-de2-de3-Merge-CSC-functions-into-one.patch
|
||||
patches.drm/drm-sun4i-de2-de3-call-csc-setup-also-for-UI-layer.patch
|
||||
patches.drm/drm-sun4i-de2-Initialize-layer-fields-earlier.patch
|
||||
patches.drm/drm-sun4i-de3-Add-YUV-formatter-module.patch
|
||||
patches.drm/drm-sun4i-de3-add-format-enumeration-function-to-engine.patch
|
||||
patches.drm/drm-sun4i-de3-add-formatter-flag-to-mixer-config.patch
|
||||
patches.drm/drm-sun4i-de3-add-YUV-support-to-the-DE3-mixer.patch
|
||||
patches.drm/drm-sun4i-de3-pass-engine-reference-to-ccsc-setup-function.patch
|
||||
patches.drm/drm-sun4i-de3-add-YUV-support-to-the-color-space-correction-mod.patch
|
||||
patches.drm/drm-sun4i-de3-add-YUV-support-to-the-TCON.patch
|
||||
patches.drm/drm-sun4i-support-YUV-formats-in-VI-scaler.patch
|
||||
patches.drm/drm-sun4i-de2-de3-add-mixer-version-enum.patch
|
||||
patches.drm/drm-sun4i-de2-de3-refactor-mixer-initialisation.patch
|
||||
patches.drm/drm-sun4i-vi_scaler-refactor-vi_scaler-enablement.patch
|
||||
patches.drm/drm-sun4i-de2-de3-add-generic-blender-register-reference-functi.patch
|
||||
patches.drm/drm-sun4i-de2-de3-use-generic-register-reference-function-for-l.patch
|
||||
patches.drm/drm-sun4i-de3-Implement-AFBC-support.patch
|
||||
patches.drm/dt-bindings-allwinner-add-H616-DE33-bus-binding.patch
|
||||
patches.drm/dt-bindings-allwinner-add-H616-DE33-clock-binding.patch
|
||||
patches.drm/dt-bindings-allwinner-add-H616-DE33-mixer-binding.patch
|
||||
patches.drm/clk-sunxi-ng-ccu-add-Display-Engine-3.3-DE33-support.patch
|
||||
patches.drm/drm-sun4i-de33-mixer-add-Display-Engine-3.3-DE33-support.patch
|
||||
patches.drm/drm-sun4i-de33-vi_scaler-add-Display-Engine-3.3-DE33-support.patch
|
||||
patches.drm/drm-sun4i-de33-fmt-add-Display-Engine-3.3-DE33-support.patch
|
||||
patches.drm/drm-sun4i-de33-csc-add-Display-Engine-3.3-DE33-support.patch
|
||||
patches.drm/drm-sun4i-add-sun50i-h616-hdmi-phy-support.patch
|
||||
patches.drm/add-TCON-global-control-reg-for-pad-selection.patch
|
||||
patches.drm/dt-bindings-power-Add-Allwinner-H6-H616-PRCM-PPU.patch
|
||||
patches.drm/pmdomain-sunxi-add-H6-PRCM-PPU-driver.patch
|
||||
patches.drm/dt-bindings-gpu-mali-bifrost-Add-Allwinner-H616-compatible.patch
|
||||
patches.drm/arm64-dts-allwinner-h616-Add-Mali-GPU-node.patch
|
||||
patches.drm/drm-panfrost-Add-PM-runtime-flags.patch
|
||||
patches.drm/drm-panfrost-add-h616-compatible-string.patch
|
||||
patches.drm/drm-panfrost-reorder-pd-clk-rst-sequence.patch
|
||||
|
|
|
|||
|
|
@ -0,0 +1,40 @@
|
|||
################################################################################
|
||||
#
|
||||
# drivers/gpu/drm/sun4i/
|
||||
#
|
||||
################################################################################
|
||||
patches.drm/drm-sun4i-de2-de3-Change-CSC-argument.patch
|
||||
patches.drm/drm-sun4i-de2-de3-Merge-CSC-functions-into-one.patch
|
||||
patches.drm/drm-sun4i-de2-de3-call-csc-setup-also-for-UI-layer.patch
|
||||
patches.drm/drm-sun4i-de2-Initialize-layer-fields-earlier.patch
|
||||
patches.drm/drm-sun4i-de3-Add-YUV-formatter-module.patch
|
||||
patches.drm/drm-sun4i-de3-add-format-enumeration-function-to-engine.patch
|
||||
patches.drm/drm-sun4i-de3-add-formatter-flag-to-mixer-config.patch
|
||||
patches.drm/drm-sun4i-de3-add-YUV-support-to-the-DE3-mixer.patch
|
||||
patches.drm/drm-sun4i-de3-pass-engine-reference-to-ccsc-setup-function.patch
|
||||
patches.drm/drm-sun4i-de3-add-YUV-support-to-the-color-space-correction-mod.patch
|
||||
patches.drm/drm-sun4i-de3-add-YUV-support-to-the-TCON.patch
|
||||
patches.drm/drm-sun4i-support-YUV-formats-in-VI-scaler.patch
|
||||
patches.drm/drm-sun4i-de2-de3-add-mixer-version-enum.patch
|
||||
patches.drm/drm-sun4i-de2-de3-refactor-mixer-initialisation.patch
|
||||
patches.drm/drm-sun4i-vi_scaler-refactor-vi_scaler-enablement.patch
|
||||
patches.drm/drm-sun4i-de2-de3-add-generic-blender-register-reference-functi.patch
|
||||
patches.drm/drm-sun4i-de2-de3-use-generic-register-reference-function-for-l.patch
|
||||
patches.drm/drm-sun4i-de3-Implement-AFBC-support.patch
|
||||
patches.drm/dt-bindings-allwinner-add-H616-DE33-bus-binding.patch
|
||||
patches.drm/dt-bindings-allwinner-add-H616-DE33-clock-binding.patch
|
||||
patches.drm/dt-bindings-allwinner-add-H616-DE33-mixer-binding.patch
|
||||
patches.drm/clk-sunxi-ng-ccu-add-Display-Engine-3.3-DE33-support.patch
|
||||
patches.drm/drm-sun4i-de33-mixer-add-Display-Engine-3.3-DE33-support.patch
|
||||
patches.drm/drm-sun4i-de33-vi_scaler-add-Display-Engine-3.3-DE33-support.patch
|
||||
patches.drm/drm-sun4i-de33-fmt-add-Display-Engine-3.3-DE33-support.patch
|
||||
patches.drm/drm-sun4i-de33-csc-add-Display-Engine-3.3-DE33-support.patch
|
||||
patches.drm/drm-sun4i-add-sun50i-h616-hdmi-phy-support.patch
|
||||
patches.drm/add-TCON-global-control-reg-for-pad-selection.patch
|
||||
patches.drm/dt-bindings-power-Add-Allwinner-H6-H616-PRCM-PPU.patch
|
||||
patches.drm/pmdomain-sunxi-add-H6-PRCM-PPU-driver.patch
|
||||
patches.drm/dt-bindings-gpu-mali-bifrost-Add-Allwinner-H616-compatible.patch
|
||||
patches.drm/arm64-dts-allwinner-h616-Add-Mali-GPU-node.patch
|
||||
patches.drm/drm-panfrost-Add-PM-runtime-flags.patch
|
||||
patches.drm/drm-panfrost-add-h616-compatible-string.patch
|
||||
patches.drm/drm-panfrost-reorder-pd-clk-rst-sequence.patch
|
||||
Loading…
Reference in New Issue