linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v4 0/9 drm: rcar-du: Add Color Management Module (CMM)
@ 2019-09-06 13:54 Jacopo Mondi
  2019-09-06 13:54 ` [PATCH v4 1/9] dt-bindings: display: renesas,cmm: Add R-Car CMM documentation Jacopo Mondi
                   ` (8 more replies)
  0 siblings, 9 replies; 38+ messages in thread
From: Jacopo Mondi @ 2019-09-06 13:54 UTC (permalink / raw)
  To: laurent.pinchart, kieran.bingham+renesas, geert, horms,
	uli+renesas, VenkataRajesh.Kalakodima
  Cc: Jacopo Mondi, airlied, daniel, koji.matsuoka.xm, muroya,
	Harsha.ManjulaMallikarjun, linux-renesas-soc, dri-devel,
	linux-kernel

[ Ugh, sorry for the double sending, but I forgot --cc-cover to git-send
  email and the series has not been delivered to the mailing lists.
  Sorry about that. ]

Hello, new iteration of CMM support, with quite a few changes compared to
v3:

References:
A reference to the v1 cover letter, with some background on the CMM is
available here:
https://lkml.org/lkml/2019/6/6/583
v2:
https://lore.kernel.org/linux-renesas-soc/20190706140746.29132-10-jacopo+renesas@jmondi.org/
v3:
https://lore.kernel.org/linux-renesas-soc/20190825135154.11488-1-jacopo+renesas@jmondi.org/

Change log:

*Bindings/DT:
- Rebased on renesas-devel-2019-09-03-v5.3-rc7
- Bindings converted to yaml: thanks Laurent for help
- s/'cmms'/'renesas,cmms'/ in DU bindings as suggested by Rob
- s/cmm-<soctype>/<soctype>-cmm/ as suggested by Geert
- squashed CMM addition for Gen3 SoCs in a single path at the end of
  the series

*CMM/DU:
- Only accept fully populated LUT tables, remove the 'size' from the CMM
  configuration structure as suggested by Laurent
- Simplify CMM configuration logic: only rely on color_mgmt_changed flag and
  unconditionally provide a populated LUT table to the cmm_setup() function
- Protect against probing order inversion (DU is operation while CMM still has
  not been probed) by adding rcar_cmm_init() operation as it is done for VSP as
  suggested by Laurent
- Add CMM function stubs to fix compilation erros when CONFIG_DRM_RCAR_CMM is
  not selected
- Minors in the CMM driver as suggested by Laurent
  - Remove per-soc strings
  - Make comments style consistent (not using /** anywhere in the .c file,
    unify comment style)
  - s/rcar_cmm_load()/rcar_cmm_write()/
  - Squash cmm configuration and suspend/resume support in rcar_du_kms.c

Testing:
I have tested by injecting a color inversion LUT table at test program
initialization:
https://jmondi.org/cgit/kmsxx/commit/?h=gamma_lut&id=3c6af4db165e5b3dc8996f0a288746c35dbb1cb9
And by changing the CMM content to switch between a color inversion table
and a linear table every 50 frames:
https://jmondi.org/cgit/kmsxx/commit/?h=gamma_lut&id=fe178a43861da7c8e79618e2a13fa0f19dbcd03d

Pretty happy with the result, which seems to be consistent across system
suspend/resume.

Testing with real world use cases might be beneficial. Rajesh are you still
interested in giving this series a spin?

Thanks
  j

Jacopo Mondi (9):
  dt-bindings: display: renesas,cmm: Add R-Car CMM documentation
  dt-bindings: display, renesas,du: Document cmms property
  drm: rcar-du: Add support for CMM
  drm: rcar-du: Claim CMM support for Gen3 SoCs
  drm: rcar-du: kms: Initialize CMM instances
  drm: rcar-du: crtc: Enable and disable CMMs
  drm: rcar-du: crtc: Register GAMMA_LUT properties
  drm: rcar-du: kms: Update CMM in atomic commit tail
  arm64: dts: renesas: Add CMM units to Gen3 SoCs

 .../bindings/display/renesas,cmm.yaml         |  64 +++++
 .../bindings/display/renesas,du.txt           |   5 +
 arch/arm64/boot/dts/renesas/r8a7795.dtsi      |  40 ++-
 arch/arm64/boot/dts/renesas/r8a7796.dtsi      |  28 ++
 arch/arm64/boot/dts/renesas/r8a77965.dtsi     |  28 ++
 arch/arm64/boot/dts/renesas/r8a77990.dtsi     |  22 +-
 arch/arm64/boot/dts/renesas/r8a77995.dtsi     |  22 +-
 drivers/gpu/drm/rcar-du/Kconfig               |   7 +
 drivers/gpu/drm/rcar-du/Makefile              |   1 +
 drivers/gpu/drm/rcar-du/rcar_cmm.c            | 251 ++++++++++++++++++
 drivers/gpu/drm/rcar-du/rcar_cmm.h            |  61 +++++
 drivers/gpu/drm/rcar-du/rcar_du_crtc.c        |  17 ++
 drivers/gpu/drm/rcar-du/rcar_du_crtc.h        |   2 +
 drivers/gpu/drm/rcar-du/rcar_du_drv.c         |  32 ++-
 drivers/gpu/drm/rcar-du/rcar_du_drv.h         |   3 +
 drivers/gpu/drm/rcar-du/rcar_du_group.c       |   8 +
 drivers/gpu/drm/rcar-du/rcar_du_group.h       |   2 +
 drivers/gpu/drm/rcar-du/rcar_du_kms.c         | 106 ++++++++
 drivers/gpu/drm/rcar-du/rcar_du_regs.h        |   5 +
 19 files changed, 697 insertions(+), 7 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/display/renesas,cmm.yaml
 create mode 100644 drivers/gpu/drm/rcar-du/rcar_cmm.c
 create mode 100644 drivers/gpu/drm/rcar-du/rcar_cmm.h

--
2.23.0


^ permalink raw reply	[flat|nested] 38+ messages in thread

* [PATCH v4 1/9] dt-bindings: display: renesas,cmm: Add R-Car CMM documentation
  2019-09-06 13:54 [PATCH v4 0/9 drm: rcar-du: Add Color Management Module (CMM) Jacopo Mondi
@ 2019-09-06 13:54 ` Jacopo Mondi
  2019-09-11 19:04   ` Kieran Bingham
                     ` (2 more replies)
  2019-09-06 13:54 ` [PATCH v4 2/9] dt-bindings: display, renesas,du: Document cmms property Jacopo Mondi
                   ` (7 subsequent siblings)
  8 siblings, 3 replies; 38+ messages in thread
From: Jacopo Mondi @ 2019-09-06 13:54 UTC (permalink / raw)
  To: laurent.pinchart, kieran.bingham+renesas, geert, horms,
	uli+renesas, VenkataRajesh.Kalakodima
  Cc: Jacopo Mondi, airlied, daniel, koji.matsuoka.xm, muroya,
	Harsha.ManjulaMallikarjun, linux-renesas-soc, dri-devel,
	linux-kernel, devicetree, robh+dt, mark.rutland

Add device tree bindings documentation for the Renesas R-Car Display
Unit Color Management Module.

CMM is the image enhancement module available on each R-Car DU video
channel on R-Car Gen2 and Gen3 SoCs (V3H and V3M excluded).

Signed-off-by: Jacopo Mondi <jacopo+renesas@jmondi.org>
---
 .../bindings/display/renesas,cmm.yaml         | 64 +++++++++++++++++++
 1 file changed, 64 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/display/renesas,cmm.yaml

diff --git a/Documentation/devicetree/bindings/display/renesas,cmm.yaml b/Documentation/devicetree/bindings/display/renesas,cmm.yaml
new file mode 100644
index 000000000000..9e5922689cd7
--- /dev/null
+++ b/Documentation/devicetree/bindings/display/renesas,cmm.yaml
@@ -0,0 +1,64 @@
+# SPDX-License-Identifier: GPL-2.0
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/display/renesas,cmm.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Renesas R-Car Color Management Module (CMM)
+
+maintainers:
+  - Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+  - Kieran Bingham <kieran.bingham+renesas@ideasonboard.com>
+  - Jacopo Mondi <jacopo+renesas@jmondi.org>
+
+description: |+
+  Renesas R-Car color management module connected to R-Car DU video channels.
+  It provides image enhancement functions such as 1-D look-up tables (LUT),
+  3-D look-up tables (CMU), 1D-histogram generation (HGO), and color
+  space conversion (CSC).
+
+properties:
+  compatible:
+    items:
+      - enum:
+        - renesas,r8a7795-cmm
+        - renesas,r8a7796-cmm
+        - renesas,r8a77965-cmm
+        - renesas,r8a77990-cmm
+        - renesas,r8a77995-cmm
+      - enum:
+        - renesas,rcar-gen3-cmm
+        - renesas,rcar-gen2-cmm
+  reg:
+    maxItems: 1
+
+  clocks:
+    maxItems: 1
+
+  resets:
+    maxItems: 1
+
+  power-domains:
+    maxItems: 1
+
+required:
+  - compatible
+  - reg
+  - clocks
+  - resets
+  - power-domains
+
+additionalProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/clock/r8a7796-cpg-mssr.h>
+    #include <dt-bindings/power/r8a7796-sysc.h>
+
+    cmm0: cmm@fea40000 {
+         compatible = "renesas,r8a7796-cmm";
+         reg = <0 0xfea40000 0 0x1000>;
+         power-domains = <&sysc R8A7796_PD_ALWAYS_ON>;
+         clocks = <&cpg CPG_MOD 711>;
+         resets = <&cpg 711>;
+    };
--
2.23.0


^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [PATCH v4 2/9] dt-bindings: display, renesas,du: Document cmms property
  2019-09-06 13:54 [PATCH v4 0/9 drm: rcar-du: Add Color Management Module (CMM) Jacopo Mondi
  2019-09-06 13:54 ` [PATCH v4 1/9] dt-bindings: display: renesas,cmm: Add R-Car CMM documentation Jacopo Mondi
@ 2019-09-06 13:54 ` Jacopo Mondi
  2019-09-11 16:06   ` Kieran Bingham
  2019-09-06 13:54 ` [PATCH v4 3/9] drm: rcar-du: Add support for CMM Jacopo Mondi
                   ` (6 subsequent siblings)
  8 siblings, 1 reply; 38+ messages in thread
From: Jacopo Mondi @ 2019-09-06 13:54 UTC (permalink / raw)
  To: laurent.pinchart, kieran.bingham+renesas, geert, horms,
	uli+renesas, VenkataRajesh.Kalakodima
  Cc: Jacopo Mondi, airlied, daniel, koji.matsuoka.xm, muroya,
	Harsha.ManjulaMallikarjun, linux-renesas-soc, dri-devel,
	linux-kernel, devicetree, robh+dt, mark.rutland

Document the newly added 'cmms' property which accepts a list of phandle
and channel index pairs that point to the CMM units available for each
Display Unit output video channel.

Signed-off-by: Jacopo Mondi <jacopo+renesas@jmondi.org>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 Documentation/devicetree/bindings/display/renesas,du.txt | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/Documentation/devicetree/bindings/display/renesas,du.txt b/Documentation/devicetree/bindings/display/renesas,du.txt
index c97dfacad281..1773b0a2f54f 100644
--- a/Documentation/devicetree/bindings/display/renesas,du.txt
+++ b/Documentation/devicetree/bindings/display/renesas,du.txt
@@ -45,6 +45,10 @@ Required Properties:
     instance that serves the DU channel, and the channel index identifies the
     LIF instance in that VSP.

+  - renesas,cmms: A list of phandles to the CMM instances present in the SoC,
+    one for each available DU channel. The property shall not be specified for
+    SoCs that do not provide any CMM (such as V3M and V3H).
+
 Required nodes:

 The connections to the DU output video ports are modeled using the OF graph
@@ -91,6 +95,7 @@ Example: R8A7795 (R-Car H3) ES2.0 DU
 			 <&cpg CPG_MOD 721>;
 		clock-names = "du.0", "du.1", "du.2", "du.3";
 		vsps = <&vspd0 0>, <&vspd1 0>, <&vspd2 0>, <&vspd0 1>;
+		renesas,cmms = <&cmm0 &cmm1 &cmm2 &cmm3>;

 		ports {
 			#address-cells = <1>;
--
2.23.0


^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [PATCH v4 3/9] drm: rcar-du: Add support for CMM
  2019-09-06 13:54 [PATCH v4 0/9 drm: rcar-du: Add Color Management Module (CMM) Jacopo Mondi
  2019-09-06 13:54 ` [PATCH v4 1/9] dt-bindings: display: renesas,cmm: Add R-Car CMM documentation Jacopo Mondi
  2019-09-06 13:54 ` [PATCH v4 2/9] dt-bindings: display, renesas,du: Document cmms property Jacopo Mondi
@ 2019-09-06 13:54 ` Jacopo Mondi
  2019-09-11 15:54   ` Kieran Bingham
  2019-09-18 22:55   ` Laurent Pinchart
  2019-09-06 13:54 ` [PATCH v4 4/9] drm: rcar-du: Claim CMM support for Gen3 SoCs Jacopo Mondi
                   ` (5 subsequent siblings)
  8 siblings, 2 replies; 38+ messages in thread
From: Jacopo Mondi @ 2019-09-06 13:54 UTC (permalink / raw)
  To: laurent.pinchart, kieran.bingham+renesas, geert, horms,
	uli+renesas, VenkataRajesh.Kalakodima
  Cc: Jacopo Mondi, airlied, daniel, koji.matsuoka.xm, muroya,
	Harsha.ManjulaMallikarjun, linux-renesas-soc, dri-devel,
	linux-kernel

Add a driver for the R-Car Display Unit Color Correction Module.

In most of Gen3 SoCs, each DU output channel is provided with a CMM unit
to perform image enhancement and color correction.

Add support for CMM through a driver that supports configuration of
the 1-dimensional LUT table. More advanced CMM feature will be
implemented on top of this basic one.

Signed-off-by: Jacopo Mondi <jacopo+renesas@jmondi.org>
---
 drivers/gpu/drm/rcar-du/Kconfig    |   7 +
 drivers/gpu/drm/rcar-du/Makefile   |   1 +
 drivers/gpu/drm/rcar-du/rcar_cmm.c | 251 +++++++++++++++++++++++++++++
 drivers/gpu/drm/rcar-du/rcar_cmm.h |  61 +++++++
 4 files changed, 320 insertions(+)
 create mode 100644 drivers/gpu/drm/rcar-du/rcar_cmm.c
 create mode 100644 drivers/gpu/drm/rcar-du/rcar_cmm.h

diff --git a/drivers/gpu/drm/rcar-du/Kconfig b/drivers/gpu/drm/rcar-du/Kconfig
index 1529849e217e..539d232790d1 100644
--- a/drivers/gpu/drm/rcar-du/Kconfig
+++ b/drivers/gpu/drm/rcar-du/Kconfig
@@ -13,6 +13,13 @@ config DRM_RCAR_DU
 	  Choose this option if you have an R-Car chipset.
 	  If M is selected the module will be called rcar-du-drm.
 
+config DRM_RCAR_CMM
+	bool "R-Car DU Color Management Module (CMM) Support"
+	depends on DRM && OF
+	depends on DRM_RCAR_DU
+	help
+	  Enable support for R-Car Color Management Module (CMM).
+
 config DRM_RCAR_DW_HDMI
 	tristate "R-Car DU Gen3 HDMI Encoder Support"
 	depends on DRM && OF
diff --git a/drivers/gpu/drm/rcar-du/Makefile b/drivers/gpu/drm/rcar-du/Makefile
index 6c2ed9c46467..4d1187ccc3e5 100644
--- a/drivers/gpu/drm/rcar-du/Makefile
+++ b/drivers/gpu/drm/rcar-du/Makefile
@@ -15,6 +15,7 @@ rcar-du-drm-$(CONFIG_DRM_RCAR_LVDS)	+= rcar_du_of.o \
 rcar-du-drm-$(CONFIG_DRM_RCAR_VSP)	+= rcar_du_vsp.o
 rcar-du-drm-$(CONFIG_DRM_RCAR_WRITEBACK) += rcar_du_writeback.o
 
+obj-$(CONFIG_DRM_RCAR_CMM)		+= rcar_cmm.o
 obj-$(CONFIG_DRM_RCAR_DU)		+= rcar-du-drm.o
 obj-$(CONFIG_DRM_RCAR_DW_HDMI)		+= rcar_dw_hdmi.o
 obj-$(CONFIG_DRM_RCAR_LVDS)		+= rcar_lvds.o
diff --git a/drivers/gpu/drm/rcar-du/rcar_cmm.c b/drivers/gpu/drm/rcar-du/rcar_cmm.c
new file mode 100644
index 000000000000..3cacdc4474c7
--- /dev/null
+++ b/drivers/gpu/drm/rcar-du/rcar_cmm.c
@@ -0,0 +1,251 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * rcar_cmm.c -- R-Car Display Unit Color Management Module
+ *
+ * Copyright (C) 2019 Jacopo Mondi <jacopo+renesas@jmondi.org>
+ */
+
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+
+#include <drm/drm_color_mgmt.h>
+
+#include "rcar_cmm.h"
+
+#define CM2_LUT_CTRL		0x0000
+#define CM2_LUT_CTRL_LUT_EN	BIT(0)
+#define CM2_LUT_TBL_BASE	0x0600
+#define CM2_LUT_TBL(__i)	(CM2_LUT_TBL_BASE + (__i) * 4)
+
+struct rcar_cmm {
+	void __iomem *base;
+	bool enabled;
+
+	/*
+	 * @lut:		1D-LUT status
+	 * @lut.enabled:	1D-LUT enabled flag
+	 * @lut.table:		Table of 1D-LUT entries scaled to hardware
+	 *			precision (8-bits per color component)
+	 */
+	struct {
+		bool enabled;
+		u32 table[CM2_LUT_SIZE];
+	} lut;
+};
+
+static inline int rcar_cmm_read(struct rcar_cmm *rcmm, u32 reg)
+{
+	return ioread32(rcmm->base + reg);
+}
+
+static inline void rcar_cmm_write(struct rcar_cmm *rcmm, u32 reg, u32 data)
+{
+	iowrite32(data, rcmm->base + reg);
+}
+
+/*
+ * rcar_cmm_lut_extract() - Scale down to hardware precision the DRM LUT table
+ *			    entries and store them.
+ * @rcmm: Pointer to the CMM device
+ * @drm_lut: Pointer to the DRM LUT table
+ */
+static void rcar_cmm_lut_extract(struct rcar_cmm *rcmm,
+				 const struct drm_color_lut *drm_lut)
+{
+	unsigned int i;
+
+	for (i = 0; i < CM2_LUT_SIZE; ++i) {
+		const struct drm_color_lut *lut = &drm_lut[i];
+
+		rcmm->lut.table[i] = drm_color_lut_extract(lut->red, 8) << 16
+				   | drm_color_lut_extract(lut->green, 8) << 8
+				   | drm_color_lut_extract(lut->blue, 8);
+	}
+}
+
+/*
+ * rcar_cmm_lut_write() - Write to hardware the LUT table entries from the
+ *			  local table.
+ * @rcmm: Pointer to the CMM device
+ */
+static void rcar_cmm_lut_write(struct rcar_cmm *rcmm)
+{
+	unsigned int i;
+
+	for (i = 0; i < CM2_LUT_SIZE; ++i)
+		rcar_cmm_write(rcmm, CM2_LUT_TBL(i), rcmm->lut.table[i]);
+}
+
+/*
+ * rcar_cmm_setup() - Configure the CMM unit.
+ * @pdev: The platform device associated with the CMM instance
+ * @config: The CRTC-provided configuration.
+ *
+ * Configure the CMM unit with the CRTC-provided configuration.
+ * Currently enabling, disabling and programming of the 1-D LUT unit is
+ * supported.
+ */
+int rcar_cmm_setup(struct platform_device *pdev,
+		   const struct rcar_cmm_config *config)
+{
+	struct rcar_cmm *rcmm = platform_get_drvdata(pdev);
+
+	/*
+	 * As rcar_cmm_setup() is called by atomic commit tail helper, it might
+	 * be called when the CMM is disabled. As we can't program the hardware
+	 * in that case, store the configuration internally and apply it when
+	 * the CMM will be enabled by the CRTC through rcar_cmm_enable().
+	 */
+	if (!rcmm->enabled) {
+		if (!config->lut.enable)
+			return 0;
+
+		rcar_cmm_lut_extract(rcmm, config->lut.table);
+		rcmm->lut.enabled = true;
+
+		return 0;
+	}
+
+	/* Stop LUT operations if requested. */
+	if (!config->lut.enable) {
+		if (rcmm->lut.enabled) {
+			rcar_cmm_write(rcmm, CM2_LUT_CTRL, 0);
+			rcmm->lut.enabled = false;
+		}
+
+		return 0;
+	}
+
+	/*
+	 * Enable LUT and program the new gamma table values.
+	 *
+	 * FIXME: In order to have stable operations it is required to first
+	 * enable the 1D-LUT and then program its table entries. This seems to
+	 * contradict what the chip manual reports, and will have to be
+	 * reconsidered when implementing support for double buffering.
+	 */
+	if (!rcmm->lut.enabled) {
+		rcar_cmm_write(rcmm, CM2_LUT_CTRL, CM2_LUT_CTRL_LUT_EN);
+		rcmm->lut.enabled = true;
+	}
+
+	rcar_cmm_lut_extract(rcmm, config->lut.table);
+	rcar_cmm_lut_write(rcmm);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(rcar_cmm_setup);
+
+/*
+ * rcar_cmm_enable() - Enable the CMM unit.
+ * @pdev: The platform device associated with the CMM instance
+ *
+ * Enable the CMM unit by enabling the parent clock and enabling the CMM
+ * components, such as 1-D LUT, if requested.
+ */
+int rcar_cmm_enable(struct platform_device *pdev)
+{
+	struct rcar_cmm *rcmm = platform_get_drvdata(pdev);
+	int ret;
+
+	ret = pm_runtime_get_sync(&pdev->dev);
+	if (ret < 0)
+		return ret;
+
+	/* Apply the LUT table values saved at rcar_cmm_setup() time. */
+	if (rcmm->lut.enabled) {
+		rcar_cmm_write(rcmm, CM2_LUT_CTRL, CM2_LUT_CTRL_LUT_EN);
+		rcar_cmm_lut_write(rcmm);
+	}
+
+	rcmm->enabled = true;
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(rcar_cmm_enable);
+
+/*
+ * rcar_cmm_disable() - Disable the CMM unit.
+ * @pdev: The platform device associated with the CMM instance
+ *
+ * Disable the CMM unit by stopping the parent clock.
+ */
+void rcar_cmm_disable(struct platform_device *pdev)
+{
+	struct rcar_cmm *rcmm = platform_get_drvdata(pdev);
+
+	rcar_cmm_write(rcmm, CM2_LUT_CTRL, 0);
+
+	pm_runtime_put(&pdev->dev);
+
+	rcmm->lut.enabled = false;
+	rcmm->enabled = false;
+}
+EXPORT_SYMBOL_GPL(rcar_cmm_disable);
+
+/*
+ * rcar_cmm_init() - Make sure the CMM has probed.
+ * @pdev: The platform device associated with the CMM instance
+ *
+ * Return: 0 if the CMM has probed, -EPROBE_DEFER otherwise
+ */
+int rcar_cmm_init(struct platform_device *pdev)
+{
+	struct rcar_cmm *rcmm = platform_get_drvdata(pdev);
+
+	if (!rcmm)
+		return -EPROBE_DEFER;
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(rcar_cmm_init);
+
+static int rcar_cmm_probe(struct platform_device *pdev)
+{
+	struct rcar_cmm *rcmm;
+
+	rcmm = devm_kzalloc(&pdev->dev, sizeof(*rcmm), GFP_KERNEL);
+	if (!rcmm)
+		return -ENOMEM;
+	platform_set_drvdata(pdev, rcmm);
+
+	rcmm->base = devm_platform_ioremap_resource(pdev, 0);
+	if (IS_ERR(rcmm->base))
+		return PTR_ERR(rcmm->base);
+
+	pm_runtime_enable(&pdev->dev);
+
+	return 0;
+}
+
+static int rcar_cmm_remove(struct platform_device *pdev)
+{
+	pm_runtime_disable(&pdev->dev);
+
+	return 0;
+}
+
+static const struct of_device_id rcar_cmm_of_table[] = {
+	{ .compatible = "renesas,rcar-gen3-cmm", },
+	{ .compatible = "renesas,rcar-gen2-cmm", },
+	{ },
+};
+MODULE_DEVICE_TABLE(of, rcar_cmm_of_table);
+
+static struct platform_driver rcar_cmm_platform_driver = {
+	.probe		= rcar_cmm_probe,
+	.remove		= rcar_cmm_remove,
+	.driver		= {
+		.name	= "rcar-cmm",
+		.of_match_table = rcar_cmm_of_table,
+	},
+};
+
+module_platform_driver(rcar_cmm_platform_driver);
+
+MODULE_AUTHOR("Jacopo Mondi <jacopo+renesas@jmondi.org>");
+MODULE_DESCRIPTION("Renesas R-Car CMM Driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/gpu/drm/rcar-du/rcar_cmm.h b/drivers/gpu/drm/rcar-du/rcar_cmm.h
new file mode 100644
index 000000000000..15a2c874b6a6
--- /dev/null
+++ b/drivers/gpu/drm/rcar-du/rcar_cmm.h
@@ -0,0 +1,61 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * rcar_cmm.h -- R-Car Display Unit Color Management Module
+ *
+ * Copyright (C) 2019 Jacopo Mondi <jacopo+renesas@jmondi.org>
+ */
+
+#ifndef __RCAR_CMM_H__
+#define __RCAR_CMM_H__
+
+#define CM2_LUT_SIZE		256
+
+struct drm_color_lut;
+struct platform_device;
+
+/**
+ * struct rcar_cmm_config - CMM configuration
+ *
+ * @lut:	1D-LUT configuration
+ * @lut.enable:	1D-LUT enable flag
+ * @lut.table:	1D-LUT table entries. Might be set to NULL when the CMM has to
+ *		be re-enabled but not re=programmed.
+ */
+struct rcar_cmm_config {
+	struct {
+		bool enable;
+		struct drm_color_lut *table;
+	} lut;
+};
+
+#if IS_ENABLED(CONFIG_DRM_RCAR_CMM)
+int rcar_cmm_init(struct platform_device *pdev);
+
+int rcar_cmm_enable(struct platform_device *pdev);
+void rcar_cmm_disable(struct platform_device *pdev);
+
+int rcar_cmm_setup(struct platform_device *pdev,
+		   const struct rcar_cmm_config *config);
+#else
+static inline int rcar_cmm_init(struct platform_device *pdev)
+{
+	return 0;
+}
+
+static inline int rcar_cmm_enable(struct platform_device *pdev)
+{
+	return 0;
+}
+
+static inline void rcar_cmm_disable(struct platform_device *pdev)
+{
+}
+
+static int rcar_cmm_setup(struct platform_device *pdev,
+			  const struct rcar_cmm_config *config)
+{
+	return 0;
+}
+#endif /* IS_ENABLED(CONFIG_DRM_RCAR_CMM) */
+
+#endif /* __RCAR_CMM_H__ */
-- 
2.23.0


^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [PATCH v4 4/9] drm: rcar-du: Claim CMM support for Gen3 SoCs
  2019-09-06 13:54 [PATCH v4 0/9 drm: rcar-du: Add Color Management Module (CMM) Jacopo Mondi
                   ` (2 preceding siblings ...)
  2019-09-06 13:54 ` [PATCH v4 3/9] drm: rcar-du: Add support for CMM Jacopo Mondi
@ 2019-09-06 13:54 ` Jacopo Mondi
  2019-09-11 18:45   ` Kieran Bingham
  2019-09-06 13:54 ` [PATCH v4 5/9] drm: rcar-du: kms: Initialize CMM instances Jacopo Mondi
                   ` (4 subsequent siblings)
  8 siblings, 1 reply; 38+ messages in thread
From: Jacopo Mondi @ 2019-09-06 13:54 UTC (permalink / raw)
  To: laurent.pinchart, kieran.bingham+renesas, geert, horms,
	uli+renesas, VenkataRajesh.Kalakodima
  Cc: Jacopo Mondi, airlied, daniel, koji.matsuoka.xm, muroya,
	Harsha.ManjulaMallikarjun, linux-renesas-soc, dri-devel,
	linux-kernel

Add CMM to the list of supported features for Gen3 SoCs that provide it:
- R8A7795
- R8A7796
- R8A77965
- R8A7799x

Leave R8A77970 out as V3M and V3H are the only Gen3 SoCs that do not
support CMM.

Reviewed-by: Ulrich Hecht <uli+renesas@fpond.eu>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Jacopo Mondi <jacopo+renesas@jmondi.org>
---
 drivers/gpu/drm/rcar-du/rcar_du_drv.c | 12 ++++++++----
 drivers/gpu/drm/rcar-du/rcar_du_drv.h |  1 +
 2 files changed, 9 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/rcar-du/rcar_du_drv.c b/drivers/gpu/drm/rcar-du/rcar_du_drv.c
index 6df37c2a9678..018480a8f35c 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_drv.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_drv.c
@@ -276,7 +276,8 @@ static const struct rcar_du_device_info rcar_du_r8a7795_info = {
 	.features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK
 		  | RCAR_DU_FEATURE_VSP1_SOURCE
 		  | RCAR_DU_FEATURE_INTERLACED
-		  | RCAR_DU_FEATURE_TVM_SYNC,
+		  | RCAR_DU_FEATURE_TVM_SYNC
+		  | RCAR_DU_FEATURE_CMM,
 	.channels_mask = BIT(3) | BIT(2) | BIT(1) | BIT(0),
 	.routes = {
 		/*
@@ -309,7 +310,8 @@ static const struct rcar_du_device_info rcar_du_r8a7796_info = {
 	.features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK
 		  | RCAR_DU_FEATURE_VSP1_SOURCE
 		  | RCAR_DU_FEATURE_INTERLACED
-		  | RCAR_DU_FEATURE_TVM_SYNC,
+		  | RCAR_DU_FEATURE_TVM_SYNC
+		  | RCAR_DU_FEATURE_CMM,
 	.channels_mask = BIT(2) | BIT(1) | BIT(0),
 	.routes = {
 		/*
@@ -338,7 +340,8 @@ static const struct rcar_du_device_info rcar_du_r8a77965_info = {
 	.features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK
 		  | RCAR_DU_FEATURE_VSP1_SOURCE
 		  | RCAR_DU_FEATURE_INTERLACED
-		  | RCAR_DU_FEATURE_TVM_SYNC,
+		  | RCAR_DU_FEATURE_TVM_SYNC
+		  | RCAR_DU_FEATURE_CMM,
 	.channels_mask = BIT(3) | BIT(1) | BIT(0),
 	.routes = {
 		/*
@@ -386,7 +389,8 @@ static const struct rcar_du_device_info rcar_du_r8a77970_info = {
 static const struct rcar_du_device_info rcar_du_r8a7799x_info = {
 	.gen = 3,
 	.features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK
-		  | RCAR_DU_FEATURE_VSP1_SOURCE,
+		  | RCAR_DU_FEATURE_VSP1_SOURCE
+		  | RCAR_DU_FEATURE_CMM,
 	.channels_mask = BIT(1) | BIT(0),
 	.routes = {
 		/*
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_drv.h b/drivers/gpu/drm/rcar-du/rcar_du_drv.h
index 1327cd0df90a..a00dccc447aa 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_drv.h
+++ b/drivers/gpu/drm/rcar-du/rcar_du_drv.h
@@ -28,6 +28,7 @@ struct rcar_du_encoder;
 #define RCAR_DU_FEATURE_VSP1_SOURCE	BIT(1)	/* Has inputs from VSP1 */
 #define RCAR_DU_FEATURE_INTERLACED	BIT(2)	/* HW supports interlaced */
 #define RCAR_DU_FEATURE_TVM_SYNC	BIT(3)	/* Has TV switch/sync modes */
+#define RCAR_DU_FEATURE_CMM		BIT(4)	/* Has CMM */
 
 #define RCAR_DU_QUIRK_ALIGN_128B	BIT(0)	/* Align pitches to 128 bytes */
 
-- 
2.23.0


^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [PATCH v4 5/9] drm: rcar-du: kms: Initialize CMM instances
  2019-09-06 13:54 [PATCH v4 0/9 drm: rcar-du: Add Color Management Module (CMM) Jacopo Mondi
                   ` (3 preceding siblings ...)
  2019-09-06 13:54 ` [PATCH v4 4/9] drm: rcar-du: Claim CMM support for Gen3 SoCs Jacopo Mondi
@ 2019-09-06 13:54 ` Jacopo Mondi
  2019-09-12  9:27   ` Kieran Bingham
  2019-09-06 13:54 ` [PATCH v4 6/9] drm: rcar-du: crtc: Enable and disable CMMs Jacopo Mondi
                   ` (3 subsequent siblings)
  8 siblings, 1 reply; 38+ messages in thread
From: Jacopo Mondi @ 2019-09-06 13:54 UTC (permalink / raw)
  To: laurent.pinchart, kieran.bingham+renesas, geert, horms,
	uli+renesas, VenkataRajesh.Kalakodima
  Cc: Jacopo Mondi, airlied, daniel, koji.matsuoka.xm, muroya,
	Harsha.ManjulaMallikarjun, linux-renesas-soc, dri-devel,
	linux-kernel

Implement device tree parsing to collect the available CMM instances
described by the 'renesas,cmms' property. Associate CMMs with CRTCs and
store a mask of active CMMs in the DU group for later enablement.

Enforce the probe and suspend/resume ordering of DU and CMM by creating
a stateless device link between the two.

Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Jacopo Mondi <jacopo+renesas@jmondi.org>
---
 drivers/gpu/drm/rcar-du/rcar_du_crtc.c  |  6 +++
 drivers/gpu/drm/rcar-du/rcar_du_crtc.h  |  2 +
 drivers/gpu/drm/rcar-du/rcar_du_drv.h   |  2 +
 drivers/gpu/drm/rcar-du/rcar_du_group.h |  2 +
 drivers/gpu/drm/rcar-du/rcar_du_kms.c   | 68 +++++++++++++++++++++++++
 5 files changed, 80 insertions(+)

diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
index 2da46e3dc4ae..23f1d6cc1719 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
@@ -1194,6 +1194,12 @@ int rcar_du_crtc_create(struct rcar_du_group *rgrp, unsigned int swindex,
 	if (ret < 0)
 		return ret;
 
+	/* CMM might be disabled for this CRTC. */
+	if (rcdu->cmms[swindex]) {
+		rcrtc->cmm = rcdu->cmms[swindex];
+		rgrp->cmms_mask |= BIT(hwindex % 2);
+	}
+
 	drm_crtc_helper_add(crtc, &crtc_helper_funcs);
 
 	/* Start with vertical blanking interrupt reporting disabled. */
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.h b/drivers/gpu/drm/rcar-du/rcar_du_crtc.h
index 3b7fc668996f..5f2940c42225 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.h
+++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.h
@@ -39,6 +39,7 @@ struct rcar_du_vsp;
  * @vblank_wait: wait queue used to signal vertical blanking
  * @vblank_count: number of vertical blanking interrupts to wait for
  * @group: CRTC group this CRTC belongs to
+ * @cmm: CMM associated with this CRTC
  * @vsp: VSP feeding video to this CRTC
  * @vsp_pipe: index of the VSP pipeline feeding video to this CRTC
  * @writeback: the writeback connector
@@ -64,6 +65,7 @@ struct rcar_du_crtc {
 	unsigned int vblank_count;
 
 	struct rcar_du_group *group;
+	struct platform_device *cmm;
 	struct rcar_du_vsp *vsp;
 	unsigned int vsp_pipe;
 
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_drv.h b/drivers/gpu/drm/rcar-du/rcar_du_drv.h
index a00dccc447aa..6316a1c5236c 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_drv.h
+++ b/drivers/gpu/drm/rcar-du/rcar_du_drv.h
@@ -13,6 +13,7 @@
 #include <linux/kernel.h>
 #include <linux/wait.h>
 
+#include "rcar_cmm.h"
 #include "rcar_du_crtc.h"
 #include "rcar_du_group.h"
 #include "rcar_du_vsp.h"
@@ -86,6 +87,7 @@ struct rcar_du_device {
 	struct rcar_du_encoder *encoders[RCAR_DU_OUTPUT_MAX];
 
 	struct rcar_du_group groups[RCAR_DU_MAX_GROUPS];
+	struct platform_device *cmms[RCAR_DU_MAX_CRTCS];
 	struct rcar_du_vsp vsps[RCAR_DU_MAX_VSPS];
 
 	struct {
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_group.h b/drivers/gpu/drm/rcar-du/rcar_du_group.h
index 87950c1f6a52..e9906609c635 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_group.h
+++ b/drivers/gpu/drm/rcar-du/rcar_du_group.h
@@ -22,6 +22,7 @@ struct rcar_du_device;
  * @mmio_offset: registers offset in the device memory map
  * @index: group index
  * @channels_mask: bitmask of populated DU channels in this group
+ * @cmms_mask: bitmask of available CMMs in this group
  * @num_crtcs: number of CRTCs in this group (1 or 2)
  * @use_count: number of users of the group (rcar_du_group_(get|put))
  * @used_crtcs: number of CRTCs currently in use
@@ -37,6 +38,7 @@ struct rcar_du_group {
 	unsigned int index;
 
 	unsigned int channels_mask;
+	unsigned int cmms_mask;
 	unsigned int num_crtcs;
 	unsigned int use_count;
 	unsigned int used_crtcs;
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_kms.c b/drivers/gpu/drm/rcar-du/rcar_du_kms.c
index 2dc9caee8767..294630e56992 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_kms.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_kms.c
@@ -17,7 +17,9 @@
 #include <drm/drm_probe_helper.h>
 #include <drm/drm_vblank.h>
 
+#include <linux/device.h>
 #include <linux/of_graph.h>
+#include <linux/of_platform.h>
 #include <linux/wait.h>
 
 #include "rcar_du_crtc.h"
@@ -614,6 +616,67 @@ static int rcar_du_vsps_init(struct rcar_du_device *rcdu)
 	return ret;
 }
 
+static int rcar_du_cmm_init(struct rcar_du_device *rcdu)
+{
+	const struct device_node *np = rcdu->dev->of_node;
+	unsigned int i;
+	int cells;
+
+	cells = of_property_count_u32_elems(np, "renesas,cmms");
+	if (cells == -EINVAL)
+		return 0;
+
+	if (cells > rcdu->num_crtcs) {
+		dev_err(rcdu->dev,
+			"Invalid number of entries in 'renesas,cmms'\n");
+		return -EINVAL;
+	}
+
+	for (i = 0; i < cells; ++i) {
+		struct platform_device *pdev;
+		struct device_link *link;
+		struct device_node *cmm;
+		int ret;
+
+		cmm = of_parse_phandle(np, "renesas,cmms", i);
+		if (IS_ERR(cmm)) {
+			dev_err(rcdu->dev,
+				"Failed to parse 'renesas,cmms' property\n");
+			return PTR_ERR(cmm);
+		}
+
+		if (!of_device_is_available(cmm)) {
+			/* It's fine to have a phandle to a non-enabled CMM. */
+			of_node_put(cmm);
+			continue;
+		}
+
+		pdev = of_find_device_by_node(cmm);
+		if (IS_ERR(pdev)) {
+			dev_err(rcdu->dev, "No device found for CMM%u\n", i);
+			of_node_put(cmm);
+			return PTR_ERR(pdev);
+		}
+
+		of_node_put(cmm);
+
+		ret = rcar_cmm_init(pdev);
+		if (ret)
+			return ret;
+
+		link = device_link_add(rcdu->dev, &pdev->dev, DL_FLAG_STATELESS);
+		if (!link) {
+			dev_err(rcdu->dev,
+				"Failed to create device link to CMM%u\n", i);
+			return -EINVAL;
+		}
+
+		rcdu->cmms[i] = pdev;
+	}
+
+	return 0;
+}
+
 int rcar_du_modeset_init(struct rcar_du_device *rcdu)
 {
 	static const unsigned int mmio_offsets[] = {
@@ -704,6 +767,11 @@ int rcar_du_modeset_init(struct rcar_du_device *rcdu)
 			return ret;
 	}
 
+	/* Initialize the Color Management Modules. */
+	ret = rcar_du_cmm_init(rcdu);
+	if (ret)
+		return ret;
+
 	/* Create the CRTCs. */
 	for (swindex = 0, hwindex = 0; swindex < rcdu->num_crtcs; ++hwindex) {
 		struct rcar_du_group *rgrp;
-- 
2.23.0


^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [PATCH v4 6/9] drm: rcar-du: crtc: Enable and disable CMMs
  2019-09-06 13:54 [PATCH v4 0/9 drm: rcar-du: Add Color Management Module (CMM) Jacopo Mondi
                   ` (4 preceding siblings ...)
  2019-09-06 13:54 ` [PATCH v4 5/9] drm: rcar-du: kms: Initialize CMM instances Jacopo Mondi
@ 2019-09-06 13:54 ` Jacopo Mondi
  2019-09-11 18:40   ` Kieran Bingham
  2019-09-06 13:54 ` [PATCH v4 7/9] drm: rcar-du: crtc: Register GAMMA_LUT properties Jacopo Mondi
                   ` (2 subsequent siblings)
  8 siblings, 1 reply; 38+ messages in thread
From: Jacopo Mondi @ 2019-09-06 13:54 UTC (permalink / raw)
  To: laurent.pinchart, kieran.bingham+renesas, geert, horms,
	uli+renesas, VenkataRajesh.Kalakodima
  Cc: Jacopo Mondi, airlied, daniel, koji.matsuoka.xm, muroya,
	Harsha.ManjulaMallikarjun, linux-renesas-soc, dri-devel,
	linux-kernel

Enable/disable the CMM associated with a CRTC at CRTC start and stop
time and enable the CMM unit through the Display Extensional Functions
register at group setup time.

Reviewed-by: Ulrich Hecht <uli+renesas@fpond.eu>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Jacopo Mondi <jacopo+renesas@jmondi.org>
---
 drivers/gpu/drm/rcar-du/rcar_du_crtc.c  | 7 +++++++
 drivers/gpu/drm/rcar-du/rcar_du_group.c | 8 ++++++++
 drivers/gpu/drm/rcar-du/rcar_du_regs.h  | 5 +++++
 3 files changed, 20 insertions(+)

diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
index 23f1d6cc1719..3dac605c3a67 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
@@ -21,6 +21,7 @@
 #include <drm/drm_plane_helper.h>
 #include <drm/drm_vblank.h>
 
+#include "rcar_cmm.h"
 #include "rcar_du_crtc.h"
 #include "rcar_du_drv.h"
 #include "rcar_du_encoder.h"
@@ -619,6 +620,9 @@ static void rcar_du_crtc_stop(struct rcar_du_crtc *rcrtc)
 	if (rcar_du_has(rcrtc->dev, RCAR_DU_FEATURE_VSP1_SOURCE))
 		rcar_du_vsp_disable(rcrtc);
 
+	if (rcrtc->cmm)
+		rcar_cmm_disable(rcrtc->cmm);
+
 	/*
 	 * Select switch sync mode. This stops display operation and configures
 	 * the HSYNC and VSYNC signals as inputs.
@@ -686,6 +690,9 @@ static void rcar_du_crtc_atomic_enable(struct drm_crtc *crtc,
 	}
 
 	rcar_du_crtc_start(rcrtc);
+
+	if (rcrtc->cmm)
+		rcar_cmm_enable(rcrtc->cmm);
 }
 
 static void rcar_du_crtc_atomic_disable(struct drm_crtc *crtc,
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_group.c b/drivers/gpu/drm/rcar-du/rcar_du_group.c
index 9eee47969e77..25d0fc125d7a 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_group.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_group.c
@@ -147,6 +147,14 @@ static void rcar_du_group_setup(struct rcar_du_group *rgrp)
 
 	rcar_du_group_setup_pins(rgrp);
 
+	if (rcar_du_has(rcdu, RCAR_DU_FEATURE_CMM)) {
+		u32 defr7 = DEFR7_CODE
+			  | (rgrp->cmms_mask & BIT(1) ? DEFR7_CMME1 : 0)
+			  | (rgrp->cmms_mask & BIT(0) ? DEFR7_CMME0 : 0);
+
+		rcar_du_group_write(rgrp, DEFR7, defr7);
+	}
+
 	if (rcdu->info->gen >= 2) {
 		rcar_du_group_setup_defr8(rgrp);
 		rcar_du_group_setup_didsr(rgrp);
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_regs.h b/drivers/gpu/drm/rcar-du/rcar_du_regs.h
index bc87f080b170..fb9964949368 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_regs.h
+++ b/drivers/gpu/drm/rcar-du/rcar_du_regs.h
@@ -197,6 +197,11 @@
 #define DEFR6_MLOS1		(1 << 2)
 #define DEFR6_DEFAULT		(DEFR6_CODE | DEFR6_TCNE1)
 
+#define DEFR7			0x000ec
+#define DEFR7_CODE		(0x7779 << 16)
+#define DEFR7_CMME1		BIT(6)
+#define DEFR7_CMME0		BIT(4)
+
 /* -----------------------------------------------------------------------------
  * R8A7790-only Control Registers
  */
-- 
2.23.0


^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [PATCH v4 7/9] drm: rcar-du: crtc: Register GAMMA_LUT properties
  2019-09-06 13:54 [PATCH v4 0/9 drm: rcar-du: Add Color Management Module (CMM) Jacopo Mondi
                   ` (5 preceding siblings ...)
  2019-09-06 13:54 ` [PATCH v4 6/9] drm: rcar-du: crtc: Enable and disable CMMs Jacopo Mondi
@ 2019-09-06 13:54 ` Jacopo Mondi
  2019-09-11 18:47   ` Kieran Bingham
  2019-09-06 13:54 ` [PATCH v4 8/9] drm: rcar-du: kms: Update CMM in atomic commit tail Jacopo Mondi
  2019-09-06 13:54 ` [PATCH v4 9/9] arm64: dts: renesas: Add CMM units to Gen3 SoCs Jacopo Mondi
  8 siblings, 1 reply; 38+ messages in thread
From: Jacopo Mondi @ 2019-09-06 13:54 UTC (permalink / raw)
  To: laurent.pinchart, kieran.bingham+renesas, geert, horms,
	uli+renesas, VenkataRajesh.Kalakodima
  Cc: Jacopo Mondi, airlied, daniel, koji.matsuoka.xm, muroya,
	Harsha.ManjulaMallikarjun, linux-renesas-soc, dri-devel,
	linux-kernel

Enable the GAMMA_LUT KMS property using the framework helpers to
register the property and set the associated gamma table maximum size.

Reviewed-by: Ulrich Hecht <uli+renesas@fpond.eu>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Jacopo Mondi <jacopo+renesas@jmondi.org>
---
 drivers/gpu/drm/rcar-du/rcar_du_crtc.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
index 3dac605c3a67..dc59eeec990c 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
@@ -1082,6 +1082,7 @@ static const struct drm_crtc_funcs crtc_funcs_gen3 = {
 	.set_crc_source = rcar_du_crtc_set_crc_source,
 	.verify_crc_source = rcar_du_crtc_verify_crc_source,
 	.get_crc_sources = rcar_du_crtc_get_crc_sources,
+	.gamma_set = drm_atomic_helper_legacy_gamma_set,
 };
 
 /* -----------------------------------------------------------------------------
@@ -1205,6 +1206,9 @@ int rcar_du_crtc_create(struct rcar_du_group *rgrp, unsigned int swindex,
 	if (rcdu->cmms[swindex]) {
 		rcrtc->cmm = rcdu->cmms[swindex];
 		rgrp->cmms_mask |= BIT(hwindex % 2);
+
+		drm_mode_crtc_set_gamma_size(crtc, CM2_LUT_SIZE);
+		drm_crtc_enable_color_mgmt(crtc, 0, false, CM2_LUT_SIZE);
 	}
 
 	drm_crtc_helper_add(crtc, &crtc_helper_funcs);
-- 
2.23.0


^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [PATCH v4 8/9] drm: rcar-du: kms: Update CMM in atomic commit tail
  2019-09-06 13:54 [PATCH v4 0/9 drm: rcar-du: Add Color Management Module (CMM) Jacopo Mondi
                   ` (6 preceding siblings ...)
  2019-09-06 13:54 ` [PATCH v4 7/9] drm: rcar-du: crtc: Register GAMMA_LUT properties Jacopo Mondi
@ 2019-09-06 13:54 ` Jacopo Mondi
  2019-09-12  9:51   ` Kieran Bingham
                     ` (2 more replies)
  2019-09-06 13:54 ` [PATCH v4 9/9] arm64: dts: renesas: Add CMM units to Gen3 SoCs Jacopo Mondi
  8 siblings, 3 replies; 38+ messages in thread
From: Jacopo Mondi @ 2019-09-06 13:54 UTC (permalink / raw)
  To: laurent.pinchart, kieran.bingham+renesas, geert, horms,
	uli+renesas, VenkataRajesh.Kalakodima, airlied, daniel
  Cc: Jacopo Mondi, koji.matsuoka.xm, muroya,
	Harsha.ManjulaMallikarjun, linux-renesas-soc, dri-devel,
	linux-kernel

Update CMM settings at in the atomic commit tail helper method.
The CMM is updated with new gamma values provided to the driver
in the GAMMA_LUT blob property.

When resuming from system suspend, the DU driver is responsible for
reprogramming and enabling the CMM unit if it was in use at the time the
system entered the suspend state.  Force the color_mgmt_changed flag to
true if the DRM gamma lut color transformation property was set in the
CRTC state duplicated at suspend time, as the CMM gets reprogrammed only
if said flag is active in the rcar_du_atomic_commit_update_cmm() method.

Reviewed-by: Ulrich Hecht <uli+renesas@fpond.eu>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Jacopo Mondi <jacopo+renesas@jmondi.org>
---

Daniel could you have a look if resume bits are worth being moved to the
DRM core? The color_mgmt_changed flag is set to false when the state is
duplicated if I read the code correctly, but when this happens in a
suspend/resume sequence its value should probably be restored to true if
any color management property was set in the crtc state when system entered
suspend.

---

 drivers/gpu/drm/rcar-du/rcar_du_drv.c | 20 ++++++++++++++
 drivers/gpu/drm/rcar-du/rcar_du_kms.c | 38 +++++++++++++++++++++++++++
 2 files changed, 58 insertions(+)

diff --git a/drivers/gpu/drm/rcar-du/rcar_du_drv.c b/drivers/gpu/drm/rcar-du/rcar_du_drv.c
index 018480a8f35c..d1003d31cfaf 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_drv.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_drv.c
@@ -17,6 +17,7 @@
 #include <linux/slab.h>
 #include <linux/wait.h>

+#include <drm/drm_atomic.h>
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_fb_cma_helper.h>
 #include <drm/drm_fb_helper.h>
@@ -482,6 +483,25 @@ static int rcar_du_pm_suspend(struct device *dev)
 static int rcar_du_pm_resume(struct device *dev)
 {
 	struct rcar_du_device *rcdu = dev_get_drvdata(dev);
+	struct drm_atomic_state *state = rcdu->ddev->mode_config.suspend_state;
+	unsigned int i;
+
+	for (i = 0; i < rcdu->num_crtcs; ++i) {
+		struct drm_crtc *crtc = &rcdu->crtcs[i].crtc;
+		struct drm_crtc_state *crtc_state;
+
+		crtc_state = drm_atomic_get_new_crtc_state(state, crtc);
+		if (!crtc_state)
+			continue;
+
+		/*
+		 * Force re-enablement of CMM after system resume if any
+		 * of the DRM color transformation properties was set in
+		 * the state saved at system suspend time.
+		 */
+		if (crtc_state->gamma_lut)
+			crtc_state->color_mgmt_changed = true;
+	}

 	return drm_mode_config_helper_resume(rcdu->ddev);
 }
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_kms.c b/drivers/gpu/drm/rcar-du/rcar_du_kms.c
index 294630e56992..fc30fff0eb8d 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_kms.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_kms.c
@@ -22,6 +22,7 @@
 #include <linux/of_platform.h>
 #include <linux/wait.h>

+#include "rcar_cmm.h"
 #include "rcar_du_crtc.h"
 #include "rcar_du_drv.h"
 #include "rcar_du_encoder.h"
@@ -368,6 +369,40 @@ rcar_du_fb_create(struct drm_device *dev, struct drm_file *file_priv,
  * Atomic Check and Update
  */

+static void rcar_du_atomic_commit_update_cmm(struct drm_crtc *crtc,
+					     struct drm_crtc_state *old_state)
+{
+	struct rcar_du_crtc *rcrtc = to_rcar_crtc(crtc);
+	struct rcar_cmm_config cmm_config = {};
+	struct device *dev = rcrtc->dev->dev;
+	struct drm_property_blob *lut_blob;
+
+	if (!rcrtc->cmm || !crtc->state->color_mgmt_changed)
+		return;
+
+	if (!crtc->state->gamma_lut) {
+		cmm_config.lut.enable = false;
+		rcar_cmm_setup(rcrtc->cmm, &cmm_config);
+		return;
+	}
+
+	lut_blob = crtc->state->gamma_lut;
+	if (lut_blob->length != (CM2_LUT_SIZE * sizeof(struct drm_color_lut))) {
+		/*
+		 * We only accept fully populated LUT tables;
+		 * be loud here, otherwise the CMM gets silently ignored.
+		 */
+		dev_err(dev, "invalid gamma lut size of %lu bytes\n",
+			lut_blob->length);
+		return;
+	}
+
+	cmm_config.lut.enable = true;
+	cmm_config.lut.table = (struct drm_color_lut *)lut_blob->data;
+
+	rcar_cmm_setup(rcrtc->cmm, &cmm_config);
+}
+
 static int rcar_du_atomic_check(struct drm_device *dev,
 				struct drm_atomic_state *state)
 {
@@ -410,6 +445,9 @@ static void rcar_du_atomic_commit_tail(struct drm_atomic_state *old_state)
 			rcdu->dpad1_source = rcrtc->index;
 	}

+	for_each_old_crtc_in_state(old_state, crtc, crtc_state, i)
+		rcar_du_atomic_commit_update_cmm(crtc, crtc_state);
+
 	/* Apply the atomic update. */
 	drm_atomic_helper_commit_modeset_disables(dev, old_state);
 	drm_atomic_helper_commit_planes(dev, old_state,
--
2.23.0


^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [PATCH v4 9/9] arm64: dts: renesas: Add CMM units to Gen3 SoCs
  2019-09-06 13:54 [PATCH v4 0/9 drm: rcar-du: Add Color Management Module (CMM) Jacopo Mondi
                   ` (7 preceding siblings ...)
  2019-09-06 13:54 ` [PATCH v4 8/9] drm: rcar-du: kms: Update CMM in atomic commit tail Jacopo Mondi
@ 2019-09-06 13:54 ` Jacopo Mondi
  2019-09-11 18:16   ` Kieran Bingham
  8 siblings, 1 reply; 38+ messages in thread
From: Jacopo Mondi @ 2019-09-06 13:54 UTC (permalink / raw)
  To: laurent.pinchart, kieran.bingham+renesas, geert, horms,
	uli+renesas, VenkataRajesh.Kalakodima
  Cc: Jacopo Mondi, airlied, daniel, koji.matsuoka.xm, muroya,
	Harsha.ManjulaMallikarjun, linux-renesas-soc, dri-devel,
	linux-kernel

Add CMM units to Renesas R-Car Gen3 SoC that support it, and reference them
from the Display Unit they are connected to.

Sort the 'vsps' and 'renesas,cmm' entries in the DU unit consistently
in all the involved DTS.

Signed-off-by: Jacopo Mondi <jacopo+renesas@jmondi.org>
---
 arch/arm64/boot/dts/renesas/r8a7795.dtsi  | 40 ++++++++++++++++++++++-
 arch/arm64/boot/dts/renesas/r8a7796.dtsi  | 28 ++++++++++++++++
 arch/arm64/boot/dts/renesas/r8a77965.dtsi | 28 ++++++++++++++++
 arch/arm64/boot/dts/renesas/r8a77990.dtsi | 22 ++++++++++++-
 arch/arm64/boot/dts/renesas/r8a77995.dtsi | 22 ++++++++++++-
 5 files changed, 137 insertions(+), 3 deletions(-)

diff --git a/arch/arm64/boot/dts/renesas/r8a7795.dtsi b/arch/arm64/boot/dts/renesas/r8a7795.dtsi
index 6675462f7585..67c242a447bc 100644
--- a/arch/arm64/boot/dts/renesas/r8a7795.dtsi
+++ b/arch/arm64/boot/dts/renesas/r8a7795.dtsi
@@ -2939,6 +2939,42 @@
 			iommus = <&ipmmu_vi1 10>;
 		};
 
+		cmm0: cmm@fea40000 {
+			compatible = "renesas,r8a7795-cmm",
+				     "renesas,rcar-gen3-cmm";
+			reg = <0 0xfea40000 0 0x1000>;
+			power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
+			clocks = <&cpg CPG_MOD 711>;
+			resets = <&cpg 711>;
+		};
+
+		cmm1: cmm@fea50000 {
+			compatible = "renesas,r8a7795-cmm",
+				     "renesas,rcar-gen3-cmm";
+			reg = <0 0xfea50000 0 0x1000>;
+			power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
+			clocks = <&cpg CPG_MOD 710>;
+			resets = <&cpg 710>;
+		};
+
+		cmm2: cmm@fea60000 {
+			compatible = "renesas,r8a7795-cmm",
+				     "renesas,rcar-gen3-cmm";
+			reg = <0 0xfea60000 0 0x1000>;
+			power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
+			clocks = <&cpg CPG_MOD 709>;
+			resets = <&cpg 709>;
+		};
+
+		cmm3: cmm@fea70000 {
+			compatible = "renesas,r8a7795-cmm",
+				     "renesas,rcar-gen3-cmm";
+			reg = <0 0xfea70000 0 0x1000>;
+			power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
+			clocks = <&cpg CPG_MOD 708>;
+			resets = <&cpg 708>;
+		};
+
 		csi20: csi2@fea80000 {
 			compatible = "renesas,r8a7795-csi2";
 			reg = <0 0xfea80000 0 0x10000>;
@@ -3142,9 +3178,11 @@
 				 <&cpg CPG_MOD 722>,
 				 <&cpg CPG_MOD 721>;
 			clock-names = "du.0", "du.1", "du.2", "du.3";
-			vsps = <&vspd0 0>, <&vspd1 0>, <&vspd2 0>, <&vspd0 1>;
 			status = "disabled";
 
+			vsps = <&vspd0 0>, <&vspd1 0>, <&vspd2 0>, <&vspd0 1>;
+			renesas,cmms = <&cmm0 &cmm1 &cmm2 &cmm3>;
+
 			ports {
 				#address-cells = <1>;
 				#size-cells = <0>;
diff --git a/arch/arm64/boot/dts/renesas/r8a7796.dtsi b/arch/arm64/boot/dts/renesas/r8a7796.dtsi
index 822c96601d3c..837c3b2da773 100644
--- a/arch/arm64/boot/dts/renesas/r8a7796.dtsi
+++ b/arch/arm64/boot/dts/renesas/r8a7796.dtsi
@@ -2641,6 +2641,33 @@
 			renesas,fcp = <&fcpvi0>;
 		};
 
+		cmm0: cmm@fea40000 {
+			compatible = "renesas,r8a7796-cmm",
+				     "renesas,rcar-gen3-cmm";
+			reg = <0 0xfea40000 0 0x1000>;
+			power-domains = <&sysc R8A7796_PD_ALWAYS_ON>;
+			clocks = <&cpg CPG_MOD 711>;
+			resets = <&cpg 711>;
+		};
+
+		cmm1: cmm@fea50000 {
+			compatible = "renesas,r8a7796-cmm",
+				     "renesas,rcar-gen3-cmm";
+			reg = <0 0xfea50000 0 0x1000>;
+			power-domains = <&sysc R8A7796_PD_ALWAYS_ON>;
+			clocks = <&cpg CPG_MOD 710>;
+			resets = <&cpg 710>;
+		};
+
+		cmm2: cmm@fea60000 {
+			compatible = "renesas,r8a7796-cmm",
+				     "renesas,rcar-gen3-cmm";
+			reg = <0 0xfea60000 0 0x1000>;
+			power-domains = <&sysc R8A7796_PD_ALWAYS_ON>;
+			clocks = <&cpg CPG_MOD 709>;
+			resets = <&cpg 709>;
+		};
+
 		csi20: csi2@fea80000 {
 			compatible = "renesas,r8a7796-csi2";
 			reg = <0 0xfea80000 0 0x10000>;
@@ -2794,6 +2821,7 @@
 			status = "disabled";
 
 			vsps = <&vspd0 0>, <&vspd1 0>, <&vspd2 0>;
+			renesas,cmms = <&cmm0 &cmm1 &cmm2>;
 
 			ports {
 				#address-cells = <1>;
diff --git a/arch/arm64/boot/dts/renesas/r8a77965.dtsi b/arch/arm64/boot/dts/renesas/r8a77965.dtsi
index 4ae163220f60..c7635e8b261c 100644
--- a/arch/arm64/boot/dts/renesas/r8a77965.dtsi
+++ b/arch/arm64/boot/dts/renesas/r8a77965.dtsi
@@ -2320,6 +2320,33 @@
 			resets = <&cpg 611>;
 		};
 
+		cmm0: cmm@fea40000 {
+			compatible = "renesas,r8a77965-cmm",
+				     "renesas,rcar-gen3-cmm";
+			reg = <0 0xfea40000 0 0x1000>;
+			power-domains = <&sysc R8A77965_PD_ALWAYS_ON>;
+			clocks = <&cpg CPG_MOD 711>;
+			resets = <&cpg 711>;
+		};
+
+		cmm1: cmm@fea50000 {
+			compatible = "renesas,r8a77965-cmm",
+				     "renesas,rcar-gen3-cmm";
+			reg = <0 0xfea50000 0 0x1000>;
+			power-domains = <&sysc R8A77965_PD_ALWAYS_ON>;
+			clocks = <&cpg CPG_MOD 710>;
+			resets = <&cpg 710>;
+		};
+
+		cmm3: cmm@fea70000 {
+			compatible = "renesas,r8a77965-cmm",
+				     "renesas,rcar-gen3-cmm";
+			reg = <0 0xfea70000 0 0x1000>;
+			power-domains = <&sysc R8A77965_PD_ALWAYS_ON>;
+			clocks = <&cpg CPG_MOD 708>;
+			resets = <&cpg 708>;
+		};
+
 		csi20: csi2@fea80000 {
 			compatible = "renesas,r8a77965-csi2";
 			reg = <0 0xfea80000 0 0x10000>;
@@ -2470,6 +2497,7 @@
 			status = "disabled";
 
 			vsps = <&vspd0 0>, <&vspd1 0>, <&vspd0 1>;
+			renesas,cmms = <&cmm0 &cmm1 &cmm3>;
 
 			ports {
 				#address-cells = <1>;
diff --git a/arch/arm64/boot/dts/renesas/r8a77990.dtsi b/arch/arm64/boot/dts/renesas/r8a77990.dtsi
index 455954c3d98e..5e3d758a033f 100644
--- a/arch/arm64/boot/dts/renesas/r8a77990.dtsi
+++ b/arch/arm64/boot/dts/renesas/r8a77990.dtsi
@@ -1727,6 +1727,24 @@
 			iommus = <&ipmmu_vi0 9>;
 		};
 
+		cmm0: cmm@fea40000 {
+			compatible = "renesas,r8a77990-cmm",
+				     "renesas,rcar-gen3-cmm";
+			reg = <0 0xfea40000 0 0x1000>;
+			power-domains = <&sysc R8A77990_PD_ALWAYS_ON>;
+			clocks = <&cpg CPG_MOD 711>;
+			resets = <&cpg 711>;
+		};
+
+		cmm1: cmm@fea50000 {
+			compatible = "renesas,r8a77990-cmm",
+				     "renesas,rcar-gen3-cmm";
+			reg = <0 0xfea50000 0 0x1000>;
+			power-domains = <&sysc R8A77990_PD_ALWAYS_ON>;
+			clocks = <&cpg CPG_MOD 710>;
+			resets = <&cpg 710>;
+		};
+
 		csi40: csi2@feaa0000 {
 			compatible = "renesas,r8a77990-csi2";
 			reg = <0 0xfeaa0000 0 0x10000>;
@@ -1768,9 +1786,11 @@
 			clock-names = "du.0", "du.1";
 			resets = <&cpg 724>;
 			reset-names = "du.0";
-			vsps = <&vspd0 0>, <&vspd1 0>;
 			status = "disabled";
 
+			vsps = <&vspd0 0>, <&vspd1 0>;
+			renesas,cmms = <&cmm0 &cmm1>;
+
 			ports {
 				#address-cells = <1>;
 				#size-cells = <0>;
diff --git a/arch/arm64/boot/dts/renesas/r8a77995.dtsi b/arch/arm64/boot/dts/renesas/r8a77995.dtsi
index 183fef86cf7c..6838a81f5caa 100644
--- a/arch/arm64/boot/dts/renesas/r8a77995.dtsi
+++ b/arch/arm64/boot/dts/renesas/r8a77995.dtsi
@@ -993,6 +993,24 @@
 			iommus = <&ipmmu_vi0 9>;
 		};
 
+		cmm0: cmm@fea40000 {
+			compatible = "renesas,r8a77995-cmm",
+				     "renesas,rcar-gen3-cmm";
+			reg = <0 0xfea40000 0 0x1000>;
+			power-domains = <&sysc R8A77995_PD_ALWAYS_ON>;
+			clocks = <&cpg CPG_MOD 711>;
+			resets = <&cpg 711>;
+		};
+
+		cmm1: cmm@fea50000 {
+			compatible = "renesas,r8a77995-cmm",
+				     "renesas,rcar-gen3-cmm";
+			reg = <0 0xfea50000 0 0x1000>;
+			power-domains = <&sysc R8A77995_PD_ALWAYS_ON>;
+			clocks = <&cpg CPG_MOD 710>;
+			resets = <&cpg 710>;
+		};
+
 		du: display@feb00000 {
 			compatible = "renesas,du-r8a77995";
 			reg = <0 0xfeb00000 0 0x40000>;
@@ -1003,9 +1021,11 @@
 			clock-names = "du.0", "du.1";
 			resets = <&cpg 724>;
 			reset-names = "du.0";
-			vsps = <&vspd0 0>, <&vspd1 0>;
 			status = "disabled";
 
+			vsps = <&vspd0 0>, <&vspd1 0>;
+			renesas,cmms = <&cmm0 &cmm1>;
+
 			ports {
 				#address-cells = <1>;
 				#size-cells = <0>;
-- 
2.23.0


^ permalink raw reply related	[flat|nested] 38+ messages in thread

* Re: [PATCH v4 3/9] drm: rcar-du: Add support for CMM
  2019-09-06 13:54 ` [PATCH v4 3/9] drm: rcar-du: Add support for CMM Jacopo Mondi
@ 2019-09-11 15:54   ` Kieran Bingham
  2019-09-12  7:59     ` Jacopo Mondi
  2019-09-18 22:55   ` Laurent Pinchart
  1 sibling, 1 reply; 38+ messages in thread
From: Kieran Bingham @ 2019-09-11 15:54 UTC (permalink / raw)
  To: Jacopo Mondi, laurent.pinchart, geert, horms, uli+renesas,
	VenkataRajesh.Kalakodima
  Cc: airlied, daniel, koji.matsuoka.xm, muroya,
	Harsha.ManjulaMallikarjun, linux-renesas-soc, dri-devel,
	linux-kernel

Hi Jacopo,

<This time replying to the mail with ML's included Doh!>

On 06/09/2019 14:43, Jacopo Mondi wrote:
> Add a driver for the R-Car Display Unit Color Correction Module.
>
> In most of Gen3 SoCs, each DU output channel is provided with a CMM unit
> to perform image enhancement and color correction.
>
> Add support for CMM through a driver that supports configuration of
> the 1-dimensional LUT table. More advanced CMM feature will be

s/feature/features/

> implemented on top of this basic one.

s/basic/initial/

>
> Signed-off-by: Jacopo Mondi <jacopo+renesas@jmondi.org>
> ---
>  drivers/gpu/drm/rcar-du/Kconfig    |   7 +
>  drivers/gpu/drm/rcar-du/Makefile   |   1 +
>  drivers/gpu/drm/rcar-du/rcar_cmm.c | 251 +++++++++++++++++++++++++++++
>  drivers/gpu/drm/rcar-du/rcar_cmm.h |  61 +++++++
>  4 files changed, 320 insertions(+)
>  create mode 100644 drivers/gpu/drm/rcar-du/rcar_cmm.c
>  create mode 100644 drivers/gpu/drm/rcar-du/rcar_cmm.h
>
> diff --git a/drivers/gpu/drm/rcar-du/Kconfig
b/drivers/gpu/drm/rcar-du/Kconfig
> index 1529849e217e..539d232790d1 100644
> --- a/drivers/gpu/drm/rcar-du/Kconfig
> +++ b/drivers/gpu/drm/rcar-du/Kconfig
> @@ -13,6 +13,13 @@ config DRM_RCAR_DU
>  	  Choose this option if you have an R-Car chipset.
>  	  If M is selected the module will be called rcar-du-drm.
>
> +config DRM_RCAR_CMM
> +	bool "R-Car DU Color Management Module (CMM) Support"
> +	depends on DRM && OF
> +	depends on DRM_RCAR_DU
> +	help
> +	  Enable support for R-Car Color Management Module (CMM).
> +
>  config DRM_RCAR_DW_HDMI
>  	tristate "R-Car DU Gen3 HDMI Encoder Support"
>  	depends on DRM && OF
> diff --git a/drivers/gpu/drm/rcar-du/Makefile
b/drivers/gpu/drm/rcar-du/Makefile
> index 6c2ed9c46467..4d1187ccc3e5 100644
> --- a/drivers/gpu/drm/rcar-du/Makefile
> +++ b/drivers/gpu/drm/rcar-du/Makefile
> @@ -15,6 +15,7 @@ rcar-du-drm-$(CONFIG_DRM_RCAR_LVDS)	+= rcar_du_of.o \
>  rcar-du-drm-$(CONFIG_DRM_RCAR_VSP)	+= rcar_du_vsp.o
>  rcar-du-drm-$(CONFIG_DRM_RCAR_WRITEBACK) += rcar_du_writeback.o
>
> +obj-$(CONFIG_DRM_RCAR_CMM)		+= rcar_cmm.o
>  obj-$(CONFIG_DRM_RCAR_DU)		+= rcar-du-drm.o
>  obj-$(CONFIG_DRM_RCAR_DW_HDMI)		+= rcar_dw_hdmi.o
>  obj-$(CONFIG_DRM_RCAR_LVDS)		+= rcar_lvds.o
> diff --git a/drivers/gpu/drm/rcar-du/rcar_cmm.c
b/drivers/gpu/drm/rcar-du/rcar_cmm.c
> new file mode 100644
> index 000000000000..3cacdc4474c7
> --- /dev/null
> +++ b/drivers/gpu/drm/rcar-du/rcar_cmm.c
> @@ -0,0 +1,251 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * rcar_cmm.c -- R-Car Display Unit Color Management Module
> + *
> + * Copyright (C) 2019 Jacopo Mondi <jacopo+renesas@jmondi.org>
> + */
> +
> +#include <linux/io.h>
> +#include <linux/module.h>
> +#include <linux/of.h>
> +#include <linux/platform_device.h>
> +#include <linux/pm_runtime.h>
> +
> +#include <drm/drm_color_mgmt.h>
> +
> +#include "rcar_cmm.h"
> +
> +#define CM2_LUT_CTRL		0x0000
> +#define CM2_LUT_CTRL_LUT_EN	BIT(0)

I'd have a new line here

> +#define CM2_LUT_TBL_BASE	0x0600
> +#define CM2_LUT_TBL(__i)	(CM2_LUT_TBL_BASE + (__i) * 4)
> +
> +struct rcar_cmm {
> +	void __iomem *base;
> +	bool enabled;
> +
> +	/*
> +	 * @lut:		1D-LUT status
> +	 * @lut.enabled:	1D-LUT enabled flag
> +	 * @lut.table:		Table of 1D-LUT entries scaled to hardware
> +	 *			precision (8-bits per color component)
> +	 */
> +	struct {
> +		bool enabled;
> +		u32 table[CM2_LUT_SIZE];
> +	} lut;
> +};
> +
> +static inline int rcar_cmm_read(struct rcar_cmm *rcmm, u32 reg)
> +{
> +	return ioread32(rcmm->base + reg);
> +}
> +
> +static inline void rcar_cmm_write(struct rcar_cmm *rcmm, u32 reg, u32
data)
> +{
> +	iowrite32(data, rcmm->base + reg);
> +}
> +
> +/*
> + * rcar_cmm_lut_extract() - Scale down to hardware precision the DRM
LUT table
> + *			    entries and store them.
> + * @rcmm: Pointer to the CMM device
> + * @drm_lut: Pointer to the DRM LUT table
> + */
> +static void rcar_cmm_lut_extract(struct rcar_cmm *rcmm,
> +				 const struct drm_color_lut *drm_lut)
> +{
> +	unsigned int i;

I think you're missing the following here:

	if (!drm_lut)
		return;

You mention below that drm_lut could be passed in as NULL, which would
cause a segfault here otherwise.


> +
> +	for (i = 0; i < CM2_LUT_SIZE; ++i) {
> +		const struct drm_color_lut *lut = &drm_lut[i];
> +
> +		rcmm->lut.table[i] = drm_color_lut_extract(lut->red, 8) << 16
> +				   | drm_color_lut_extract(lut->green, 8) << 8
> +				   | drm_color_lut_extract(lut->blue, 8);
> +	}
> +}
> +
> +/*
> + * rcar_cmm_lut_write() - Write to hardware the LUT table entries
from the
> + *			  local table.
> + * @rcmm: Pointer to the CMM device
> + */
> +static void rcar_cmm_lut_write(struct rcar_cmm *rcmm)
> +{
> +	unsigned int i;
> +
> +	for (i = 0; i < CM2_LUT_SIZE; ++i)
> +		rcar_cmm_write(rcmm, CM2_LUT_TBL(i), rcmm->lut.table[i]);
> +}
> +
> +/*
> + * rcar_cmm_setup() - Configure the CMM unit.
> + * @pdev: The platform device associated with the CMM instance
> + * @config: The CRTC-provided configuration.

I don't think CRTC-provided should be hyphenated like that.
Perhaps just:
	"The colour management configuration".

As I don't think who provides the configuration is relevant to the
actual call.

> + *
> + * Configure the CMM unit with the CRTC-provided configuration.

s/CRTC-provided/given/

> + * Currently enabling, disabling and programming of the 1-D LUT unit is
> + * supported.
> + */
> +int rcar_cmm_setup(struct platform_device *pdev,
> +		   const struct rcar_cmm_config *config)
> +{
> +	struct rcar_cmm *rcmm = platform_get_drvdata(pdev);
> +
> +	/*
> +	 * As rcar_cmm_setup() is called by atomic commit tail helper, it might
> +	 * be called when the CMM is disabled. As we can't program the hardware
> +	 * in that case, store the configuration internally and apply it when
> +	 * the CMM will be enabled by the CRTC through rcar_cmm_enable().
> +	 */
> +	if (!rcmm->enabled) {
> +		if (!config->lut.enable)
> +			return 0;
> +
> +		rcar_cmm_lut_extract(rcmm, config->lut.table);
> +		rcmm->lut.enabled = true;
> +
> +		return 0;
> +	}
> +
> +	/* Stop LUT operations if requested. */
> +	if (!config->lut.enable) {
> +		if (rcmm->lut.enabled) {
> +			rcar_cmm_write(rcmm, CM2_LUT_CTRL, 0);
> +			rcmm->lut.enabled = false;
> +		}
> +
> +		return 0;
> +	}
> +
> +	/*
> +	 * Enable LUT and program the new gamma table values.
> +	 *
> +	 * FIXME: In order to have stable operations it is required to first
> +	 * enable the 1D-LUT and then program its table entries. This seems to
> +	 * contradict what the chip manual reports, and will have to be
> +	 * reconsidered when implementing support for double buffering.
> +	 */
> +	if (!rcmm->lut.enabled) {
> +		rcar_cmm_write(rcmm, CM2_LUT_CTRL, CM2_LUT_CTRL_LUT_EN);
> +		rcmm->lut.enabled = true;
> +	}
> +
> +	rcar_cmm_lut_extract(rcmm, config->lut.table);
> +	rcar_cmm_lut_write(rcmm);
> +
> +	return 0;
> +}
> +EXPORT_SYMBOL_GPL(rcar_cmm_setup);
> +
> +/*
> + * rcar_cmm_enable() - Enable the CMM unit.
> + * @pdev: The platform device associated with the CMM instance
> + *
> + * Enable the CMM unit by enabling the parent clock and enabling the CMM
> + * components, such as 1-D LUT, if requested.
> + */
> +int rcar_cmm_enable(struct platform_device *pdev)
> +{
> +	struct rcar_cmm *rcmm = platform_get_drvdata(pdev);
> +	int ret;
> +
> +	ret = pm_runtime_get_sync(&pdev->dev);
> +	if (ret < 0)
> +		return ret;
> +
> +	/* Apply the LUT table values saved at rcar_cmm_setup() time. */
> +	if (rcmm->lut.enabled) {
> +		rcar_cmm_write(rcmm, CM2_LUT_CTRL, CM2_LUT_CTRL_LUT_EN);
> +		rcar_cmm_lut_write(rcmm);
> +	}
> +
> +	rcmm->enabled = true;
> +
> +	return 0;
> +}
> +EXPORT_SYMBOL_GPL(rcar_cmm_enable);
> +
> +/*
> + * rcar_cmm_disable() - Disable the CMM unit.
> + * @pdev: The platform device associated with the CMM instance
> + *
> + * Disable the CMM unit by stopping the parent clock.
> + */
> +void rcar_cmm_disable(struct platform_device *pdev)
> +{
> +	struct rcar_cmm *rcmm = platform_get_drvdata(pdev);
> +
> +	rcar_cmm_write(rcmm, CM2_LUT_CTRL, 0);
> +
> +	pm_runtime_put(&pdev->dev);
> +
> +	rcmm->lut.enabled = false;
> +	rcmm->enabled = false;
> +}
> +EXPORT_SYMBOL_GPL(rcar_cmm_disable);
> +
> +/*
> + * rcar_cmm_init() - Make sure the CMM has probed.
> + * @pdev: The platform device associated with the CMM instance
> + *
> + * Return: 0 if the CMM has probed, -EPROBE_DEFER otherwise
> + */
> +int rcar_cmm_init(struct platform_device *pdev)
> +{
> +	struct rcar_cmm *rcmm = platform_get_drvdata(pdev);
> +
> +	if (!rcmm)
> +		return -EPROBE_DEFER;
> +
> +	return 0;
> +}
> +EXPORT_SYMBOL_GPL(rcar_cmm_init);
> +
> +static int rcar_cmm_probe(struct platform_device *pdev)
> +{
> +	struct rcar_cmm *rcmm;
> +
> +	rcmm = devm_kzalloc(&pdev->dev, sizeof(*rcmm), GFP_KERNEL);
> +	if (!rcmm)
> +		return -ENOMEM;
> +	platform_set_drvdata(pdev, rcmm);
> +
> +	rcmm->base = devm_platform_ioremap_resource(pdev, 0);
> +	if (IS_ERR(rcmm->base))
> +		return PTR_ERR(rcmm->base);
> +
> +	pm_runtime_enable(&pdev->dev);
> +
> +	return 0;
> +}
> +
> +static int rcar_cmm_remove(struct platform_device *pdev)
> +{
> +	pm_runtime_disable(&pdev->dev);
> +
> +	return 0;
> +}
> +
> +static const struct of_device_id rcar_cmm_of_table[] = {
> +	{ .compatible = "renesas,rcar-gen3-cmm", },
> +	{ .compatible = "renesas,rcar-gen2-cmm", },
> +	{ },
> +};
> +MODULE_DEVICE_TABLE(of, rcar_cmm_of_table);
> +
> +static struct platform_driver rcar_cmm_platform_driver = {
> +	.probe		= rcar_cmm_probe,
> +	.remove		= rcar_cmm_remove,
> +	.driver		= {
> +		.name	= "rcar-cmm",
> +		.of_match_table = rcar_cmm_of_table,
> +	},
> +};
> +
> +module_platform_driver(rcar_cmm_platform_driver);
> +
> +MODULE_AUTHOR("Jacopo Mondi <jacopo+renesas@jmondi.org>");
> +MODULE_DESCRIPTION("Renesas R-Car CMM Driver");
> +MODULE_LICENSE("GPL v2");
> diff --git a/drivers/gpu/drm/rcar-du/rcar_cmm.h
b/drivers/gpu/drm/rcar-du/rcar_cmm.h
> new file mode 100644
> index 000000000000..15a2c874b6a6
> --- /dev/null
> +++ b/drivers/gpu/drm/rcar-du/rcar_cmm.h
> @@ -0,0 +1,61 @@
> +/* SPDX-License-Identifier: GPL-2.0+ */
> +/*
> + * rcar_cmm.h -- R-Car Display Unit Color Management Module
> + *
> + * Copyright (C) 2019 Jacopo Mondi <jacopo+renesas@jmondi.org>
> + */
> +
> +#ifndef __RCAR_CMM_H__
> +#define __RCAR_CMM_H__
> +
> +#define CM2_LUT_SIZE		256
> +
> +struct drm_color_lut;
> +struct platform_device;
> +
> +/**
> + * struct rcar_cmm_config - CMM configuration
> + *
> + * @lut:	1D-LUT configuration
> + * @lut.enable:	1D-LUT enable flag
> + * @lut.table:	1D-LUT table entries. Might be set to NULL when the
CMM has to
> + *		be re-enabled but not re=programmed.

So lut.table can be NULL ... See comment at rcar_cmm_lut_extract()

> + */
> +struct rcar_cmm_config {
> +	struct {
> +		bool enable;
> +		struct drm_color_lut *table;
> +	} lut;
> +};
> +
> +#if IS_ENABLED(CONFIG_DRM_RCAR_CMM)
> +int rcar_cmm_init(struct platform_device *pdev);
> +
> +int rcar_cmm_enable(struct platform_device *pdev);
> +void rcar_cmm_disable(struct platform_device *pdev);
> +
> +int rcar_cmm_setup(struct platform_device *pdev,
> +		   const struct rcar_cmm_config *config);
> +#else
> +static inline int rcar_cmm_init(struct platform_device *pdev)
> +{
> +	return 0;
> +}
> +
> +static inline int rcar_cmm_enable(struct platform_device *pdev)
> +{
> +	return 0;
> +}
> +
> +static inline void rcar_cmm_disable(struct platform_device *pdev)
> +{
> +}
> +
> +static int rcar_cmm_setup(struct platform_device *pdev,
> +			  const struct rcar_cmm_config *config)
> +{
> +	return 0;
> +}
> +#endif /* IS_ENABLED(CONFIG_DRM_RCAR_CMM) */
> +
> +#endif /* __RCAR_CMM_H__ */
>


^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [PATCH v4 2/9] dt-bindings: display, renesas,du: Document cmms property
  2019-09-06 13:54 ` [PATCH v4 2/9] dt-bindings: display, renesas,du: Document cmms property Jacopo Mondi
@ 2019-09-11 16:06   ` Kieran Bingham
  2019-09-17 17:58     ` Rob Herring
  0 siblings, 1 reply; 38+ messages in thread
From: Kieran Bingham @ 2019-09-11 16:06 UTC (permalink / raw)
  To: Jacopo Mondi, laurent.pinchart, geert, horms, uli+renesas,
	VenkataRajesh.Kalakodima
  Cc: airlied, daniel, koji.matsuoka.xm, muroya,
	Harsha.ManjulaMallikarjun, linux-renesas-soc, dri-devel,
	linux-kernel, devicetree, robh+dt, mark.rutland

Hi Jacopo,

On 06/09/2019 14:54, Jacopo Mondi wrote:
> Document the newly added 'cmms' property which accepts a list of phandle
> and channel index pairs that point to the CMM units available for each
> Display Unit output video channel.
> 
> Signed-off-by: Jacopo Mondi <jacopo+renesas@jmondi.org>
> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> ---
>  Documentation/devicetree/bindings/display/renesas,du.txt | 5 +++++
>  1 file changed, 5 insertions(+)
> 
> diff --git a/Documentation/devicetree/bindings/display/renesas,du.txt b/Documentation/devicetree/bindings/display/renesas,du.txt
> index c97dfacad281..1773b0a2f54f 100644
> --- a/Documentation/devicetree/bindings/display/renesas,du.txt
> +++ b/Documentation/devicetree/bindings/display/renesas,du.txt
> @@ -45,6 +45,10 @@ Required Properties:
>      instance that serves the DU channel, and the channel index identifies the
>      LIF instance in that VSP.
> 
> +  - renesas,cmms: A list of phandles to the CMM instances present in the SoC,
> +    one for each available DU channel. The property shall not be specified for
> +    SoCs that do not provide any CMM (such as V3M and V3H).
> +
>  Required nodes:
> 
>  The connections to the DU output video ports are modeled using the OF graph
> @@ -91,6 +95,7 @@ Example: R8A7795 (R-Car H3) ES2.0 DU
>  			 <&cpg CPG_MOD 721>;
>  		clock-names = "du.0", "du.1", "du.2", "du.3";
>  		vsps = <&vspd0 0>, <&vspd1 0>, <&vspd2 0>, <&vspd0 1>;
> +		renesas,cmms = <&cmm0 &cmm1 &cmm2 &cmm3>;

Should these be comma separated in the same fashion as the vsps are
separated?

I don't really mind either way though ...

Reviewed-by: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com>


> 
>  		ports {
>  			#address-cells = <1>;
> --
> 2.23.0
> 


^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [PATCH v4 9/9] arm64: dts: renesas: Add CMM units to Gen3 SoCs
  2019-09-06 13:54 ` [PATCH v4 9/9] arm64: dts: renesas: Add CMM units to Gen3 SoCs Jacopo Mondi
@ 2019-09-11 18:16   ` Kieran Bingham
  2019-09-11 19:35     ` Geert Uytterhoeven
  0 siblings, 1 reply; 38+ messages in thread
From: Kieran Bingham @ 2019-09-11 18:16 UTC (permalink / raw)
  To: Jacopo Mondi, laurent.pinchart, geert, horms, uli+renesas,
	VenkataRajesh.Kalakodima
  Cc: airlied, daniel, koji.matsuoka.xm, muroya,
	Harsha.ManjulaMallikarjun, linux-renesas-soc, dri-devel,
	linux-kernel

Hi Jacopo,

On 06/09/2019 14:54, Jacopo Mondi wrote:
> Add CMM units to Renesas R-Car Gen3 SoC that support it, and reference them
> from the Display Unit they are connected to.
> 
> Sort the 'vsps' and 'renesas,cmm' entries in the DU unit consistently
> in all the involved DTS.

I think if you chose the ordering in the r8a7795, then you only have to
adjust/correct the ordering in the r8a7796 and r8a77965 ...

Especially as you haven't changed the ordering of r8a77970, and r8a77980
which have the status after the vsps entry.


> 
> Signed-off-by: Jacopo Mondi <jacopo+renesas@jmondi.org>
> ---
>  arch/arm64/boot/dts/renesas/r8a7795.dtsi  | 40 ++++++++++++++++++++++-
>  arch/arm64/boot/dts/renesas/r8a7796.dtsi  | 28 ++++++++++++++++
>  arch/arm64/boot/dts/renesas/r8a77965.dtsi | 28 ++++++++++++++++
>  arch/arm64/boot/dts/renesas/r8a77990.dtsi | 22 ++++++++++++-
>  arch/arm64/boot/dts/renesas/r8a77995.dtsi | 22 ++++++++++++-
>  5 files changed, 137 insertions(+), 3 deletions(-)
> 
> diff --git a/arch/arm64/boot/dts/renesas/r8a7795.dtsi b/arch/arm64/boot/dts/renesas/r8a7795.dtsi
> index 6675462f7585..67c242a447bc 100644
> --- a/arch/arm64/boot/dts/renesas/r8a7795.dtsi
> +++ b/arch/arm64/boot/dts/renesas/r8a7795.dtsi
> @@ -2939,6 +2939,42 @@
>  			iommus = <&ipmmu_vi1 10>;
>  		};
>  
> +		cmm0: cmm@fea40000 {
> +			compatible = "renesas,r8a7795-cmm",
> +				     "renesas,rcar-gen3-cmm";
> +			reg = <0 0xfea40000 0 0x1000>;
> +			power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
> +			clocks = <&cpg CPG_MOD 711>;
> +			resets = <&cpg 711>;
> +		};
> +
> +		cmm1: cmm@fea50000 {
> +			compatible = "renesas,r8a7795-cmm",
> +				     "renesas,rcar-gen3-cmm";
> +			reg = <0 0xfea50000 0 0x1000>;
> +			power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
> +			clocks = <&cpg CPG_MOD 710>;
> +			resets = <&cpg 710>;
> +		};
> +
> +		cmm2: cmm@fea60000 {
> +			compatible = "renesas,r8a7795-cmm",
> +				     "renesas,rcar-gen3-cmm";
> +			reg = <0 0xfea60000 0 0x1000>;
> +			power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
> +			clocks = <&cpg CPG_MOD 709>;
> +			resets = <&cpg 709>;
> +		};
> +
> +		cmm3: cmm@fea70000 {
> +			compatible = "renesas,r8a7795-cmm",
> +				     "renesas,rcar-gen3-cmm";
> +			reg = <0 0xfea70000 0 0x1000>;
> +			power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
> +			clocks = <&cpg CPG_MOD 708>;
> +			resets = <&cpg 708>;
> +		};
> +
>  		csi20: csi2@fea80000 {
>  			compatible = "renesas,r8a7795-csi2";
>  			reg = <0 0xfea80000 0 0x10000>;
> @@ -3142,9 +3178,11 @@
>  				 <&cpg CPG_MOD 722>,
>  				 <&cpg CPG_MOD 721>;
>  			clock-names = "du.0", "du.1", "du.2", "du.3";
> -			vsps = <&vspd0 0>, <&vspd1 0>, <&vspd2 0>, <&vspd0 1>;
>  			status = "disabled";

I'm not sure the vsps should be below the status = disabled line.

I'd have this as:

	clock-names...
	vsps...
	renesas,cmms...
		<blank line>
	status...
		<blank line>
	ports...

>  
> +			vsps = <&vspd0 0>, <&vspd1 0>, <&vspd2 0>, <&vspd0 1>;
> +			renesas,cmms = <&cmm0 &cmm1 &cmm2 &cmm3>;

I think these should be separated by comma's to show they are separate
references, or references to separate phandles or such.

The only precedence I could find was in pmu_a53:

          interrupt-affinity = <&a53_0>, <&a53_1>, <&a53_2>, <&a53_3>;


> +
>  			ports {
>  				#address-cells = <1>;
>  				#size-cells = <0>;
> diff --git a/arch/arm64/boot/dts/renesas/r8a7796.dtsi b/arch/arm64/boot/dts/renesas/r8a7796.dtsi
> index 822c96601d3c..837c3b2da773 100644
> --- a/arch/arm64/boot/dts/renesas/r8a7796.dtsi
> +++ b/arch/arm64/boot/dts/renesas/r8a7796.dtsi
> @@ -2641,6 +2641,33 @@
>  			renesas,fcp = <&fcpvi0>;
>  		};
>  
> +		cmm0: cmm@fea40000 {
> +			compatible = "renesas,r8a7796-cmm",
> +				     "renesas,rcar-gen3-cmm";
> +			reg = <0 0xfea40000 0 0x1000>;
> +			power-domains = <&sysc R8A7796_PD_ALWAYS_ON>;
> +			clocks = <&cpg CPG_MOD 711>;
> +			resets = <&cpg 711>;
> +		};
> +
> +		cmm1: cmm@fea50000 {
> +			compatible = "renesas,r8a7796-cmm",
> +				     "renesas,rcar-gen3-cmm";
> +			reg = <0 0xfea50000 0 0x1000>;
> +			power-domains = <&sysc R8A7796_PD_ALWAYS_ON>;
> +			clocks = <&cpg CPG_MOD 710>;
> +			resets = <&cpg 710>;
> +		};
> +
> +		cmm2: cmm@fea60000 {
> +			compatible = "renesas,r8a7796-cmm",
> +				     "renesas,rcar-gen3-cmm";
> +			reg = <0 0xfea60000 0 0x1000>;
> +			power-domains = <&sysc R8A7796_PD_ALWAYS_ON>;
> +			clocks = <&cpg CPG_MOD 709>;
> +			resets = <&cpg 709>;
> +		};
> +
>  		csi20: csi2@fea80000 {
>  			compatible = "renesas,r8a7796-csi2";
>  			reg = <0 0xfea80000 0 0x10000>;
> @@ -2794,6 +2821,7 @@
>  			status = "disabled";
>  
>  			vsps = <&vspd0 0>, <&vspd1 0>, <&vspd2 0>;
> +			renesas,cmms = <&cmm0 &cmm1 &cmm2>;

Aha, yes, I'd move this vsps rather than the one at r8a7795, which I'd
consider to be more 'correct'.


>  
>  			ports {
>  				#address-cells = <1>;
> diff --git a/arch/arm64/boot/dts/renesas/r8a77965.dtsi b/arch/arm64/boot/dts/renesas/r8a77965.dtsi
> index 4ae163220f60..c7635e8b261c 100644
> --- a/arch/arm64/boot/dts/renesas/r8a77965.dtsi
> +++ b/arch/arm64/boot/dts/renesas/r8a77965.dtsi
> @@ -2320,6 +2320,33 @@
>  			resets = <&cpg 611>;
>  		};
>  
> +		cmm0: cmm@fea40000 {
> +			compatible = "renesas,r8a77965-cmm",
> +				     "renesas,rcar-gen3-cmm";
> +			reg = <0 0xfea40000 0 0x1000>;
> +			power-domains = <&sysc R8A77965_PD_ALWAYS_ON>;
> +			clocks = <&cpg CPG_MOD 711>;
> +			resets = <&cpg 711>;
> +		};
> +
> +		cmm1: cmm@fea50000 {
> +			compatible = "renesas,r8a77965-cmm",
> +				     "renesas,rcar-gen3-cmm";
> +			reg = <0 0xfea50000 0 0x1000>;
> +			power-domains = <&sysc R8A77965_PD_ALWAYS_ON>;
> +			clocks = <&cpg CPG_MOD 710>;
> +			resets = <&cpg 710>;
> +		};
> +
> +		cmm3: cmm@fea70000 {
> +			compatible = "renesas,r8a77965-cmm",
> +				     "renesas,rcar-gen3-cmm";
> +			reg = <0 0xfea70000 0 0x1000>;
> +			power-domains = <&sysc R8A77965_PD_ALWAYS_ON>;
> +			clocks = <&cpg CPG_MOD 708>;
> +			resets = <&cpg 708>;
> +		};
> +
>  		csi20: csi2@fea80000 {
>  			compatible = "renesas,r8a77965-csi2";
>  			reg = <0 0xfea80000 0 0x10000>;
> @@ -2470,6 +2497,7 @@
>  			status = "disabled";
>  
>  			vsps = <&vspd0 0>, <&vspd1 0>, <&vspd0 1>;
> +			renesas,cmms = <&cmm0 &cmm1 &cmm3>;

Again, I'd consider this the wrong sort order, due to the status'
importance. I wouldn't hide it in the middle.

>  
>  			ports {
>  				#address-cells = <1>;
> diff --git a/arch/arm64/boot/dts/renesas/r8a77990.dtsi b/arch/arm64/boot/dts/renesas/r8a77990.dtsi
> index 455954c3d98e..5e3d758a033f 100644
> --- a/arch/arm64/boot/dts/renesas/r8a77990.dtsi
> +++ b/arch/arm64/boot/dts/renesas/r8a77990.dtsi
> @@ -1727,6 +1727,24 @@
>  			iommus = <&ipmmu_vi0 9>;
>  		};
>  
> +		cmm0: cmm@fea40000 {
> +			compatible = "renesas,r8a77990-cmm",
> +				     "renesas,rcar-gen3-cmm";
> +			reg = <0 0xfea40000 0 0x1000>;
> +			power-domains = <&sysc R8A77990_PD_ALWAYS_ON>;
> +			clocks = <&cpg CPG_MOD 711>;
> +			resets = <&cpg 711>;
> +		};
> +
> +		cmm1: cmm@fea50000 {
> +			compatible = "renesas,r8a77990-cmm",
> +				     "renesas,rcar-gen3-cmm";
> +			reg = <0 0xfea50000 0 0x1000>;
> +			power-domains = <&sysc R8A77990_PD_ALWAYS_ON>;
> +			clocks = <&cpg CPG_MOD 710>;
> +			resets = <&cpg 710>;
> +		};
> +
>  		csi40: csi2@feaa0000 {
>  			compatible = "renesas,r8a77990-csi2";
>  			reg = <0 0xfeaa0000 0 0x10000>;
> @@ -1768,9 +1786,11 @@
>  			clock-names = "du.0", "du.1";
>  			resets = <&cpg 724>;
>  			reset-names = "du.0";
> -			vsps = <&vspd0 0>, <&vspd1 0>;
>  			status = "disabled";
>  
> +			vsps = <&vspd0 0>, <&vspd1 0>;
> +			renesas,cmms = <&cmm0 &cmm1>;


Same ... :D

> +
>  			ports {
>  				#address-cells = <1>;
>  				#size-cells = <0>;
> diff --git a/arch/arm64/boot/dts/renesas/r8a77995.dtsi b/arch/arm64/boot/dts/renesas/r8a77995.dtsi
> index 183fef86cf7c..6838a81f5caa 100644
> --- a/arch/arm64/boot/dts/renesas/r8a77995.dtsi
> +++ b/arch/arm64/boot/dts/renesas/r8a77995.dtsi
> @@ -993,6 +993,24 @@
>  			iommus = <&ipmmu_vi0 9>;
>  		};
>  
> +		cmm0: cmm@fea40000 {
> +			compatible = "renesas,r8a77995-cmm",
> +				     "renesas,rcar-gen3-cmm";
> +			reg = <0 0xfea40000 0 0x1000>;
> +			power-domains = <&sysc R8A77995_PD_ALWAYS_ON>;
> +			clocks = <&cpg CPG_MOD 711>;
> +			resets = <&cpg 711>;
> +		};
> +
> +		cmm1: cmm@fea50000 {
> +			compatible = "renesas,r8a77995-cmm",
> +				     "renesas,rcar-gen3-cmm";
> +			reg = <0 0xfea50000 0 0x1000>;
> +			power-domains = <&sysc R8A77995_PD_ALWAYS_ON>;
> +			clocks = <&cpg CPG_MOD 710>;
> +			resets = <&cpg 710>;
> +		};
> +
>  		du: display@feb00000 {
>  			compatible = "renesas,du-r8a77995";
>  			reg = <0 0xfeb00000 0 0x40000>;
> @@ -1003,9 +1021,11 @@
>  			clock-names = "du.0", "du.1";
>  			resets = <&cpg 724>;
>  			reset-names = "du.0";
> -			vsps = <&vspd0 0>, <&vspd1 0>;
>  			status = "disabled";
>  
> +			vsps = <&vspd0 0>, <&vspd1 0>;
> +			renesas,cmms = <&cmm0 &cmm1>;
> +

Same.

>  			ports {
>  				#address-cells = <1>;
>  				#size-cells = <0>;
> 


^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [PATCH v4 6/9] drm: rcar-du: crtc: Enable and disable CMMs
  2019-09-06 13:54 ` [PATCH v4 6/9] drm: rcar-du: crtc: Enable and disable CMMs Jacopo Mondi
@ 2019-09-11 18:40   ` Kieran Bingham
  2019-09-12  8:07     ` Jacopo Mondi
  0 siblings, 1 reply; 38+ messages in thread
From: Kieran Bingham @ 2019-09-11 18:40 UTC (permalink / raw)
  To: Jacopo Mondi, laurent.pinchart, geert, horms, uli+renesas,
	VenkataRajesh.Kalakodima
  Cc: airlied, daniel, koji.matsuoka.xm, muroya,
	Harsha.ManjulaMallikarjun, linux-renesas-soc, dri-devel,
	linux-kernel

Hi Jacopo,

On 06/09/2019 14:54, Jacopo Mondi wrote:
> Enable/disable the CMM associated with a CRTC at CRTC start and stop
> time and enable the CMM unit through the Display Extensional Functions
> register at group setup time.
> 
> Reviewed-by: Ulrich Hecht <uli+renesas@fpond.eu>
> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> Signed-off-by: Jacopo Mondi <jacopo+renesas@jmondi.org>
> ---
>  drivers/gpu/drm/rcar-du/rcar_du_crtc.c  | 7 +++++++
>  drivers/gpu/drm/rcar-du/rcar_du_group.c | 8 ++++++++
>  drivers/gpu/drm/rcar-du/rcar_du_regs.h  | 5 +++++
>  3 files changed, 20 insertions(+)
> 
> diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
> index 23f1d6cc1719..3dac605c3a67 100644
> --- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
> +++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
> @@ -21,6 +21,7 @@
>  #include <drm/drm_plane_helper.h>
>  #include <drm/drm_vblank.h>
>  
> +#include "rcar_cmm.h"
>  #include "rcar_du_crtc.h"
>  #include "rcar_du_drv.h"
>  #include "rcar_du_encoder.h"
> @@ -619,6 +620,9 @@ static void rcar_du_crtc_stop(struct rcar_du_crtc *rcrtc)
>  	if (rcar_du_has(rcrtc->dev, RCAR_DU_FEATURE_VSP1_SOURCE))
>  		rcar_du_vsp_disable(rcrtc);
>  
> +	if (rcrtc->cmm)
> +		rcar_cmm_disable(rcrtc->cmm);
> +
>  	/*
>  	 * Select switch sync mode. This stops display operation and configures
>  	 * the HSYNC and VSYNC signals as inputs.
> @@ -686,6 +690,9 @@ static void rcar_du_crtc_atomic_enable(struct drm_crtc *crtc,
>  	}
>  
>  	rcar_du_crtc_start(rcrtc);
> +
> +	if (rcrtc->cmm)
> +		rcar_cmm_enable(rcrtc->cmm);
>  }
>  
>  static void rcar_du_crtc_atomic_disable(struct drm_crtc *crtc,
> diff --git a/drivers/gpu/drm/rcar-du/rcar_du_group.c b/drivers/gpu/drm/rcar-du/rcar_du_group.c
> index 9eee47969e77..25d0fc125d7a 100644
> --- a/drivers/gpu/drm/rcar-du/rcar_du_group.c
> +++ b/drivers/gpu/drm/rcar-du/rcar_du_group.c
> @@ -147,6 +147,14 @@ static void rcar_du_group_setup(struct rcar_du_group *rgrp)
>  
>  	rcar_du_group_setup_pins(rgrp);
>  
> +	if (rcar_du_has(rcdu, RCAR_DU_FEATURE_CMM)) {
> +		u32 defr7 = DEFR7_CODE
> +			  | (rgrp->cmms_mask & BIT(1) ? DEFR7_CMME1 : 0)
> +			  | (rgrp->cmms_mask & BIT(0) ? DEFR7_CMME0 : 0);
> +
> +		rcar_du_group_write(rgrp, DEFR7, defr7);
> +	}
> +

What's the effect here on platforms with a CMM, but with
CONFIG_DRM_RCAR_CMM unset?

Will this incorrectly configure the DU ?

Will it stall the display if the DU tries to interact with another
module which is not enabled?


>  	if (rcdu->info->gen >= 2) {
>  		rcar_du_group_setup_defr8(rgrp);
>  		rcar_du_group_setup_didsr(rgrp);
> diff --git a/drivers/gpu/drm/rcar-du/rcar_du_regs.h b/drivers/gpu/drm/rcar-du/rcar_du_regs.h
> index bc87f080b170..fb9964949368 100644
> --- a/drivers/gpu/drm/rcar-du/rcar_du_regs.h
> +++ b/drivers/gpu/drm/rcar-du/rcar_du_regs.h
> @@ -197,6 +197,11 @@
>  #define DEFR6_MLOS1		(1 << 2)
>  #define DEFR6_DEFAULT		(DEFR6_CODE | DEFR6_TCNE1)
>  
> +#define DEFR7			0x000ec
> +#define DEFR7_CODE		(0x7779 << 16)
> +#define DEFR7_CMME1		BIT(6)
> +#define DEFR7_CMME0		BIT(4)
> +
>  /* -----------------------------------------------------------------------------
>   * R8A7790-only Control Registers
>   */
> 


^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [PATCH v4 4/9] drm: rcar-du: Claim CMM support for Gen3 SoCs
  2019-09-06 13:54 ` [PATCH v4 4/9] drm: rcar-du: Claim CMM support for Gen3 SoCs Jacopo Mondi
@ 2019-09-11 18:45   ` Kieran Bingham
  0 siblings, 0 replies; 38+ messages in thread
From: Kieran Bingham @ 2019-09-11 18:45 UTC (permalink / raw)
  To: Jacopo Mondi, laurent.pinchart, geert, horms, uli+renesas,
	VenkataRajesh.Kalakodima
  Cc: airlied, daniel, koji.matsuoka.xm, muroya,
	Harsha.ManjulaMallikarjun, linux-renesas-soc, dri-devel,
	linux-kernel

Hi Jacopo,

On 06/09/2019 14:54, Jacopo Mondi wrote:
> Add CMM to the list of supported features for Gen3 SoCs that provide it:
> - R8A7795
> - R8A7796
> - R8A77965
> - R8A7799x
> 
> Leave R8A77970 out as V3M and V3H are the only Gen3 SoCs that do not
> support CMM.
> 
> Reviewed-by: Ulrich Hecht <uli+renesas@fpond.eu>
> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>

LGTM.

Reviewed-by: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com>

> Signed-off-by: Jacopo Mondi <jacopo+renesas@jmondi.org>
> ---
>  drivers/gpu/drm/rcar-du/rcar_du_drv.c | 12 ++++++++----
>  drivers/gpu/drm/rcar-du/rcar_du_drv.h |  1 +
>  2 files changed, 9 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/gpu/drm/rcar-du/rcar_du_drv.c b/drivers/gpu/drm/rcar-du/rcar_du_drv.c
> index 6df37c2a9678..018480a8f35c 100644
> --- a/drivers/gpu/drm/rcar-du/rcar_du_drv.c
> +++ b/drivers/gpu/drm/rcar-du/rcar_du_drv.c
> @@ -276,7 +276,8 @@ static const struct rcar_du_device_info rcar_du_r8a7795_info = {
>  	.features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK
>  		  | RCAR_DU_FEATURE_VSP1_SOURCE
>  		  | RCAR_DU_FEATURE_INTERLACED
> -		  | RCAR_DU_FEATURE_TVM_SYNC,
> +		  | RCAR_DU_FEATURE_TVM_SYNC
> +		  | RCAR_DU_FEATURE_CMM,
>  	.channels_mask = BIT(3) | BIT(2) | BIT(1) | BIT(0),
>  	.routes = {
>  		/*
> @@ -309,7 +310,8 @@ static const struct rcar_du_device_info rcar_du_r8a7796_info = {
>  	.features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK
>  		  | RCAR_DU_FEATURE_VSP1_SOURCE
>  		  | RCAR_DU_FEATURE_INTERLACED
> -		  | RCAR_DU_FEATURE_TVM_SYNC,
> +		  | RCAR_DU_FEATURE_TVM_SYNC
> +		  | RCAR_DU_FEATURE_CMM,
>  	.channels_mask = BIT(2) | BIT(1) | BIT(0),
>  	.routes = {
>  		/*
> @@ -338,7 +340,8 @@ static const struct rcar_du_device_info rcar_du_r8a77965_info = {
>  	.features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK
>  		  | RCAR_DU_FEATURE_VSP1_SOURCE
>  		  | RCAR_DU_FEATURE_INTERLACED
> -		  | RCAR_DU_FEATURE_TVM_SYNC,
> +		  | RCAR_DU_FEATURE_TVM_SYNC
> +		  | RCAR_DU_FEATURE_CMM,
>  	.channels_mask = BIT(3) | BIT(1) | BIT(0),
>  	.routes = {
>  		/*
> @@ -386,7 +389,8 @@ static const struct rcar_du_device_info rcar_du_r8a77970_info = {
>  static const struct rcar_du_device_info rcar_du_r8a7799x_info = {
>  	.gen = 3,
>  	.features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK
> -		  | RCAR_DU_FEATURE_VSP1_SOURCE,
> +		  | RCAR_DU_FEATURE_VSP1_SOURCE
> +		  | RCAR_DU_FEATURE_CMM,
>  	.channels_mask = BIT(1) | BIT(0),
>  	.routes = {
>  		/*
> diff --git a/drivers/gpu/drm/rcar-du/rcar_du_drv.h b/drivers/gpu/drm/rcar-du/rcar_du_drv.h
> index 1327cd0df90a..a00dccc447aa 100644
> --- a/drivers/gpu/drm/rcar-du/rcar_du_drv.h
> +++ b/drivers/gpu/drm/rcar-du/rcar_du_drv.h
> @@ -28,6 +28,7 @@ struct rcar_du_encoder;
>  #define RCAR_DU_FEATURE_VSP1_SOURCE	BIT(1)	/* Has inputs from VSP1 */
>  #define RCAR_DU_FEATURE_INTERLACED	BIT(2)	/* HW supports interlaced */
>  #define RCAR_DU_FEATURE_TVM_SYNC	BIT(3)	/* Has TV switch/sync modes */
> +#define RCAR_DU_FEATURE_CMM		BIT(4)	/* Has CMM */
>  
>  #define RCAR_DU_QUIRK_ALIGN_128B	BIT(0)	/* Align pitches to 128 bytes */
>  
> 


^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [PATCH v4 7/9] drm: rcar-du: crtc: Register GAMMA_LUT properties
  2019-09-06 13:54 ` [PATCH v4 7/9] drm: rcar-du: crtc: Register GAMMA_LUT properties Jacopo Mondi
@ 2019-09-11 18:47   ` Kieran Bingham
  0 siblings, 0 replies; 38+ messages in thread
From: Kieran Bingham @ 2019-09-11 18:47 UTC (permalink / raw)
  To: Jacopo Mondi, laurent.pinchart, geert, horms, uli+renesas,
	VenkataRajesh.Kalakodima
  Cc: airlied, daniel, koji.matsuoka.xm, muroya,
	Harsha.ManjulaMallikarjun, linux-renesas-soc, dri-devel,
	linux-kernel

Hi Jacopo,

On 06/09/2019 14:54, Jacopo Mondi wrote:
> Enable the GAMMA_LUT KMS property using the framework helpers to
> register the property and set the associated gamma table maximum size.
> 
> Reviewed-by: Ulrich Hecht <uli+renesas@fpond.eu>
> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>

LGTM.

Reviewed-by: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com>

> Signed-off-by: Jacopo Mondi <jacopo+renesas@jmondi.org>
> ---
>  drivers/gpu/drm/rcar-du/rcar_du_crtc.c | 4 ++++
>  1 file changed, 4 insertions(+)
> 
> diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
> index 3dac605c3a67..dc59eeec990c 100644
> --- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
> +++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
> @@ -1082,6 +1082,7 @@ static const struct drm_crtc_funcs crtc_funcs_gen3 = {
>  	.set_crc_source = rcar_du_crtc_set_crc_source,
>  	.verify_crc_source = rcar_du_crtc_verify_crc_source,
>  	.get_crc_sources = rcar_du_crtc_get_crc_sources,
> +	.gamma_set = drm_atomic_helper_legacy_gamma_set,
>  };
>  
>  /* -----------------------------------------------------------------------------
> @@ -1205,6 +1206,9 @@ int rcar_du_crtc_create(struct rcar_du_group *rgrp, unsigned int swindex,
>  	if (rcdu->cmms[swindex]) {
>  		rcrtc->cmm = rcdu->cmms[swindex];
>  		rgrp->cmms_mask |= BIT(hwindex % 2);
> +
> +		drm_mode_crtc_set_gamma_size(crtc, CM2_LUT_SIZE);
> +		drm_crtc_enable_color_mgmt(crtc, 0, false, CM2_LUT_SIZE);
>  	}
>  
>  	drm_crtc_helper_add(crtc, &crtc_helper_funcs);
> 


^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [PATCH v4 1/9] dt-bindings: display: renesas,cmm: Add R-Car CMM documentation
  2019-09-06 13:54 ` [PATCH v4 1/9] dt-bindings: display: renesas,cmm: Add R-Car CMM documentation Jacopo Mondi
@ 2019-09-11 19:04   ` Kieran Bingham
  2019-09-17 17:55   ` Rob Herring
  2019-09-18 22:08   ` Laurent Pinchart
  2 siblings, 0 replies; 38+ messages in thread
From: Kieran Bingham @ 2019-09-11 19:04 UTC (permalink / raw)
  To: Jacopo Mondi, laurent.pinchart, geert, horms, uli+renesas,
	VenkataRajesh.Kalakodima
  Cc: airlied, daniel, koji.matsuoka.xm, muroya,
	Harsha.ManjulaMallikarjun, linux-renesas-soc, dri-devel,
	linux-kernel, devicetree, robh+dt, mark.rutland

Hi Jacopo,

On 06/09/2019 14:54, Jacopo Mondi wrote:
> Add device tree bindings documentation for the Renesas R-Car Display
> Unit Color Management Module.
> 
> CMM is the image enhancement module available on each R-Car DU video
> channel on R-Car Gen2 and Gen3 SoCs (V3H and V3M excluded).
> 
> Signed-off-by: Jacopo Mondi <jacopo+renesas@jmondi.org>
> ---
>  .../bindings/display/renesas,cmm.yaml         | 64 +++++++++++++++++++
>  1 file changed, 64 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/display/renesas,cmm.yaml
> 
> diff --git a/Documentation/devicetree/bindings/display/renesas,cmm.yaml b/Documentation/devicetree/bindings/display/renesas,cmm.yaml
> new file mode 100644
> index 000000000000..9e5922689cd7
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/display/renesas,cmm.yaml
> @@ -0,0 +1,64 @@
> +# SPDX-License-Identifier: GPL-2.0
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/display/renesas,cmm.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: Renesas R-Car Color Management Module (CMM)
> +
> +maintainers:
> +  - Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> +  - Kieran Bingham <kieran.bingham+renesas@ideasonboard.com>
> +  - Jacopo Mondi <jacopo+renesas@jmondi.org>
> +
> +description: |+
> +  Renesas R-Car color management module connected to R-Car DU video channels.
> +  It provides image enhancement functions such as 1-D look-up tables (LUT),
> +  3-D look-up tables (CMU), 1D-histogram generation (HGO), and color

s/CMU/CLU/


> +  space conversion (CSC).
> +
> +properties:
> +  compatible:
> +    items:
> +      - enum:
> +        - renesas,r8a7795-cmm
> +        - renesas,r8a7796-cmm
> +        - renesas,r8a77965-cmm
> +        - renesas,r8a77990-cmm
> +        - renesas,r8a77995-cmm
> +      - enum:
> +        - renesas,rcar-gen3-cmm
> +        - renesas,rcar-gen2-cmm
> +  reg:
> +    maxItems: 1
> +
> +  clocks:
> +    maxItems: 1
> +
> +  resets:
> +    maxItems: 1
> +
> +  power-domains:
> +    maxItems: 1
> +
> +required:
> +  - compatible
> +  - reg
> +  - clocks
> +  - resets
> +  - power-domains
> +
> +additionalProperties: false
> +
> +examples:
> +  - |
> +    #include <dt-bindings/clock/r8a7796-cpg-mssr.h>
> +    #include <dt-bindings/power/r8a7796-sysc.h>
> +
> +    cmm0: cmm@fea40000 {
> +         compatible = "renesas,r8a7796-cmm";
> +         reg = <0 0xfea40000 0 0x1000>;
> +         power-domains = <&sysc R8A7796_PD_ALWAYS_ON>;
> +         clocks = <&cpg CPG_MOD 711>;
> +         resets = <&cpg 711>;
> +    };
> --
> 2.23.0
> 


^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [PATCH v4 9/9] arm64: dts: renesas: Add CMM units to Gen3 SoCs
  2019-09-11 18:16   ` Kieran Bingham
@ 2019-09-11 19:35     ` Geert Uytterhoeven
  0 siblings, 0 replies; 38+ messages in thread
From: Geert Uytterhoeven @ 2019-09-11 19:35 UTC (permalink / raw)
  To: Kieran Bingham, Jacopo Mondi
  Cc: Laurent Pinchart, Simon Horman, Ulrich Hecht,
	VenkataRajesh.Kalakodima, David Airlie, Daniel Vetter,
	Koji Matsuoka, muroya, Harsha.ManjulaMallikarjun, Linux-Renesas,
	DRI Development, Linux Kernel Mailing List

Hi Kieran, Jacopo,

On Wed, Sep 11, 2019 at 8:16 PM Kieran Bingham
<kieran.bingham+renesas@ideasonboard.com> wrote:
> On 06/09/2019 14:54, Jacopo Mondi wrote:
> > Add CMM units to Renesas R-Car Gen3 SoC that support it, and reference them
> > from the Display Unit they are connected to.
> >
> > Sort the 'vsps' and 'renesas,cmm' entries in the DU unit consistently
> > in all the involved DTS.
>
> I think if you chose the ordering in the r8a7795, then you only have to
> adjust/correct the ordering in the r8a7796 and r8a77965 ...
>
> Especially as you haven't changed the ordering of r8a77970, and r8a77980
> which have the status after the vsps entry.
>
>
> >
> > Signed-off-by: Jacopo Mondi <jacopo+renesas@jmondi.org>

> > --- a/arch/arm64/boot/dts/renesas/r8a7795.dtsi
> > +++ b/arch/arm64/boot/dts/renesas/r8a7795.dtsi

> > @@ -3142,9 +3178,11 @@
> >                                <&cpg CPG_MOD 722>,
> >                                <&cpg CPG_MOD 721>;
> >                       clock-names = "du.0", "du.1", "du.2", "du.3";
> > -                     vsps = <&vspd0 0>, <&vspd1 0>, <&vspd2 0>, <&vspd0 1>;
> >                       status = "disabled";
>
> I'm not sure the vsps should be below the status = disabled line.
>
> I'd have this as:
>
>         clock-names...
>         vsps...
>         renesas,cmms...
>                 <blank line>
>         status...
>                 <blank line>
>         ports...

Indeed.

And better write "ports { ... }", so it's clear this is a subnode.

>
> >
> > +                     vsps = <&vspd0 0>, <&vspd1 0>, <&vspd2 0>, <&vspd0 1>;

And the above will become "renesas,vsps", needing another reordering?

> > +                     renesas,cmms = <&cmm0 &cmm1 &cmm2 &cmm3>;
>
> I think these should be separated by comma's to show they are separate
> references, or references to separate phandles or such.

Yep, looks better, and makes the grouping clear.

> The only precedence I could find was in pmu_a53:
>
>           interrupt-affinity = <&a53_0>, <&a53_1>, <&a53_2>, <&a53_3>;

That's because most other phandle stuff has #<foo>-cells as non-zero.

We do have

    clocks = ... <&audio_clk_a>, <&audio_clk_b>, <&audio_clk_c>;

Gr{oetje,eeting}s,

                        Geert

-- 
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [PATCH v4 3/9] drm: rcar-du: Add support for CMM
  2019-09-11 15:54   ` Kieran Bingham
@ 2019-09-12  7:59     ` Jacopo Mondi
  2019-09-12  9:49       ` Kieran Bingham
  0 siblings, 1 reply; 38+ messages in thread
From: Jacopo Mondi @ 2019-09-12  7:59 UTC (permalink / raw)
  To: Kieran Bingham
  Cc: Jacopo Mondi, laurent.pinchart, geert, horms, uli+renesas,
	VenkataRajesh.Kalakodima, airlied, daniel, koji.matsuoka.xm,
	muroya, Harsha.ManjulaMallikarjun, linux-renesas-soc, dri-devel,
	linux-kernel

[-- Attachment #1: Type: text/plain, Size: 13027 bytes --]

Hi Kiernan,
   thanks for review

On Wed, Sep 11, 2019 at 04:54:58PM +0100, Kieran Bingham wrote:
> Hi Jacopo,
>
> <This time replying to the mail with ML's included Doh!>
>
> On 06/09/2019 14:43, Jacopo Mondi wrote:
> > Add a driver for the R-Car Display Unit Color Correction Module.
> >
> > In most of Gen3 SoCs, each DU output channel is provided with a CMM unit
> > to perform image enhancement and color correction.
> >
> > Add support for CMM through a driver that supports configuration of
> > the 1-dimensional LUT table. More advanced CMM feature will be
>
> s/feature/features/
>
> > implemented on top of this basic one.
>
> s/basic/initial/
>
> >
> > Signed-off-by: Jacopo Mondi <jacopo+renesas@jmondi.org>
> > ---
> >  drivers/gpu/drm/rcar-du/Kconfig    |   7 +
> >  drivers/gpu/drm/rcar-du/Makefile   |   1 +
> >  drivers/gpu/drm/rcar-du/rcar_cmm.c | 251 +++++++++++++++++++++++++++++
> >  drivers/gpu/drm/rcar-du/rcar_cmm.h |  61 +++++++
> >  4 files changed, 320 insertions(+)
> >  create mode 100644 drivers/gpu/drm/rcar-du/rcar_cmm.c
> >  create mode 100644 drivers/gpu/drm/rcar-du/rcar_cmm.h
> >
> > diff --git a/drivers/gpu/drm/rcar-du/Kconfig
> b/drivers/gpu/drm/rcar-du/Kconfig
> > index 1529849e217e..539d232790d1 100644
> > --- a/drivers/gpu/drm/rcar-du/Kconfig
> > +++ b/drivers/gpu/drm/rcar-du/Kconfig
> > @@ -13,6 +13,13 @@ config DRM_RCAR_DU
> >  	  Choose this option if you have an R-Car chipset.
> >  	  If M is selected the module will be called rcar-du-drm.
> >
> > +config DRM_RCAR_CMM
> > +	bool "R-Car DU Color Management Module (CMM) Support"
> > +	depends on DRM && OF
> > +	depends on DRM_RCAR_DU
> > +	help
> > +	  Enable support for R-Car Color Management Module (CMM).
> > +
> >  config DRM_RCAR_DW_HDMI
> >  	tristate "R-Car DU Gen3 HDMI Encoder Support"
> >  	depends on DRM && OF
> > diff --git a/drivers/gpu/drm/rcar-du/Makefile
> b/drivers/gpu/drm/rcar-du/Makefile
> > index 6c2ed9c46467..4d1187ccc3e5 100644
> > --- a/drivers/gpu/drm/rcar-du/Makefile
> > +++ b/drivers/gpu/drm/rcar-du/Makefile
> > @@ -15,6 +15,7 @@ rcar-du-drm-$(CONFIG_DRM_RCAR_LVDS)	+= rcar_du_of.o \
> >  rcar-du-drm-$(CONFIG_DRM_RCAR_VSP)	+= rcar_du_vsp.o
> >  rcar-du-drm-$(CONFIG_DRM_RCAR_WRITEBACK) += rcar_du_writeback.o
> >
> > +obj-$(CONFIG_DRM_RCAR_CMM)		+= rcar_cmm.o
> >  obj-$(CONFIG_DRM_RCAR_DU)		+= rcar-du-drm.o
> >  obj-$(CONFIG_DRM_RCAR_DW_HDMI)		+= rcar_dw_hdmi.o
> >  obj-$(CONFIG_DRM_RCAR_LVDS)		+= rcar_lvds.o
> > diff --git a/drivers/gpu/drm/rcar-du/rcar_cmm.c
> b/drivers/gpu/drm/rcar-du/rcar_cmm.c
> > new file mode 100644
> > index 000000000000..3cacdc4474c7
> > --- /dev/null
> > +++ b/drivers/gpu/drm/rcar-du/rcar_cmm.c
> > @@ -0,0 +1,251 @@
> > +// SPDX-License-Identifier: GPL-2.0+
> > +/*
> > + * rcar_cmm.c -- R-Car Display Unit Color Management Module
> > + *
> > + * Copyright (C) 2019 Jacopo Mondi <jacopo+renesas@jmondi.org>
> > + */
> > +
> > +#include <linux/io.h>
> > +#include <linux/module.h>
> > +#include <linux/of.h>
> > +#include <linux/platform_device.h>
> > +#include <linux/pm_runtime.h>
> > +
> > +#include <drm/drm_color_mgmt.h>
> > +
> > +#include "rcar_cmm.h"
> > +
> > +#define CM2_LUT_CTRL		0x0000
> > +#define CM2_LUT_CTRL_LUT_EN	BIT(0)
>
> I'd have a new line here
>
> > +#define CM2_LUT_TBL_BASE	0x0600
> > +#define CM2_LUT_TBL(__i)	(CM2_LUT_TBL_BASE + (__i) * 4)
> > +
> > +struct rcar_cmm {
> > +	void __iomem *base;
> > +	bool enabled;
> > +
> > +	/*
> > +	 * @lut:		1D-LUT status
> > +	 * @lut.enabled:	1D-LUT enabled flag
> > +	 * @lut.table:		Table of 1D-LUT entries scaled to hardware
> > +	 *			precision (8-bits per color component)
> > +	 */
> > +	struct {
> > +		bool enabled;
> > +		u32 table[CM2_LUT_SIZE];
> > +	} lut;
> > +};
> > +
> > +static inline int rcar_cmm_read(struct rcar_cmm *rcmm, u32 reg)
> > +{
> > +	return ioread32(rcmm->base + reg);
> > +}
> > +
> > +static inline void rcar_cmm_write(struct rcar_cmm *rcmm, u32 reg, u32
> data)
> > +{
> > +	iowrite32(data, rcmm->base + reg);
> > +}
> > +
> > +/*
> > + * rcar_cmm_lut_extract() - Scale down to hardware precision the DRM
> LUT table
> > + *			    entries and store them.
> > + * @rcmm: Pointer to the CMM device
> > + * @drm_lut: Pointer to the DRM LUT table
> > + */
> > +static void rcar_cmm_lut_extract(struct rcar_cmm *rcmm,
> > +				 const struct drm_color_lut *drm_lut)
> > +{
> > +	unsigned int i;
>
> I think you're missing the following here:
>
> 	if (!drm_lut)
> 		return;
>
> You mention below that drm_lut could be passed in as NULL, which would
> cause a segfault here otherwise.
>

Thanks for spotting, but I should have removed that comment, as I have
killed that case in rcar_du_atomic_commit_update_cmm() in patch 8/9,
as from my testing it seems it is not possible to provide from
userspace a non populated LUT table to just re-enable the CMM.

So we're fine here.

>
> > +
> > +	for (i = 0; i < CM2_LUT_SIZE; ++i) {
> > +		const struct drm_color_lut *lut = &drm_lut[i];
> > +
> > +		rcmm->lut.table[i] = drm_color_lut_extract(lut->red, 8) << 16
> > +				   | drm_color_lut_extract(lut->green, 8) << 8
> > +				   | drm_color_lut_extract(lut->blue, 8);
> > +	}
> > +}
> > +
> > +/*
> > + * rcar_cmm_lut_write() - Write to hardware the LUT table entries
> from the
> > + *			  local table.
> > + * @rcmm: Pointer to the CMM device
> > + */
> > +static void rcar_cmm_lut_write(struct rcar_cmm *rcmm)
> > +{
> > +	unsigned int i;
> > +
> > +	for (i = 0; i < CM2_LUT_SIZE; ++i)
> > +		rcar_cmm_write(rcmm, CM2_LUT_TBL(i), rcmm->lut.table[i]);
> > +}
> > +
> > +/*
> > + * rcar_cmm_setup() - Configure the CMM unit.
> > + * @pdev: The platform device associated with the CMM instance
> > + * @config: The CRTC-provided configuration.
>
> I don't think CRTC-provided should be hyphenated like that.
> Perhaps just:
> 	"The colour management configuration".
>
> As I don't think who provides the configuration is relevant to the
> actual call.
>

I have no idea. I've been bought into this by the comment

"CRTC-provided" is a compound adjective, qualifying the noun
"configuration". It thus needs a hyphen.

I'm happy to remove it for a simpler version.

Thanks
   j

> > + * Configure the CMM unit with the CRTC-provided configuration.
>
> s/CRTC-provided/given/
>
> > + * Currently enabling, disabling and programming of the 1-D LUT unit is
> > + * supported.
> > + */
> > +int rcar_cmm_setup(struct platform_device *pdev,
> > +		   const struct rcar_cmm_config *config)
> > +{
> > +	struct rcar_cmm *rcmm = platform_get_drvdata(pdev);
> > +
> > +	/*
> > +	 * As rcar_cmm_setup() is called by atomic commit tail helper, it might
> > +	 * be called when the CMM is disabled. As we can't program the hardware
> > +	 * in that case, store the configuration internally and apply it when
> > +	 * the CMM will be enabled by the CRTC through rcar_cmm_enable().
> > +	 */
> > +	if (!rcmm->enabled) {
> > +		if (!config->lut.enable)
> > +			return 0;
> > +
> > +		rcar_cmm_lut_extract(rcmm, config->lut.table);
> > +		rcmm->lut.enabled = true;
> > +
> > +		return 0;
> > +	}
> > +
> > +	/* Stop LUT operations if requested. */
> > +	if (!config->lut.enable) {
> > +		if (rcmm->lut.enabled) {
> > +			rcar_cmm_write(rcmm, CM2_LUT_CTRL, 0);
> > +			rcmm->lut.enabled = false;
> > +		}
> > +
> > +		return 0;
> > +	}
> > +
> > +	/*
> > +	 * Enable LUT and program the new gamma table values.
> > +	 *
> > +	 * FIXME: In order to have stable operations it is required to first
> > +	 * enable the 1D-LUT and then program its table entries. This seems to
> > +	 * contradict what the chip manual reports, and will have to be
> > +	 * reconsidered when implementing support for double buffering.
> > +	 */
> > +	if (!rcmm->lut.enabled) {
> > +		rcar_cmm_write(rcmm, CM2_LUT_CTRL, CM2_LUT_CTRL_LUT_EN);
> > +		rcmm->lut.enabled = true;
> > +	}
> > +
> > +	rcar_cmm_lut_extract(rcmm, config->lut.table);
> > +	rcar_cmm_lut_write(rcmm);
> > +
> > +	return 0;
> > +}
> > +EXPORT_SYMBOL_GPL(rcar_cmm_setup);
> > +
> > +/*
> > + * rcar_cmm_enable() - Enable the CMM unit.
> > + * @pdev: The platform device associated with the CMM instance
> > + *
> > + * Enable the CMM unit by enabling the parent clock and enabling the CMM
> > + * components, such as 1-D LUT, if requested.
> > + */
> > +int rcar_cmm_enable(struct platform_device *pdev)
> > +{
> > +	struct rcar_cmm *rcmm = platform_get_drvdata(pdev);
> > +	int ret;
> > +
> > +	ret = pm_runtime_get_sync(&pdev->dev);
> > +	if (ret < 0)
> > +		return ret;
> > +
> > +	/* Apply the LUT table values saved at rcar_cmm_setup() time. */
> > +	if (rcmm->lut.enabled) {
> > +		rcar_cmm_write(rcmm, CM2_LUT_CTRL, CM2_LUT_CTRL_LUT_EN);
> > +		rcar_cmm_lut_write(rcmm);
> > +	}
> > +
> > +	rcmm->enabled = true;
> > +
> > +	return 0;
> > +}
> > +EXPORT_SYMBOL_GPL(rcar_cmm_enable);
> > +
> > +/*
> > + * rcar_cmm_disable() - Disable the CMM unit.
> > + * @pdev: The platform device associated with the CMM instance
> > + *
> > + * Disable the CMM unit by stopping the parent clock.
> > + */
> > +void rcar_cmm_disable(struct platform_device *pdev)
> > +{
> > +	struct rcar_cmm *rcmm = platform_get_drvdata(pdev);
> > +
> > +	rcar_cmm_write(rcmm, CM2_LUT_CTRL, 0);
> > +
> > +	pm_runtime_put(&pdev->dev);
> > +
> > +	rcmm->lut.enabled = false;
> > +	rcmm->enabled = false;
> > +}
> > +EXPORT_SYMBOL_GPL(rcar_cmm_disable);
> > +
> > +/*
> > + * rcar_cmm_init() - Make sure the CMM has probed.
> > + * @pdev: The platform device associated with the CMM instance
> > + *
> > + * Return: 0 if the CMM has probed, -EPROBE_DEFER otherwise
> > + */
> > +int rcar_cmm_init(struct platform_device *pdev)
> > +{
> > +	struct rcar_cmm *rcmm = platform_get_drvdata(pdev);
> > +
> > +	if (!rcmm)
> > +		return -EPROBE_DEFER;
> > +
> > +	return 0;
> > +}
> > +EXPORT_SYMBOL_GPL(rcar_cmm_init);
> > +
> > +static int rcar_cmm_probe(struct platform_device *pdev)
> > +{
> > +	struct rcar_cmm *rcmm;
> > +
> > +	rcmm = devm_kzalloc(&pdev->dev, sizeof(*rcmm), GFP_KERNEL);
> > +	if (!rcmm)
> > +		return -ENOMEM;
> > +	platform_set_drvdata(pdev, rcmm);
> > +
> > +	rcmm->base = devm_platform_ioremap_resource(pdev, 0);
> > +	if (IS_ERR(rcmm->base))
> > +		return PTR_ERR(rcmm->base);
> > +
> > +	pm_runtime_enable(&pdev->dev);
> > +
> > +	return 0;
> > +}
> > +
> > +static int rcar_cmm_remove(struct platform_device *pdev)
> > +{
> > +	pm_runtime_disable(&pdev->dev);
> > +
> > +	return 0;
> > +}
> > +
> > +static const struct of_device_id rcar_cmm_of_table[] = {
> > +	{ .compatible = "renesas,rcar-gen3-cmm", },
> > +	{ .compatible = "renesas,rcar-gen2-cmm", },
> > +	{ },
> > +};
> > +MODULE_DEVICE_TABLE(of, rcar_cmm_of_table);
> > +
> > +static struct platform_driver rcar_cmm_platform_driver = {
> > +	.probe		= rcar_cmm_probe,
> > +	.remove		= rcar_cmm_remove,
> > +	.driver		= {
> > +		.name	= "rcar-cmm",
> > +		.of_match_table = rcar_cmm_of_table,
> > +	},
> > +};
> > +
> > +module_platform_driver(rcar_cmm_platform_driver);
> > +
> > +MODULE_AUTHOR("Jacopo Mondi <jacopo+renesas@jmondi.org>");
> > +MODULE_DESCRIPTION("Renesas R-Car CMM Driver");
> > +MODULE_LICENSE("GPL v2");
> > diff --git a/drivers/gpu/drm/rcar-du/rcar_cmm.h
> b/drivers/gpu/drm/rcar-du/rcar_cmm.h
> > new file mode 100644
> > index 000000000000..15a2c874b6a6
> > --- /dev/null
> > +++ b/drivers/gpu/drm/rcar-du/rcar_cmm.h
> > @@ -0,0 +1,61 @@
> > +/* SPDX-License-Identifier: GPL-2.0+ */
> > +/*
> > + * rcar_cmm.h -- R-Car Display Unit Color Management Module
> > + *
> > + * Copyright (C) 2019 Jacopo Mondi <jacopo+renesas@jmondi.org>
> > + */
> > +
> > +#ifndef __RCAR_CMM_H__
> > +#define __RCAR_CMM_H__
> > +
> > +#define CM2_LUT_SIZE		256
> > +
> > +struct drm_color_lut;
> > +struct platform_device;
> > +
> > +/**
> > + * struct rcar_cmm_config - CMM configuration
> > + *
> > + * @lut:	1D-LUT configuration
> > + * @lut.enable:	1D-LUT enable flag
> > + * @lut.table:	1D-LUT table entries. Might be set to NULL when the
> CMM has to
> > + *		be re-enabled but not re=programmed.
>
> So lut.table can be NULL ... See comment at rcar_cmm_lut_extract()
>
> > + */
> > +struct rcar_cmm_config {
> > +	struct {
> > +		bool enable;
> > +		struct drm_color_lut *table;
> > +	} lut;
> > +};
> > +
> > +#if IS_ENABLED(CONFIG_DRM_RCAR_CMM)
> > +int rcar_cmm_init(struct platform_device *pdev);
> > +
> > +int rcar_cmm_enable(struct platform_device *pdev);
> > +void rcar_cmm_disable(struct platform_device *pdev);
> > +
> > +int rcar_cmm_setup(struct platform_device *pdev,
> > +		   const struct rcar_cmm_config *config);
> > +#else
> > +static inline int rcar_cmm_init(struct platform_device *pdev)
> > +{
> > +	return 0;
> > +}
> > +
> > +static inline int rcar_cmm_enable(struct platform_device *pdev)
> > +{
> > +	return 0;
> > +}
> > +
> > +static inline void rcar_cmm_disable(struct platform_device *pdev)
> > +{
> > +}
> > +
> > +static int rcar_cmm_setup(struct platform_device *pdev,
> > +			  const struct rcar_cmm_config *config)
> > +{
> > +	return 0;
> > +}
> > +#endif /* IS_ENABLED(CONFIG_DRM_RCAR_CMM) */
> > +
> > +#endif /* __RCAR_CMM_H__ */
> >
>

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [PATCH v4 6/9] drm: rcar-du: crtc: Enable and disable CMMs
  2019-09-11 18:40   ` Kieran Bingham
@ 2019-09-12  8:07     ` Jacopo Mondi
  2019-09-12  9:19       ` Kieran Bingham
  0 siblings, 1 reply; 38+ messages in thread
From: Jacopo Mondi @ 2019-09-12  8:07 UTC (permalink / raw)
  To: Kieran Bingham
  Cc: Jacopo Mondi, laurent.pinchart, geert, horms, uli+renesas,
	VenkataRajesh.Kalakodima, airlied, daniel, koji.matsuoka.xm,
	muroya, Harsha.ManjulaMallikarjun, linux-renesas-soc, dri-devel,
	linux-kernel

[-- Attachment #1: Type: text/plain, Size: 3753 bytes --]

Hi Kieran,

On Wed, Sep 11, 2019 at 07:40:27PM +0100, Kieran Bingham wrote:
> Hi Jacopo,
>
> On 06/09/2019 14:54, Jacopo Mondi wrote:
> > Enable/disable the CMM associated with a CRTC at CRTC start and stop
> > time and enable the CMM unit through the Display Extensional Functions
> > register at group setup time.
> >
> > Reviewed-by: Ulrich Hecht <uli+renesas@fpond.eu>
> > Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> > Signed-off-by: Jacopo Mondi <jacopo+renesas@jmondi.org>
> > ---
> >  drivers/gpu/drm/rcar-du/rcar_du_crtc.c  | 7 +++++++
> >  drivers/gpu/drm/rcar-du/rcar_du_group.c | 8 ++++++++
> >  drivers/gpu/drm/rcar-du/rcar_du_regs.h  | 5 +++++
> >  3 files changed, 20 insertions(+)
> >
> > diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
> > index 23f1d6cc1719..3dac605c3a67 100644
> > --- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
> > +++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
> > @@ -21,6 +21,7 @@
> >  #include <drm/drm_plane_helper.h>
> >  #include <drm/drm_vblank.h>
> >
> > +#include "rcar_cmm.h"
> >  #include "rcar_du_crtc.h"
> >  #include "rcar_du_drv.h"
> >  #include "rcar_du_encoder.h"
> > @@ -619,6 +620,9 @@ static void rcar_du_crtc_stop(struct rcar_du_crtc *rcrtc)
> >  	if (rcar_du_has(rcrtc->dev, RCAR_DU_FEATURE_VSP1_SOURCE))
> >  		rcar_du_vsp_disable(rcrtc);
> >
> > +	if (rcrtc->cmm)
> > +		rcar_cmm_disable(rcrtc->cmm);
> > +
> >  	/*
> >  	 * Select switch sync mode. This stops display operation and configures
> >  	 * the HSYNC and VSYNC signals as inputs.
> > @@ -686,6 +690,9 @@ static void rcar_du_crtc_atomic_enable(struct drm_crtc *crtc,
> >  	}
> >
> >  	rcar_du_crtc_start(rcrtc);
> > +
> > +	if (rcrtc->cmm)
> > +		rcar_cmm_enable(rcrtc->cmm);
> >  }
> >
> >  static void rcar_du_crtc_atomic_disable(struct drm_crtc *crtc,
> > diff --git a/drivers/gpu/drm/rcar-du/rcar_du_group.c b/drivers/gpu/drm/rcar-du/rcar_du_group.c
> > index 9eee47969e77..25d0fc125d7a 100644
> > --- a/drivers/gpu/drm/rcar-du/rcar_du_group.c
> > +++ b/drivers/gpu/drm/rcar-du/rcar_du_group.c
> > @@ -147,6 +147,14 @@ static void rcar_du_group_setup(struct rcar_du_group *rgrp)
> >
> >  	rcar_du_group_setup_pins(rgrp);
> >
> > +	if (rcar_du_has(rcdu, RCAR_DU_FEATURE_CMM)) {
> > +		u32 defr7 = DEFR7_CODE
> > +			  | (rgrp->cmms_mask & BIT(1) ? DEFR7_CMME1 : 0)
> > +			  | (rgrp->cmms_mask & BIT(0) ? DEFR7_CMME0 : 0);
> > +
> > +		rcar_du_group_write(rgrp, DEFR7, defr7);
> > +	}
> > +
>
> What's the effect here on platforms with a CMM, but with
> CONFIG_DRM_RCAR_CMM unset?
>
> Will this incorrectly configure the DU ?
>
> Will it stall the display if the DU tries to interact with another
> module which is not enabled?

I recall I tested that (that's why I had to add stubs for CMM
functions, as I had linkage errors otherwise) and thing seems to be
fine as the CMM configuration/enblement resolve to an empty function.

Would you prefer to have this guarded by an #if IS_ENABLED() ?

Thanks
   j
>
>
> >  	if (rcdu->info->gen >= 2) {
> >  		rcar_du_group_setup_defr8(rgrp);
> >  		rcar_du_group_setup_didsr(rgrp);
> > diff --git a/drivers/gpu/drm/rcar-du/rcar_du_regs.h b/drivers/gpu/drm/rcar-du/rcar_du_regs.h
> > index bc87f080b170..fb9964949368 100644
> > --- a/drivers/gpu/drm/rcar-du/rcar_du_regs.h
> > +++ b/drivers/gpu/drm/rcar-du/rcar_du_regs.h
> > @@ -197,6 +197,11 @@
> >  #define DEFR6_MLOS1		(1 << 2)
> >  #define DEFR6_DEFAULT		(DEFR6_CODE | DEFR6_TCNE1)
> >
> > +#define DEFR7			0x000ec
> > +#define DEFR7_CODE		(0x7779 << 16)
> > +#define DEFR7_CMME1		BIT(6)
> > +#define DEFR7_CMME0		BIT(4)
> > +
> >  /* -----------------------------------------------------------------------------
> >   * R8A7790-only Control Registers
> >   */
> >
>

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [PATCH v4 6/9] drm: rcar-du: crtc: Enable and disable CMMs
  2019-09-12  8:07     ` Jacopo Mondi
@ 2019-09-12  9:19       ` Kieran Bingham
  2019-09-18 23:23         ` Laurent Pinchart
  0 siblings, 1 reply; 38+ messages in thread
From: Kieran Bingham @ 2019-09-12  9:19 UTC (permalink / raw)
  To: Jacopo Mondi
  Cc: Jacopo Mondi, laurent.pinchart, geert, horms, uli+renesas,
	VenkataRajesh.Kalakodima, airlied, daniel, koji.matsuoka.xm,
	muroya, Harsha.ManjulaMallikarjun, linux-renesas-soc, dri-devel,
	linux-kernel

Hi Jacopo,

On 12/09/2019 09:07, Jacopo Mondi wrote:
> Hi Kieran,
> 
> On Wed, Sep 11, 2019 at 07:40:27PM +0100, Kieran Bingham wrote:
>> Hi Jacopo,
>>
>> On 06/09/2019 14:54, Jacopo Mondi wrote:
>>> Enable/disable the CMM associated with a CRTC at CRTC start and stop
>>> time and enable the CMM unit through the Display Extensional Functions
>>> register at group setup time.
>>>
>>> Reviewed-by: Ulrich Hecht <uli+renesas@fpond.eu>
>>> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
>>> Signed-off-by: Jacopo Mondi <jacopo+renesas@jmondi.org>
>>> ---
>>>  drivers/gpu/drm/rcar-du/rcar_du_crtc.c  | 7 +++++++
>>>  drivers/gpu/drm/rcar-du/rcar_du_group.c | 8 ++++++++
>>>  drivers/gpu/drm/rcar-du/rcar_du_regs.h  | 5 +++++
>>>  3 files changed, 20 insertions(+)
>>>
>>> diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
>>> index 23f1d6cc1719..3dac605c3a67 100644
>>> --- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
>>> +++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
>>> @@ -21,6 +21,7 @@
>>>  #include <drm/drm_plane_helper.h>
>>>  #include <drm/drm_vblank.h>
>>>
>>> +#include "rcar_cmm.h"
>>>  #include "rcar_du_crtc.h"
>>>  #include "rcar_du_drv.h"
>>>  #include "rcar_du_encoder.h"
>>> @@ -619,6 +620,9 @@ static void rcar_du_crtc_stop(struct rcar_du_crtc *rcrtc)
>>>  	if (rcar_du_has(rcrtc->dev, RCAR_DU_FEATURE_VSP1_SOURCE))
>>>  		rcar_du_vsp_disable(rcrtc);
>>>
>>> +	if (rcrtc->cmm)
>>> +		rcar_cmm_disable(rcrtc->cmm);
>>> +
>>>  	/*
>>>  	 * Select switch sync mode. This stops display operation and configures
>>>  	 * the HSYNC and VSYNC signals as inputs.
>>> @@ -686,6 +690,9 @@ static void rcar_du_crtc_atomic_enable(struct drm_crtc *crtc,
>>>  	}
>>>
>>>  	rcar_du_crtc_start(rcrtc);
>>> +
>>> +	if (rcrtc->cmm)
>>> +		rcar_cmm_enable(rcrtc->cmm);
>>>  }
>>>
>>>  static void rcar_du_crtc_atomic_disable(struct drm_crtc *crtc,
>>> diff --git a/drivers/gpu/drm/rcar-du/rcar_du_group.c b/drivers/gpu/drm/rcar-du/rcar_du_group.c
>>> index 9eee47969e77..25d0fc125d7a 100644
>>> --- a/drivers/gpu/drm/rcar-du/rcar_du_group.c
>>> +++ b/drivers/gpu/drm/rcar-du/rcar_du_group.c
>>> @@ -147,6 +147,14 @@ static void rcar_du_group_setup(struct rcar_du_group *rgrp)
>>>
>>>  	rcar_du_group_setup_pins(rgrp);
>>>
>>> +	if (rcar_du_has(rcdu, RCAR_DU_FEATURE_CMM)) {
>>> +		u32 defr7 = DEFR7_CODE
>>> +			  | (rgrp->cmms_mask & BIT(1) ? DEFR7_CMME1 : 0)
>>> +			  | (rgrp->cmms_mask & BIT(0) ? DEFR7_CMME0 : 0);
>>> +
>>> +		rcar_du_group_write(rgrp, DEFR7, defr7);
>>> +	}
>>> +
>>
>> What's the effect here on platforms with a CMM, but with
>> CONFIG_DRM_RCAR_CMM unset?
>>
>> Will this incorrectly configure the DU ?
>>
>> Will it stall the display if the DU tries to interact with another
>> module which is not enabled?
> 
> I recall I tested that (that's why I had to add stubs for CMM
> functions, as I had linkage errors otherwise) and thing seems to be
> fine as the CMM configuration/enblement resolve to an empty function.

Yes, I see the stubs to allow for linkage, but it's the hardware I'm
concerned about. If it passes the tests and doesn't break then that's
probably ok ... but I'm really weary that we're enabling a hardware
pipeline with a disabled component in the middle.


> Would you prefer to have this guarded by an #if IS_ENABLED() ?

I don't think we need a compile time conditional, but I'd say it
probably needs to be more about whether the CMM has actually probed or not

Aha, and I see that in rcar_du_cmm_init() we already do a
call to rcar_cmm_init(), which if fails will leave rcdu->cmms[i] as
NULL. So that's catered for, which results in the rgrp->cmms_mask being
correctly representative of whether there is a CMM connected or not.

 ... so I think that means the ...
 "if (rcar_du_has(rcdu, RCAR_DU_FEATURE_CMM))" is somewhat redundant:


This could be:

  if (rgrp->cmms_mask) {
	u32 defr7 = DEFR7_CODE
		  | (rgrp->cmms_mask & BIT(1) ? DEFR7_CMME1 : 0)
		  | (rgrp->cmms_mask & BIT(0) ? DEFR7_CMME0 : 0);

  rcar_du_group_write(rgrp, DEFR7, defr7);

Or in fact, if we don't mind writing 0 to DEFR7 when there is no CMM
(which is safe by the looks of things as DEFR7 is available on all
platforms), then we can even remove the outer conditional, and leave
this all up to the ternary operators to write the correct value to the
defr7.


Phew ... net result - your current code *is* safe with the
CONFIG_DRM_RCAR_CMM option disabled. I'll leave it up to you if you want
to simplify the code here and remove the RCAR_DU_FEATURE_CMM.

As this RCAR_DU_FEATURE_CMM flag is only checked here, removing it would
however simplify all of the rcar_du_device_info structures.

So - with or without the _FEATURE_CMM" simplification, this patch looks
functional and safe so:


Reviewed-by: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com>


> Thanks
>    j
>>
>>
>>>  	if (rcdu->info->gen >= 2) {
>>>  		rcar_du_group_setup_defr8(rgrp);
>>>  		rcar_du_group_setup_didsr(rgrp);
>>> diff --git a/drivers/gpu/drm/rcar-du/rcar_du_regs.h b/drivers/gpu/drm/rcar-du/rcar_du_regs.h
>>> index bc87f080b170..fb9964949368 100644
>>> --- a/drivers/gpu/drm/rcar-du/rcar_du_regs.h
>>> +++ b/drivers/gpu/drm/rcar-du/rcar_du_regs.h
>>> @@ -197,6 +197,11 @@
>>>  #define DEFR6_MLOS1		(1 << 2)
>>>  #define DEFR6_DEFAULT		(DEFR6_CODE | DEFR6_TCNE1)
>>>
>>> +#define DEFR7			0x000ec
>>> +#define DEFR7_CODE		(0x7779 << 16)
>>> +#define DEFR7_CMME1		BIT(6)
>>> +#define DEFR7_CMME0		BIT(4)
>>> +
>>>  /* -----------------------------------------------------------------------------
>>>   * R8A7790-only Control Registers
>>>   */
>>>
>>


^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [PATCH v4 5/9] drm: rcar-du: kms: Initialize CMM instances
  2019-09-06 13:54 ` [PATCH v4 5/9] drm: rcar-du: kms: Initialize CMM instances Jacopo Mondi
@ 2019-09-12  9:27   ` Kieran Bingham
  0 siblings, 0 replies; 38+ messages in thread
From: Kieran Bingham @ 2019-09-12  9:27 UTC (permalink / raw)
  To: Jacopo Mondi, laurent.pinchart, geert, horms, uli+renesas,
	VenkataRajesh.Kalakodima
  Cc: airlied, daniel, koji.matsuoka.xm, muroya,
	Harsha.ManjulaMallikarjun, linux-renesas-soc, dri-devel,
	linux-kernel

Hi Jacopo,

On 06/09/2019 14:54, Jacopo Mondi wrote:
> Implement device tree parsing to collect the available CMM instances
> described by the 'renesas,cmms' property. Associate CMMs with CRTCs and
> store a mask of active CMMs in the DU group for later enablement.
> 
> Enforce the probe and suspend/resume ordering of DU and CMM by creating
> a stateless device link between the two.
> 
> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> Signed-off-by: Jacopo Mondi <jacopo+renesas@jmondi.org>
> ---
>  drivers/gpu/drm/rcar-du/rcar_du_crtc.c  |  6 +++
>  drivers/gpu/drm/rcar-du/rcar_du_crtc.h  |  2 +
>  drivers/gpu/drm/rcar-du/rcar_du_drv.h   |  2 +
>  drivers/gpu/drm/rcar-du/rcar_du_group.h |  2 +
>  drivers/gpu/drm/rcar-du/rcar_du_kms.c   | 68 +++++++++++++++++++++++++
>  5 files changed, 80 insertions(+)
> 
> diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
> index 2da46e3dc4ae..23f1d6cc1719 100644
> --- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
> +++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
> @@ -1194,6 +1194,12 @@ int rcar_du_crtc_create(struct rcar_du_group *rgrp, unsigned int swindex,
>  	if (ret < 0)
>  		return ret;
>  
> +	/* CMM might be disabled for this CRTC. */
> +	if (rcdu->cmms[swindex]) {
> +		rcrtc->cmm = rcdu->cmms[swindex];
> +		rgrp->cmms_mask |= BIT(hwindex % 2);
> +	}
> +

Good - this checks out :-D


>  	drm_crtc_helper_add(crtc, &crtc_helper_funcs);
>  
>  	/* Start with vertical blanking interrupt reporting disabled. */
> diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.h b/drivers/gpu/drm/rcar-du/rcar_du_crtc.h
> index 3b7fc668996f..5f2940c42225 100644
> --- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.h
> +++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.h
> @@ -39,6 +39,7 @@ struct rcar_du_vsp;
>   * @vblank_wait: wait queue used to signal vertical blanking
>   * @vblank_count: number of vertical blanking interrupts to wait for
>   * @group: CRTC group this CRTC belongs to
> + * @cmm: CMM associated with this CRTC
>   * @vsp: VSP feeding video to this CRTC
>   * @vsp_pipe: index of the VSP pipeline feeding video to this CRTC
>   * @writeback: the writeback connector
> @@ -64,6 +65,7 @@ struct rcar_du_crtc {
>  	unsigned int vblank_count;
>  
>  	struct rcar_du_group *group;
> +	struct platform_device *cmm;
>  	struct rcar_du_vsp *vsp;
>  	unsigned int vsp_pipe;
>  
> diff --git a/drivers/gpu/drm/rcar-du/rcar_du_drv.h b/drivers/gpu/drm/rcar-du/rcar_du_drv.h
> index a00dccc447aa..6316a1c5236c 100644
> --- a/drivers/gpu/drm/rcar-du/rcar_du_drv.h
> +++ b/drivers/gpu/drm/rcar-du/rcar_du_drv.h
> @@ -13,6 +13,7 @@
>  #include <linux/kernel.h>
>  #include <linux/wait.h>
>  
> +#include "rcar_cmm.h"
>  #include "rcar_du_crtc.h"
>  #include "rcar_du_group.h"
>  #include "rcar_du_vsp.h"
> @@ -86,6 +87,7 @@ struct rcar_du_device {
>  	struct rcar_du_encoder *encoders[RCAR_DU_OUTPUT_MAX];
>  
>  	struct rcar_du_group groups[RCAR_DU_MAX_GROUPS];
> +	struct platform_device *cmms[RCAR_DU_MAX_CRTCS];
>  	struct rcar_du_vsp vsps[RCAR_DU_MAX_VSPS];
>  
>  	struct {
> diff --git a/drivers/gpu/drm/rcar-du/rcar_du_group.h b/drivers/gpu/drm/rcar-du/rcar_du_group.h
> index 87950c1f6a52..e9906609c635 100644
> --- a/drivers/gpu/drm/rcar-du/rcar_du_group.h
> +++ b/drivers/gpu/drm/rcar-du/rcar_du_group.h
> @@ -22,6 +22,7 @@ struct rcar_du_device;
>   * @mmio_offset: registers offset in the device memory map
>   * @index: group index
>   * @channels_mask: bitmask of populated DU channels in this group
> + * @cmms_mask: bitmask of available CMMs in this group
>   * @num_crtcs: number of CRTCs in this group (1 or 2)
>   * @use_count: number of users of the group (rcar_du_group_(get|put))
>   * @used_crtcs: number of CRTCs currently in use
> @@ -37,6 +38,7 @@ struct rcar_du_group {
>  	unsigned int index;
>  
>  	unsigned int channels_mask;
> +	unsigned int cmms_mask;
>  	unsigned int num_crtcs;
>  	unsigned int use_count;
>  	unsigned int used_crtcs;
> diff --git a/drivers/gpu/drm/rcar-du/rcar_du_kms.c b/drivers/gpu/drm/rcar-du/rcar_du_kms.c
> index 2dc9caee8767..294630e56992 100644
> --- a/drivers/gpu/drm/rcar-du/rcar_du_kms.c
> +++ b/drivers/gpu/drm/rcar-du/rcar_du_kms.c
> @@ -17,7 +17,9 @@
>  #include <drm/drm_probe_helper.h>
>  #include <drm/drm_vblank.h>
>  
> +#include <linux/device.h>
>  #include <linux/of_graph.h>
> +#include <linux/of_platform.h>
>  #include <linux/wait.h>
>  
>  #include "rcar_du_crtc.h"
> @@ -614,6 +616,67 @@ static int rcar_du_vsps_init(struct rcar_du_device *rcdu)
>  	return ret;
>  }
>  
> +static int rcar_du_cmm_init(struct rcar_du_device *rcdu)
> +{
> +	const struct device_node *np = rcdu->dev->of_node;
> +	unsigned int i;
> +	int cells;
> +
> +	cells = of_property_count_u32_elems(np, "renesas,cmms");
> +	if (cells == -EINVAL)
> +		return 0;
> +
> +	if (cells > rcdu->num_crtcs) {
> +		dev_err(rcdu->dev,
> +			"Invalid number of entries in 'renesas,cmms'\n");
> +		return -EINVAL;
> +	}
> +
> +	for (i = 0; i < cells; ++i) {
> +		struct platform_device *pdev;
> +		struct device_link *link;
> +		struct device_node *cmm;
> +		int ret;
> +
> +		cmm = of_parse_phandle(np, "renesas,cmms", i);
> +		if (IS_ERR(cmm)) {
> +			dev_err(rcdu->dev,
> +				"Failed to parse 'renesas,cmms' property\n");
> +			return PTR_ERR(cmm);

Should we have a -ENOENT exception here somewhere?

Otherwise I think platforms without a CMM will fail, and new kernels
with old DTBs would also fail ?

(based on my interpretation in __of_parse_phandle_with_args() that not
finding a requested phandle returns -ENOENT).


Scratch that - I've just seen above with the
  cells = of_property_count_u32_elems(np, "renesas,cmms");

which will return 0 if this device doesn't have a CMM.

So - this all looks good to me.

Reviewed-by: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com>




> +		}
> +
> +		if (!of_device_is_available(cmm)) {
> +			/* It's fine to have a phandle to a non-enabled CMM. */
> +			of_node_put(cmm);
> +			continue;
> +		}
> +
> +		pdev = of_find_device_by_node(cmm);
> +		if (IS_ERR(pdev)) {
> +			dev_err(rcdu->dev, "No device found for CMM%u\n", i);
> +			of_node_put(cmm);
> +			return PTR_ERR(pdev);
> +		}
> +
> +		of_node_put(cmm);
> +
> +		ret = rcar_cmm_init(pdev);
> +		if (ret)
> +			return ret;
> +
> +		link = device_link_add(rcdu->dev, &pdev->dev, DL_FLAG_STATELESS);
> +		if (!link) {
> +			dev_err(rcdu->dev,
> +				"Failed to create device link to CMM%u\n", i);
> +			return -EINVAL;
> +		}
> +
> +		rcdu->cmms[i] = pdev;
> +	}
> +
> +	return 0;
> +}
> +
>  int rcar_du_modeset_init(struct rcar_du_device *rcdu)
>  {
>  	static const unsigned int mmio_offsets[] = {
> @@ -704,6 +767,11 @@ int rcar_du_modeset_init(struct rcar_du_device *rcdu)
>  			return ret;
>  	}
>  
> +	/* Initialize the Color Management Modules. */
> +	ret = rcar_du_cmm_init(rcdu);
> +	if (ret)
> +		return ret;> +
>  	/* Create the CRTCs. */
>  	for (swindex = 0, hwindex = 0; swindex < rcdu->num_crtcs; ++hwindex) {
>  		struct rcar_du_group *rgrp;
> 


^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [PATCH v4 3/9] drm: rcar-du: Add support for CMM
  2019-09-12  7:59     ` Jacopo Mondi
@ 2019-09-12  9:49       ` Kieran Bingham
  0 siblings, 0 replies; 38+ messages in thread
From: Kieran Bingham @ 2019-09-12  9:49 UTC (permalink / raw)
  To: Jacopo Mondi
  Cc: Jacopo Mondi, laurent.pinchart, geert, horms, uli+renesas,
	VenkataRajesh.Kalakodima, airlied, daniel, koji.matsuoka.xm,
	muroya, Harsha.ManjulaMallikarjun, linux-renesas-soc, dri-devel,
	linux-kernel

Hi Jacopo,

On 12/09/2019 08:59, Jacopo Mondi wrote:
> Hi Kiernan,
>    thanks for review
> 
> On Wed, Sep 11, 2019 at 04:54:58PM +0100, Kieran Bingham wrote:
>> Hi Jacopo,
>>
>> <This time replying to the mail with ML's included Doh!>
>>
>> On 06/09/2019 14:43, Jacopo Mondi wrote:
>>> Add a driver for the R-Car Display Unit Color Correction Module.
>>>
>>> In most of Gen3 SoCs, each DU output channel is provided with a CMM unit
>>> to perform image enhancement and color correction.
>>>
>>> Add support for CMM through a driver that supports configuration of
>>> the 1-dimensional LUT table. More advanced CMM feature will be
>>
>> s/feature/features/
>>
>>> implemented on top of this basic one.
>>
>> s/basic/initial/
>>
>>>
>>> Signed-off-by: Jacopo Mondi <jacopo+renesas@jmondi.org>
>>> ---
>>>  drivers/gpu/drm/rcar-du/Kconfig    |   7 +
>>>  drivers/gpu/drm/rcar-du/Makefile   |   1 +
>>>  drivers/gpu/drm/rcar-du/rcar_cmm.c | 251 +++++++++++++++++++++++++++++
>>>  drivers/gpu/drm/rcar-du/rcar_cmm.h |  61 +++++++
>>>  4 files changed, 320 insertions(+)
>>>  create mode 100644 drivers/gpu/drm/rcar-du/rcar_cmm.c
>>>  create mode 100644 drivers/gpu/drm/rcar-du/rcar_cmm.h
>>>
>>> diff --git a/drivers/gpu/drm/rcar-du/Kconfig
>> b/drivers/gpu/drm/rcar-du/Kconfig
>>> index 1529849e217e..539d232790d1 100644
>>> --- a/drivers/gpu/drm/rcar-du/Kconfig
>>> +++ b/drivers/gpu/drm/rcar-du/Kconfig
>>> @@ -13,6 +13,13 @@ config DRM_RCAR_DU
>>>  	  Choose this option if you have an R-Car chipset.
>>>  	  If M is selected the module will be called rcar-du-drm.
>>>
>>> +config DRM_RCAR_CMM
>>> +	bool "R-Car DU Color Management Module (CMM) Support"
>>> +	depends on DRM && OF
>>> +	depends on DRM_RCAR_DU
>>> +	help
>>> +	  Enable support for R-Car Color Management Module (CMM).
>>> +
>>>  config DRM_RCAR_DW_HDMI
>>>  	tristate "R-Car DU Gen3 HDMI Encoder Support"
>>>  	depends on DRM && OF
>>> diff --git a/drivers/gpu/drm/rcar-du/Makefile
>> b/drivers/gpu/drm/rcar-du/Makefile
>>> index 6c2ed9c46467..4d1187ccc3e5 100644
>>> --- a/drivers/gpu/drm/rcar-du/Makefile
>>> +++ b/drivers/gpu/drm/rcar-du/Makefile
>>> @@ -15,6 +15,7 @@ rcar-du-drm-$(CONFIG_DRM_RCAR_LVDS)	+= rcar_du_of.o \
>>>  rcar-du-drm-$(CONFIG_DRM_RCAR_VSP)	+= rcar_du_vsp.o
>>>  rcar-du-drm-$(CONFIG_DRM_RCAR_WRITEBACK) += rcar_du_writeback.o
>>>
>>> +obj-$(CONFIG_DRM_RCAR_CMM)		+= rcar_cmm.o
>>>  obj-$(CONFIG_DRM_RCAR_DU)		+= rcar-du-drm.o
>>>  obj-$(CONFIG_DRM_RCAR_DW_HDMI)		+= rcar_dw_hdmi.o
>>>  obj-$(CONFIG_DRM_RCAR_LVDS)		+= rcar_lvds.o
>>> diff --git a/drivers/gpu/drm/rcar-du/rcar_cmm.c
>> b/drivers/gpu/drm/rcar-du/rcar_cmm.c
>>> new file mode 100644
>>> index 000000000000..3cacdc4474c7
>>> --- /dev/null
>>> +++ b/drivers/gpu/drm/rcar-du/rcar_cmm.c
>>> @@ -0,0 +1,251 @@
>>> +// SPDX-License-Identifier: GPL-2.0+
>>> +/*
>>> + * rcar_cmm.c -- R-Car Display Unit Color Management Module
>>> + *
>>> + * Copyright (C) 2019 Jacopo Mondi <jacopo+renesas@jmondi.org>
>>> + */
>>> +
>>> +#include <linux/io.h>
>>> +#include <linux/module.h>
>>> +#include <linux/of.h>
>>> +#include <linux/platform_device.h>
>>> +#include <linux/pm_runtime.h>
>>> +
>>> +#include <drm/drm_color_mgmt.h>
>>> +
>>> +#include "rcar_cmm.h"
>>> +
>>> +#define CM2_LUT_CTRL		0x0000
>>> +#define CM2_LUT_CTRL_LUT_EN	BIT(0)
>>
>> I'd have a new line here
>>
>>> +#define CM2_LUT_TBL_BASE	0x0600
>>> +#define CM2_LUT_TBL(__i)	(CM2_LUT_TBL_BASE + (__i) * 4)
>>> +
>>> +struct rcar_cmm {
>>> +	void __iomem *base;
>>> +	bool enabled;
>>> +
>>> +	/*
>>> +	 * @lut:		1D-LUT status
>>> +	 * @lut.enabled:	1D-LUT enabled flag
>>> +	 * @lut.table:		Table of 1D-LUT entries scaled to hardware
>>> +	 *			precision (8-bits per color component)
>>> +	 */
>>> +	struct {
>>> +		bool enabled;
>>> +		u32 table[CM2_LUT_SIZE];
>>> +	} lut;
>>> +};
>>> +
>>> +static inline int rcar_cmm_read(struct rcar_cmm *rcmm, u32 reg)
>>> +{
>>> +	return ioread32(rcmm->base + reg);
>>> +}
>>> +
>>> +static inline void rcar_cmm_write(struct rcar_cmm *rcmm, u32 reg, u32
>> data)
>>> +{
>>> +	iowrite32(data, rcmm->base + reg);
>>> +}
>>> +
>>> +/*
>>> + * rcar_cmm_lut_extract() - Scale down to hardware precision the DRM
>> LUT table
>>> + *			    entries and store them.
>>> + * @rcmm: Pointer to the CMM device
>>> + * @drm_lut: Pointer to the DRM LUT table
>>> + */
>>> +static void rcar_cmm_lut_extract(struct rcar_cmm *rcmm,
>>> +				 const struct drm_color_lut *drm_lut)
>>> +{
>>> +	unsigned int i;
>>
>> I think you're missing the following here:
>>
>> 	if (!drm_lut)
>> 		return;
>>
>> You mention below that drm_lut could be passed in as NULL, which would
>> cause a segfault here otherwise.
>>
> 
> Thanks for spotting, but I should have removed that comment, as I have
> killed that case in rcar_du_atomic_commit_update_cmm() in patch 8/9,
> as from my testing it seems it is not possible to provide from
> userspace a non populated LUT table to just re-enable the CMM.
> 
> So we're fine here.

Great, in that case then with the comment removed, and the other
trivials in this handled however you see fit,

Reviewed-by: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com>



> 
>>
>>> +
>>> +	for (i = 0; i < CM2_LUT_SIZE; ++i) {
>>> +		const struct drm_color_lut *lut = &drm_lut[i];
>>> +
>>> +		rcmm->lut.table[i] = drm_color_lut_extract(lut->red, 8) << 16
>>> +				   | drm_color_lut_extract(lut->green, 8) << 8
>>> +				   | drm_color_lut_extract(lut->blue, 8);
>>> +	}
>>> +}
>>> +
>>> +/*
>>> + * rcar_cmm_lut_write() - Write to hardware the LUT table entries
>> from the
>>> + *			  local table.
>>> + * @rcmm: Pointer to the CMM device
>>> + */
>>> +static void rcar_cmm_lut_write(struct rcar_cmm *rcmm)
>>> +{
>>> +	unsigned int i;
>>> +
>>> +	for (i = 0; i < CM2_LUT_SIZE; ++i)
>>> +		rcar_cmm_write(rcmm, CM2_LUT_TBL(i), rcmm->lut.table[i]);
>>> +}
>>> +
>>> +/*
>>> + * rcar_cmm_setup() - Configure the CMM unit.
>>> + * @pdev: The platform device associated with the CMM instance
>>> + * @config: The CRTC-provided configuration.
>>
>> I don't think CRTC-provided should be hyphenated like that.
>> Perhaps just:
>> 	"The colour management configuration".
>>
>> As I don't think who provides the configuration is relevant to the
>> actual call.
>>
> 
> I have no idea. I've been bought into this by the comment
> 
> "CRTC-provided" is a compound adjective, qualifying the noun
> "configuration". It thus needs a hyphen.
> 
> I'm happy to remove it for a simpler version.

CRTC-provided just looks weird to me :-D however you wish to leave it is
up to you though :D


> +++ b/arch/arm64/boot/dts/renesas/r8a77965.dtsi
@@ -2320,6 +2320,33 @@
 			resets = <&cpg 611>;
 		};

+		cmm0: cmm@fea40000 {
+			compatible = "renesas,r8a77965-cmm",
+				     "renesas,rcar-gen3-cmm";
+			reg = <0 0xfea40000 0 0x1000>;
+			power-domains = <&sysc R8A77965_PD_ALWAYS_ON>;
+			clocks = <&cpg CPG_MOD 711>;
+			resets = <&cpg 711>;
+		};
+
+		cmm1: cmm@fea50000 {
+			compatible = "renesas,r8a77965-cmm",
+				     "renesas,rcar-gen3-cmm";
+			reg = <0 0xfea50000 0 0x1000>;
+			power-domains = <&sysc R8A77965_PD_ALWAYS_ON>;
+			clocks = <&cpg CPG_MOD 710>;
+			resets = <&cpg 710>;
+		};
+
+		cmm3: cmm@fea70000 {
+			compatible = "renesas,r8a77965-cmm",
+				     "renesas,rcar-gen3-cmm";
+			reg = <0 0xfea70000 0 0x1000>;
+			power-domains = <&sysc R8A77965_PD_ALWAYS_ON>;
+			clocks = <&cpg CPG_MOD 708>;
+			resets = <&cpg 708>;
+		};
+
 		csi20: csi2@fea80000 {
 			compatible = "renesas,r8a77965-csi2";
 			reg = <0 0xfea80000 0 0x10000>;
@@ -2470,6 +2497,7 @@
 			status = "disabled";

 			vsps = <&vspd0 0>, <&vspd1 0>, <&vspd0 1>;
+			renesas,cmms = <&cmm0 &cmm1 &cmm3>;
> Thanks
>    j
> 
>>> + * Configure the CMM unit with the CRTC-provided configuration.
>>
>> s/CRTC-provided/given/
>>
>>> + * Currently enabling, disabling and programming of the 1-D LUT unit is
>>> + * supported.
>>> + */
>>> +int rcar_cmm_setup(struct platform_device *pdev,
>>> +		   const struct rcar_cmm_config *config)
>>> +{
>>> +	struct rcar_cmm *rcmm = platform_get_drvdata(pdev);
>>> +
>>> +	/*
>>> +	 * As rcar_cmm_setup() is called by atomic commit tail helper, it might
>>> +	 * be called when the CMM is disabled. As we can't program the hardware
>>> +	 * in that case, store the configuration internally and apply it when
>>> +	 * the CMM will be enabled by the CRTC through rcar_cmm_enable().
>>> +	 */
>>> +	if (!rcmm->enabled) {
>>> +		if (!config->lut.enable)
>>> +			return 0;
>>> +
>>> +		rcar_cmm_lut_extract(rcmm, config->lut.table);
>>> +		rcmm->lut.enabled = true;
>>> +
>>> +		return 0;
>>> +	}
>>> +
>>> +	/* Stop LUT operations if requested. */
>>> +	if (!config->lut.enable) {
>>> +		if (rcmm->lut.enabled) {
>>> +			rcar_cmm_write(rcmm, CM2_LUT_CTRL, 0);
>>> +			rcmm->lut.enabled = false;
>>> +		}
>>> +
>>> +		return 0;
>>> +	}
>>> +
>>> +	/*
>>> +	 * Enable LUT and program the new gamma table values.
>>> +	 *
>>> +	 * FIXME: In order to have stable operations it is required to first
>>> +	 * enable the 1D-LUT and then program its table entries. This seems to
>>> +	 * contradict what the chip manual reports, and will have to be
>>> +	 * reconsidered when implementing support for double buffering.
>>> +	 */
>>> +	if (!rcmm->lut.enabled) {
>>> +		rcar_cmm_write(rcmm, CM2_LUT_CTRL, CM2_LUT_CTRL_LUT_EN);
>>> +		rcmm->lut.enabled = true;
>>> +	}
>>> +
>>> +	rcar_cmm_lut_extract(rcmm, config->lut.table);
>>> +	rcar_cmm_lut_write(rcmm);
>>> +
>>> +	return 0;
>>> +}
>>> +EXPORT_SYMBOL_GPL(rcar_cmm_setup);
>>> +
>>> +/*
>>> + * rcar_cmm_enable() - Enable the CMM unit.
>>> + * @pdev: The platform device associated with the CMM instance
>>> + *
>>> + * Enable the CMM unit by enabling the parent clock and enabling the CMM
>>> + * components, such as 1-D LUT, if requested.
>>> + */
>>> +int rcar_cmm_enable(struct platform_device *pdev)
>>> +{
>>> +	struct rcar_cmm *rcmm = platform_get_drvdata(pdev);
>>> +	int ret;
>>> +
>>> +	ret = pm_runtime_get_sync(&pdev->dev);
>>> +	if (ret < 0)
>>> +		return ret;
>>> +
>>> +	/* Apply the LUT table values saved at rcar_cmm_setup() time. */
>>> +	if (rcmm->lut.enabled) {
>>> +		rcar_cmm_write(rcmm, CM2_LUT_CTRL, CM2_LUT_CTRL_LUT_EN);
>>> +		rcar_cmm_lut_write(rcmm);
>>> +	}
>>> +
>>> +	rcmm->enabled = true;
>>> +
>>> +	return 0;
>>> +}
>>> +EXPORT_SYMBOL_GPL(rcar_cmm_enable);
>>> +
>>> +/*
>>> + * rcar_cmm_disable() - Disable the CMM unit.
>>> + * @pdev: The platform device associated with the CMM instance
>>> + *
>>> + * Disable the CMM unit by stopping the parent clock.
>>> + */
>>> +void rcar_cmm_disable(struct platform_device *pdev)
>>> +{
>>> +	struct rcar_cmm *rcmm = platform_get_drvdata(pdev);
>>> +
>>> +	rcar_cmm_write(rcmm, CM2_LUT_CTRL, 0);
>>> +
>>> +	pm_runtime_put(&pdev->dev);
>>> +
>>> +	rcmm->lut.enabled = false;
>>> +	rcmm->enabled = false;
>>> +}
>>> +EXPORT_SYMBOL_GPL(rcar_cmm_disable);
>>> +
>>> +/*
>>> + * rcar_cmm_init() - Make sure the CMM has probed.
>>> + * @pdev: The platform device associated with the CMM instance
>>> + *
>>> + * Return: 0 if the CMM has probed, -EPROBE_DEFER otherwise
>>> + */
>>> +int rcar_cmm_init(struct platform_device *pdev)
>>> +{
>>> +	struct rcar_cmm *rcmm = platform_get_drvdata(pdev);
>>> +
>>> +	if (!rcmm)
>>> +		return -EPROBE_DEFER;
>>> +
>>> +	return 0;
>>> +}
>>> +EXPORT_SYMBOL_GPL(rcar_cmm_init);
>>> +
>>> +static int rcar_cmm_probe(struct platform_device *pdev)
>>> +{
>>> +	struct rcar_cmm *rcmm;
>>> +
>>> +	rcmm = devm_kzalloc(&pdev->dev, sizeof(*rcmm), GFP_KERNEL);
>>> +	if (!rcmm)
>>> +		return -ENOMEM;
>>> +	platform_set_drvdata(pdev, rcmm);
>>> +
>>> +	rcmm->base = devm_platform_ioremap_resource(pdev, 0);
>>> +	if (IS_ERR(rcmm->base))
>>> +		return PTR_ERR(rcmm->base);
>>> +
>>> +	pm_runtime_enable(&pdev->dev);
>>> +
>>> +	return 0;
>>> +}
>>> +
>>> +static int rcar_cmm_remove(struct platform_device *pdev)
>>> +{
>>> +	pm_runtime_disable(&pdev->dev);
>>> +
>>> +	return 0;
>>> +}
>>> +
>>> +static const struct of_device_id rcar_cmm_of_table[] = {
>>> +	{ .compatible = "renesas,rcar-gen3-cmm", },
>>> +	{ .compatible = "renesas,rcar-gen2-cmm", },
>>> +	{ },
>>> +};
>>> +MODULE_DEVICE_TABLE(of, rcar_cmm_of_table);
>>> +
>>> +static struct platform_driver rcar_cmm_platform_driver = {
>>> +	.probe		= rcar_cmm_probe,
>>> +	.remove		= rcar_cmm_remove,
>>> +	.driver		= {
>>> +		.name	= "rcar-cmm",
>>> +		.of_match_table = rcar_cmm_of_table,
>>> +	},
>>> +};
>>> +
>>> +module_platform_driver(rcar_cmm_platform_driver);
>>> +
>>> +MODULE_AUTHOR("Jacopo Mondi <jacopo+renesas@jmondi.org>");
>>> +MODULE_DESCRIPTION("Renesas R-Car CMM Driver");
>>> +MODULE_LICENSE("GPL v2");
>>> diff --git a/drivers/gpu/drm/rcar-du/rcar_cmm.h
>> b/drivers/gpu/drm/rcar-du/rcar_cmm.h
>>> new file mode 100644
>>> index 000000000000..15a2c874b6a6
>>> --- /dev/null
>>> +++ b/drivers/gpu/drm/rcar-du/rcar_cmm.h
>>> @@ -0,0 +1,61 @@
>>> +/* SPDX-License-Identifier: GPL-2.0+ */
>>> +/*
>>> + * rcar_cmm.h -- R-Car Display Unit Color Management Module
>>> + *
>>> + * Copyright (C) 2019 Jacopo Mondi <jacopo+renesas@jmondi.org>
>>> + */
>>> +
>>> +#ifndef __RCAR_CMM_H__
>>> +#define __RCAR_CMM_H__
>>> +
>>> +#define CM2_LUT_SIZE		256
>>> +
>>> +struct drm_color_lut;
>>> +struct platform_device;
>>> +
>>> +/**
>>> + * struct rcar_cmm_config - CMM configuration
>>> + *
>>> + * @lut:	1D-LUT configuration
>>> + * @lut.enable:	1D-LUT enable flag
>>> + * @lut.table:	1D-LUT table entries. Might be set to NULL when the
>> CMM has to
>>> + *		be re-enabled but not re=programmed.
>>
>> So lut.table can be NULL ... See comment at rcar_cmm_lut_extract()

Ok - so this comment will be removed.



>>
>>> + */
>>> +struct rcar_cmm_config {
>>> +	struct {
>>> +		bool enable;
>>> +		struct drm_color_lut *table;
>>> +	} lut;
>>> +};
>>> +
>>> +#if IS_ENABLED(CONFIG_DRM_RCAR_CMM)
>>> +int rcar_cmm_init(struct platform_device *pdev);
>>> +
>>> +int rcar_cmm_enable(struct platform_device *pdev);
>>> +void rcar_cmm_disable(struct platform_device *pdev);
>>> +
>>> +int rcar_cmm_setup(struct platform_device *pdev,
>>> +		   const struct rcar_cmm_config *config);
>>> +#else
>>> +static inline int rcar_cmm_init(struct platform_device *pdev)
>>> +{
>>> +	return 0;
>>> +}
>>> +
>>> +static inline int rcar_cmm_enable(struct platform_device *pdev)
>>> +{
>>> +	return 0;
>>> +}
>>> +
>>> +static inline void rcar_cmm_disable(struct platform_device *pdev)
>>> +{
>>> +}
>>> +
>>> +static int rcar_cmm_setup(struct platform_device *pdev,
>>> +			  const struct rcar_cmm_config *config)
>>> +{
>>> +	return 0;
>>> +}
>>> +#endif /* IS_ENABLED(CONFIG_DRM_RCAR_CMM) */
>>> +
>>> +#endif /* __RCAR_CMM_H__ */
>>>
>>


^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [PATCH v4 8/9] drm: rcar-du: kms: Update CMM in atomic commit tail
  2019-09-06 13:54 ` [PATCH v4 8/9] drm: rcar-du: kms: Update CMM in atomic commit tail Jacopo Mondi
@ 2019-09-12  9:51   ` Kieran Bingham
  2019-09-20 22:49   ` Laurent Pinchart
  2019-09-30 20:53   ` Ezequiel Garcia
  2 siblings, 0 replies; 38+ messages in thread
From: Kieran Bingham @ 2019-09-12  9:51 UTC (permalink / raw)
  To: Jacopo Mondi, laurent.pinchart, geert, horms, uli+renesas,
	VenkataRajesh.Kalakodima, airlied, daniel
  Cc: koji.matsuoka.xm, muroya, Harsha.ManjulaMallikarjun,
	linux-renesas-soc, dri-devel, linux-kernel

Hi Jacopo,

On 06/09/2019 14:54, Jacopo Mondi wrote:
> Update CMM settings at in the atomic commit tail helper method.
> The CMM is updated with new gamma values provided to the driver
> in the GAMMA_LUT blob property.
> 
> When resuming from system suspend, the DU driver is responsible for
> reprogramming and enabling the CMM unit if it was in use at the time the
> system entered the suspend state.  Force the color_mgmt_changed flag to
> true if the DRM gamma lut color transformation property was set in the
> CRTC state duplicated at suspend time, as the CMM gets reprogrammed only
> if said flag is active in the rcar_du_atomic_commit_update_cmm() method.
> 
> Reviewed-by: Ulrich Hecht <uli+renesas@fpond.eu>
> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> Signed-off-by: Jacopo Mondi <jacopo+renesas@jmondi.org>

Also throwing in an LGTM here.

Reviewed-by: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com>



> ---
> 
> Daniel could you have a look if resume bits are worth being moved to the
> DRM core? The color_mgmt_changed flag is set to false when the state is
> duplicated if I read the code correctly, but when this happens in a
> suspend/resume sequence its value should probably be restored to true if
> any color management property was set in the crtc state when system entered
> suspend.
> 
> ---
> 
>  drivers/gpu/drm/rcar-du/rcar_du_drv.c | 20 ++++++++++++++
>  drivers/gpu/drm/rcar-du/rcar_du_kms.c | 38 +++++++++++++++++++++++++++
>  2 files changed, 58 insertions(+)
> 
> diff --git a/drivers/gpu/drm/rcar-du/rcar_du_drv.c b/drivers/gpu/drm/rcar-du/rcar_du_drv.c
> index 018480a8f35c..d1003d31cfaf 100644
> --- a/drivers/gpu/drm/rcar-du/rcar_du_drv.c
> +++ b/drivers/gpu/drm/rcar-du/rcar_du_drv.c
> @@ -17,6 +17,7 @@
>  #include <linux/slab.h>
>  #include <linux/wait.h>
> 
> +#include <drm/drm_atomic.h>
>  #include <drm/drm_atomic_helper.h>
>  #include <drm/drm_fb_cma_helper.h>
>  #include <drm/drm_fb_helper.h>
> @@ -482,6 +483,25 @@ static int rcar_du_pm_suspend(struct device *dev)
>  static int rcar_du_pm_resume(struct device *dev)
>  {
>  	struct rcar_du_device *rcdu = dev_get_drvdata(dev);
> +	struct drm_atomic_state *state = rcdu->ddev->mode_config.suspend_state;
> +	unsigned int i;
> +
> +	for (i = 0; i < rcdu->num_crtcs; ++i) {
> +		struct drm_crtc *crtc = &rcdu->crtcs[i].crtc;
> +		struct drm_crtc_state *crtc_state;
> +
> +		crtc_state = drm_atomic_get_new_crtc_state(state, crtc);
> +		if (!crtc_state)
> +			continue;
> +
> +		/*
> +		 * Force re-enablement of CMM after system resume if any
> +		 * of the DRM color transformation properties was set in
> +		 * the state saved at system suspend time.
> +		 */
> +		if (crtc_state->gamma_lut)
> +			crtc_state->color_mgmt_changed = true;
> +	}
> 
>  	return drm_mode_config_helper_resume(rcdu->ddev);
>  }
> diff --git a/drivers/gpu/drm/rcar-du/rcar_du_kms.c b/drivers/gpu/drm/rcar-du/rcar_du_kms.c
> index 294630e56992..fc30fff0eb8d 100644
> --- a/drivers/gpu/drm/rcar-du/rcar_du_kms.c
> +++ b/drivers/gpu/drm/rcar-du/rcar_du_kms.c
> @@ -22,6 +22,7 @@
>  #include <linux/of_platform.h>
>  #include <linux/wait.h>
> 
> +#include "rcar_cmm.h"
>  #include "rcar_du_crtc.h"
>  #include "rcar_du_drv.h"
>  #include "rcar_du_encoder.h"
> @@ -368,6 +369,40 @@ rcar_du_fb_create(struct drm_device *dev, struct drm_file *file_priv,
>   * Atomic Check and Update
>   */
> 
> +static void rcar_du_atomic_commit_update_cmm(struct drm_crtc *crtc,
> +					     struct drm_crtc_state *old_state)
> +{
> +	struct rcar_du_crtc *rcrtc = to_rcar_crtc(crtc);
> +	struct rcar_cmm_config cmm_config = {};
> +	struct device *dev = rcrtc->dev->dev;
> +	struct drm_property_blob *lut_blob;
> +
> +	if (!rcrtc->cmm || !crtc->state->color_mgmt_changed)
> +		return;
> +
> +	if (!crtc->state->gamma_lut) {
> +		cmm_config.lut.enable = false;
> +		rcar_cmm_setup(rcrtc->cmm, &cmm_config);
> +		return;
> +	}
> +
> +	lut_blob = crtc->state->gamma_lut;
> +	if (lut_blob->length != (CM2_LUT_SIZE * sizeof(struct drm_color_lut))) {
> +		/*
> +		 * We only accept fully populated LUT tables;
> +		 * be loud here, otherwise the CMM gets silently ignored.
> +		 */
> +		dev_err(dev, "invalid gamma lut size of %lu bytes\n",
> +			lut_blob->length);
> +		return;
> +	}
> +
> +	cmm_config.lut.enable = true;
> +	cmm_config.lut.table = (struct drm_color_lut *)lut_blob->data;
> +
> +	rcar_cmm_setup(rcrtc->cmm, &cmm_config);
> +}
> +
>  static int rcar_du_atomic_check(struct drm_device *dev,
>  				struct drm_atomic_state *state)
>  {
> @@ -410,6 +445,9 @@ static void rcar_du_atomic_commit_tail(struct drm_atomic_state *old_state)
>  			rcdu->dpad1_source = rcrtc->index;
>  	}
> 
> +	for_each_old_crtc_in_state(old_state, crtc, crtc_state, i)
> +		rcar_du_atomic_commit_update_cmm(crtc, crtc_state);
> +
>  	/* Apply the atomic update. */
>  	drm_atomic_helper_commit_modeset_disables(dev, old_state);
>  	drm_atomic_helper_commit_planes(dev, old_state,
> --
> 2.23.0
> 


^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [PATCH v4 1/9] dt-bindings: display: renesas,cmm: Add R-Car CMM documentation
  2019-09-06 13:54 ` [PATCH v4 1/9] dt-bindings: display: renesas,cmm: Add R-Car CMM documentation Jacopo Mondi
  2019-09-11 19:04   ` Kieran Bingham
@ 2019-09-17 17:55   ` Rob Herring
  2019-09-18 22:08   ` Laurent Pinchart
  2 siblings, 0 replies; 38+ messages in thread
From: Rob Herring @ 2019-09-17 17:55 UTC (permalink / raw)
  To: Jacopo Mondi
  Cc: laurent.pinchart, kieran.bingham+renesas, geert, horms,
	uli+renesas, VenkataRajesh.Kalakodima, airlied, daniel,
	koji.matsuoka.xm, muroya, Harsha.ManjulaMallikarjun,
	linux-renesas-soc, dri-devel, linux-kernel, devicetree,
	mark.rutland

On Fri, Sep 06, 2019 at 03:54:28PM +0200, Jacopo Mondi wrote:
> Add device tree bindings documentation for the Renesas R-Car Display
> Unit Color Management Module.
> 
> CMM is the image enhancement module available on each R-Car DU video
> channel on R-Car Gen2 and Gen3 SoCs (V3H and V3M excluded).
> 
> Signed-off-by: Jacopo Mondi <jacopo+renesas@jmondi.org>
> ---
>  .../bindings/display/renesas,cmm.yaml         | 64 +++++++++++++++++++
>  1 file changed, 64 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/display/renesas,cmm.yaml
> 
> diff --git a/Documentation/devicetree/bindings/display/renesas,cmm.yaml b/Documentation/devicetree/bindings/display/renesas,cmm.yaml
> new file mode 100644
> index 000000000000..9e5922689cd7
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/display/renesas,cmm.yaml
> @@ -0,0 +1,64 @@
> +# SPDX-License-Identifier: GPL-2.0

For new bindings:

GPL-2.0-only OR BSD-2-Clause

> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/display/renesas,cmm.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: Renesas R-Car Color Management Module (CMM)
> +
> +maintainers:
> +  - Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> +  - Kieran Bingham <kieran.bingham+renesas@ideasonboard.com>
> +  - Jacopo Mondi <jacopo+renesas@jmondi.org>
> +
> +description: |+
> +  Renesas R-Car color management module connected to R-Car DU video channels.
> +  It provides image enhancement functions such as 1-D look-up tables (LUT),
> +  3-D look-up tables (CMU), 1D-histogram generation (HGO), and color
> +  space conversion (CSC).
> +
> +properties:
> +  compatible:
> +    items:
> +      - enum:
> +        - renesas,r8a7795-cmm
> +        - renesas,r8a7796-cmm
> +        - renesas,r8a77965-cmm
> +        - renesas,r8a77990-cmm
> +        - renesas,r8a77995-cmm
> +      - enum:
> +        - renesas,rcar-gen3-cmm
> +        - renesas,rcar-gen2-cmm

This allows 10 valid cases when I imagine there's only really 5. I'm 
okay leaving it, but might be better to split into 2 under a 'oneOf'.

I imagine there will be a lot of these for Renesas, so just be 
consistent.

> +  reg:
> +    maxItems: 1
> +
> +  clocks:
> +    maxItems: 1
> +
> +  resets:
> +    maxItems: 1
> +
> +  power-domains:
> +    maxItems: 1
> +
> +required:
> +  - compatible
> +  - reg
> +  - clocks
> +  - resets
> +  - power-domains
> +
> +additionalProperties: false
> +
> +examples:
> +  - |
> +    #include <dt-bindings/clock/r8a7796-cpg-mssr.h>
> +    #include <dt-bindings/power/r8a7796-sysc.h>
> +
> +    cmm0: cmm@fea40000 {
> +         compatible = "renesas,r8a7796-cmm";
> +         reg = <0 0xfea40000 0 0x1000>;
> +         power-domains = <&sysc R8A7796_PD_ALWAYS_ON>;
> +         clocks = <&cpg CPG_MOD 711>;
> +         resets = <&cpg 711>;
> +    };
> --
> 2.23.0
> 

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [PATCH v4 2/9] dt-bindings: display, renesas,du: Document cmms property
  2019-09-11 16:06   ` Kieran Bingham
@ 2019-09-17 17:58     ` Rob Herring
  0 siblings, 0 replies; 38+ messages in thread
From: Rob Herring @ 2019-09-17 17:58 UTC (permalink / raw)
  To: Kieran Bingham
  Cc: Jacopo Mondi, laurent.pinchart, geert, horms, uli+renesas,
	VenkataRajesh.Kalakodima, airlied, daniel, koji.matsuoka.xm,
	muroya, Harsha.ManjulaMallikarjun, linux-renesas-soc, dri-devel,
	linux-kernel, devicetree, mark.rutland

On Wed, Sep 11, 2019 at 05:06:33PM +0100, Kieran Bingham wrote:
> Hi Jacopo,
> 
> On 06/09/2019 14:54, Jacopo Mondi wrote:
> > Document the newly added 'cmms' property which accepts a list of phandle
> > and channel index pairs that point to the CMM units available for each
> > Display Unit output video channel.
> > 
> > Signed-off-by: Jacopo Mondi <jacopo+renesas@jmondi.org>
> > Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> > ---
> >  Documentation/devicetree/bindings/display/renesas,du.txt | 5 +++++
> >  1 file changed, 5 insertions(+)
> > 
> > diff --git a/Documentation/devicetree/bindings/display/renesas,du.txt b/Documentation/devicetree/bindings/display/renesas,du.txt
> > index c97dfacad281..1773b0a2f54f 100644
> > --- a/Documentation/devicetree/bindings/display/renesas,du.txt
> > +++ b/Documentation/devicetree/bindings/display/renesas,du.txt
> > @@ -45,6 +45,10 @@ Required Properties:
> >      instance that serves the DU channel, and the channel index identifies the
> >      LIF instance in that VSP.
> > 
> > +  - renesas,cmms: A list of phandles to the CMM instances present in the SoC,
> > +    one for each available DU channel. The property shall not be specified for
> > +    SoCs that do not provide any CMM (such as V3M and V3H).
> > +
> >  Required nodes:
> > 
> >  The connections to the DU output video ports are modeled using the OF graph
> > @@ -91,6 +95,7 @@ Example: R8A7795 (R-Car H3) ES2.0 DU
> >  			 <&cpg CPG_MOD 721>;
> >  		clock-names = "du.0", "du.1", "du.2", "du.3";
> >  		vsps = <&vspd0 0>, <&vspd1 0>, <&vspd2 0>, <&vspd0 1>;
> > +		renesas,cmms = <&cmm0 &cmm1 &cmm2 &cmm3>;
> 
> Should these be comma separated in the same fashion as the vsps are
> separated?

Yes. Doesn't matter from a dtb standpoint, but the schema are going to 
be stricter here. Bracket each unit.

With that,

Reviewed-by: Rob Herring <robh@kernel.org>

> 
> I don't really mind either way though ...
> 
> Reviewed-by: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com>
> 
> 
> > 
> >  		ports {
> >  			#address-cells = <1>;
> > --
> > 2.23.0
> > 
> 

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [PATCH v4 1/9] dt-bindings: display: renesas,cmm: Add R-Car CMM documentation
  2019-09-06 13:54 ` [PATCH v4 1/9] dt-bindings: display: renesas,cmm: Add R-Car CMM documentation Jacopo Mondi
  2019-09-11 19:04   ` Kieran Bingham
  2019-09-17 17:55   ` Rob Herring
@ 2019-09-18 22:08   ` Laurent Pinchart
  2 siblings, 0 replies; 38+ messages in thread
From: Laurent Pinchart @ 2019-09-18 22:08 UTC (permalink / raw)
  To: Jacopo Mondi
  Cc: kieran.bingham+renesas, geert, horms, uli+renesas,
	VenkataRajesh.Kalakodima, airlied, daniel, koji.matsuoka.xm,
	muroya, Harsha.ManjulaMallikarjun, linux-renesas-soc, dri-devel,
	linux-kernel, devicetree, robh+dt, mark.rutland

Hi Jacopo,

Thank you for the patch.

On Fri, Sep 06, 2019 at 03:54:28PM +0200, Jacopo Mondi wrote:
> Add device tree bindings documentation for the Renesas R-Car Display
> Unit Color Management Module.
> 
> CMM is the image enhancement module available on each R-Car DU video
> channel on R-Car Gen2 and Gen3 SoCs (V3H and V3M excluded).
> 
> Signed-off-by: Jacopo Mondi <jacopo+renesas@jmondi.org>

With the small issues pointed out by Kieran and Rob fixed,

Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>

> ---
>  .../bindings/display/renesas,cmm.yaml         | 64 +++++++++++++++++++
>  1 file changed, 64 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/display/renesas,cmm.yaml
> 
> diff --git a/Documentation/devicetree/bindings/display/renesas,cmm.yaml b/Documentation/devicetree/bindings/display/renesas,cmm.yaml
> new file mode 100644
> index 000000000000..9e5922689cd7
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/display/renesas,cmm.yaml
> @@ -0,0 +1,64 @@
> +# SPDX-License-Identifier: GPL-2.0
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/display/renesas,cmm.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: Renesas R-Car Color Management Module (CMM)
> +
> +maintainers:
> +  - Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> +  - Kieran Bingham <kieran.bingham+renesas@ideasonboard.com>
> +  - Jacopo Mondi <jacopo+renesas@jmondi.org>
> +
> +description: |+
> +  Renesas R-Car color management module connected to R-Car DU video channels.
> +  It provides image enhancement functions such as 1-D look-up tables (LUT),
> +  3-D look-up tables (CMU), 1D-histogram generation (HGO), and color
> +  space conversion (CSC).
> +
> +properties:
> +  compatible:
> +    items:
> +      - enum:
> +        - renesas,r8a7795-cmm
> +        - renesas,r8a7796-cmm
> +        - renesas,r8a77965-cmm
> +        - renesas,r8a77990-cmm
> +        - renesas,r8a77995-cmm
> +      - enum:
> +        - renesas,rcar-gen3-cmm
> +        - renesas,rcar-gen2-cmm
> +  reg:
> +    maxItems: 1
> +
> +  clocks:
> +    maxItems: 1
> +
> +  resets:
> +    maxItems: 1
> +
> +  power-domains:
> +    maxItems: 1
> +
> +required:
> +  - compatible
> +  - reg
> +  - clocks
> +  - resets
> +  - power-domains
> +
> +additionalProperties: false
> +
> +examples:
> +  - |
> +    #include <dt-bindings/clock/r8a7796-cpg-mssr.h>
> +    #include <dt-bindings/power/r8a7796-sysc.h>
> +
> +    cmm0: cmm@fea40000 {
> +         compatible = "renesas,r8a7796-cmm";
> +         reg = <0 0xfea40000 0 0x1000>;
> +         power-domains = <&sysc R8A7796_PD_ALWAYS_ON>;
> +         clocks = <&cpg CPG_MOD 711>;
> +         resets = <&cpg 711>;
> +    };

-- 
Regards,

Laurent Pinchart

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [PATCH v4 3/9] drm: rcar-du: Add support for CMM
  2019-09-06 13:54 ` [PATCH v4 3/9] drm: rcar-du: Add support for CMM Jacopo Mondi
  2019-09-11 15:54   ` Kieran Bingham
@ 2019-09-18 22:55   ` Laurent Pinchart
  2019-09-19  8:59     ` Kieran Bingham
  2019-10-10 17:46     ` Jacopo Mondi
  1 sibling, 2 replies; 38+ messages in thread
From: Laurent Pinchart @ 2019-09-18 22:55 UTC (permalink / raw)
  To: Jacopo Mondi
  Cc: kieran.bingham+renesas, geert, horms, uli+renesas,
	VenkataRajesh.Kalakodima, airlied, daniel, koji.matsuoka.xm,
	muroya, Harsha.ManjulaMallikarjun, linux-renesas-soc, dri-devel,
	linux-kernel

Hi Jacopo,

Thank you for the patch.

On Fri, Sep 06, 2019 at 03:54:30PM +0200, Jacopo Mondi wrote:
> Add a driver for the R-Car Display Unit Color Correction Module.
> 
> In most of Gen3 SoCs, each DU output channel is provided with a CMM unit
> to perform image enhancement and color correction.
> 
> Add support for CMM through a driver that supports configuration of
> the 1-dimensional LUT table. More advanced CMM feature will be
> implemented on top of this basic one.
> 
> Signed-off-by: Jacopo Mondi <jacopo+renesas@jmondi.org>
> ---
>  drivers/gpu/drm/rcar-du/Kconfig    |   7 +
>  drivers/gpu/drm/rcar-du/Makefile   |   1 +
>  drivers/gpu/drm/rcar-du/rcar_cmm.c | 251 +++++++++++++++++++++++++++++
>  drivers/gpu/drm/rcar-du/rcar_cmm.h |  61 +++++++
>  4 files changed, 320 insertions(+)
>  create mode 100644 drivers/gpu/drm/rcar-du/rcar_cmm.c
>  create mode 100644 drivers/gpu/drm/rcar-du/rcar_cmm.h
> 
> diff --git a/drivers/gpu/drm/rcar-du/Kconfig b/drivers/gpu/drm/rcar-du/Kconfig
> index 1529849e217e..539d232790d1 100644
> --- a/drivers/gpu/drm/rcar-du/Kconfig
> +++ b/drivers/gpu/drm/rcar-du/Kconfig
> @@ -13,6 +13,13 @@ config DRM_RCAR_DU
>  	  Choose this option if you have an R-Car chipset.
>  	  If M is selected the module will be called rcar-du-drm.
>  
> +config DRM_RCAR_CMM
> +	bool "R-Car DU Color Management Module (CMM) Support"
> +	depends on DRM && OF
> +	depends on DRM_RCAR_DU
> +	help
> +	  Enable support for R-Car Color Management Module (CMM).
> +
>  config DRM_RCAR_DW_HDMI
>  	tristate "R-Car DU Gen3 HDMI Encoder Support"
>  	depends on DRM && OF
> diff --git a/drivers/gpu/drm/rcar-du/Makefile b/drivers/gpu/drm/rcar-du/Makefile
> index 6c2ed9c46467..4d1187ccc3e5 100644
> --- a/drivers/gpu/drm/rcar-du/Makefile
> +++ b/drivers/gpu/drm/rcar-du/Makefile
> @@ -15,6 +15,7 @@ rcar-du-drm-$(CONFIG_DRM_RCAR_LVDS)	+= rcar_du_of.o \
>  rcar-du-drm-$(CONFIG_DRM_RCAR_VSP)	+= rcar_du_vsp.o
>  rcar-du-drm-$(CONFIG_DRM_RCAR_WRITEBACK) += rcar_du_writeback.o
>  
> +obj-$(CONFIG_DRM_RCAR_CMM)		+= rcar_cmm.o
>  obj-$(CONFIG_DRM_RCAR_DU)		+= rcar-du-drm.o
>  obj-$(CONFIG_DRM_RCAR_DW_HDMI)		+= rcar_dw_hdmi.o
>  obj-$(CONFIG_DRM_RCAR_LVDS)		+= rcar_lvds.o
> diff --git a/drivers/gpu/drm/rcar-du/rcar_cmm.c b/drivers/gpu/drm/rcar-du/rcar_cmm.c
> new file mode 100644
> index 000000000000..3cacdc4474c7
> --- /dev/null
> +++ b/drivers/gpu/drm/rcar-du/rcar_cmm.c
> @@ -0,0 +1,251 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * rcar_cmm.c -- R-Car Display Unit Color Management Module
> + *
> + * Copyright (C) 2019 Jacopo Mondi <jacopo+renesas@jmondi.org>
> + */
> +
> +#include <linux/io.h>
> +#include <linux/module.h>
> +#include <linux/of.h>
> +#include <linux/platform_device.h>
> +#include <linux/pm_runtime.h>
> +
> +#include <drm/drm_color_mgmt.h>
> +
> +#include "rcar_cmm.h"
> +
> +#define CM2_LUT_CTRL		0x0000
> +#define CM2_LUT_CTRL_LUT_EN	BIT(0)
> +#define CM2_LUT_TBL_BASE	0x0600
> +#define CM2_LUT_TBL(__i)	(CM2_LUT_TBL_BASE + (__i) * 4)
> +
> +struct rcar_cmm {
> +	void __iomem *base;
> +	bool enabled;
> +
> +	/*
> +	 * @lut:		1D-LUT status
> +	 * @lut.enabled:	1D-LUT enabled flag
> +	 * @lut.table:		Table of 1D-LUT entries scaled to hardware
> +	 *			precision (8-bits per color component)
> +	 */
> +	struct {
> +		bool enabled;
> +		u32 table[CM2_LUT_SIZE];
> +	} lut;
> +};
> +
> +static inline int rcar_cmm_read(struct rcar_cmm *rcmm, u32 reg)
> +{
> +	return ioread32(rcmm->base + reg);
> +}
> +
> +static inline void rcar_cmm_write(struct rcar_cmm *rcmm, u32 reg, u32 data)
> +{
> +	iowrite32(data, rcmm->base + reg);
> +}
> +
> +/*
> + * rcar_cmm_lut_extract() - Scale down to hardware precision the DRM LUT table
> + *			    entries and store them.

"Scale the DRM LUT table entries to hardware precision and store them."

> + * @rcmm: Pointer to the CMM device
> + * @drm_lut: Pointer to the DRM LUT table
> + */
> +static void rcar_cmm_lut_extract(struct rcar_cmm *rcmm,
> +				 const struct drm_color_lut *drm_lut)
> +{
> +	unsigned int i;
> +
> +	for (i = 0; i < CM2_LUT_SIZE; ++i) {
> +		const struct drm_color_lut *lut = &drm_lut[i];
> +
> +		rcmm->lut.table[i] = drm_color_lut_extract(lut->red, 8) << 16
> +				   | drm_color_lut_extract(lut->green, 8) << 8
> +				   | drm_color_lut_extract(lut->blue, 8);
> +	}
> +}
> +
> +/*
> + * rcar_cmm_lut_write() - Write to hardware the LUT table entries from the
> + *			  local table.

"Write the LUT table entries from the local table to the hardware."

> + * @rcmm: Pointer to the CMM device
> + */
> +static void rcar_cmm_lut_write(struct rcar_cmm *rcmm)
> +{
> +	unsigned int i;
> +
> +	for (i = 0; i < CM2_LUT_SIZE; ++i)
> +		rcar_cmm_write(rcmm, CM2_LUT_TBL(i), rcmm->lut.table[i]);
> +}
> +
> +/*
> + * rcar_cmm_setup() - Configure the CMM unit.
> + * @pdev: The platform device associated with the CMM instance
> + * @config: The CRTC-provided configuration.
> + *
> + * Configure the CMM unit with the CRTC-provided configuration.
> + * Currently enabling, disabling and programming of the 1-D LUT unit is
> + * supported.
> + */
> +int rcar_cmm_setup(struct platform_device *pdev,
> +		   const struct rcar_cmm_config *config)
> +{
> +	struct rcar_cmm *rcmm = platform_get_drvdata(pdev);
> +
> +	/*
> +	 * As rcar_cmm_setup() is called by atomic commit tail helper, it might
> +	 * be called when the CMM is disabled. As we can't program the hardware
> +	 * in that case, store the configuration internally and apply it when
> +	 * the CMM will be enabled by the CRTC through rcar_cmm_enable().
> +	 */
> +	if (!rcmm->enabled) {
> +		if (!config->lut.enable)
> +			return 0;
> +
> +		rcar_cmm_lut_extract(rcmm, config->lut.table);
> +		rcmm->lut.enabled = true;
> +
> +		return 0;
> +	}
> +
> +	/* Stop LUT operations if requested. */
> +	if (!config->lut.enable) {
> +		if (rcmm->lut.enabled) {
> +			rcar_cmm_write(rcmm, CM2_LUT_CTRL, 0);
> +			rcmm->lut.enabled = false;
> +		}
> +
> +		return 0;
> +	}
> +
> +	/*
> +	 * Enable LUT and program the new gamma table values.
> +	 *
> +	 * FIXME: In order to have stable operations it is required to first
> +	 * enable the 1D-LUT and then program its table entries. This seems to
> +	 * contradict what the chip manual reports, and will have to be
> +	 * reconsidered when implementing support for double buffering.
> +	 */
> +	if (!rcmm->lut.enabled) {
> +		rcar_cmm_write(rcmm, CM2_LUT_CTRL, CM2_LUT_CTRL_LUT_EN);
> +		rcmm->lut.enabled = true;
> +	}
> +
> +	rcar_cmm_lut_extract(rcmm, config->lut.table);
> +	rcar_cmm_lut_write(rcmm);
> +
> +	return 0;
> +}
> +EXPORT_SYMBOL_GPL(rcar_cmm_setup);
> +
> +/*
> + * rcar_cmm_enable() - Enable the CMM unit.
> + * @pdev: The platform device associated with the CMM instance
> + *
> + * Enable the CMM unit by enabling the parent clock and enabling the CMM
> + * components, such as 1-D LUT, if requested.
> + */
> +int rcar_cmm_enable(struct platform_device *pdev)
> +{
> +	struct rcar_cmm *rcmm = platform_get_drvdata(pdev);
> +	int ret;
> +
> +	ret = pm_runtime_get_sync(&pdev->dev);
> +	if (ret < 0)
> +		return ret;
> +
> +	/* Apply the LUT table values saved at rcar_cmm_setup() time. */
> +	if (rcmm->lut.enabled) {
> +		rcar_cmm_write(rcmm, CM2_LUT_CTRL, CM2_LUT_CTRL_LUT_EN);
> +		rcar_cmm_lut_write(rcmm);
> +	}
> +
> +	rcmm->enabled = true;
> +
> +	return 0;
> +}
> +EXPORT_SYMBOL_GPL(rcar_cmm_enable);
> +
> +/*
> + * rcar_cmm_disable() - Disable the CMM unit.
> + * @pdev: The platform device associated with the CMM instance
> + *
> + * Disable the CMM unit by stopping the parent clock.
> + */
> +void rcar_cmm_disable(struct platform_device *pdev)
> +{
> +	struct rcar_cmm *rcmm = platform_get_drvdata(pdev);
> +
> +	rcar_cmm_write(rcmm, CM2_LUT_CTRL, 0);
> +
> +	pm_runtime_put(&pdev->dev);
> +
> +	rcmm->lut.enabled = false;
> +	rcmm->enabled = false;
> +}
> +EXPORT_SYMBOL_GPL(rcar_cmm_disable);
> +
> +/*
> + * rcar_cmm_init() - Make sure the CMM has probed.

I would document this as "Intialize the CMM" to match the function name.
We may add more initialization in the future.

> + * @pdev: The platform device associated with the CMM instance
> + *
> + * Return: 0 if the CMM has probed, -EPROBE_DEFER otherwise

0 on success, -EPROBE_DEFER is the CMM isn't availablet yet

> + */
> +int rcar_cmm_init(struct platform_device *pdev)
> +{
> +	struct rcar_cmm *rcmm = platform_get_drvdata(pdev);
> +
> +	if (!rcmm)
> +		return -EPROBE_DEFER;
> +
> +	return 0;
> +}
> +EXPORT_SYMBOL_GPL(rcar_cmm_init);
> +
> +static int rcar_cmm_probe(struct platform_device *pdev)
> +{
> +	struct rcar_cmm *rcmm;
> +
> +	rcmm = devm_kzalloc(&pdev->dev, sizeof(*rcmm), GFP_KERNEL);
> +	if (!rcmm)
> +		return -ENOMEM;
> +	platform_set_drvdata(pdev, rcmm);
> +
> +	rcmm->base = devm_platform_ioremap_resource(pdev, 0);
> +	if (IS_ERR(rcmm->base))
> +		return PTR_ERR(rcmm->base);
> +
> +	pm_runtime_enable(&pdev->dev);
> +
> +	return 0;
> +}
> +
> +static int rcar_cmm_remove(struct platform_device *pdev)
> +{
> +	pm_runtime_disable(&pdev->dev);
> +
> +	return 0;
> +}
> +
> +static const struct of_device_id rcar_cmm_of_table[] = {
> +	{ .compatible = "renesas,rcar-gen3-cmm", },
> +	{ .compatible = "renesas,rcar-gen2-cmm", },
> +	{ },
> +};
> +MODULE_DEVICE_TABLE(of, rcar_cmm_of_table);
> +
> +static struct platform_driver rcar_cmm_platform_driver = {
> +	.probe		= rcar_cmm_probe,
> +	.remove		= rcar_cmm_remove,
> +	.driver		= {
> +		.name	= "rcar-cmm",
> +		.of_match_table = rcar_cmm_of_table,
> +	},
> +};
> +
> +module_platform_driver(rcar_cmm_platform_driver);
> +
> +MODULE_AUTHOR("Jacopo Mondi <jacopo+renesas@jmondi.org>");
> +MODULE_DESCRIPTION("Renesas R-Car CMM Driver");
> +MODULE_LICENSE("GPL v2");
> diff --git a/drivers/gpu/drm/rcar-du/rcar_cmm.h b/drivers/gpu/drm/rcar-du/rcar_cmm.h
> new file mode 100644
> index 000000000000..15a2c874b6a6
> --- /dev/null
> +++ b/drivers/gpu/drm/rcar-du/rcar_cmm.h
> @@ -0,0 +1,61 @@
> +/* SPDX-License-Identifier: GPL-2.0+ */
> +/*
> + * rcar_cmm.h -- R-Car Display Unit Color Management Module
> + *
> + * Copyright (C) 2019 Jacopo Mondi <jacopo+renesas@jmondi.org>
> + */
> +
> +#ifndef __RCAR_CMM_H__
> +#define __RCAR_CMM_H__
> +
> +#define CM2_LUT_SIZE		256
> +
> +struct drm_color_lut;
> +struct platform_device;
> +
> +/**
> + * struct rcar_cmm_config - CMM configuration
> + *
> + * @lut:	1D-LUT configuration
> + * @lut.enable:	1D-LUT enable flag
> + * @lut.table:	1D-LUT table entries. Might be set to NULL when the CMM has to
> + *		be re-enabled but not re=programmed.

s/re=programmed/re-programmed/

As discussed offline this can't really happen as far as I can tell.
However, it will still be useful when we'll add CLU support, as then a
CLU reprogramming without a LUT reprogramming could happen.

I think we should make the documentation a bit clearer:

"1D-LUT table entries. Only valid when lut.enable is true, shall be NULL
otherwise. When non-NULL, the LUT table will be programmed with the new
values. Otherwise the LUT table will retain its previously programmed
values."

This being said, the code in rcar_cmm_setup() will crash if table is
NULL. I would either drop the option of table being NULL (and thus
update the documentation here) if you don't need this yet in the DU
driver, or fix rcar_cmm_setup(). You've posted enough versions of this
series in my opinion, so please pick the easiest option, and we'll
rework the code when adding CLU support anyway.

With those small issues fixes,

Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>

> + */
> +struct rcar_cmm_config {
> +	struct {
> +		bool enable;
> +		struct drm_color_lut *table;
> +	} lut;
> +};
> +
> +#if IS_ENABLED(CONFIG_DRM_RCAR_CMM)
> +int rcar_cmm_init(struct platform_device *pdev);
> +
> +int rcar_cmm_enable(struct platform_device *pdev);
> +void rcar_cmm_disable(struct platform_device *pdev);
> +
> +int rcar_cmm_setup(struct platform_device *pdev,
> +		   const struct rcar_cmm_config *config);
> +#else
> +static inline int rcar_cmm_init(struct platform_device *pdev)
> +{
> +	return 0;
> +}
> +
> +static inline int rcar_cmm_enable(struct platform_device *pdev)
> +{
> +	return 0;
> +}
> +
> +static inline void rcar_cmm_disable(struct platform_device *pdev)
> +{
> +}
> +
> +static int rcar_cmm_setup(struct platform_device *pdev,
> +			  const struct rcar_cmm_config *config)
> +{
> +	return 0;
> +}
> +#endif /* IS_ENABLED(CONFIG_DRM_RCAR_CMM) */
> +
> +#endif /* __RCAR_CMM_H__ */

-- 
Regards,

Laurent Pinchart

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [PATCH v4 6/9] drm: rcar-du: crtc: Enable and disable CMMs
  2019-09-12  9:19       ` Kieran Bingham
@ 2019-09-18 23:23         ` Laurent Pinchart
  2019-09-19  8:08           ` Kieran Bingham
  0 siblings, 1 reply; 38+ messages in thread
From: Laurent Pinchart @ 2019-09-18 23:23 UTC (permalink / raw)
  To: Kieran Bingham
  Cc: Jacopo Mondi, Jacopo Mondi, geert, horms, uli+renesas,
	VenkataRajesh.Kalakodima, airlied, daniel, koji.matsuoka.xm,
	muroya, Harsha.ManjulaMallikarjun, linux-renesas-soc, dri-devel,
	linux-kernel

Hello,

On Thu, Sep 12, 2019 at 10:19:30AM +0100, Kieran Bingham wrote:
> On 12/09/2019 09:07, Jacopo Mondi wrote:
> > On Wed, Sep 11, 2019 at 07:40:27PM +0100, Kieran Bingham wrote:
> >> On 06/09/2019 14:54, Jacopo Mondi wrote:
> >>> Enable/disable the CMM associated with a CRTC at CRTC start and stop
> >>> time and enable the CMM unit through the Display Extensional Functions
> >>> register at group setup time.
> >>>
> >>> Reviewed-by: Ulrich Hecht <uli+renesas@fpond.eu>
> >>> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> >>> Signed-off-by: Jacopo Mondi <jacopo+renesas@jmondi.org>
> >>> ---
> >>>  drivers/gpu/drm/rcar-du/rcar_du_crtc.c  | 7 +++++++
> >>>  drivers/gpu/drm/rcar-du/rcar_du_group.c | 8 ++++++++
> >>>  drivers/gpu/drm/rcar-du/rcar_du_regs.h  | 5 +++++
> >>>  3 files changed, 20 insertions(+)
> >>>
> >>> diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
> >>> index 23f1d6cc1719..3dac605c3a67 100644
> >>> --- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
> >>> +++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
> >>> @@ -21,6 +21,7 @@
> >>>  #include <drm/drm_plane_helper.h>
> >>>  #include <drm/drm_vblank.h>
> >>>
> >>> +#include "rcar_cmm.h"
> >>>  #include "rcar_du_crtc.h"
> >>>  #include "rcar_du_drv.h"
> >>>  #include "rcar_du_encoder.h"
> >>> @@ -619,6 +620,9 @@ static void rcar_du_crtc_stop(struct rcar_du_crtc *rcrtc)
> >>>  	if (rcar_du_has(rcrtc->dev, RCAR_DU_FEATURE_VSP1_SOURCE))
> >>>  		rcar_du_vsp_disable(rcrtc);
> >>>
> >>> +	if (rcrtc->cmm)
> >>> +		rcar_cmm_disable(rcrtc->cmm);
> >>> +
> >>>  	/*
> >>>  	 * Select switch sync mode. This stops display operation and configures
> >>>  	 * the HSYNC and VSYNC signals as inputs.
> >>> @@ -686,6 +690,9 @@ static void rcar_du_crtc_atomic_enable(struct drm_crtc *crtc,
> >>>  	}
> >>>
> >>>  	rcar_du_crtc_start(rcrtc);
> >>> +
> >>> +	if (rcrtc->cmm)
> >>> +		rcar_cmm_enable(rcrtc->cmm);
> >>>  }
> >>>
> >>>  static void rcar_du_crtc_atomic_disable(struct drm_crtc *crtc,
> >>> diff --git a/drivers/gpu/drm/rcar-du/rcar_du_group.c b/drivers/gpu/drm/rcar-du/rcar_du_group.c
> >>> index 9eee47969e77..25d0fc125d7a 100644
> >>> --- a/drivers/gpu/drm/rcar-du/rcar_du_group.c
> >>> +++ b/drivers/gpu/drm/rcar-du/rcar_du_group.c
> >>> @@ -147,6 +147,14 @@ static void rcar_du_group_setup(struct rcar_du_group *rgrp)
> >>>
> >>>  	rcar_du_group_setup_pins(rgrp);
> >>>
> >>> +	if (rcar_du_has(rcdu, RCAR_DU_FEATURE_CMM)) {
> >>> +		u32 defr7 = DEFR7_CODE
> >>> +			  | (rgrp->cmms_mask & BIT(1) ? DEFR7_CMME1 : 0)
> >>> +			  | (rgrp->cmms_mask & BIT(0) ? DEFR7_CMME0 : 0);
> >>> +
> >>> +		rcar_du_group_write(rgrp, DEFR7, defr7);
> >>> +	}
> >>> +
> >>
> >> What's the effect here on platforms with a CMM, but with
> >> CONFIG_DRM_RCAR_CMM unset?
> >>
> >> Will this incorrectly configure the DU ?
> >>
> >> Will it stall the display if the DU tries to interact with another
> >> module which is not enabled?
> > 
> > I recall I tested that (that's why I had to add stubs for CMM
> > functions, as I had linkage errors otherwise) and thing seems to be
> > fine as the CMM configuration/enblement resolve to an empty function.
> 
> Yes, I see the stubs to allow for linkage, but it's the hardware I'm
> concerned about. If it passes the tests and doesn't break then that's
> probably ok ... but I'm really weary that we're enabling a hardware
> pipeline with a disabled component in the middle.
> 
> > Would you prefer to have this guarded by an #if IS_ENABLED() ?
> 
> I don't think we need a compile time conditional, but I'd say it
> probably needs to be more about whether the CMM has actually probed or not
> 
> Aha, and I see that in rcar_du_cmm_init() we already do a
> call to rcar_cmm_init(), which if fails will leave rcdu->cmms[i] as
> NULL. So that's catered for, which results in the rgrp->cmms_mask being
> correctly representative of whether there is a CMM connected or not.

Doesn't this result in probe failure ?

>  ... so I think that means the ...
>  "if (rcar_du_has(rcdu, RCAR_DU_FEATURE_CMM))" is somewhat redundant:
> 
> 
> This could be:
> 
>   if (rgrp->cmms_mask) {
> 	u32 defr7 = DEFR7_CODE
> 		  | (rgrp->cmms_mask & BIT(1) ? DEFR7_CMME1 : 0)
> 		  | (rgrp->cmms_mask & BIT(0) ? DEFR7_CMME0 : 0);
> 
>   rcar_du_group_write(rgrp, DEFR7, defr7);
> 
> Or in fact, if we don't mind writing 0 to DEFR7 when there is no CMM
> (which is safe by the looks of things as DEFR7 is available on all
> platforms), then we can even remove the outer conditional, and leave
> this all up to the ternary operators to write the correct value to the
> defr7.
> 
> Phew ... net result - your current code *is* safe with the
> CONFIG_DRM_RCAR_CMM option disabled. I'll leave it up to you if you want
> to simplify the code here and remove the RCAR_DU_FEATURE_CMM.
> 
> As this RCAR_DU_FEATURE_CMM flag is only checked here, removing it would
> however simplify all of the rcar_du_device_info structures.
> 
> So - with or without the _FEATURE_CMM" simplification, this patch looks
> functional and safe so:
> 
> 
> Reviewed-by: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com>
> 
> >>>  	if (rcdu->info->gen >= 2) {
> >>>  		rcar_du_group_setup_defr8(rgrp);
> >>>  		rcar_du_group_setup_didsr(rgrp);
> >>> diff --git a/drivers/gpu/drm/rcar-du/rcar_du_regs.h b/drivers/gpu/drm/rcar-du/rcar_du_regs.h
> >>> index bc87f080b170..fb9964949368 100644
> >>> --- a/drivers/gpu/drm/rcar-du/rcar_du_regs.h
> >>> +++ b/drivers/gpu/drm/rcar-du/rcar_du_regs.h
> >>> @@ -197,6 +197,11 @@
> >>>  #define DEFR6_MLOS1		(1 << 2)
> >>>  #define DEFR6_DEFAULT		(DEFR6_CODE | DEFR6_TCNE1)
> >>>
> >>> +#define DEFR7			0x000ec
> >>> +#define DEFR7_CODE		(0x7779 << 16)
> >>> +#define DEFR7_CMME1		BIT(6)
> >>> +#define DEFR7_CMME0		BIT(4)
> >>> +
> >>>  /* -----------------------------------------------------------------------------
> >>>   * R8A7790-only Control Registers
> >>>   */

-- 
Regards,

Laurent Pinchart

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [PATCH v4 6/9] drm: rcar-du: crtc: Enable and disable CMMs
  2019-09-18 23:23         ` Laurent Pinchart
@ 2019-09-19  8:08           ` Kieran Bingham
  2019-09-20 22:44             ` Laurent Pinchart
  0 siblings, 1 reply; 38+ messages in thread
From: Kieran Bingham @ 2019-09-19  8:08 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: Jacopo Mondi, Jacopo Mondi, geert, horms, uli+renesas,
	VenkataRajesh.Kalakodima, airlied, daniel, koji.matsuoka.xm,
	muroya, Harsha.ManjulaMallikarjun, linux-renesas-soc, dri-devel,
	linux-kernel

Hi Laurent, / Jacopo

On 19/09/2019 00:23, Laurent Pinchart wrote:
> Hello,
> 
> On Thu, Sep 12, 2019 at 10:19:30AM +0100, Kieran Bingham wrote:
>> On 12/09/2019 09:07, Jacopo Mondi wrote:
>>> On Wed, Sep 11, 2019 at 07:40:27PM +0100, Kieran Bingham wrote:
>>>> On 06/09/2019 14:54, Jacopo Mondi wrote:
>>>>> Enable/disable the CMM associated with a CRTC at CRTC start and stop
>>>>> time and enable the CMM unit through the Display Extensional Functions
>>>>> register at group setup time.
>>>>>
>>>>> Reviewed-by: Ulrich Hecht <uli+renesas@fpond.eu>
>>>>> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
>>>>> Signed-off-by: Jacopo Mondi <jacopo+renesas@jmondi.org>
>>>>> ---
>>>>>  drivers/gpu/drm/rcar-du/rcar_du_crtc.c  | 7 +++++++
>>>>>  drivers/gpu/drm/rcar-du/rcar_du_group.c | 8 ++++++++
>>>>>  drivers/gpu/drm/rcar-du/rcar_du_regs.h  | 5 +++++
>>>>>  3 files changed, 20 insertions(+)
>>>>>
>>>>> diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
>>>>> index 23f1d6cc1719..3dac605c3a67 100644
>>>>> --- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
>>>>> +++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
>>>>> @@ -21,6 +21,7 @@
>>>>>  #include <drm/drm_plane_helper.h>
>>>>>  #include <drm/drm_vblank.h>
>>>>>
>>>>> +#include "rcar_cmm.h"
>>>>>  #include "rcar_du_crtc.h"
>>>>>  #include "rcar_du_drv.h"
>>>>>  #include "rcar_du_encoder.h"
>>>>> @@ -619,6 +620,9 @@ static void rcar_du_crtc_stop(struct rcar_du_crtc *rcrtc)
>>>>>  	if (rcar_du_has(rcrtc->dev, RCAR_DU_FEATURE_VSP1_SOURCE))
>>>>>  		rcar_du_vsp_disable(rcrtc);
>>>>>
>>>>> +	if (rcrtc->cmm)
>>>>> +		rcar_cmm_disable(rcrtc->cmm);
>>>>> +
>>>>>  	/*
>>>>>  	 * Select switch sync mode. This stops display operation and configures
>>>>>  	 * the HSYNC and VSYNC signals as inputs.
>>>>> @@ -686,6 +690,9 @@ static void rcar_du_crtc_atomic_enable(struct drm_crtc *crtc,
>>>>>  	}
>>>>>
>>>>>  	rcar_du_crtc_start(rcrtc);
>>>>> +
>>>>> +	if (rcrtc->cmm)
>>>>> +		rcar_cmm_enable(rcrtc->cmm);
>>>>>  }
>>>>>
>>>>>  static void rcar_du_crtc_atomic_disable(struct drm_crtc *crtc,
>>>>> diff --git a/drivers/gpu/drm/rcar-du/rcar_du_group.c b/drivers/gpu/drm/rcar-du/rcar_du_group.c
>>>>> index 9eee47969e77..25d0fc125d7a 100644
>>>>> --- a/drivers/gpu/drm/rcar-du/rcar_du_group.c
>>>>> +++ b/drivers/gpu/drm/rcar-du/rcar_du_group.c
>>>>> @@ -147,6 +147,14 @@ static void rcar_du_group_setup(struct rcar_du_group *rgrp)
>>>>>
>>>>>  	rcar_du_group_setup_pins(rgrp);
>>>>>
>>>>> +	if (rcar_du_has(rcdu, RCAR_DU_FEATURE_CMM)) {
>>>>> +		u32 defr7 = DEFR7_CODE
>>>>> +			  | (rgrp->cmms_mask & BIT(1) ? DEFR7_CMME1 : 0)
>>>>> +			  | (rgrp->cmms_mask & BIT(0) ? DEFR7_CMME0 : 0);
>>>>> +
>>>>> +		rcar_du_group_write(rgrp, DEFR7, defr7);
>>>>> +	}
>>>>> +
>>>>
>>>> What's the effect here on platforms with a CMM, but with
>>>> CONFIG_DRM_RCAR_CMM unset?
>>>>
>>>> Will this incorrectly configure the DU ?
>>>>
>>>> Will it stall the display if the DU tries to interact with another
>>>> module which is not enabled?
>>>
>>> I recall I tested that (that's why I had to add stubs for CMM
>>> functions, as I had linkage errors otherwise) and thing seems to be
>>> fine as the CMM configuration/enblement resolve to an empty function.
>>
>> Yes, I see the stubs to allow for linkage, but it's the hardware I'm
>> concerned about. If it passes the tests and doesn't break then that's
>> probably ok ... but I'm really weary that we're enabling a hardware
>> pipeline with a disabled component in the middle.
>>
>>> Would you prefer to have this guarded by an #if IS_ENABLED() ?
>>
>> I don't think we need a compile time conditional, but I'd say it
>> probably needs to be more about whether the CMM has actually probed or not
>>
>> Aha, and I see that in rcar_du_cmm_init() we already do a
>> call to rcar_cmm_init(), which if fails will leave rcdu->cmms[i] as
>> NULL. So that's catered for, which results in the rgrp->cmms_mask being
>> correctly representative of whether there is a CMM connected or not.
> 
> Doesn't this result in probe failure ?

I think I mis-spoke above, I didn't mean "if rcar_cmm_init() fails" I
meant "if rcar_du_cmm_init() determines there are no connected CMM's or
if they are disabled."


If rcar_cmm_init() returns a failure, then yes we will fail to probe.

But I think it's up to rcar_du_cmm_init() to determine if the CMM exists
or not (or is enabled) and if that's not a failure case then it should
not prevent the probing of the DU.


In fact, I've now seen that if CONFIG_DRM_RCAR_CMM is not enabled,
rcar_cmm_init() returns 0, and I think in fact it should return -ENODEV,
with an exception on that return value in rcar_du_cmm_init() so that the
DU continues with no CMM attached there.


> 
>>  ... so I think that means the ...
>>  "if (rcar_du_has(rcdu, RCAR_DU_FEATURE_CMM))" is somewhat redundant:
>>
>>
>> This could be:
>>
>>   if (rgrp->cmms_mask) {
>> 	u32 defr7 = DEFR7_CODE
>> 		  | (rgrp->cmms_mask & BIT(1) ? DEFR7_CMME1 : 0)
>> 		  | (rgrp->cmms_mask & BIT(0) ? DEFR7_CMME0 : 0);
>>
>>   rcar_du_group_write(rgrp, DEFR7, defr7);
>>
>> Or in fact, if we don't mind writing 0 to DEFR7 when there is no CMM
>> (which is safe by the looks of things as DEFR7 is available on all
>> platforms), then we can even remove the outer conditional, and leave
>> this all up to the ternary operators to write the correct value to the
>> defr7.
>>
>> Phew ... net result - your current code *is* safe with the
>> CONFIG_DRM_RCAR_CMM option disabled. I'll leave it up to you if you want
>> to simplify the code here and remove the RCAR_DU_FEATURE_CMM.
>>
>> As this RCAR_DU_FEATURE_CMM flag is only checked here, removing it would
>> however simplify all of the rcar_du_device_info structures.
>>
>> So - with or without the _FEATURE_CMM" simplification, this patch looks
>> functional and safe so:
>>
>>
>> Reviewed-by: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com>
>>
>>>>>  	if (rcdu->info->gen >= 2) {
>>>>>  		rcar_du_group_setup_defr8(rgrp);
>>>>>  		rcar_du_group_setup_didsr(rgrp);
>>>>> diff --git a/drivers/gpu/drm/rcar-du/rcar_du_regs.h b/drivers/gpu/drm/rcar-du/rcar_du_regs.h
>>>>> index bc87f080b170..fb9964949368 100644
>>>>> --- a/drivers/gpu/drm/rcar-du/rcar_du_regs.h
>>>>> +++ b/drivers/gpu/drm/rcar-du/rcar_du_regs.h
>>>>> @@ -197,6 +197,11 @@
>>>>>  #define DEFR6_MLOS1		(1 << 2)
>>>>>  #define DEFR6_DEFAULT		(DEFR6_CODE | DEFR6_TCNE1)
>>>>>
>>>>> +#define DEFR7			0x000ec
>>>>> +#define DEFR7_CODE		(0x7779 << 16)
>>>>> +#define DEFR7_CMME1		BIT(6)
>>>>> +#define DEFR7_CMME0		BIT(4)
>>>>> +
>>>>>  /* -----------------------------------------------------------------------------
>>>>>   * R8A7790-only Control Registers
>>>>>   */
> 


^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [PATCH v4 3/9] drm: rcar-du: Add support for CMM
  2019-09-18 22:55   ` Laurent Pinchart
@ 2019-09-19  8:59     ` Kieran Bingham
  2019-09-20 22:43       ` Laurent Pinchart
  2019-10-10 17:46     ` Jacopo Mondi
  1 sibling, 1 reply; 38+ messages in thread
From: Kieran Bingham @ 2019-09-19  8:59 UTC (permalink / raw)
  To: Laurent Pinchart, Jacopo Mondi
  Cc: geert, horms, uli+renesas, VenkataRajesh.Kalakodima, airlied,
	daniel, koji.matsuoka.xm, muroya, Harsha.ManjulaMallikarjun,
	linux-renesas-soc, dri-devel, linux-kernel

Hi Jacopo, Laurent,


On 18/09/2019 23:55, Laurent Pinchart wrote:
> Hi Jacopo,
> 
> Thank you for the patch.
> 
> On Fri, Sep 06, 2019 at 03:54:30PM +0200, Jacopo Mondi wrote:
>> Add a driver for the R-Car Display Unit Color Correction Module.
>>
>> In most of Gen3 SoCs, each DU output channel is provided with a CMM unit
>> to perform image enhancement and color correction.
>>
>> Add support for CMM through a driver that supports configuration of
>> the 1-dimensional LUT table. More advanced CMM feature will be
>> implemented on top of this basic one.
>>
>> Signed-off-by: Jacopo Mondi <jacopo+renesas@jmondi.org>
>> ---
>>  drivers/gpu/drm/rcar-du/Kconfig    |   7 +
>>  drivers/gpu/drm/rcar-du/Makefile   |   1 +
>>  drivers/gpu/drm/rcar-du/rcar_cmm.c | 251 +++++++++++++++++++++++++++++
>>  drivers/gpu/drm/rcar-du/rcar_cmm.h |  61 +++++++
>>  4 files changed, 320 insertions(+)
>>  create mode 100644 drivers/gpu/drm/rcar-du/rcar_cmm.c
>>  create mode 100644 drivers/gpu/drm/rcar-du/rcar_cmm.h
>>
>> diff --git a/drivers/gpu/drm/rcar-du/Kconfig b/drivers/gpu/drm/rcar-du/Kconfig
>> index 1529849e217e..539d232790d1 100644
>> --- a/drivers/gpu/drm/rcar-du/Kconfig
>> +++ b/drivers/gpu/drm/rcar-du/Kconfig
>> @@ -13,6 +13,13 @@ config DRM_RCAR_DU
>>  	  Choose this option if you have an R-Car chipset.
>>  	  If M is selected the module will be called rcar-du-drm.
>>  
>> +config DRM_RCAR_CMM
>> +	bool "R-Car DU Color Management Module (CMM) Support"
>> +	depends on DRM && OF
>> +	depends on DRM_RCAR_DU
>> +	help
>> +	  Enable support for R-Car Color Management Module (CMM).
>> +
>>  config DRM_RCAR_DW_HDMI
>>  	tristate "R-Car DU Gen3 HDMI Encoder Support"
>>  	depends on DRM && OF
>> diff --git a/drivers/gpu/drm/rcar-du/Makefile b/drivers/gpu/drm/rcar-du/Makefile
>> index 6c2ed9c46467..4d1187ccc3e5 100644
>> --- a/drivers/gpu/drm/rcar-du/Makefile
>> +++ b/drivers/gpu/drm/rcar-du/Makefile
>> @@ -15,6 +15,7 @@ rcar-du-drm-$(CONFIG_DRM_RCAR_LVDS)	+= rcar_du_of.o \
>>  rcar-du-drm-$(CONFIG_DRM_RCAR_VSP)	+= rcar_du_vsp.o
>>  rcar-du-drm-$(CONFIG_DRM_RCAR_WRITEBACK) += rcar_du_writeback.o
>>  
>> +obj-$(CONFIG_DRM_RCAR_CMM)		+= rcar_cmm.o
>>  obj-$(CONFIG_DRM_RCAR_DU)		+= rcar-du-drm.o
>>  obj-$(CONFIG_DRM_RCAR_DW_HDMI)		+= rcar_dw_hdmi.o
>>  obj-$(CONFIG_DRM_RCAR_LVDS)		+= rcar_lvds.o
>> diff --git a/drivers/gpu/drm/rcar-du/rcar_cmm.c b/drivers/gpu/drm/rcar-du/rcar_cmm.c
>> new file mode 100644
>> index 000000000000..3cacdc4474c7
>> --- /dev/null
>> +++ b/drivers/gpu/drm/rcar-du/rcar_cmm.c
>> @@ -0,0 +1,251 @@
>> +// SPDX-License-Identifier: GPL-2.0+
>> +/*
>> + * rcar_cmm.c -- R-Car Display Unit Color Management Module
>> + *
>> + * Copyright (C) 2019 Jacopo Mondi <jacopo+renesas@jmondi.org>
>> + */
>> +
>> +#include <linux/io.h>
>> +#include <linux/module.h>
>> +#include <linux/of.h>
>> +#include <linux/platform_device.h>
>> +#include <linux/pm_runtime.h>
>> +
>> +#include <drm/drm_color_mgmt.h>
>> +
>> +#include "rcar_cmm.h"
>> +
>> +#define CM2_LUT_CTRL		0x0000
>> +#define CM2_LUT_CTRL_LUT_EN	BIT(0)
>> +#define CM2_LUT_TBL_BASE	0x0600
>> +#define CM2_LUT_TBL(__i)	(CM2_LUT_TBL_BASE + (__i) * 4)
>> +
>> +struct rcar_cmm {
>> +	void __iomem *base;
>> +	bool enabled;
>> +
>> +	/*
>> +	 * @lut:		1D-LUT status
>> +	 * @lut.enabled:	1D-LUT enabled flag
>> +	 * @lut.table:		Table of 1D-LUT entries scaled to hardware
>> +	 *			precision (8-bits per color component)
>> +	 */
>> +	struct {
>> +		bool enabled;
>> +		u32 table[CM2_LUT_SIZE];
>> +	} lut;
>> +};
>> +
>> +static inline int rcar_cmm_read(struct rcar_cmm *rcmm, u32 reg)
>> +{
>> +	return ioread32(rcmm->base + reg);
>> +}
>> +
>> +static inline void rcar_cmm_write(struct rcar_cmm *rcmm, u32 reg, u32 data)
>> +{
>> +	iowrite32(data, rcmm->base + reg);
>> +}
>> +
>> +/*
>> + * rcar_cmm_lut_extract() - Scale down to hardware precision the DRM LUT table
>> + *			    entries and store them.
> 
> "Scale the DRM LUT table entries to hardware precision and store them."
> 
>> + * @rcmm: Pointer to the CMM device
>> + * @drm_lut: Pointer to the DRM LUT table
>> + */
>> +static void rcar_cmm_lut_extract(struct rcar_cmm *rcmm,
>> +				 const struct drm_color_lut *drm_lut)
>> +{
>> +	unsigned int i;
>> +
>> +	for (i = 0; i < CM2_LUT_SIZE; ++i) {
>> +		const struct drm_color_lut *lut = &drm_lut[i];
>> +
>> +		rcmm->lut.table[i] = drm_color_lut_extract(lut->red, 8) << 16
>> +				   | drm_color_lut_extract(lut->green, 8) << 8
>> +				   | drm_color_lut_extract(lut->blue, 8);
>> +	}
>> +}
>> +
>> +/*
>> + * rcar_cmm_lut_write() - Write to hardware the LUT table entries from the
>> + *			  local table.
> 
> "Write the LUT table entries from the local table to the hardware."
> 
>> + * @rcmm: Pointer to the CMM device
>> + */
>> +static void rcar_cmm_lut_write(struct rcar_cmm *rcmm)
>> +{
>> +	unsigned int i;
>> +
>> +	for (i = 0; i < CM2_LUT_SIZE; ++i)
>> +		rcar_cmm_write(rcmm, CM2_LUT_TBL(i), rcmm->lut.table[i]);
>> +}
>> +
>> +/*
>> + * rcar_cmm_setup() - Configure the CMM unit.
>> + * @pdev: The platform device associated with the CMM instance
>> + * @config: The CRTC-provided configuration.
>> + *
>> + * Configure the CMM unit with the CRTC-provided configuration.
>> + * Currently enabling, disabling and programming of the 1-D LUT unit is
>> + * supported.
>> + */
>> +int rcar_cmm_setup(struct platform_device *pdev,
>> +		   const struct rcar_cmm_config *config)
>> +{
>> +	struct rcar_cmm *rcmm = platform_get_drvdata(pdev);
>> +
>> +	/*
>> +	 * As rcar_cmm_setup() is called by atomic commit tail helper, it might
>> +	 * be called when the CMM is disabled. As we can't program the hardware
>> +	 * in that case, store the configuration internally and apply it when
>> +	 * the CMM will be enabled by the CRTC through rcar_cmm_enable().
>> +	 */
>> +	if (!rcmm->enabled) {
>> +		if (!config->lut.enable)
>> +			return 0;
>> +
>> +		rcar_cmm_lut_extract(rcmm, config->lut.table);
>> +		rcmm->lut.enabled = true;
>> +
>> +		return 0;
>> +	}
>> +
>> +	/* Stop LUT operations if requested. */
>> +	if (!config->lut.enable) {
>> +		if (rcmm->lut.enabled) {
>> +			rcar_cmm_write(rcmm, CM2_LUT_CTRL, 0);
>> +			rcmm->lut.enabled = false;
>> +		}
>> +
>> +		return 0;
>> +	}
>> +
>> +	/*
>> +	 * Enable LUT and program the new gamma table values.
>> +	 *
>> +	 * FIXME: In order to have stable operations it is required to first
>> +	 * enable the 1D-LUT and then program its table entries. This seems to
>> +	 * contradict what the chip manual reports, and will have to be
>> +	 * reconsidered when implementing support for double buffering.
>> +	 */
>> +	if (!rcmm->lut.enabled) {
>> +		rcar_cmm_write(rcmm, CM2_LUT_CTRL, CM2_LUT_CTRL_LUT_EN);
>> +		rcmm->lut.enabled = true;
>> +	}
>> +
>> +	rcar_cmm_lut_extract(rcmm, config->lut.table);
>> +	rcar_cmm_lut_write(rcmm);
>> +
>> +	return 0;
>> +}
>> +EXPORT_SYMBOL_GPL(rcar_cmm_setup);
>> +
>> +/*
>> + * rcar_cmm_enable() - Enable the CMM unit.
>> + * @pdev: The platform device associated with the CMM instance
>> + *
>> + * Enable the CMM unit by enabling the parent clock and enabling the CMM
>> + * components, such as 1-D LUT, if requested.
>> + */
>> +int rcar_cmm_enable(struct platform_device *pdev)
>> +{
>> +	struct rcar_cmm *rcmm = platform_get_drvdata(pdev);
>> +	int ret;
>> +
>> +	ret = pm_runtime_get_sync(&pdev->dev);
>> +	if (ret < 0)
>> +		return ret;
>> +
>> +	/* Apply the LUT table values saved at rcar_cmm_setup() time. */
>> +	if (rcmm->lut.enabled) {
>> +		rcar_cmm_write(rcmm, CM2_LUT_CTRL, CM2_LUT_CTRL_LUT_EN);
>> +		rcar_cmm_lut_write(rcmm);
>> +	}
>> +
>> +	rcmm->enabled = true;
>> +
>> +	return 0;
>> +}
>> +EXPORT_SYMBOL_GPL(rcar_cmm_enable);
>> +
>> +/*
>> + * rcar_cmm_disable() - Disable the CMM unit.
>> + * @pdev: The platform device associated with the CMM instance
>> + *
>> + * Disable the CMM unit by stopping the parent clock.
>> + */
>> +void rcar_cmm_disable(struct platform_device *pdev)
>> +{
>> +	struct rcar_cmm *rcmm = platform_get_drvdata(pdev);
>> +
>> +	rcar_cmm_write(rcmm, CM2_LUT_CTRL, 0);
>> +
>> +	pm_runtime_put(&pdev->dev);
>> +
>> +	rcmm->lut.enabled = false;
>> +	rcmm->enabled = false;
>> +}
>> +EXPORT_SYMBOL_GPL(rcar_cmm_disable);
>> +
>> +/*
>> + * rcar_cmm_init() - Make sure the CMM has probed.
> 
> I would document this as "Intialize the CMM" to match the function name.
> We may add more initialization in the future.
> 
>> + * @pdev: The platform device associated with the CMM instance
>> + *
>> + * Return: 0 if the CMM has probed, -EPROBE_DEFER otherwise
> 
> 0 on success, -EPROBE_DEFER is the CMM isn't availablet yet

And possibly -ENODEV if the suggestion below in the header is worthy, to
return no device if the CMM is disabled at the CONFIG_ level.



> 
>> + */
>> +int rcar_cmm_init(struct platform_device *pdev)
>> +{
>> +	struct rcar_cmm *rcmm = platform_get_drvdata(pdev);
>> +
>> +	if (!rcmm)
>> +		return -EPROBE_DEFER;
>> +
>> +	return 0;
>> +}
>> +EXPORT_SYMBOL_GPL(rcar_cmm_init);
>> +
>> +static int rcar_cmm_probe(struct platform_device *pdev)
>> +{
>> +	struct rcar_cmm *rcmm;
>> +
>> +	rcmm = devm_kzalloc(&pdev->dev, sizeof(*rcmm), GFP_KERNEL);
>> +	if (!rcmm)
>> +		return -ENOMEM;
>> +	platform_set_drvdata(pdev, rcmm);
>> +
>> +	rcmm->base = devm_platform_ioremap_resource(pdev, 0);
>> +	if (IS_ERR(rcmm->base))
>> +		return PTR_ERR(rcmm->base);
>> +
>> +	pm_runtime_enable(&pdev->dev);
>> +
>> +	return 0;
>> +}
>> +
>> +static int rcar_cmm_remove(struct platform_device *pdev)
>> +{
>> +	pm_runtime_disable(&pdev->dev);
>> +
>> +	return 0;
>> +}
>> +
>> +static const struct of_device_id rcar_cmm_of_table[] = {
>> +	{ .compatible = "renesas,rcar-gen3-cmm", },
>> +	{ .compatible = "renesas,rcar-gen2-cmm", },
>> +	{ },
>> +};
>> +MODULE_DEVICE_TABLE(of, rcar_cmm_of_table);
>> +
>> +static struct platform_driver rcar_cmm_platform_driver = {
>> +	.probe		= rcar_cmm_probe,
>> +	.remove		= rcar_cmm_remove,
>> +	.driver		= {
>> +		.name	= "rcar-cmm",
>> +		.of_match_table = rcar_cmm_of_table,
>> +	},
>> +};
>> +
>> +module_platform_driver(rcar_cmm_platform_driver);
>> +
>> +MODULE_AUTHOR("Jacopo Mondi <jacopo+renesas@jmondi.org>");
>> +MODULE_DESCRIPTION("Renesas R-Car CMM Driver");
>> +MODULE_LICENSE("GPL v2");
>> diff --git a/drivers/gpu/drm/rcar-du/rcar_cmm.h b/drivers/gpu/drm/rcar-du/rcar_cmm.h
>> new file mode 100644
>> index 000000000000..15a2c874b6a6
>> --- /dev/null
>> +++ b/drivers/gpu/drm/rcar-du/rcar_cmm.h
>> @@ -0,0 +1,61 @@
>> +/* SPDX-License-Identifier: GPL-2.0+ */
>> +/*
>> + * rcar_cmm.h -- R-Car Display Unit Color Management Module
>> + *
>> + * Copyright (C) 2019 Jacopo Mondi <jacopo+renesas@jmondi.org>
>> + */
>> +
>> +#ifndef __RCAR_CMM_H__
>> +#define __RCAR_CMM_H__
>> +
>> +#define CM2_LUT_SIZE		256
>> +
>> +struct drm_color_lut;
>> +struct platform_device;
>> +
>> +/**
>> + * struct rcar_cmm_config - CMM configuration
>> + *
>> + * @lut:	1D-LUT configuration
>> + * @lut.enable:	1D-LUT enable flag
>> + * @lut.table:	1D-LUT table entries. Might be set to NULL when the CMM has to
>> + *		be re-enabled but not re=programmed.
> 
> s/re=programmed/re-programmed/
> 
> As discussed offline this can't really happen as far as I can tell.
> However, it will still be useful when we'll add CLU support, as then a
> CLU reprogramming without a LUT reprogramming could happen.
> 
> I think we should make the documentation a bit clearer:
> 
> "1D-LUT table entries. Only valid when lut.enable is true, shall be NULL
> otherwise. When non-NULL, the LUT table will be programmed with the new
> values. Otherwise the LUT table will retain its previously programmed
> values."
> 
> This being said, the code in rcar_cmm_setup() will crash if table is
> NULL. I would either drop the option of table being NULL (and thus
> update the documentation here) if you don't need this yet in the DU
> driver, or fix rcar_cmm_setup(). You've posted enough versions of this
> series in my opinion, so please pick the easiest option, and we'll
> rework the code when adding CLU support anyway.
> 
> With those small issues fixes,
> 
> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> 
>> + */
>> +struct rcar_cmm_config {
>> +	struct {
>> +		bool enable;
>> +		struct drm_color_lut *table;
>> +	} lut;
>> +};
>> +
>> +#if IS_ENABLED(CONFIG_DRM_RCAR_CMM)
>> +int rcar_cmm_init(struct platform_device *pdev);
>> +
>> +int rcar_cmm_enable(struct platform_device *pdev);
>> +void rcar_cmm_disable(struct platform_device *pdev);
>> +
>> +int rcar_cmm_setup(struct platform_device *pdev,
>> +		   const struct rcar_cmm_config *config);
>> +#else
>> +static inline int rcar_cmm_init(struct platform_device *pdev)
>> +{
>> +	return 0;

I feel like here, this should return -ENODEV if CMM is disabled, and
allow rcar_du_cmm_init() to succeed, but leave the rcdu->cmms[i]
unpopulated. ...

But this could be updated later too if it's awkward ...

--
Kieran


>> +}
>> +
>> +static inline int rcar_cmm_enable(struct platform_device *pdev)
>> +{
>> +	return 0;
>> +}
>> +
>> +static inline void rcar_cmm_disable(struct platform_device *pdev)
>> +{
>> +}
>> +
>> +static int rcar_cmm_setup(struct platform_device *pdev,
>> +			  const struct rcar_cmm_config *config)
>> +{
>> +	return 0;
>> +}
>> +#endif /* IS_ENABLED(CONFIG_DRM_RCAR_CMM) */
>> +
>> +#endif /* __RCAR_CMM_H__ */
> 


^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [PATCH v4 3/9] drm: rcar-du: Add support for CMM
  2019-09-19  8:59     ` Kieran Bingham
@ 2019-09-20 22:43       ` Laurent Pinchart
  0 siblings, 0 replies; 38+ messages in thread
From: Laurent Pinchart @ 2019-09-20 22:43 UTC (permalink / raw)
  To: Kieran Bingham
  Cc: Jacopo Mondi, geert, horms, uli+renesas,
	VenkataRajesh.Kalakodima, airlied, daniel, koji.matsuoka.xm,
	muroya, Harsha.ManjulaMallikarjun, linux-renesas-soc, dri-devel,
	linux-kernel

Hi Kieran,

On Thu, Sep 19, 2019 at 09:59:39AM +0100, Kieran Bingham wrote:
> On 18/09/2019 23:55, Laurent Pinchart wrote:
> > On Fri, Sep 06, 2019 at 03:54:30PM +0200, Jacopo Mondi wrote:
> >> Add a driver for the R-Car Display Unit Color Correction Module.
> >>
> >> In most of Gen3 SoCs, each DU output channel is provided with a CMM unit
> >> to perform image enhancement and color correction.
> >>
> >> Add support for CMM through a driver that supports configuration of
> >> the 1-dimensional LUT table. More advanced CMM feature will be
> >> implemented on top of this basic one.
> >>
> >> Signed-off-by: Jacopo Mondi <jacopo+renesas@jmondi.org>
> >> ---
> >>  drivers/gpu/drm/rcar-du/Kconfig    |   7 +
> >>  drivers/gpu/drm/rcar-du/Makefile   |   1 +
> >>  drivers/gpu/drm/rcar-du/rcar_cmm.c | 251 +++++++++++++++++++++++++++++
> >>  drivers/gpu/drm/rcar-du/rcar_cmm.h |  61 +++++++
> >>  4 files changed, 320 insertions(+)
> >>  create mode 100644 drivers/gpu/drm/rcar-du/rcar_cmm.c
> >>  create mode 100644 drivers/gpu/drm/rcar-du/rcar_cmm.h
> >>
> >> diff --git a/drivers/gpu/drm/rcar-du/Kconfig b/drivers/gpu/drm/rcar-du/Kconfig
> >> index 1529849e217e..539d232790d1 100644
> >> --- a/drivers/gpu/drm/rcar-du/Kconfig
> >> +++ b/drivers/gpu/drm/rcar-du/Kconfig
> >> @@ -13,6 +13,13 @@ config DRM_RCAR_DU
> >>  	  Choose this option if you have an R-Car chipset.
> >>  	  If M is selected the module will be called rcar-du-drm.
> >>  
> >> +config DRM_RCAR_CMM
> >> +	bool "R-Car DU Color Management Module (CMM) Support"
> >> +	depends on DRM && OF
> >> +	depends on DRM_RCAR_DU
> >> +	help
> >> +	  Enable support for R-Car Color Management Module (CMM).
> >> +
> >>  config DRM_RCAR_DW_HDMI
> >>  	tristate "R-Car DU Gen3 HDMI Encoder Support"
> >>  	depends on DRM && OF
> >> diff --git a/drivers/gpu/drm/rcar-du/Makefile b/drivers/gpu/drm/rcar-du/Makefile
> >> index 6c2ed9c46467..4d1187ccc3e5 100644
> >> --- a/drivers/gpu/drm/rcar-du/Makefile
> >> +++ b/drivers/gpu/drm/rcar-du/Makefile
> >> @@ -15,6 +15,7 @@ rcar-du-drm-$(CONFIG_DRM_RCAR_LVDS)	+= rcar_du_of.o \
> >>  rcar-du-drm-$(CONFIG_DRM_RCAR_VSP)	+= rcar_du_vsp.o
> >>  rcar-du-drm-$(CONFIG_DRM_RCAR_WRITEBACK) += rcar_du_writeback.o
> >>  
> >> +obj-$(CONFIG_DRM_RCAR_CMM)		+= rcar_cmm.o
> >>  obj-$(CONFIG_DRM_RCAR_DU)		+= rcar-du-drm.o
> >>  obj-$(CONFIG_DRM_RCAR_DW_HDMI)		+= rcar_dw_hdmi.o
> >>  obj-$(CONFIG_DRM_RCAR_LVDS)		+= rcar_lvds.o
> >> diff --git a/drivers/gpu/drm/rcar-du/rcar_cmm.c b/drivers/gpu/drm/rcar-du/rcar_cmm.c
> >> new file mode 100644
> >> index 000000000000..3cacdc4474c7
> >> --- /dev/null
> >> +++ b/drivers/gpu/drm/rcar-du/rcar_cmm.c
> >> @@ -0,0 +1,251 @@
> >> +// SPDX-License-Identifier: GPL-2.0+
> >> +/*
> >> + * rcar_cmm.c -- R-Car Display Unit Color Management Module
> >> + *
> >> + * Copyright (C) 2019 Jacopo Mondi <jacopo+renesas@jmondi.org>
> >> + */
> >> +
> >> +#include <linux/io.h>
> >> +#include <linux/module.h>
> >> +#include <linux/of.h>
> >> +#include <linux/platform_device.h>
> >> +#include <linux/pm_runtime.h>
> >> +
> >> +#include <drm/drm_color_mgmt.h>
> >> +
> >> +#include "rcar_cmm.h"
> >> +
> >> +#define CM2_LUT_CTRL		0x0000
> >> +#define CM2_LUT_CTRL_LUT_EN	BIT(0)
> >> +#define CM2_LUT_TBL_BASE	0x0600
> >> +#define CM2_LUT_TBL(__i)	(CM2_LUT_TBL_BASE + (__i) * 4)
> >> +
> >> +struct rcar_cmm {
> >> +	void __iomem *base;
> >> +	bool enabled;
> >> +
> >> +	/*
> >> +	 * @lut:		1D-LUT status
> >> +	 * @lut.enabled:	1D-LUT enabled flag
> >> +	 * @lut.table:		Table of 1D-LUT entries scaled to hardware
> >> +	 *			precision (8-bits per color component)
> >> +	 */
> >> +	struct {
> >> +		bool enabled;
> >> +		u32 table[CM2_LUT_SIZE];
> >> +	} lut;
> >> +};
> >> +
> >> +static inline int rcar_cmm_read(struct rcar_cmm *rcmm, u32 reg)
> >> +{
> >> +	return ioread32(rcmm->base + reg);
> >> +}
> >> +
> >> +static inline void rcar_cmm_write(struct rcar_cmm *rcmm, u32 reg, u32 data)
> >> +{
> >> +	iowrite32(data, rcmm->base + reg);
> >> +}
> >> +
> >> +/*
> >> + * rcar_cmm_lut_extract() - Scale down to hardware precision the DRM LUT table
> >> + *			    entries and store them.
> > 
> > "Scale the DRM LUT table entries to hardware precision and store them."
> > 
> >> + * @rcmm: Pointer to the CMM device
> >> + * @drm_lut: Pointer to the DRM LUT table
> >> + */
> >> +static void rcar_cmm_lut_extract(struct rcar_cmm *rcmm,
> >> +				 const struct drm_color_lut *drm_lut)
> >> +{
> >> +	unsigned int i;
> >> +
> >> +	for (i = 0; i < CM2_LUT_SIZE; ++i) {
> >> +		const struct drm_color_lut *lut = &drm_lut[i];
> >> +
> >> +		rcmm->lut.table[i] = drm_color_lut_extract(lut->red, 8) << 16
> >> +				   | drm_color_lut_extract(lut->green, 8) << 8
> >> +				   | drm_color_lut_extract(lut->blue, 8);
> >> +	}
> >> +}
> >> +
> >> +/*
> >> + * rcar_cmm_lut_write() - Write to hardware the LUT table entries from the
> >> + *			  local table.
> > 
> > "Write the LUT table entries from the local table to the hardware."
> > 
> >> + * @rcmm: Pointer to the CMM device
> >> + */
> >> +static void rcar_cmm_lut_write(struct rcar_cmm *rcmm)
> >> +{
> >> +	unsigned int i;
> >> +
> >> +	for (i = 0; i < CM2_LUT_SIZE; ++i)
> >> +		rcar_cmm_write(rcmm, CM2_LUT_TBL(i), rcmm->lut.table[i]);
> >> +}
> >> +
> >> +/*
> >> + * rcar_cmm_setup() - Configure the CMM unit.
> >> + * @pdev: The platform device associated with the CMM instance
> >> + * @config: The CRTC-provided configuration.
> >> + *
> >> + * Configure the CMM unit with the CRTC-provided configuration.
> >> + * Currently enabling, disabling and programming of the 1-D LUT unit is
> >> + * supported.
> >> + */
> >> +int rcar_cmm_setup(struct platform_device *pdev,
> >> +		   const struct rcar_cmm_config *config)
> >> +{
> >> +	struct rcar_cmm *rcmm = platform_get_drvdata(pdev);
> >> +
> >> +	/*
> >> +	 * As rcar_cmm_setup() is called by atomic commit tail helper, it might
> >> +	 * be called when the CMM is disabled. As we can't program the hardware
> >> +	 * in that case, store the configuration internally and apply it when
> >> +	 * the CMM will be enabled by the CRTC through rcar_cmm_enable().
> >> +	 */
> >> +	if (!rcmm->enabled) {
> >> +		if (!config->lut.enable)
> >> +			return 0;
> >> +
> >> +		rcar_cmm_lut_extract(rcmm, config->lut.table);
> >> +		rcmm->lut.enabled = true;
> >> +
> >> +		return 0;
> >> +	}
> >> +
> >> +	/* Stop LUT operations if requested. */
> >> +	if (!config->lut.enable) {
> >> +		if (rcmm->lut.enabled) {
> >> +			rcar_cmm_write(rcmm, CM2_LUT_CTRL, 0);
> >> +			rcmm->lut.enabled = false;
> >> +		}
> >> +
> >> +		return 0;
> >> +	}
> >> +
> >> +	/*
> >> +	 * Enable LUT and program the new gamma table values.
> >> +	 *
> >> +	 * FIXME: In order to have stable operations it is required to first
> >> +	 * enable the 1D-LUT and then program its table entries. This seems to
> >> +	 * contradict what the chip manual reports, and will have to be
> >> +	 * reconsidered when implementing support for double buffering.
> >> +	 */
> >> +	if (!rcmm->lut.enabled) {
> >> +		rcar_cmm_write(rcmm, CM2_LUT_CTRL, CM2_LUT_CTRL_LUT_EN);
> >> +		rcmm->lut.enabled = true;
> >> +	}
> >> +
> >> +	rcar_cmm_lut_extract(rcmm, config->lut.table);
> >> +	rcar_cmm_lut_write(rcmm);
> >> +
> >> +	return 0;
> >> +}
> >> +EXPORT_SYMBOL_GPL(rcar_cmm_setup);
> >> +
> >> +/*
> >> + * rcar_cmm_enable() - Enable the CMM unit.
> >> + * @pdev: The platform device associated with the CMM instance
> >> + *
> >> + * Enable the CMM unit by enabling the parent clock and enabling the CMM
> >> + * components, such as 1-D LUT, if requested.
> >> + */
> >> +int rcar_cmm_enable(struct platform_device *pdev)
> >> +{
> >> +	struct rcar_cmm *rcmm = platform_get_drvdata(pdev);
> >> +	int ret;
> >> +
> >> +	ret = pm_runtime_get_sync(&pdev->dev);
> >> +	if (ret < 0)
> >> +		return ret;
> >> +
> >> +	/* Apply the LUT table values saved at rcar_cmm_setup() time. */
> >> +	if (rcmm->lut.enabled) {
> >> +		rcar_cmm_write(rcmm, CM2_LUT_CTRL, CM2_LUT_CTRL_LUT_EN);
> >> +		rcar_cmm_lut_write(rcmm);
> >> +	}
> >> +
> >> +	rcmm->enabled = true;
> >> +
> >> +	return 0;
> >> +}
> >> +EXPORT_SYMBOL_GPL(rcar_cmm_enable);
> >> +
> >> +/*
> >> + * rcar_cmm_disable() - Disable the CMM unit.
> >> + * @pdev: The platform device associated with the CMM instance
> >> + *
> >> + * Disable the CMM unit by stopping the parent clock.
> >> + */
> >> +void rcar_cmm_disable(struct platform_device *pdev)
> >> +{
> >> +	struct rcar_cmm *rcmm = platform_get_drvdata(pdev);
> >> +
> >> +	rcar_cmm_write(rcmm, CM2_LUT_CTRL, 0);
> >> +
> >> +	pm_runtime_put(&pdev->dev);
> >> +
> >> +	rcmm->lut.enabled = false;
> >> +	rcmm->enabled = false;
> >> +}
> >> +EXPORT_SYMBOL_GPL(rcar_cmm_disable);
> >> +
> >> +/*
> >> + * rcar_cmm_init() - Make sure the CMM has probed.
> > 
> > I would document this as "Intialize the CMM" to match the function name.
> > We may add more initialization in the future.
> > 
> >> + * @pdev: The platform device associated with the CMM instance
> >> + *
> >> + * Return: 0 if the CMM has probed, -EPROBE_DEFER otherwise
> > 
> > 0 on success, -EPROBE_DEFER is the CMM isn't availablet yet
> 
> And possibly -ENODEV if the suggestion below in the header is worthy, to
> return no device if the CMM is disabled at the CONFIG_ level.
> 
> >> + */
> >> +int rcar_cmm_init(struct platform_device *pdev)
> >> +{
> >> +	struct rcar_cmm *rcmm = platform_get_drvdata(pdev);
> >> +
> >> +	if (!rcmm)
> >> +		return -EPROBE_DEFER;
> >> +
> >> +	return 0;
> >> +}
> >> +EXPORT_SYMBOL_GPL(rcar_cmm_init);
> >> +
> >> +static int rcar_cmm_probe(struct platform_device *pdev)
> >> +{
> >> +	struct rcar_cmm *rcmm;
> >> +
> >> +	rcmm = devm_kzalloc(&pdev->dev, sizeof(*rcmm), GFP_KERNEL);
> >> +	if (!rcmm)
> >> +		return -ENOMEM;
> >> +	platform_set_drvdata(pdev, rcmm);
> >> +
> >> +	rcmm->base = devm_platform_ioremap_resource(pdev, 0);
> >> +	if (IS_ERR(rcmm->base))
> >> +		return PTR_ERR(rcmm->base);
> >> +
> >> +	pm_runtime_enable(&pdev->dev);
> >> +
> >> +	return 0;
> >> +}
> >> +
> >> +static int rcar_cmm_remove(struct platform_device *pdev)
> >> +{
> >> +	pm_runtime_disable(&pdev->dev);
> >> +
> >> +	return 0;
> >> +}
> >> +
> >> +static const struct of_device_id rcar_cmm_of_table[] = {
> >> +	{ .compatible = "renesas,rcar-gen3-cmm", },
> >> +	{ .compatible = "renesas,rcar-gen2-cmm", },
> >> +	{ },
> >> +};
> >> +MODULE_DEVICE_TABLE(of, rcar_cmm_of_table);
> >> +
> >> +static struct platform_driver rcar_cmm_platform_driver = {
> >> +	.probe		= rcar_cmm_probe,
> >> +	.remove		= rcar_cmm_remove,
> >> +	.driver		= {
> >> +		.name	= "rcar-cmm",
> >> +		.of_match_table = rcar_cmm_of_table,
> >> +	},
> >> +};
> >> +
> >> +module_platform_driver(rcar_cmm_platform_driver);
> >> +
> >> +MODULE_AUTHOR("Jacopo Mondi <jacopo+renesas@jmondi.org>");
> >> +MODULE_DESCRIPTION("Renesas R-Car CMM Driver");
> >> +MODULE_LICENSE("GPL v2");
> >> diff --git a/drivers/gpu/drm/rcar-du/rcar_cmm.h b/drivers/gpu/drm/rcar-du/rcar_cmm.h
> >> new file mode 100644
> >> index 000000000000..15a2c874b6a6
> >> --- /dev/null
> >> +++ b/drivers/gpu/drm/rcar-du/rcar_cmm.h
> >> @@ -0,0 +1,61 @@
> >> +/* SPDX-License-Identifier: GPL-2.0+ */
> >> +/*
> >> + * rcar_cmm.h -- R-Car Display Unit Color Management Module
> >> + *
> >> + * Copyright (C) 2019 Jacopo Mondi <jacopo+renesas@jmondi.org>
> >> + */
> >> +
> >> +#ifndef __RCAR_CMM_H__
> >> +#define __RCAR_CMM_H__
> >> +
> >> +#define CM2_LUT_SIZE		256
> >> +
> >> +struct drm_color_lut;
> >> +struct platform_device;
> >> +
> >> +/**
> >> + * struct rcar_cmm_config - CMM configuration
> >> + *
> >> + * @lut:	1D-LUT configuration
> >> + * @lut.enable:	1D-LUT enable flag
> >> + * @lut.table:	1D-LUT table entries. Might be set to NULL when the CMM has to
> >> + *		be re-enabled but not re=programmed.
> > 
> > s/re=programmed/re-programmed/
> > 
> > As discussed offline this can't really happen as far as I can tell.
> > However, it will still be useful when we'll add CLU support, as then a
> > CLU reprogramming without a LUT reprogramming could happen.
> > 
> > I think we should make the documentation a bit clearer:
> > 
> > "1D-LUT table entries. Only valid when lut.enable is true, shall be NULL
> > otherwise. When non-NULL, the LUT table will be programmed with the new
> > values. Otherwise the LUT table will retain its previously programmed
> > values."
> > 
> > This being said, the code in rcar_cmm_setup() will crash if table is
> > NULL. I would either drop the option of table being NULL (and thus
> > update the documentation here) if you don't need this yet in the DU
> > driver, or fix rcar_cmm_setup(). You've posted enough versions of this
> > series in my opinion, so please pick the easiest option, and we'll
> > rework the code when adding CLU support anyway.
> > 
> > With those small issues fixes,
> > 
> > Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> > 
> >> + */
> >> +struct rcar_cmm_config {
> >> +	struct {
> >> +		bool enable;
> >> +		struct drm_color_lut *table;
> >> +	} lut;
> >> +};
> >> +
> >> +#if IS_ENABLED(CONFIG_DRM_RCAR_CMM)
> >> +int rcar_cmm_init(struct platform_device *pdev);
> >> +
> >> +int rcar_cmm_enable(struct platform_device *pdev);
> >> +void rcar_cmm_disable(struct platform_device *pdev);
> >> +
> >> +int rcar_cmm_setup(struct platform_device *pdev,
> >> +		   const struct rcar_cmm_config *config);
> >> +#else
> >> +static inline int rcar_cmm_init(struct platform_device *pdev)
> >> +{
> >> +	return 0;
> 
> I feel like here, this should return -ENODEV if CMM is disabled, and
> allow rcar_du_cmm_init() to succeed, but leave the rcdu->cmms[i]
> unpopulated. ...

I think that's a good idea, otherwise the DU driver will believe that
CMM initialisation succeeded, and will configure the DU to route its
outputs to the CMM. I don't think that would work nicely without a
driver :-) Although, in practice, for the processing (non-statistics)
path, the DU output clock may be all that is needed, so the CMM might be
operational in its default configuration without the MSTP clock. Still,
that's probably not a very safe path, so I'd rather see CMM being
disabled on the DU side in that case.

> But this could be updated later too if it's awkward ...

Hopefully that would be easy to do :-)

> >> +}
> >> +
> >> +static inline int rcar_cmm_enable(struct platform_device *pdev)
> >> +{
> >> +	return 0;
> >> +}
> >> +
> >> +static inline void rcar_cmm_disable(struct platform_device *pdev)
> >> +{
> >> +}
> >> +
> >> +static int rcar_cmm_setup(struct platform_device *pdev,
> >> +			  const struct rcar_cmm_config *config)
> >> +{
> >> +	return 0;
> >> +}
> >> +#endif /* IS_ENABLED(CONFIG_DRM_RCAR_CMM) */
> >> +
> >> +#endif /* __RCAR_CMM_H__ */

-- 
Regards,

Laurent Pinchart

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [PATCH v4 6/9] drm: rcar-du: crtc: Enable and disable CMMs
  2019-09-19  8:08           ` Kieran Bingham
@ 2019-09-20 22:44             ` Laurent Pinchart
  0 siblings, 0 replies; 38+ messages in thread
From: Laurent Pinchart @ 2019-09-20 22:44 UTC (permalink / raw)
  To: Kieran Bingham
  Cc: Jacopo Mondi, Jacopo Mondi, geert, horms, uli+renesas,
	VenkataRajesh.Kalakodima, airlied, daniel, koji.matsuoka.xm,
	muroya, Harsha.ManjulaMallikarjun, linux-renesas-soc, dri-devel,
	linux-kernel

Hi Kieran,

On Thu, Sep 19, 2019 at 09:08:18AM +0100, Kieran Bingham wrote:
> On 19/09/2019 00:23, Laurent Pinchart wrote:
> > On Thu, Sep 12, 2019 at 10:19:30AM +0100, Kieran Bingham wrote:
> >> On 12/09/2019 09:07, Jacopo Mondi wrote:
> >>> On Wed, Sep 11, 2019 at 07:40:27PM +0100, Kieran Bingham wrote:
> >>>> On 06/09/2019 14:54, Jacopo Mondi wrote:
> >>>>> Enable/disable the CMM associated with a CRTC at CRTC start and stop
> >>>>> time and enable the CMM unit through the Display Extensional Functions
> >>>>> register at group setup time.
> >>>>>
> >>>>> Reviewed-by: Ulrich Hecht <uli+renesas@fpond.eu>
> >>>>> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> >>>>> Signed-off-by: Jacopo Mondi <jacopo+renesas@jmondi.org>
> >>>>> ---
> >>>>>  drivers/gpu/drm/rcar-du/rcar_du_crtc.c  | 7 +++++++
> >>>>>  drivers/gpu/drm/rcar-du/rcar_du_group.c | 8 ++++++++
> >>>>>  drivers/gpu/drm/rcar-du/rcar_du_regs.h  | 5 +++++
> >>>>>  3 files changed, 20 insertions(+)
> >>>>>
> >>>>> diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
> >>>>> index 23f1d6cc1719..3dac605c3a67 100644
> >>>>> --- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
> >>>>> +++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
> >>>>> @@ -21,6 +21,7 @@
> >>>>>  #include <drm/drm_plane_helper.h>
> >>>>>  #include <drm/drm_vblank.h>
> >>>>>
> >>>>> +#include "rcar_cmm.h"
> >>>>>  #include "rcar_du_crtc.h"
> >>>>>  #include "rcar_du_drv.h"
> >>>>>  #include "rcar_du_encoder.h"
> >>>>> @@ -619,6 +620,9 @@ static void rcar_du_crtc_stop(struct rcar_du_crtc *rcrtc)
> >>>>>  	if (rcar_du_has(rcrtc->dev, RCAR_DU_FEATURE_VSP1_SOURCE))
> >>>>>  		rcar_du_vsp_disable(rcrtc);
> >>>>>
> >>>>> +	if (rcrtc->cmm)
> >>>>> +		rcar_cmm_disable(rcrtc->cmm);
> >>>>> +
> >>>>>  	/*
> >>>>>  	 * Select switch sync mode. This stops display operation and configures
> >>>>>  	 * the HSYNC and VSYNC signals as inputs.
> >>>>> @@ -686,6 +690,9 @@ static void rcar_du_crtc_atomic_enable(struct drm_crtc *crtc,
> >>>>>  	}
> >>>>>
> >>>>>  	rcar_du_crtc_start(rcrtc);
> >>>>> +
> >>>>> +	if (rcrtc->cmm)
> >>>>> +		rcar_cmm_enable(rcrtc->cmm);
> >>>>>  }
> >>>>>
> >>>>>  static void rcar_du_crtc_atomic_disable(struct drm_crtc *crtc,
> >>>>> diff --git a/drivers/gpu/drm/rcar-du/rcar_du_group.c b/drivers/gpu/drm/rcar-du/rcar_du_group.c
> >>>>> index 9eee47969e77..25d0fc125d7a 100644
> >>>>> --- a/drivers/gpu/drm/rcar-du/rcar_du_group.c
> >>>>> +++ b/drivers/gpu/drm/rcar-du/rcar_du_group.c
> >>>>> @@ -147,6 +147,14 @@ static void rcar_du_group_setup(struct rcar_du_group *rgrp)
> >>>>>
> >>>>>  	rcar_du_group_setup_pins(rgrp);
> >>>>>
> >>>>> +	if (rcar_du_has(rcdu, RCAR_DU_FEATURE_CMM)) {
> >>>>> +		u32 defr7 = DEFR7_CODE
> >>>>> +			  | (rgrp->cmms_mask & BIT(1) ? DEFR7_CMME1 : 0)
> >>>>> +			  | (rgrp->cmms_mask & BIT(0) ? DEFR7_CMME0 : 0);
> >>>>> +
> >>>>> +		rcar_du_group_write(rgrp, DEFR7, defr7);
> >>>>> +	}
> >>>>> +
> >>>>
> >>>> What's the effect here on platforms with a CMM, but with
> >>>> CONFIG_DRM_RCAR_CMM unset?
> >>>>
> >>>> Will this incorrectly configure the DU ?
> >>>>
> >>>> Will it stall the display if the DU tries to interact with another
> >>>> module which is not enabled?
> >>>
> >>> I recall I tested that (that's why I had to add stubs for CMM
> >>> functions, as I had linkage errors otherwise) and thing seems to be
> >>> fine as the CMM configuration/enblement resolve to an empty function.
> >>
> >> Yes, I see the stubs to allow for linkage, but it's the hardware I'm
> >> concerned about. If it passes the tests and doesn't break then that's
> >> probably ok ... but I'm really weary that we're enabling a hardware
> >> pipeline with a disabled component in the middle.
> >>
> >>> Would you prefer to have this guarded by an #if IS_ENABLED() ?
> >>
> >> I don't think we need a compile time conditional, but I'd say it
> >> probably needs to be more about whether the CMM has actually probed or not
> >>
> >> Aha, and I see that in rcar_du_cmm_init() we already do a
> >> call to rcar_cmm_init(), which if fails will leave rcdu->cmms[i] as
> >> NULL. So that's catered for, which results in the rgrp->cmms_mask being
> >> correctly representative of whether there is a CMM connected or not.
> > 
> > Doesn't this result in probe failure ?
> 
> I think I mis-spoke above, I didn't mean "if rcar_cmm_init() fails" I
> meant "if rcar_du_cmm_init() determines there are no connected CMM's or
> if they are disabled."
> 
> If rcar_cmm_init() returns a failure, then yes we will fail to probe.
> 
> But I think it's up to rcar_du_cmm_init() to determine if the CMM exists
> or not (or is enabled) and if that's not a failure case then it should
> not prevent the probing of the DU.
> 
> In fact, I've now seen that if CONFIG_DRM_RCAR_CMM is not enabled,
> rcar_cmm_init() returns 0, and I think in fact it should return -ENODEV,
> with an exception on that return value in rcar_du_cmm_init() so that the
> DU continues with no CMM attached there.

I've replied to your other e-mail regarding this, and I agree with you.

> >>  ... so I think that means the ...
> >>  "if (rcar_du_has(rcdu, RCAR_DU_FEATURE_CMM))" is somewhat redundant:
> >>
> >>
> >> This could be:
> >>
> >>   if (rgrp->cmms_mask) {
> >> 	u32 defr7 = DEFR7_CODE
> >> 		  | (rgrp->cmms_mask & BIT(1) ? DEFR7_CMME1 : 0)
> >> 		  | (rgrp->cmms_mask & BIT(0) ? DEFR7_CMME0 : 0);
> >>
> >>   rcar_du_group_write(rgrp, DEFR7, defr7);
> >>
> >> Or in fact, if we don't mind writing 0 to DEFR7 when there is no CMM
> >> (which is safe by the looks of things as DEFR7 is available on all
> >> platforms), then we can even remove the outer conditional, and leave
> >> this all up to the ternary operators to write the correct value to the
> >> defr7.
> >>
> >> Phew ... net result - your current code *is* safe with the
> >> CONFIG_DRM_RCAR_CMM option disabled. I'll leave it up to you if you want
> >> to simplify the code here and remove the RCAR_DU_FEATURE_CMM.
> >>
> >> As this RCAR_DU_FEATURE_CMM flag is only checked here, removing it would
> >> however simplify all of the rcar_du_device_info structures.
> >>
> >> So - with or without the _FEATURE_CMM" simplification, this patch looks
> >> functional and safe so:
> >>
> >>
> >> Reviewed-by: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com>
> >>
> >>>>>  	if (rcdu->info->gen >= 2) {
> >>>>>  		rcar_du_group_setup_defr8(rgrp);
> >>>>>  		rcar_du_group_setup_didsr(rgrp);
> >>>>> diff --git a/drivers/gpu/drm/rcar-du/rcar_du_regs.h b/drivers/gpu/drm/rcar-du/rcar_du_regs.h
> >>>>> index bc87f080b170..fb9964949368 100644
> >>>>> --- a/drivers/gpu/drm/rcar-du/rcar_du_regs.h
> >>>>> +++ b/drivers/gpu/drm/rcar-du/rcar_du_regs.h
> >>>>> @@ -197,6 +197,11 @@
> >>>>>  #define DEFR6_MLOS1		(1 << 2)
> >>>>>  #define DEFR6_DEFAULT		(DEFR6_CODE | DEFR6_TCNE1)
> >>>>>
> >>>>> +#define DEFR7			0x000ec
> >>>>> +#define DEFR7_CODE		(0x7779 << 16)
> >>>>> +#define DEFR7_CMME1		BIT(6)
> >>>>> +#define DEFR7_CMME0		BIT(4)
> >>>>> +
> >>>>>  /* -----------------------------------------------------------------------------
> >>>>>   * R8A7790-only Control Registers
> >>>>>   */

-- 
Regards,

Laurent Pinchart

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [PATCH v4 8/9] drm: rcar-du: kms: Update CMM in atomic commit tail
  2019-09-06 13:54 ` [PATCH v4 8/9] drm: rcar-du: kms: Update CMM in atomic commit tail Jacopo Mondi
  2019-09-12  9:51   ` Kieran Bingham
@ 2019-09-20 22:49   ` Laurent Pinchart
  2019-09-30 20:53   ` Ezequiel Garcia
  2 siblings, 0 replies; 38+ messages in thread
From: Laurent Pinchart @ 2019-09-20 22:49 UTC (permalink / raw)
  To: daniel
  Cc: Jacopo Mondi, kieran.bingham+renesas, geert, horms, uli+renesas,
	VenkataRajesh.Kalakodima, airlied, koji.matsuoka.xm, muroya,
	Harsha.ManjulaMallikarjun, linux-renesas-soc, dri-devel,
	linux-kernel

Hi Daniel,

On Fri, Sep 06, 2019 at 03:54:35PM +0200, Jacopo Mondi wrote:
> Update CMM settings at in the atomic commit tail helper method.
> The CMM is updated with new gamma values provided to the driver
> in the GAMMA_LUT blob property.
> 
> When resuming from system suspend, the DU driver is responsible for
> reprogramming and enabling the CMM unit if it was in use at the time the
> system entered the suspend state.  Force the color_mgmt_changed flag to
> true if the DRM gamma lut color transformation property was set in the
> CRTC state duplicated at suspend time, as the CMM gets reprogrammed only
> if said flag is active in the rcar_du_atomic_commit_update_cmm() method.
> 
> Reviewed-by: Ulrich Hecht <uli+renesas@fpond.eu>
> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> Signed-off-by: Jacopo Mondi <jacopo+renesas@jmondi.org>
> ---
> 
> Daniel could you have a look if resume bits are worth being moved to the
> DRM core? The color_mgmt_changed flag is set to false when the state is
> duplicated if I read the code correctly, but when this happens in a
> suspend/resume sequence its value should probably be restored to true if
> any color management property was set in the crtc state when system entered
> suspend.

Gentle ping on this.

> ---
> 
>  drivers/gpu/drm/rcar-du/rcar_du_drv.c | 20 ++++++++++++++
>  drivers/gpu/drm/rcar-du/rcar_du_kms.c | 38 +++++++++++++++++++++++++++
>  2 files changed, 58 insertions(+)
> 
> diff --git a/drivers/gpu/drm/rcar-du/rcar_du_drv.c b/drivers/gpu/drm/rcar-du/rcar_du_drv.c
> index 018480a8f35c..d1003d31cfaf 100644
> --- a/drivers/gpu/drm/rcar-du/rcar_du_drv.c
> +++ b/drivers/gpu/drm/rcar-du/rcar_du_drv.c
> @@ -17,6 +17,7 @@
>  #include <linux/slab.h>
>  #include <linux/wait.h>
> 
> +#include <drm/drm_atomic.h>
>  #include <drm/drm_atomic_helper.h>
>  #include <drm/drm_fb_cma_helper.h>
>  #include <drm/drm_fb_helper.h>
> @@ -482,6 +483,25 @@ static int rcar_du_pm_suspend(struct device *dev)
>  static int rcar_du_pm_resume(struct device *dev)
>  {
>  	struct rcar_du_device *rcdu = dev_get_drvdata(dev);
> +	struct drm_atomic_state *state = rcdu->ddev->mode_config.suspend_state;
> +	unsigned int i;
> +
> +	for (i = 0; i < rcdu->num_crtcs; ++i) {
> +		struct drm_crtc *crtc = &rcdu->crtcs[i].crtc;
> +		struct drm_crtc_state *crtc_state;
> +
> +		crtc_state = drm_atomic_get_new_crtc_state(state, crtc);
> +		if (!crtc_state)
> +			continue;
> +
> +		/*
> +		 * Force re-enablement of CMM after system resume if any
> +		 * of the DRM color transformation properties was set in
> +		 * the state saved at system suspend time.
> +		 */
> +		if (crtc_state->gamma_lut)
> +			crtc_state->color_mgmt_changed = true;
> +	}
> 
>  	return drm_mode_config_helper_resume(rcdu->ddev);
>  }
> diff --git a/drivers/gpu/drm/rcar-du/rcar_du_kms.c b/drivers/gpu/drm/rcar-du/rcar_du_kms.c
> index 294630e56992..fc30fff0eb8d 100644
> --- a/drivers/gpu/drm/rcar-du/rcar_du_kms.c
> +++ b/drivers/gpu/drm/rcar-du/rcar_du_kms.c
> @@ -22,6 +22,7 @@
>  #include <linux/of_platform.h>
>  #include <linux/wait.h>
> 
> +#include "rcar_cmm.h"
>  #include "rcar_du_crtc.h"
>  #include "rcar_du_drv.h"
>  #include "rcar_du_encoder.h"
> @@ -368,6 +369,40 @@ rcar_du_fb_create(struct drm_device *dev, struct drm_file *file_priv,
>   * Atomic Check and Update
>   */
> 
> +static void rcar_du_atomic_commit_update_cmm(struct drm_crtc *crtc,
> +					     struct drm_crtc_state *old_state)
> +{
> +	struct rcar_du_crtc *rcrtc = to_rcar_crtc(crtc);
> +	struct rcar_cmm_config cmm_config = {};
> +	struct device *dev = rcrtc->dev->dev;
> +	struct drm_property_blob *lut_blob;
> +
> +	if (!rcrtc->cmm || !crtc->state->color_mgmt_changed)
> +		return;
> +
> +	if (!crtc->state->gamma_lut) {
> +		cmm_config.lut.enable = false;
> +		rcar_cmm_setup(rcrtc->cmm, &cmm_config);
> +		return;
> +	}
> +
> +	lut_blob = crtc->state->gamma_lut;
> +	if (lut_blob->length != (CM2_LUT_SIZE * sizeof(struct drm_color_lut))) {
> +		/*
> +		 * We only accept fully populated LUT tables;
> +		 * be loud here, otherwise the CMM gets silently ignored.
> +		 */
> +		dev_err(dev, "invalid gamma lut size of %lu bytes\n",
> +			lut_blob->length);
> +		return;
> +	}
> +
> +	cmm_config.lut.enable = true;
> +	cmm_config.lut.table = (struct drm_color_lut *)lut_blob->data;
> +
> +	rcar_cmm_setup(rcrtc->cmm, &cmm_config);
> +}
> +
>  static int rcar_du_atomic_check(struct drm_device *dev,
>  				struct drm_atomic_state *state)
>  {
> @@ -410,6 +445,9 @@ static void rcar_du_atomic_commit_tail(struct drm_atomic_state *old_state)
>  			rcdu->dpad1_source = rcrtc->index;
>  	}
> 
> +	for_each_old_crtc_in_state(old_state, crtc, crtc_state, i)
> +		rcar_du_atomic_commit_update_cmm(crtc, crtc_state);
> +
>  	/* Apply the atomic update. */
>  	drm_atomic_helper_commit_modeset_disables(dev, old_state);
>  	drm_atomic_helper_commit_planes(dev, old_state,

-- 
Regards,

Laurent Pinchart

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [PATCH v4 8/9] drm: rcar-du: kms: Update CMM in atomic commit tail
  2019-09-06 13:54 ` [PATCH v4 8/9] drm: rcar-du: kms: Update CMM in atomic commit tail Jacopo Mondi
  2019-09-12  9:51   ` Kieran Bingham
  2019-09-20 22:49   ` Laurent Pinchart
@ 2019-09-30 20:53   ` Ezequiel Garcia
  2019-10-01 19:20     ` Laurent Pinchart
  2 siblings, 1 reply; 38+ messages in thread
From: Ezequiel Garcia @ 2019-09-30 20:53 UTC (permalink / raw)
  To: Jacopo Mondi, laurent.pinchart, kieran.bingham+renesas, geert,
	horms, uli+renesas, VenkataRajesh.Kalakodima, airlied, daniel
  Cc: muroya, koji.matsuoka.xm, dri-devel, linux-kernel,
	linux-renesas-soc, Harsha.ManjulaMallikarjun, Doug Anderson,
	Heiko Stuebner

+Doug, Heiko:

On Fri, 2019-09-06 at 15:54 +0200, Jacopo Mondi wrote:
> Update CMM settings at in the atomic commit tail helper method.
> The CMM is updated with new gamma values provided to the driver
> in the GAMMA_LUT blob property.
> 
> When resuming from system suspend, the DU driver is responsible for
> reprogramming and enabling the CMM unit if it was in use at the time the
> system entered the suspend state.  Force the color_mgmt_changed flag to
> true if the DRM gamma lut color transformation property was set in the
> CRTC state duplicated at suspend time, as the CMM gets reprogrammed only
> if said flag is active in the rcar_du_atomic_commit_update_cmm() method.
> 
> Reviewed-by: Ulrich Hecht <uli+renesas@fpond.eu>
> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> Signed-off-by: Jacopo Mondi <jacopo+renesas@jmondi.org>
> ---
> 
> Daniel could you have a look if resume bits are worth being moved to the
> DRM core? The color_mgmt_changed flag is set to false when the state is
> duplicated if I read the code correctly, but when this happens in a
> suspend/resume sequence its value should probably be restored to true if
> any color management property was set in the crtc state when system entered
> suspend.
> 

Perhaps we can use the for_each_new_crtc_in_state() helper here,
and move it to the core like this:

--- a/drivers/gpu/drm/drm_atomic_helper.c
+++ b/drivers/gpu/drm/drm_atomic_helper.c
@@ -3234,8 +3234,20 @@ int drm_atomic_helper_resume(struct
drm_device *dev,
                             struct drm_atomic_state *state)
 {
        struct drm_modeset_acquire_ctx ctx;
+       struct drm_crtc_state
*crtc_state;
+       struct drm_crtc *crtc;
+       unsigned int i;
        int err;
 
+       for_each_new_crtc_in_state(state, crtc, crtc_state, i) {
+   
            /*
+                * Force re-enablement of CMM after system resume if any
+                * of the DRM color transformation properties
was set in
+                * the state saved at system suspend time.
+                */
+               if (crtc_state->gamma_lut)
+                    
   crtc_state->color_mgmt_changed = true;
+       }

This probably is wrong, and should be instead constrained to some
condition of some sort.

FWIW, the Rockchip DRM is going to need this as well.

Any ideas?

Thanks,
Ezequiel


^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [PATCH v4 8/9] drm: rcar-du: kms: Update CMM in atomic commit tail
  2019-09-30 20:53   ` Ezequiel Garcia
@ 2019-10-01 19:20     ` Laurent Pinchart
  0 siblings, 0 replies; 38+ messages in thread
From: Laurent Pinchart @ 2019-10-01 19:20 UTC (permalink / raw)
  To: Ezequiel Garcia
  Cc: Jacopo Mondi, kieran.bingham+renesas, geert, horms, uli+renesas,
	VenkataRajesh.Kalakodima, airlied, daniel, muroya,
	koji.matsuoka.xm, dri-devel, linux-kernel, linux-renesas-soc,
	Harsha.ManjulaMallikarjun, Doug Anderson, Heiko Stuebner

Hi Ezequiel,

On Mon, Sep 30, 2019 at 05:53:00PM -0300, Ezequiel Garcia wrote:
> +Doug, Heiko:
> 
> On Fri, 2019-09-06 at 15:54 +0200, Jacopo Mondi wrote:
> > Update CMM settings at in the atomic commit tail helper method.
> > The CMM is updated with new gamma values provided to the driver
> > in the GAMMA_LUT blob property.
> > 
> > When resuming from system suspend, the DU driver is responsible for
> > reprogramming and enabling the CMM unit if it was in use at the time the
> > system entered the suspend state.  Force the color_mgmt_changed flag to
> > true if the DRM gamma lut color transformation property was set in the
> > CRTC state duplicated at suspend time, as the CMM gets reprogrammed only
> > if said flag is active in the rcar_du_atomic_commit_update_cmm() method.
> > 
> > Reviewed-by: Ulrich Hecht <uli+renesas@fpond.eu>
> > Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> > Signed-off-by: Jacopo Mondi <jacopo+renesas@jmondi.org>
> > ---
> > 
> > Daniel could you have a look if resume bits are worth being moved to the
> > DRM core? The color_mgmt_changed flag is set to false when the state is
> > duplicated if I read the code correctly, but when this happens in a
> > suspend/resume sequence its value should probably be restored to true if
> > any color management property was set in the crtc state when system entered
> > suspend.
> 
> Perhaps we can use the for_each_new_crtc_in_state() helper here,
> and move it to the core like this:
> 
> --- a/drivers/gpu/drm/drm_atomic_helper.c
> +++ b/drivers/gpu/drm/drm_atomic_helper.c
> @@ -3234,8 +3234,20 @@ int drm_atomic_helper_resume(struct
> drm_device *dev,
>                              struct drm_atomic_state *state)
>  {
>         struct drm_modeset_acquire_ctx ctx;
> +       struct drm_crtc_state
> *crtc_state;
> +       struct drm_crtc *crtc;
> +       unsigned int i;
>         int err;
>  
> +       for_each_new_crtc_in_state(state, crtc, crtc_state, i) {
> +   
>             /*
> +                * Force re-enablement of CMM after system resume if any
> +                * of the DRM color transformation properties
> was set in
> +                * the state saved at system suspend time.
> +                */
> +               if (crtc_state->gamma_lut)
> +                    
>    crtc_state->color_mgmt_changed = true;
> +       }
> 
> This probably is wrong, and should be instead constrained to some
> condition of some sort.
> 
> FWIW, the Rockchip DRM is going to need this as well.
> 
> Any ideas?

That's more or less what I had in mind, yes. The question is if
something like this would make sense. If there's a consensus it would, I
think it can be done as part of this series.

-- 
Regards,

Laurent Pinchart

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [PATCH v4 3/9] drm: rcar-du: Add support for CMM
  2019-09-18 22:55   ` Laurent Pinchart
  2019-09-19  8:59     ` Kieran Bingham
@ 2019-10-10 17:46     ` Jacopo Mondi
  2019-10-14 23:54       ` Laurent Pinchart
  1 sibling, 1 reply; 38+ messages in thread
From: Jacopo Mondi @ 2019-10-10 17:46 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: Jacopo Mondi, kieran.bingham+renesas, geert, horms, uli+renesas,
	VenkataRajesh.Kalakodima, airlied, daniel, koji.matsuoka.xm,
	muroya, Harsha.ManjulaMallikarjun, linux-renesas-soc, dri-devel,
	linux-kernel, ezequiel, seanpaul

[-- Attachment #1: Type: text/plain, Size: 14716 bytes --]

Hi Laurent,

On Thu, Sep 19, 2019 at 01:55:35AM +0300, Laurent Pinchart wrote:
> Hi Jacopo,
>
> Thank you for the patch.
>
> On Fri, Sep 06, 2019 at 03:54:30PM +0200, Jacopo Mondi wrote:
> > Add a driver for the R-Car Display Unit Color Correction Module.
> >
> > In most of Gen3 SoCs, each DU output channel is provided with a CMM unit
> > to perform image enhancement and color correction.
> >
> > Add support for CMM through a driver that supports configuration of
> > the 1-dimensional LUT table. More advanced CMM feature will be
> > implemented on top of this basic one.
> >
> > Signed-off-by: Jacopo Mondi <jacopo+renesas@jmondi.org>
> > ---
> >  drivers/gpu/drm/rcar-du/Kconfig    |   7 +
> >  drivers/gpu/drm/rcar-du/Makefile   |   1 +
> >  drivers/gpu/drm/rcar-du/rcar_cmm.c | 251 +++++++++++++++++++++++++++++
> >  drivers/gpu/drm/rcar-du/rcar_cmm.h |  61 +++++++
> >  4 files changed, 320 insertions(+)
> >  create mode 100644 drivers/gpu/drm/rcar-du/rcar_cmm.c
> >  create mode 100644 drivers/gpu/drm/rcar-du/rcar_cmm.h
> >
> > diff --git a/drivers/gpu/drm/rcar-du/Kconfig b/drivers/gpu/drm/rcar-du/Kconfig
> > index 1529849e217e..539d232790d1 100644
> > --- a/drivers/gpu/drm/rcar-du/Kconfig
> > +++ b/drivers/gpu/drm/rcar-du/Kconfig
> > @@ -13,6 +13,13 @@ config DRM_RCAR_DU
> >  	  Choose this option if you have an R-Car chipset.
> >  	  If M is selected the module will be called rcar-du-drm.
> >
> > +config DRM_RCAR_CMM
> > +	bool "R-Car DU Color Management Module (CMM) Support"
> > +	depends on DRM && OF
> > +	depends on DRM_RCAR_DU
> > +	help
> > +	  Enable support for R-Car Color Management Module (CMM).
> > +
> >  config DRM_RCAR_DW_HDMI
> >  	tristate "R-Car DU Gen3 HDMI Encoder Support"
> >  	depends on DRM && OF
> > diff --git a/drivers/gpu/drm/rcar-du/Makefile b/drivers/gpu/drm/rcar-du/Makefile
> > index 6c2ed9c46467..4d1187ccc3e5 100644
> > --- a/drivers/gpu/drm/rcar-du/Makefile
> > +++ b/drivers/gpu/drm/rcar-du/Makefile
> > @@ -15,6 +15,7 @@ rcar-du-drm-$(CONFIG_DRM_RCAR_LVDS)	+= rcar_du_of.o \
> >  rcar-du-drm-$(CONFIG_DRM_RCAR_VSP)	+= rcar_du_vsp.o
> >  rcar-du-drm-$(CONFIG_DRM_RCAR_WRITEBACK) += rcar_du_writeback.o
> >
> > +obj-$(CONFIG_DRM_RCAR_CMM)		+= rcar_cmm.o
> >  obj-$(CONFIG_DRM_RCAR_DU)		+= rcar-du-drm.o
> >  obj-$(CONFIG_DRM_RCAR_DW_HDMI)		+= rcar_dw_hdmi.o
> >  obj-$(CONFIG_DRM_RCAR_LVDS)		+= rcar_lvds.o
> > diff --git a/drivers/gpu/drm/rcar-du/rcar_cmm.c b/drivers/gpu/drm/rcar-du/rcar_cmm.c
> > new file mode 100644
> > index 000000000000..3cacdc4474c7
> > --- /dev/null
> > +++ b/drivers/gpu/drm/rcar-du/rcar_cmm.c
> > @@ -0,0 +1,251 @@
> > +// SPDX-License-Identifier: GPL-2.0+
> > +/*
> > + * rcar_cmm.c -- R-Car Display Unit Color Management Module
> > + *
> > + * Copyright (C) 2019 Jacopo Mondi <jacopo+renesas@jmondi.org>
> > + */
> > +
> > +#include <linux/io.h>
> > +#include <linux/module.h>
> > +#include <linux/of.h>
> > +#include <linux/platform_device.h>
> > +#include <linux/pm_runtime.h>
> > +
> > +#include <drm/drm_color_mgmt.h>
> > +
> > +#include "rcar_cmm.h"
> > +
> > +#define CM2_LUT_CTRL		0x0000
> > +#define CM2_LUT_CTRL_LUT_EN	BIT(0)
> > +#define CM2_LUT_TBL_BASE	0x0600
> > +#define CM2_LUT_TBL(__i)	(CM2_LUT_TBL_BASE + (__i) * 4)
> > +
> > +struct rcar_cmm {
> > +	void __iomem *base;
> > +	bool enabled;
> > +
> > +	/*
> > +	 * @lut:		1D-LUT status
> > +	 * @lut.enabled:	1D-LUT enabled flag
> > +	 * @lut.table:		Table of 1D-LUT entries scaled to hardware
> > +	 *			precision (8-bits per color component)
> > +	 */
> > +	struct {
> > +		bool enabled;
> > +		u32 table[CM2_LUT_SIZE];
> > +	} lut;
> > +};
> > +
> > +static inline int rcar_cmm_read(struct rcar_cmm *rcmm, u32 reg)
> > +{
> > +	return ioread32(rcmm->base + reg);
> > +}
> > +
> > +static inline void rcar_cmm_write(struct rcar_cmm *rcmm, u32 reg, u32 data)
> > +{
> > +	iowrite32(data, rcmm->base + reg);
> > +}
> > +
> > +/*
> > + * rcar_cmm_lut_extract() - Scale down to hardware precision the DRM LUT table
> > + *			    entries and store them.
>
> "Scale the DRM LUT table entries to hardware precision and store them."
>
> > + * @rcmm: Pointer to the CMM device
> > + * @drm_lut: Pointer to the DRM LUT table
> > + */
> > +static void rcar_cmm_lut_extract(struct rcar_cmm *rcmm,
> > +				 const struct drm_color_lut *drm_lut)
> > +{
> > +	unsigned int i;
> > +
> > +	for (i = 0; i < CM2_LUT_SIZE; ++i) {
> > +		const struct drm_color_lut *lut = &drm_lut[i];
> > +
> > +		rcmm->lut.table[i] = drm_color_lut_extract(lut->red, 8) << 16
> > +				   | drm_color_lut_extract(lut->green, 8) << 8
> > +				   | drm_color_lut_extract(lut->blue, 8);
> > +	}
> > +}
> > +
> > +/*
> > + * rcar_cmm_lut_write() - Write to hardware the LUT table entries from the
> > + *			  local table.
>
> "Write the LUT table entries from the local table to the hardware."
>
> > + * @rcmm: Pointer to the CMM device
> > + */
> > +static void rcar_cmm_lut_write(struct rcar_cmm *rcmm)
> > +{
> > +	unsigned int i;
> > +
> > +	for (i = 0; i < CM2_LUT_SIZE; ++i)
> > +		rcar_cmm_write(rcmm, CM2_LUT_TBL(i), rcmm->lut.table[i]);
> > +}
> > +
> > +/*
> > + * rcar_cmm_setup() - Configure the CMM unit.
> > + * @pdev: The platform device associated with the CMM instance
> > + * @config: The CRTC-provided configuration.
> > + *
> > + * Configure the CMM unit with the CRTC-provided configuration.
> > + * Currently enabling, disabling and programming of the 1-D LUT unit is
> > + * supported.
> > + */
> > +int rcar_cmm_setup(struct platform_device *pdev,
> > +		   const struct rcar_cmm_config *config)
> > +{
> > +	struct rcar_cmm *rcmm = platform_get_drvdata(pdev);
> > +
> > +	/*
> > +	 * As rcar_cmm_setup() is called by atomic commit tail helper, it might
> > +	 * be called when the CMM is disabled. As we can't program the hardware
> > +	 * in that case, store the configuration internally and apply it when
> > +	 * the CMM will be enabled by the CRTC through rcar_cmm_enable().
> > +	 */
> > +	if (!rcmm->enabled) {
> > +		if (!config->lut.enable)
> > +			return 0;
> > +
> > +		rcar_cmm_lut_extract(rcmm, config->lut.table);
> > +		rcmm->lut.enabled = true;
> > +
> > +		return 0;
> > +	}
> > +
> > +	/* Stop LUT operations if requested. */
> > +	if (!config->lut.enable) {
> > +		if (rcmm->lut.enabled) {
> > +			rcar_cmm_write(rcmm, CM2_LUT_CTRL, 0);
> > +			rcmm->lut.enabled = false;
> > +		}
> > +
> > +		return 0;
> > +	}
> > +
> > +	/*
> > +	 * Enable LUT and program the new gamma table values.
> > +	 *
> > +	 * FIXME: In order to have stable operations it is required to first
> > +	 * enable the 1D-LUT and then program its table entries. This seems to
> > +	 * contradict what the chip manual reports, and will have to be
> > +	 * reconsidered when implementing support for double buffering.
> > +	 */
> > +	if (!rcmm->lut.enabled) {
> > +		rcar_cmm_write(rcmm, CM2_LUT_CTRL, CM2_LUT_CTRL_LUT_EN);
> > +		rcmm->lut.enabled = true;
> > +	}
> > +
> > +	rcar_cmm_lut_extract(rcmm, config->lut.table);
> > +	rcar_cmm_lut_write(rcmm);
> > +
> > +	return 0;
> > +}
> > +EXPORT_SYMBOL_GPL(rcar_cmm_setup);
> > +
> > +/*
> > + * rcar_cmm_enable() - Enable the CMM unit.
> > + * @pdev: The platform device associated with the CMM instance
> > + *
> > + * Enable the CMM unit by enabling the parent clock and enabling the CMM
> > + * components, such as 1-D LUT, if requested.
> > + */
> > +int rcar_cmm_enable(struct platform_device *pdev)
> > +{
> > +	struct rcar_cmm *rcmm = platform_get_drvdata(pdev);
> > +	int ret;
> > +
> > +	ret = pm_runtime_get_sync(&pdev->dev);
> > +	if (ret < 0)
> > +		return ret;
> > +
> > +	/* Apply the LUT table values saved at rcar_cmm_setup() time. */
> > +	if (rcmm->lut.enabled) {
> > +		rcar_cmm_write(rcmm, CM2_LUT_CTRL, CM2_LUT_CTRL_LUT_EN);
> > +		rcar_cmm_lut_write(rcmm);
> > +	}
> > +
> > +	rcmm->enabled = true;
> > +
> > +	return 0;
> > +}
> > +EXPORT_SYMBOL_GPL(rcar_cmm_enable);
> > +
> > +/*
> > + * rcar_cmm_disable() - Disable the CMM unit.
> > + * @pdev: The platform device associated with the CMM instance
> > + *
> > + * Disable the CMM unit by stopping the parent clock.
> > + */
> > +void rcar_cmm_disable(struct platform_device *pdev)
> > +{
> > +	struct rcar_cmm *rcmm = platform_get_drvdata(pdev);
> > +
> > +	rcar_cmm_write(rcmm, CM2_LUT_CTRL, 0);
> > +
> > +	pm_runtime_put(&pdev->dev);
> > +
> > +	rcmm->lut.enabled = false;
> > +	rcmm->enabled = false;
> > +}
> > +EXPORT_SYMBOL_GPL(rcar_cmm_disable);
> > +
> > +/*
> > + * rcar_cmm_init() - Make sure the CMM has probed.
>
> I would document this as "Intialize the CMM" to match the function name.
> We may add more initialization in the future.
>
> > + * @pdev: The platform device associated with the CMM instance
> > + *
> > + * Return: 0 if the CMM has probed, -EPROBE_DEFER otherwise
>
> 0 on success, -EPROBE_DEFER is the CMM isn't availablet yet
>

Just to note I've take Kieran's suggestion in to return -ENODEV when
the CMM config option is not set.

> > + */
> > +int rcar_cmm_init(struct platform_device *pdev)
> > +{
> > +	struct rcar_cmm *rcmm = platform_get_drvdata(pdev);
> > +
> > +	if (!rcmm)
> > +		return -EPROBE_DEFER;
> > +
> > +	return 0;
> > +}
> > +EXPORT_SYMBOL_GPL(rcar_cmm_init);
> > +
> > +static int rcar_cmm_probe(struct platform_device *pdev)
> > +{
> > +	struct rcar_cmm *rcmm;
> > +
> > +	rcmm = devm_kzalloc(&pdev->dev, sizeof(*rcmm), GFP_KERNEL);
> > +	if (!rcmm)
> > +		return -ENOMEM;
> > +	platform_set_drvdata(pdev, rcmm);
> > +
> > +	rcmm->base = devm_platform_ioremap_resource(pdev, 0);
> > +	if (IS_ERR(rcmm->base))
> > +		return PTR_ERR(rcmm->base);
> > +
> > +	pm_runtime_enable(&pdev->dev);
> > +
> > +	return 0;
> > +}
> > +
> > +static int rcar_cmm_remove(struct platform_device *pdev)
> > +{
> > +	pm_runtime_disable(&pdev->dev);
> > +
> > +	return 0;
> > +}
> > +
> > +static const struct of_device_id rcar_cmm_of_table[] = {
> > +	{ .compatible = "renesas,rcar-gen3-cmm", },
> > +	{ .compatible = "renesas,rcar-gen2-cmm", },
> > +	{ },
> > +};
> > +MODULE_DEVICE_TABLE(of, rcar_cmm_of_table);
> > +
> > +static struct platform_driver rcar_cmm_platform_driver = {
> > +	.probe		= rcar_cmm_probe,
> > +	.remove		= rcar_cmm_remove,
> > +	.driver		= {
> > +		.name	= "rcar-cmm",
> > +		.of_match_table = rcar_cmm_of_table,
> > +	},
> > +};
> > +
> > +module_platform_driver(rcar_cmm_platform_driver);
> > +
> > +MODULE_AUTHOR("Jacopo Mondi <jacopo+renesas@jmondi.org>");
> > +MODULE_DESCRIPTION("Renesas R-Car CMM Driver");
> > +MODULE_LICENSE("GPL v2");
> > diff --git a/drivers/gpu/drm/rcar-du/rcar_cmm.h b/drivers/gpu/drm/rcar-du/rcar_cmm.h
> > new file mode 100644
> > index 000000000000..15a2c874b6a6
> > --- /dev/null
> > +++ b/drivers/gpu/drm/rcar-du/rcar_cmm.h
> > @@ -0,0 +1,61 @@
> > +/* SPDX-License-Identifier: GPL-2.0+ */
> > +/*
> > + * rcar_cmm.h -- R-Car Display Unit Color Management Module
> > + *
> > + * Copyright (C) 2019 Jacopo Mondi <jacopo+renesas@jmondi.org>
> > + */
> > +
> > +#ifndef __RCAR_CMM_H__
> > +#define __RCAR_CMM_H__
> > +
> > +#define CM2_LUT_SIZE		256
> > +
> > +struct drm_color_lut;
> > +struct platform_device;
> > +
> > +/**
> > + * struct rcar_cmm_config - CMM configuration
> > + *
> > + * @lut:	1D-LUT configuration
> > + * @lut.enable:	1D-LUT enable flag
> > + * @lut.table:	1D-LUT table entries. Might be set to NULL when the CMM has to
> > + *		be re-enabled but not re=programmed.
>
> s/re=programmed/re-programmed/
>
> As discussed offline this can't really happen as far as I can tell.
> However, it will still be useful when we'll add CLU support, as then a
> CLU reprogramming without a LUT reprogramming could happen.

How are we going to program CLU ? Using which DRM property ?
I had a look at 'ctm', but it does not seems to apply, as it only
provides 9 64bits entries (why 9??)
https://elixir.bootlin.com/linux/latest/source/include/uapi/drm/drm_mode.h#L623

The CLU is programmed with pairs of 32bits entries, assembled using
8 bit data/addresses for each color components. Considering the LUT
entries have 16 bits per color components, we could re-use those, but
seems a bit of an abuse to me. Is there somethig more trivial I am
missing ?

Anyway, for now I think you are right, and if the 'crtc->state->gamma_lut'
field is set, then the table (provided it's of the right size) cannot be
NULL.

Disabling the CMM with:
			req.add(crtc, {
					{ "GAMMA_LUT", 0 },
			});

results in 'crtc->state->gamma_lut' being not set, and this is already
handled by setting to false the rcar_cmm_config.lut.enable flag in
rcar_du_atomic_commit_update_cmm() so I would rather drop the table ==
NULL case from documentation and re-think about it once we handle CLU.

>
> I think we should make the documentation a bit clearer:
>
> "1D-LUT table entries. Only valid when lut.enable is true, shall be NULL
> otherwise. When non-NULL, the LUT table will be programmed with the new
> values. Otherwise the LUT table will retain its previously programmed
> values."
>
> This being said, the code in rcar_cmm_setup() will crash if table is
> NULL. I would either drop the option of table being NULL (and thus
> update the documentation here) if you don't need this yet in the DU
> driver, or fix rcar_cmm_setup(). You've posted enough versions of this
> series in my opinion, so please pick the easiest option, and we'll
> rework the code when adding CLU support anyway.

Unfortunately I would love to take your tag in and being done with
this, but considering Sean's advices on Ezequiel's series, I think
I'll now need to move CMM handling to crtc's begin/enable as well, so
another review round will likely be required.

>
> With those small issues fixes,
>
> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
>
> > + */
> > +struct rcar_cmm_config {
> > +	struct {
> > +		bool enable;
> > +		struct drm_color_lut *table;
> > +	} lut;
> > +};
> > +
> > +#if IS_ENABLED(CONFIG_DRM_RCAR_CMM)
> > +int rcar_cmm_init(struct platform_device *pdev);
> > +
> > +int rcar_cmm_enable(struct platform_device *pdev);
> > +void rcar_cmm_disable(struct platform_device *pdev);
> > +
> > +int rcar_cmm_setup(struct platform_device *pdev,
> > +		   const struct rcar_cmm_config *config);
> > +#else
> > +static inline int rcar_cmm_init(struct platform_device *pdev)
> > +{
> > +	return 0;
> > +}
> > +
> > +static inline int rcar_cmm_enable(struct platform_device *pdev)
> > +{
> > +	return 0;
> > +}
> > +
> > +static inline void rcar_cmm_disable(struct platform_device *pdev)
> > +{
> > +}
> > +
> > +static int rcar_cmm_setup(struct platform_device *pdev,
> > +			  const struct rcar_cmm_config *config)
> > +{
> > +	return 0;
> > +}
> > +#endif /* IS_ENABLED(CONFIG_DRM_RCAR_CMM) */
> > +
> > +#endif /* __RCAR_CMM_H__ */
>
> --
> Regards,
>
> Laurent Pinchart

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [PATCH v4 3/9] drm: rcar-du: Add support for CMM
  2019-10-10 17:46     ` Jacopo Mondi
@ 2019-10-14 23:54       ` Laurent Pinchart
  0 siblings, 0 replies; 38+ messages in thread
From: Laurent Pinchart @ 2019-10-14 23:54 UTC (permalink / raw)
  To: Jacopo Mondi
  Cc: Jacopo Mondi, kieran.bingham+renesas, geert, horms, uli+renesas,
	VenkataRajesh.Kalakodima, airlied, daniel, koji.matsuoka.xm,
	muroya, Harsha.ManjulaMallikarjun, linux-renesas-soc, dri-devel,
	linux-kernel, ezequiel, seanpaul

Hi Jacopo,

On Thu, Oct 10, 2019 at 07:46:28PM +0200, Jacopo Mondi wrote:
> On Thu, Sep 19, 2019 at 01:55:35AM +0300, Laurent Pinchart wrote:
> > On Fri, Sep 06, 2019 at 03:54:30PM +0200, Jacopo Mondi wrote:
> >> Add a driver for the R-Car Display Unit Color Correction Module.
> >>
> >> In most of Gen3 SoCs, each DU output channel is provided with a CMM unit
> >> to perform image enhancement and color correction.
> >>
> >> Add support for CMM through a driver that supports configuration of
> >> the 1-dimensional LUT table. More advanced CMM feature will be
> >> implemented on top of this basic one.
> >>
> >> Signed-off-by: Jacopo Mondi <jacopo+renesas@jmondi.org>
> >> ---
> >>  drivers/gpu/drm/rcar-du/Kconfig    |   7 +
> >>  drivers/gpu/drm/rcar-du/Makefile   |   1 +
> >>  drivers/gpu/drm/rcar-du/rcar_cmm.c | 251 +++++++++++++++++++++++++++++
> >>  drivers/gpu/drm/rcar-du/rcar_cmm.h |  61 +++++++
> >>  4 files changed, 320 insertions(+)
> >>  create mode 100644 drivers/gpu/drm/rcar-du/rcar_cmm.c
> >>  create mode 100644 drivers/gpu/drm/rcar-du/rcar_cmm.h
> >>
> >> diff --git a/drivers/gpu/drm/rcar-du/Kconfig b/drivers/gpu/drm/rcar-du/Kconfig
> >> index 1529849e217e..539d232790d1 100644
> >> --- a/drivers/gpu/drm/rcar-du/Kconfig
> >> +++ b/drivers/gpu/drm/rcar-du/Kconfig
> >> @@ -13,6 +13,13 @@ config DRM_RCAR_DU
> >>  	  Choose this option if you have an R-Car chipset.
> >>  	  If M is selected the module will be called rcar-du-drm.
> >>
> >> +config DRM_RCAR_CMM
> >> +	bool "R-Car DU Color Management Module (CMM) Support"
> >> +	depends on DRM && OF
> >> +	depends on DRM_RCAR_DU
> >> +	help
> >> +	  Enable support for R-Car Color Management Module (CMM).
> >> +
> >>  config DRM_RCAR_DW_HDMI
> >>  	tristate "R-Car DU Gen3 HDMI Encoder Support"
> >>  	depends on DRM && OF
> >> diff --git a/drivers/gpu/drm/rcar-du/Makefile b/drivers/gpu/drm/rcar-du/Makefile
> >> index 6c2ed9c46467..4d1187ccc3e5 100644
> >> --- a/drivers/gpu/drm/rcar-du/Makefile
> >> +++ b/drivers/gpu/drm/rcar-du/Makefile
> >> @@ -15,6 +15,7 @@ rcar-du-drm-$(CONFIG_DRM_RCAR_LVDS)	+= rcar_du_of.o \
> >>  rcar-du-drm-$(CONFIG_DRM_RCAR_VSP)	+= rcar_du_vsp.o
> >>  rcar-du-drm-$(CONFIG_DRM_RCAR_WRITEBACK) += rcar_du_writeback.o
> >>
> >> +obj-$(CONFIG_DRM_RCAR_CMM)		+= rcar_cmm.o
> >>  obj-$(CONFIG_DRM_RCAR_DU)		+= rcar-du-drm.o
> >>  obj-$(CONFIG_DRM_RCAR_DW_HDMI)		+= rcar_dw_hdmi.o
> >>  obj-$(CONFIG_DRM_RCAR_LVDS)		+= rcar_lvds.o
> >> diff --git a/drivers/gpu/drm/rcar-du/rcar_cmm.c b/drivers/gpu/drm/rcar-du/rcar_cmm.c
> >> new file mode 100644
> >> index 000000000000..3cacdc4474c7
> >> --- /dev/null
> >> +++ b/drivers/gpu/drm/rcar-du/rcar_cmm.c
> >> @@ -0,0 +1,251 @@
> >> +// SPDX-License-Identifier: GPL-2.0+
> >> +/*
> >> + * rcar_cmm.c -- R-Car Display Unit Color Management Module
> >> + *
> >> + * Copyright (C) 2019 Jacopo Mondi <jacopo+renesas@jmondi.org>
> >> + */
> >> +
> >> +#include <linux/io.h>
> >> +#include <linux/module.h>
> >> +#include <linux/of.h>
> >> +#include <linux/platform_device.h>
> >> +#include <linux/pm_runtime.h>
> >> +
> >> +#include <drm/drm_color_mgmt.h>
> >> +
> >> +#include "rcar_cmm.h"
> >> +
> >> +#define CM2_LUT_CTRL		0x0000
> >> +#define CM2_LUT_CTRL_LUT_EN	BIT(0)
> >> +#define CM2_LUT_TBL_BASE	0x0600
> >> +#define CM2_LUT_TBL(__i)	(CM2_LUT_TBL_BASE + (__i) * 4)
> >> +
> >> +struct rcar_cmm {
> >> +	void __iomem *base;
> >> +	bool enabled;
> >> +
> >> +	/*
> >> +	 * @lut:		1D-LUT status
> >> +	 * @lut.enabled:	1D-LUT enabled flag
> >> +	 * @lut.table:		Table of 1D-LUT entries scaled to hardware
> >> +	 *			precision (8-bits per color component)
> >> +	 */
> >> +	struct {
> >> +		bool enabled;
> >> +		u32 table[CM2_LUT_SIZE];
> >> +	} lut;
> >> +};
> >> +
> >> +static inline int rcar_cmm_read(struct rcar_cmm *rcmm, u32 reg)
> >> +{
> >> +	return ioread32(rcmm->base + reg);
> >> +}
> >> +
> >> +static inline void rcar_cmm_write(struct rcar_cmm *rcmm, u32 reg, u32 data)
> >> +{
> >> +	iowrite32(data, rcmm->base + reg);
> >> +}
> >> +
> >> +/*
> >> + * rcar_cmm_lut_extract() - Scale down to hardware precision the DRM LUT table
> >> + *			    entries and store them.
> >
> > "Scale the DRM LUT table entries to hardware precision and store them."
> >
> >> + * @rcmm: Pointer to the CMM device
> >> + * @drm_lut: Pointer to the DRM LUT table
> >> + */
> >> +static void rcar_cmm_lut_extract(struct rcar_cmm *rcmm,
> >> +				 const struct drm_color_lut *drm_lut)
> >> +{
> >> +	unsigned int i;
> >> +
> >> +	for (i = 0; i < CM2_LUT_SIZE; ++i) {
> >> +		const struct drm_color_lut *lut = &drm_lut[i];
> >> +
> >> +		rcmm->lut.table[i] = drm_color_lut_extract(lut->red, 8) << 16
> >> +				   | drm_color_lut_extract(lut->green, 8) << 8
> >> +				   | drm_color_lut_extract(lut->blue, 8);
> >> +	}
> >> +}
> >> +
> >> +/*
> >> + * rcar_cmm_lut_write() - Write to hardware the LUT table entries from the
> >> + *			  local table.
> >
> > "Write the LUT table entries from the local table to the hardware."
> >
> >> + * @rcmm: Pointer to the CMM device
> >> + */
> >> +static void rcar_cmm_lut_write(struct rcar_cmm *rcmm)
> >> +{
> >> +	unsigned int i;
> >> +
> >> +	for (i = 0; i < CM2_LUT_SIZE; ++i)
> >> +		rcar_cmm_write(rcmm, CM2_LUT_TBL(i), rcmm->lut.table[i]);
> >> +}
> >> +
> >> +/*
> >> + * rcar_cmm_setup() - Configure the CMM unit.
> >> + * @pdev: The platform device associated with the CMM instance
> >> + * @config: The CRTC-provided configuration.
> >> + *
> >> + * Configure the CMM unit with the CRTC-provided configuration.
> >> + * Currently enabling, disabling and programming of the 1-D LUT unit is
> >> + * supported.
> >> + */
> >> +int rcar_cmm_setup(struct platform_device *pdev,
> >> +		   const struct rcar_cmm_config *config)
> >> +{
> >> +	struct rcar_cmm *rcmm = platform_get_drvdata(pdev);
> >> +
> >> +	/*
> >> +	 * As rcar_cmm_setup() is called by atomic commit tail helper, it might
> >> +	 * be called when the CMM is disabled. As we can't program the hardware
> >> +	 * in that case, store the configuration internally and apply it when
> >> +	 * the CMM will be enabled by the CRTC through rcar_cmm_enable().
> >> +	 */
> >> +	if (!rcmm->enabled) {
> >> +		if (!config->lut.enable)
> >> +			return 0;
> >> +
> >> +		rcar_cmm_lut_extract(rcmm, config->lut.table);
> >> +		rcmm->lut.enabled = true;
> >> +
> >> +		return 0;
> >> +	}
> >> +
> >> +	/* Stop LUT operations if requested. */
> >> +	if (!config->lut.enable) {
> >> +		if (rcmm->lut.enabled) {
> >> +			rcar_cmm_write(rcmm, CM2_LUT_CTRL, 0);
> >> +			rcmm->lut.enabled = false;
> >> +		}
> >> +
> >> +		return 0;
> >> +	}
> >> +
> >> +	/*
> >> +	 * Enable LUT and program the new gamma table values.
> >> +	 *
> >> +	 * FIXME: In order to have stable operations it is required to first
> >> +	 * enable the 1D-LUT and then program its table entries. This seems to
> >> +	 * contradict what the chip manual reports, and will have to be
> >> +	 * reconsidered when implementing support for double buffering.
> >> +	 */
> >> +	if (!rcmm->lut.enabled) {
> >> +		rcar_cmm_write(rcmm, CM2_LUT_CTRL, CM2_LUT_CTRL_LUT_EN);
> >> +		rcmm->lut.enabled = true;
> >> +	}
> >> +
> >> +	rcar_cmm_lut_extract(rcmm, config->lut.table);
> >> +	rcar_cmm_lut_write(rcmm);
> >> +
> >> +	return 0;
> >> +}
> >> +EXPORT_SYMBOL_GPL(rcar_cmm_setup);
> >> +
> >> +/*
> >> + * rcar_cmm_enable() - Enable the CMM unit.
> >> + * @pdev: The platform device associated with the CMM instance
> >> + *
> >> + * Enable the CMM unit by enabling the parent clock and enabling the CMM
> >> + * components, such as 1-D LUT, if requested.
> >> + */
> >> +int rcar_cmm_enable(struct platform_device *pdev)
> >> +{
> >> +	struct rcar_cmm *rcmm = platform_get_drvdata(pdev);
> >> +	int ret;
> >> +
> >> +	ret = pm_runtime_get_sync(&pdev->dev);
> >> +	if (ret < 0)
> >> +		return ret;
> >> +
> >> +	/* Apply the LUT table values saved at rcar_cmm_setup() time. */
> >> +	if (rcmm->lut.enabled) {
> >> +		rcar_cmm_write(rcmm, CM2_LUT_CTRL, CM2_LUT_CTRL_LUT_EN);
> >> +		rcar_cmm_lut_write(rcmm);
> >> +	}
> >> +
> >> +	rcmm->enabled = true;
> >> +
> >> +	return 0;
> >> +}
> >> +EXPORT_SYMBOL_GPL(rcar_cmm_enable);
> >> +
> >> +/*
> >> + * rcar_cmm_disable() - Disable the CMM unit.
> >> + * @pdev: The platform device associated with the CMM instance
> >> + *
> >> + * Disable the CMM unit by stopping the parent clock.
> >> + */
> >> +void rcar_cmm_disable(struct platform_device *pdev)
> >> +{
> >> +	struct rcar_cmm *rcmm = platform_get_drvdata(pdev);
> >> +
> >> +	rcar_cmm_write(rcmm, CM2_LUT_CTRL, 0);
> >> +
> >> +	pm_runtime_put(&pdev->dev);
> >> +
> >> +	rcmm->lut.enabled = false;
> >> +	rcmm->enabled = false;
> >> +}
> >> +EXPORT_SYMBOL_GPL(rcar_cmm_disable);
> >> +
> >> +/*
> >> + * rcar_cmm_init() - Make sure the CMM has probed.
> >
> > I would document this as "Intialize the CMM" to match the function name.
> > We may add more initialization in the future.
> >
> >> + * @pdev: The platform device associated with the CMM instance
> >> + *
> >> + * Return: 0 if the CMM has probed, -EPROBE_DEFER otherwise
> >
> > 0 on success, -EPROBE_DEFER is the CMM isn't availablet yet
> >
> 
> Just to note I've take Kieran's suggestion in to return -ENODEV when
> the CMM config option is not set.
> 
> >> + */
> >> +int rcar_cmm_init(struct platform_device *pdev)
> >> +{
> >> +	struct rcar_cmm *rcmm = platform_get_drvdata(pdev);
> >> +
> >> +	if (!rcmm)
> >> +		return -EPROBE_DEFER;
> >> +
> >> +	return 0;
> >> +}
> >> +EXPORT_SYMBOL_GPL(rcar_cmm_init);
> >> +
> >> +static int rcar_cmm_probe(struct platform_device *pdev)
> >> +{
> >> +	struct rcar_cmm *rcmm;
> >> +
> >> +	rcmm = devm_kzalloc(&pdev->dev, sizeof(*rcmm), GFP_KERNEL);
> >> +	if (!rcmm)
> >> +		return -ENOMEM;
> >> +	platform_set_drvdata(pdev, rcmm);
> >> +
> >> +	rcmm->base = devm_platform_ioremap_resource(pdev, 0);
> >> +	if (IS_ERR(rcmm->base))
> >> +		return PTR_ERR(rcmm->base);
> >> +
> >> +	pm_runtime_enable(&pdev->dev);
> >> +
> >> +	return 0;
> >> +}
> >> +
> >> +static int rcar_cmm_remove(struct platform_device *pdev)
> >> +{
> >> +	pm_runtime_disable(&pdev->dev);
> >> +
> >> +	return 0;
> >> +}
> >> +
> >> +static const struct of_device_id rcar_cmm_of_table[] = {
> >> +	{ .compatible = "renesas,rcar-gen3-cmm", },
> >> +	{ .compatible = "renesas,rcar-gen2-cmm", },
> >> +	{ },
> >> +};
> >> +MODULE_DEVICE_TABLE(of, rcar_cmm_of_table);
> >> +
> >> +static struct platform_driver rcar_cmm_platform_driver = {
> >> +	.probe		= rcar_cmm_probe,
> >> +	.remove		= rcar_cmm_remove,
> >> +	.driver		= {
> >> +		.name	= "rcar-cmm",
> >> +		.of_match_table = rcar_cmm_of_table,
> >> +	},
> >> +};
> >> +
> >> +module_platform_driver(rcar_cmm_platform_driver);
> >> +
> >> +MODULE_AUTHOR("Jacopo Mondi <jacopo+renesas@jmondi.org>");
> >> +MODULE_DESCRIPTION("Renesas R-Car CMM Driver");
> >> +MODULE_LICENSE("GPL v2");
> >> diff --git a/drivers/gpu/drm/rcar-du/rcar_cmm.h b/drivers/gpu/drm/rcar-du/rcar_cmm.h
> >> new file mode 100644
> >> index 000000000000..15a2c874b6a6
> >> --- /dev/null
> >> +++ b/drivers/gpu/drm/rcar-du/rcar_cmm.h
> >> @@ -0,0 +1,61 @@
> >> +/* SPDX-License-Identifier: GPL-2.0+ */
> >> +/*
> >> + * rcar_cmm.h -- R-Car Display Unit Color Management Module
> >> + *
> >> + * Copyright (C) 2019 Jacopo Mondi <jacopo+renesas@jmondi.org>
> >> + */
> >> +
> >> +#ifndef __RCAR_CMM_H__
> >> +#define __RCAR_CMM_H__
> >> +
> >> +#define CM2_LUT_SIZE		256
> >> +
> >> +struct drm_color_lut;
> >> +struct platform_device;
> >> +
> >> +/**
> >> + * struct rcar_cmm_config - CMM configuration
> >> + *
> >> + * @lut:	1D-LUT configuration
> >> + * @lut.enable:	1D-LUT enable flag
> >> + * @lut.table:	1D-LUT table entries. Might be set to NULL when the CMM has to
> >> + *		be re-enabled but not re=programmed.
> >
> > s/re=programmed/re-programmed/
> >
> > As discussed offline this can't really happen as far as I can tell.
> > However, it will still be useful when we'll add CLU support, as then a
> > CLU reprogramming without a LUT reprogramming could happen.
> 
> How are we going to program CLU ? Using which DRM property ?
> I had a look at 'ctm', but it does not seems to apply, as it only
> provides 9 64bits entries (why 9??)
> https://elixir.bootlin.com/linux/latest/source/include/uapi/drm/drm_mode.h#L623
> 
> The CLU is programmed with pairs of 32bits entries, assembled using
> 8 bit data/addresses for each color components. Considering the LUT
> entries have 16 bits per color components, we could re-use those, but
> seems a bit of an abuse to me. Is there somethig more trivial I am
> missing ?

You're not missing anything, we'll have to create a new property for
this. The CLU is a 17x17x17 matrix of 32-bit values, that's what we'll
have to pass.

> Anyway, for now I think you are right, and if the 'crtc->state->gamma_lut'
> field is set, then the table (provided it's of the right size) cannot be
> NULL.
> 
> Disabling the CMM with:
> 			req.add(crtc, {
> 					{ "GAMMA_LUT", 0 },
> 			});
> 
> results in 'crtc->state->gamma_lut' being not set, and this is already
> handled by setting to false the rcar_cmm_config.lut.enable flag in
> rcar_du_atomic_commit_update_cmm() so I would rather drop the table ==
> NULL case from documentation and re-think about it once we handle CLU.
> 
> > I think we should make the documentation a bit clearer:
> >
> > "1D-LUT table entries. Only valid when lut.enable is true, shall be NULL
> > otherwise. When non-NULL, the LUT table will be programmed with the new
> > values. Otherwise the LUT table will retain its previously programmed
> > values."
> >
> > This being said, the code in rcar_cmm_setup() will crash if table is
> > NULL. I would either drop the option of table being NULL (and thus
> > update the documentation here) if you don't need this yet in the DU
> > driver, or fix rcar_cmm_setup(). You've posted enough versions of this
> > series in my opinion, so please pick the easiest option, and we'll
> > rework the code when adding CLU support anyway.
> 
> Unfortunately I would love to take your tag in and being done with
> this, but considering Sean's advices on Ezequiel's series, I think
> I'll now need to move CMM handling to crtc's begin/enable as well, so
> another review round will likely be required.
> 
> > With those small issues fixes,
> >
> > Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> >
> >> + */
> >> +struct rcar_cmm_config {
> >> +	struct {
> >> +		bool enable;
> >> +		struct drm_color_lut *table;
> >> +	} lut;
> >> +};
> >> +
> >> +#if IS_ENABLED(CONFIG_DRM_RCAR_CMM)
> >> +int rcar_cmm_init(struct platform_device *pdev);
> >> +
> >> +int rcar_cmm_enable(struct platform_device *pdev);
> >> +void rcar_cmm_disable(struct platform_device *pdev);
> >> +
> >> +int rcar_cmm_setup(struct platform_device *pdev,
> >> +		   const struct rcar_cmm_config *config);
> >> +#else
> >> +static inline int rcar_cmm_init(struct platform_device *pdev)
> >> +{
> >> +	return 0;
> >> +}
> >> +
> >> +static inline int rcar_cmm_enable(struct platform_device *pdev)
> >> +{
> >> +	return 0;
> >> +}
> >> +
> >> +static inline void rcar_cmm_disable(struct platform_device *pdev)
> >> +{
> >> +}
> >> +
> >> +static int rcar_cmm_setup(struct platform_device *pdev,
> >> +			  const struct rcar_cmm_config *config)
> >> +{
> >> +	return 0;
> >> +}
> >> +#endif /* IS_ENABLED(CONFIG_DRM_RCAR_CMM) */
> >> +
> >> +#endif /* __RCAR_CMM_H__ */

-- 
Regards,

Laurent Pinchart

^ permalink raw reply	[flat|nested] 38+ messages in thread

end of thread, other threads:[~2019-10-14 23:54 UTC | newest]

Thread overview: 38+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-09-06 13:54 [PATCH v4 0/9 drm: rcar-du: Add Color Management Module (CMM) Jacopo Mondi
2019-09-06 13:54 ` [PATCH v4 1/9] dt-bindings: display: renesas,cmm: Add R-Car CMM documentation Jacopo Mondi
2019-09-11 19:04   ` Kieran Bingham
2019-09-17 17:55   ` Rob Herring
2019-09-18 22:08   ` Laurent Pinchart
2019-09-06 13:54 ` [PATCH v4 2/9] dt-bindings: display, renesas,du: Document cmms property Jacopo Mondi
2019-09-11 16:06   ` Kieran Bingham
2019-09-17 17:58     ` Rob Herring
2019-09-06 13:54 ` [PATCH v4 3/9] drm: rcar-du: Add support for CMM Jacopo Mondi
2019-09-11 15:54   ` Kieran Bingham
2019-09-12  7:59     ` Jacopo Mondi
2019-09-12  9:49       ` Kieran Bingham
2019-09-18 22:55   ` Laurent Pinchart
2019-09-19  8:59     ` Kieran Bingham
2019-09-20 22:43       ` Laurent Pinchart
2019-10-10 17:46     ` Jacopo Mondi
2019-10-14 23:54       ` Laurent Pinchart
2019-09-06 13:54 ` [PATCH v4 4/9] drm: rcar-du: Claim CMM support for Gen3 SoCs Jacopo Mondi
2019-09-11 18:45   ` Kieran Bingham
2019-09-06 13:54 ` [PATCH v4 5/9] drm: rcar-du: kms: Initialize CMM instances Jacopo Mondi
2019-09-12  9:27   ` Kieran Bingham
2019-09-06 13:54 ` [PATCH v4 6/9] drm: rcar-du: crtc: Enable and disable CMMs Jacopo Mondi
2019-09-11 18:40   ` Kieran Bingham
2019-09-12  8:07     ` Jacopo Mondi
2019-09-12  9:19       ` Kieran Bingham
2019-09-18 23:23         ` Laurent Pinchart
2019-09-19  8:08           ` Kieran Bingham
2019-09-20 22:44             ` Laurent Pinchart
2019-09-06 13:54 ` [PATCH v4 7/9] drm: rcar-du: crtc: Register GAMMA_LUT properties Jacopo Mondi
2019-09-11 18:47   ` Kieran Bingham
2019-09-06 13:54 ` [PATCH v4 8/9] drm: rcar-du: kms: Update CMM in atomic commit tail Jacopo Mondi
2019-09-12  9:51   ` Kieran Bingham
2019-09-20 22:49   ` Laurent Pinchart
2019-09-30 20:53   ` Ezequiel Garcia
2019-10-01 19:20     ` Laurent Pinchart
2019-09-06 13:54 ` [PATCH v4 9/9] arm64: dts: renesas: Add CMM units to Gen3 SoCs Jacopo Mondi
2019-09-11 18:16   ` Kieran Bingham
2019-09-11 19:35     ` Geert Uytterhoeven

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).