The Amlogic G12A/G12B/SM1 SoCs embeds a Synopsys DW-MIPI-DSI transceiver (ver
1.21a),
with a custom glue managing the IP resets, clock and data input similar to the
DW-HDMI
Glue on other Amlogic SoCs.
This adds support for the Glue managing the transceiver, mimicing the init flow
provided
by Amlogic to setup the ENCL encoder, the glue, the transceiver, the digital
D-PHY and the
Analog PHY in the proper way.
An optional "MEAS" clock can be enabled to measure the delay between each vsync
feeding the
DW-MIPI-DSI transceiver.
Signed-off-by: Neil Armstrong
Reviewed-by: Jagan Teki
---
drivers/gpu/drm/meson/Kconfig | 7 +
drivers/gpu/drm/meson/Makefile| 1 +
drivers/gpu/drm/meson/meson_dw_mipi_dsi.c | 358 ++
drivers/gpu/drm/meson/meson_dw_mipi_dsi.h | 160 ++
4 files changed, 526 insertions(+)
create mode 100644 drivers/gpu/drm/meson/meson_dw_mipi_dsi.c
create mode 100644 drivers/gpu/drm/meson/meson_dw_mipi_dsi.h
diff --git a/drivers/gpu/drm/meson/Kconfig b/drivers/gpu/drm/meson/Kconfig
index 6c70fc3214af..71a1364b51e1 100644
--- a/drivers/gpu/drm/meson/Kconfig
+++ b/drivers/gpu/drm/meson/Kconfig
@@ -17,3 +17,10 @@ config DRM_MESON_DW_HDMI
default y if DRM_MESON
select DRM_DW_HDMI
imply DRM_DW_HDMI_I2S_AUDIO
+
+config DRM_MESON_DW_MIPI_DSI
+ tristate "MIPI DSI Synopsys Controller support for Amlogic Meson
Display"
+ depends on DRM_MESON
+ default y if DRM_MESON
+ select DRM_DW_MIPI_DSI
+ select GENERIC_PHY_MIPI_DPHY
diff --git a/drivers/gpu/drm/meson/Makefile b/drivers/gpu/drm/meson/Makefile
index 833e18c20603..43071bdbd4b9 100644
--- a/drivers/gpu/drm/meson/Makefile
+++ b/drivers/gpu/drm/meson/Makefile
@@ -6,3 +6,4 @@ meson-drm-y += meson_encoder_hdmi.o meson_encoder_dsi.o
obj-$(CONFIG_DRM_MESON) += meson-drm.o
obj-$(CONFIG_DRM_MESON_DW_HDMI) += meson_dw_hdmi.o
+obj-$(CONFIG_DRM_MESON_DW_MIPI_DSI) += meson_dw_mipi_dsi.o
diff --git a/drivers/gpu/drm/meson/meson_dw_mipi_dsi.c
b/drivers/gpu/drm/meson/meson_dw_mipi_dsi.c
new file mode 100644
index ..52c8578914b6
--- /dev/null
+++ b/drivers/gpu/drm/meson/meson_dw_mipi_dsi.c
@@ -0,0 +1,358 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2021 BayLibre, SAS
+ * Author: Neil Armstrong
+ * Copyright (C) 2015 Amlogic, Inc. All rights reserved.
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+
+#include
+#include
+
+#include
+#include
+#include
+#include
+
+#include "meson_drv.h"
+#include "meson_dw_mipi_dsi.h"
+#include "meson_registers.h"
+#include "meson_venc.h"
+
+#define DRIVER_NAME "meson-dw-mipi-dsi"
+#define DRIVER_DESC "Amlogic Meson MIPI-DSI DRM driver"
+
+struct meson_dw_mipi_dsi {
+ struct meson_drm *priv;
+ struct device *dev;
+ void __iomem *base;
+ struct phy *phy;
+ union phy_configure_opts phy_opts;
+ struct dw_mipi_dsi *dmd;
+ struct dw_mipi_dsi_plat_data pdata;
+ struct mipi_dsi_device *dsi_device;
+ const struct drm_display_mode *mode;
+ struct clk *px_clk;
+};
+
+#define encoder_to_meson_dw_mipi_dsi(x) \
+ container_of(x, struct meson_dw_mipi_dsi, encoder)
+
+static void meson_dw_mipi_dsi_hw_init(struct meson_dw_mipi_dsi *mipi_dsi)
+{
+ /* Software reset */
+ writel_bits_relaxed(MIPI_DSI_TOP_SW_RESET_DWC |
MIPI_DSI_TOP_SW_RESET_INTR |
+ MIPI_DSI_TOP_SW_RESET_DPI |
MIPI_DSI_TOP_SW_RESET_TIMING,
+ MIPI_DSI_TOP_SW_RESET_DWC |
MIPI_DSI_TOP_SW_RESET_INTR |
+ MIPI_DSI_TOP_SW_RESET_DPI |
MIPI_DSI_TOP_SW_RESET_TIMING,
+ mipi_dsi->base + MIPI_DSI_TOP_SW_RESET);
+ writel_bits_relaxed(MIPI_DSI_TOP_SW_RESET_DWC |
MIPI_DSI_TOP_SW_RESET_INTR |
+ MIPI_DSI_TOP_SW_RESET_DPI |
MIPI_DSI_TOP_SW_RESET_TIMING,
+ 0, mipi_dsi->base + MIPI_DSI_TOP_SW_RESET);
+
+ /* Enable clocks */
+ writel_bits_relaxed(MIPI_DSI_TOP_CLK_SYSCLK_EN |
MIPI_DSI_TOP_CLK_PIXCLK_EN,
+ MIPI_DSI_TOP_CLK_SYSCLK_EN |
MIPI_DSI_TOP_CLK_PIXCLK_EN,
+ mipi_dsi->base + MIPI_DSI_TOP_CLK_CNTL);
+
+ /* Take memory out of power down */
+ writel_relaxed(0, mipi_dsi->base + MIPI_DSI_TOP_MEM_PD);
+}
+
+static int dw_mipi_dsi_phy_init(void *priv_data)
+{
+ struct meson_dw_mipi_dsi *mipi_dsi = priv_data;
+ unsigned int dpi_data_format, venc_data_width;
+ int ret;
+
+ ret = clk_set_rate(mipi_dsi->px_clk,
mipi_dsi->phy_opts.mipi_dphy.hs_clk_rate);
+ if (ret) {
+ pr_err("Failed to set DSI PLL rate %lu\n",
+ mipi_dsi->phy_opts.mipi_dphy.hs_clk_rate);
+
+ return ret;
+ }
+
+ switch (mipi_dsi->dsi_device->format) {
+ case MIPI_DSI_FMT_RGB888:
+