summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/imx/dcss/dcss-blkctl.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/imx/dcss/dcss-blkctl.c')
-rw-r--r--drivers/gpu/drm/imx/dcss/dcss-blkctl.c75
1 files changed, 75 insertions, 0 deletions
diff --git a/drivers/gpu/drm/imx/dcss/dcss-blkctl.c b/drivers/gpu/drm/imx/dcss/dcss-blkctl.c
new file mode 100644
index 000000000000..ee7ffa18dd6d
--- /dev/null
+++ b/drivers/gpu/drm/imx/dcss/dcss-blkctl.c
@@ -0,0 +1,75 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright 2019 NXP.
+ */
+
+#include <linux/device.h>
+#include <linux/of.h>
+
+#include "dcss-dev.h"
+
+#define DCSS_BLKCTL_RESET_CTRL 0x00
+#define B_CLK_RESETN BIT(0)
+#define APB_CLK_RESETN BIT(1)
+#define P_CLK_RESETN BIT(2)
+#define RTR_CLK_RESETN BIT(3)
+#define DCSS_BLKCTL_CONTROL0 0x10
+#define HDMI_MIPI_CLK_SEL BIT(0)
+#define DISPMIX_REFCLK_SEL_POS 4
+#define DISPMIX_REFCLK_SEL_MASK GENMASK(5, 4)
+#define DISPMIX_PIXCLK_SEL BIT(8)
+#define HDMI_SRC_SECURE_EN BIT(16)
+
+struct dcss_blkctl {
+ struct device *dev;
+ void __iomem *base_reg;
+
+ bool hdmi_output;
+};
+
+void dcss_blkctl_cfg(struct dcss_blkctl *blkctl)
+{
+ if (blkctl->hdmi_output)
+ dcss_writel(0, blkctl->base_reg + DCSS_BLKCTL_CONTROL0);
+ else
+ dcss_writel(DISPMIX_PIXCLK_SEL,
+ blkctl->base_reg + DCSS_BLKCTL_CONTROL0);
+
+ dcss_set(B_CLK_RESETN | APB_CLK_RESETN | P_CLK_RESETN | RTR_CLK_RESETN,
+ blkctl->base_reg + DCSS_BLKCTL_RESET_CTRL);
+}
+
+int dcss_blkctl_init(struct dcss_dev *dcss, unsigned long blkctl_base)
+{
+ struct dcss_blkctl *blkctl;
+
+ blkctl = devm_kzalloc(dcss->dev, sizeof(*blkctl), GFP_KERNEL);
+ if (!blkctl)
+ return -ENOMEM;
+
+ blkctl->base_reg = devm_ioremap(dcss->dev, blkctl_base, SZ_4K);
+ if (!blkctl->base_reg) {
+ dev_err(dcss->dev, "unable to remap BLK CTRL base\n");
+ devm_kfree(dcss->dev, blkctl);
+ return -ENOMEM;
+ }
+
+ dcss->blkctl = blkctl;
+ blkctl->dev = dcss->dev;
+ blkctl->hdmi_output = dcss->hdmi_output;
+
+ dcss_blkctl_cfg(blkctl);
+
+ return 0;
+}
+
+void dcss_blkctl_exit(struct dcss_blkctl *blkctl)
+{
+ dcss_clr(P_CLK_RESETN | RTR_CLK_RESETN,
+ blkctl->base_reg + DCSS_BLKCTL_RESET_CTRL);
+
+ if (blkctl->base_reg)
+ devm_iounmap(blkctl->dev, blkctl->base_reg);
+
+ devm_kfree(blkctl->dev, blkctl);
+}