Re: [PATCH v3 6/6] drm/meson: add support for MIPI-DSI transceiver

2022-06-27 Thread Neil Armstrong

Hi,

On 27/06/2022 00:32, Martin Blumenstingl wrote:

Hi Neil,

On Fri, Jun 17, 2022 at 9:27 AM Neil Armstrong  wrote:

+/* [31:16] RW intr_stat/clr. Default 0.
+ * For each bit, read as this interrupt level status,
+ * write 1 to clear.

Do you know if an interrupt line from GIC is routed to the MIPI-DSI
transceiver? If so, we should make it mandatory in patch #1 of this
series (dt-bindings patch), even though it's not in use by the driver
at the moment.


Probably yes, let me check


Re: [PATCH v3 6/6] drm/meson: add support for MIPI-DSI transceiver

2022-06-26 Thread Martin Blumenstingl
Hi Neil,

On Fri, Jun 17, 2022 at 9:27 AM Neil Armstrong  wrote:
> +/* [31:16] RW intr_stat/clr. Default 0.
> + * For each bit, read as this interrupt level status,
> + * write 1 to clear.
Do you know if an interrupt line from GIC is routed to the MIPI-DSI
transceiver? If so, we should make it mandatory in patch #1 of this
series (dt-bindings patch), even though it's not in use by the driver
at the moment.


[PATCH v3 6/6] drm/meson: add support for MIPI-DSI transceiver

2022-06-17 Thread Neil Armstrong
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:
+