The mutex serialises the components of a pipeline on the same frame: it
holds the list of the modules started together and the source of the
start and end of frame signals driving them.

Extend the driver, so far only used by the MT8188 HDMI pipeline, with the
DSI pipeline of the MT8365 and the MT8366: the overlay to the DSI,
through the colour pipeline on the MT8365 and straight out of the rdma on
the MT8366. mtk_disp_mutex_ovl_dsi_enable() calls the SoC one,
mt8365_mutex_ovl_dsi_enable() or mt8366_mutex_ovl_dsi_enable(), and
fails on a mutex without a DSI pipeline.

Two compatibles are added, "mediatek,mt8365-disp-mutex" and
"mediatek,mt8366-disp-mutex". Neither node declares a generic fallback,
so both SoC specific strings have to be listed; they also differ in
the module indices, in the DSI0 module bit the MT8366 needs, and in the
shift of the end-of-frame selector (6 on the MT8365, 7 on the MT8366).

The MT8365 mutex has no clock of its own: as in Linux, a "no_clk" flag of
its driver data says so, and its probe then only maps the registers.

The driver includes <dm/device.h> and <dm/device_compat.h>, for the
dev_err() it now uses, instead of <dm.h>.

Signed-off-by: Julien Stephan <[email protected]>
---
 drivers/video/mediatek/mtk_disp_mutex.c | 133 ++++++++++++++++++++++++++++++--
 drivers/video/mediatek/mtk_disp_mutex.h |  11 +++
 2 files changed, 138 insertions(+), 6 deletions(-)

diff --git a/drivers/video/mediatek/mtk_disp_mutex.c 
b/drivers/video/mediatek/mtk_disp_mutex.c
index 571d4c8b672..af8e7032a01 100644
--- a/drivers/video/mediatek/mtk_disp_mutex.c
+++ b/drivers/video/mediatek/mtk_disp_mutex.c
@@ -6,7 +6,10 @@
  * Author: Julien Stephan <[email protected]>
  */
 
-#include <dm.h>
+#include <dm/device.h>
+#include <dm/device_compat.h>
+#include <dm/read.h>
+#include <errno.h>
 #include <linux/bitops.h>
 
 #include "mtk_disp_comp.h"
@@ -16,8 +19,8 @@
  * Register layout of one mutex instance @id (as in the Linux mtk-mutex
  * driver): the block packs the per-mutex registers 0x20 apart. SOF holds
  * the start/end-of-frame source, MOD0/MOD1 the attached modules 0-31 and
- * 32-63. The offsets are index-based so a future DSI helper can drive a
- * different instance/controller.
+ * 32-63. The offsets are index-based so the HDMI and DSI helpers below can
+ * drive a different instance/controller each.
  */
 #define DISP_MUTEX_EN(id)      (0x20 + 0x20 * (id))
 #define MUTEX_EN                       BIT(0)
@@ -48,6 +51,49 @@
 #define MT8188_MUTEX_MOD_DISP1_DISP_MIXER      30
 #define MT8188_MUTEX_MOD_DISP1_DPI1            38
 
+/* The MT8365 and MT8366 DSI pipelines use instance 0 of the mmsys mutex */
+#define MUTEX_DSI_ID           0
+
+/* the MT8365 shifts the end-of-frame selector by 6 instead of 7 */
+#define MT8365_MUTEX_SOF_DSI0          1
+#define MT8365_MUTEX_EOF_DSI0          (MT8365_MUTEX_SOF_DSI0 << 6)
+
+#define MT8365_MUTEX_MOD_DISP_OVL0     7
+#define MT8365_MUTEX_MOD_DISP_RDMA0    9
+#define MT8365_MUTEX_MOD_DISP_COLOR0   12
+#define MT8365_MUTEX_MOD_DISP_CCORR    13
+#define MT8365_MUTEX_MOD_DISP_AAL      14
+#define MT8365_MUTEX_MOD_DISP_GAMMA    15
+#define MT8365_MUTEX_MOD_DISP_DITHER   16
+
+/* the MT8366 drives the DSI straight out of the rdma, without the PQ blocks */
+#define MT8366_MUTEX_SOF_DSI0          1
+#define MT8366_MUTEX_EOF_DSI0          (MT8366_MUTEX_SOF_DSI0 << 7)
+
+#define MT8366_MUTEX_MOD_DISP_OVL0     0
+#define MT8366_MUTEX_MOD_DISP_RDMA0    4
+#define MT8366_MUTEX_MOD_DISP_DSI0     13
+
+/**
+ * struct mtk_disp_mutex_data - per-SoC mutex data
+ * @ovl_dsi_enable: set up the mutex of the OVL -> DSI pipeline
+ * @no_clk: the mutex has no clock of its own
+ */
+struct mtk_disp_mutex_data {
+       void (*ovl_dsi_enable)(struct udevice *dev);
+       bool no_clk;
+};
+
+/**
+ * struct mtk_disp_mutex_priv - private data of a mutex
+ * @comp: common component state, must be the first member
+ * @data: per-SoC data, NULL on the SoCs without a DSI pipeline
+ */
+struct mtk_disp_mutex_priv {
+       struct mtk_disp_comp_priv comp;
+       const struct mtk_disp_mutex_data *data;
+};
+
 void mt8188_mutex_config_hdmi(struct udevice *dev)
 {
        mtk_disp_comp_write(dev, DISP_MUTEX_SOF(MUTEX_HDMI_ID),
@@ -65,8 +111,83 @@ void mt8188_mutex_config_hdmi(struct udevice *dev)
        mtk_disp_comp_write(dev, DISP_MUTEX_EN(MUTEX_HDMI_ID), MUTEX_EN);
 }
 
+static void mt8365_mutex_ovl_dsi_enable(struct udevice *dev)
+{
+       mtk_disp_comp_write(dev, DISP_MUTEX_MOD0(MUTEX_DSI_ID),
+                           MUTEX_MOD_BIT(MT8365_MUTEX_MOD_DISP_OVL0) |
+                           MUTEX_MOD_BIT(MT8365_MUTEX_MOD_DISP_RDMA0) |
+                           MUTEX_MOD_BIT(MT8365_MUTEX_MOD_DISP_COLOR0) |
+                           MUTEX_MOD_BIT(MT8365_MUTEX_MOD_DISP_CCORR) |
+                           MUTEX_MOD_BIT(MT8365_MUTEX_MOD_DISP_AAL) |
+                           MUTEX_MOD_BIT(MT8365_MUTEX_MOD_DISP_GAMMA) |
+                           MUTEX_MOD_BIT(MT8365_MUTEX_MOD_DISP_DITHER));
+       mtk_disp_comp_write(dev, DISP_MUTEX_SOF(MUTEX_DSI_ID),
+                           MT8365_MUTEX_EOF_DSI0 | MT8365_MUTEX_SOF_DSI0);
+       mtk_disp_comp_write(dev, DISP_MUTEX_EN(MUTEX_DSI_ID), MUTEX_EN);
+}
+
+static void mt8366_mutex_ovl_dsi_enable(struct udevice *dev)
+{
+       mtk_disp_comp_write(dev, DISP_MUTEX_MOD0(MUTEX_DSI_ID),
+                           MUTEX_MOD_BIT(MT8366_MUTEX_MOD_DISP_OVL0) |
+                           MUTEX_MOD_BIT(MT8366_MUTEX_MOD_DISP_RDMA0) |
+                           MUTEX_MOD_BIT(MT8366_MUTEX_MOD_DISP_DSI0));
+       mtk_disp_comp_write(dev, DISP_MUTEX_SOF(MUTEX_DSI_ID),
+                           MT8366_MUTEX_EOF_DSI0 | MT8366_MUTEX_SOF_DSI0);
+       mtk_disp_comp_write(dev, DISP_MUTEX_EN(MUTEX_DSI_ID), MUTEX_EN);
+}
+
+static const struct mtk_disp_mutex_data mt8365_mutex_data = {
+       .ovl_dsi_enable = mt8365_mutex_ovl_dsi_enable,
+       .no_clk = true,
+};
+
+static const struct mtk_disp_mutex_data mt8366_mutex_data = {
+       .ovl_dsi_enable = mt8366_mutex_ovl_dsi_enable,
+};
+
+int mtk_disp_mutex_ovl_dsi_enable(struct udevice *dev)
+{
+       struct mtk_disp_mutex_priv *mutex = dev_get_priv(dev);
+
+       if (!mutex->data) {
+               dev_err(dev, "no DSI pipeline on this mutex\n");
+               return -EOPNOTSUPP;
+       }
+
+       mutex->data->ovl_dsi_enable(dev);
+
+       return 0;
+}
+
+static int mtk_disp_mutex_probe(struct udevice *dev)
+{
+       struct mtk_disp_mutex_priv *mutex = dev_get_priv(dev);
+
+       /* the HDMI pipeline needs no per-SoC data */
+       mutex->data = (const struct mtk_disp_mutex_data 
*)dev_get_driver_data(dev);
+
+       if (mutex->data && mutex->data->no_clk) {
+               mutex->comp.base = dev_remap_addr(dev);
+
+               return mutex->comp.base ? 0 : -EINVAL;
+       }
+
+       return mtk_disp_comp_probe(dev);
+}
+
 static const struct udevice_id mtk_disp_mutex_ids[] = {
-       { .compatible = "mediatek,mt8188-disp-mutex" },
+       {
+               .compatible = "mediatek,mt8188-disp-mutex",
+       },
+       {
+               .compatible = "mediatek,mt8365-disp-mutex",
+               .data = (ulong)&mt8365_mutex_data,
+       },
+       {
+               .compatible = "mediatek,mt8366-disp-mutex",
+               .data = (ulong)&mt8366_mutex_data,
+       },
        { }
 };
 
@@ -74,6 +195,6 @@ U_BOOT_DRIVER(mtk_disp_mutex) = {
        .name      = "mtk_disp_mutex",
        .id        = UCLASS_MISC,
        .of_match  = mtk_disp_mutex_ids,
-       .probe     = mtk_disp_comp_probe,
-       .priv_auto = sizeof(struct mtk_disp_comp_priv),
+       .probe     = mtk_disp_mutex_probe,
+       .priv_auto = sizeof(struct mtk_disp_mutex_priv),
 };
diff --git a/drivers/video/mediatek/mtk_disp_mutex.h 
b/drivers/video/mediatek/mtk_disp_mutex.h
index 6b2c8863a20..3b97c7020a2 100644
--- a/drivers/video/mediatek/mtk_disp_mutex.h
+++ b/drivers/video/mediatek/mtk_disp_mutex.h
@@ -18,4 +18,15 @@ struct udevice;
  */
 void mt8188_mutex_config_hdmi(struct udevice *dev);
 
+/**
+ * mtk_disp_mutex_ovl_dsi_enable() - set up the mutex of the DSI pipeline
+ * @dev: mmsys mutex device
+ *
+ * Put all the components of the OVL -> DSI pipeline under one mutex
+ * instance, and start and end their frames on the DSI ones.
+ *
+ * Return: 0 on success, -EOPNOTSUPP if the mutex has no DSI pipeline
+ */
+int mtk_disp_mutex_ovl_dsi_enable(struct udevice *dev);
+
 #endif /* _MTK_DISP_MUTEX_H */

-- 
2.55.0

Reply via email to