All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 1/2] dt-bindings: display: msm: Add optional resets
@ 2022-03-02  1:29 ` Bjorn Andersson
  0 siblings, 0 replies; 14+ messages in thread
From: Bjorn Andersson @ 2022-03-02  1:29 UTC (permalink / raw)
  To: Rob Clark, Abhinav Kumar, Rob Herring, Krzysztof Kozlowski,
	Philipp Zabel, Dmitry Baryshkov, Loic Poulain
  Cc: linux-arm-msm, dri-devel, freedreno, devicetree, linux-kernel

Add an optional reference to the MDSS_CORE reset, which when specified
can be used by the implementation to reset the hardware blocks.

Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
---

Changes since v1:
- New approach/patch

 .../devicetree/bindings/display/msm/dpu-qcm2290.yaml          | 4 ++++
 Documentation/devicetree/bindings/display/msm/dpu-sc7180.yaml | 4 ++++
 Documentation/devicetree/bindings/display/msm/dpu-sc7280.yaml | 4 ++++
 Documentation/devicetree/bindings/display/msm/dpu-sdm845.yaml | 4 ++++
 4 files changed, 16 insertions(+)

diff --git a/Documentation/devicetree/bindings/display/msm/dpu-qcm2290.yaml b/Documentation/devicetree/bindings/display/msm/dpu-qcm2290.yaml
index 8766b13f0c46..965027fe205c 100644
--- a/Documentation/devicetree/bindings/display/msm/dpu-qcm2290.yaml
+++ b/Documentation/devicetree/bindings/display/msm/dpu-qcm2290.yaml
@@ -66,6 +66,10 @@ properties:
   interconnect-names:
     const: mdp0-mem
 
+  resets:
+    items:
+      - description: MDSS_CORE reset
+
 patternProperties:
   "^display-controller@[0-9a-f]+$":
     type: object
diff --git a/Documentation/devicetree/bindings/display/msm/dpu-sc7180.yaml b/Documentation/devicetree/bindings/display/msm/dpu-sc7180.yaml
index 12a86b1ec1bc..b41991eaa454 100644
--- a/Documentation/devicetree/bindings/display/msm/dpu-sc7180.yaml
+++ b/Documentation/devicetree/bindings/display/msm/dpu-sc7180.yaml
@@ -65,6 +65,10 @@ properties:
   interconnect-names:
     const: mdp0-mem
 
+  resets:
+    items:
+      - description: MDSS_CORE reset
+
 patternProperties:
   "^display-controller@[0-9a-f]+$":
     type: object
diff --git a/Documentation/devicetree/bindings/display/msm/dpu-sc7280.yaml b/Documentation/devicetree/bindings/display/msm/dpu-sc7280.yaml
index fbeb931a026e..6e417d06fc79 100644
--- a/Documentation/devicetree/bindings/display/msm/dpu-sc7280.yaml
+++ b/Documentation/devicetree/bindings/display/msm/dpu-sc7280.yaml
@@ -64,6 +64,10 @@ properties:
   interconnect-names:
     const: mdp0-mem
 
+  resets:
+    items:
+      - description: MDSS_CORE reset
+
 patternProperties:
   "^display-controller@[0-9a-f]+$":
     type: object
diff --git a/Documentation/devicetree/bindings/display/msm/dpu-sdm845.yaml b/Documentation/devicetree/bindings/display/msm/dpu-sdm845.yaml
index 0dca4b3d66e4..1a42491efdbc 100644
--- a/Documentation/devicetree/bindings/display/msm/dpu-sdm845.yaml
+++ b/Documentation/devicetree/bindings/display/msm/dpu-sdm845.yaml
@@ -57,6 +57,10 @@ properties:
 
   ranges: true
 
+  resets:
+    items:
+      - description: MDSS_CORE reset
+
 patternProperties:
   "^display-controller@[0-9a-f]+$":
     type: object
-- 
2.33.1


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

* [PATCH v2 1/2] dt-bindings: display: msm: Add optional resets
@ 2022-03-02  1:29 ` Bjorn Andersson
  0 siblings, 0 replies; 14+ messages in thread
From: Bjorn Andersson @ 2022-03-02  1:29 UTC (permalink / raw)
  To: Rob Clark, Abhinav Kumar, Rob Herring, Krzysztof Kozlowski,
	Philipp Zabel, Dmitry Baryshkov, Loic Poulain
  Cc: linux-arm-msm, freedreno, linux-kernel, dri-devel, devicetree

Add an optional reference to the MDSS_CORE reset, which when specified
can be used by the implementation to reset the hardware blocks.

Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
---

Changes since v1:
- New approach/patch

 .../devicetree/bindings/display/msm/dpu-qcm2290.yaml          | 4 ++++
 Documentation/devicetree/bindings/display/msm/dpu-sc7180.yaml | 4 ++++
 Documentation/devicetree/bindings/display/msm/dpu-sc7280.yaml | 4 ++++
 Documentation/devicetree/bindings/display/msm/dpu-sdm845.yaml | 4 ++++
 4 files changed, 16 insertions(+)

diff --git a/Documentation/devicetree/bindings/display/msm/dpu-qcm2290.yaml b/Documentation/devicetree/bindings/display/msm/dpu-qcm2290.yaml
index 8766b13f0c46..965027fe205c 100644
--- a/Documentation/devicetree/bindings/display/msm/dpu-qcm2290.yaml
+++ b/Documentation/devicetree/bindings/display/msm/dpu-qcm2290.yaml
@@ -66,6 +66,10 @@ properties:
   interconnect-names:
     const: mdp0-mem
 
+  resets:
+    items:
+      - description: MDSS_CORE reset
+
 patternProperties:
   "^display-controller@[0-9a-f]+$":
     type: object
diff --git a/Documentation/devicetree/bindings/display/msm/dpu-sc7180.yaml b/Documentation/devicetree/bindings/display/msm/dpu-sc7180.yaml
index 12a86b1ec1bc..b41991eaa454 100644
--- a/Documentation/devicetree/bindings/display/msm/dpu-sc7180.yaml
+++ b/Documentation/devicetree/bindings/display/msm/dpu-sc7180.yaml
@@ -65,6 +65,10 @@ properties:
   interconnect-names:
     const: mdp0-mem
 
+  resets:
+    items:
+      - description: MDSS_CORE reset
+
 patternProperties:
   "^display-controller@[0-9a-f]+$":
     type: object
diff --git a/Documentation/devicetree/bindings/display/msm/dpu-sc7280.yaml b/Documentation/devicetree/bindings/display/msm/dpu-sc7280.yaml
index fbeb931a026e..6e417d06fc79 100644
--- a/Documentation/devicetree/bindings/display/msm/dpu-sc7280.yaml
+++ b/Documentation/devicetree/bindings/display/msm/dpu-sc7280.yaml
@@ -64,6 +64,10 @@ properties:
   interconnect-names:
     const: mdp0-mem
 
+  resets:
+    items:
+      - description: MDSS_CORE reset
+
 patternProperties:
   "^display-controller@[0-9a-f]+$":
     type: object
diff --git a/Documentation/devicetree/bindings/display/msm/dpu-sdm845.yaml b/Documentation/devicetree/bindings/display/msm/dpu-sdm845.yaml
index 0dca4b3d66e4..1a42491efdbc 100644
--- a/Documentation/devicetree/bindings/display/msm/dpu-sdm845.yaml
+++ b/Documentation/devicetree/bindings/display/msm/dpu-sdm845.yaml
@@ -57,6 +57,10 @@ properties:
 
   ranges: true
 
+  resets:
+    items:
+      - description: MDSS_CORE reset
+
 patternProperties:
   "^display-controller@[0-9a-f]+$":
     type: object
-- 
2.33.1


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

* [PATCH v2 2/2] drm/msm/dpu: Issue MDSS reset during initialization
  2022-03-02  1:29 ` Bjorn Andersson
@ 2022-03-02  1:29   ` Bjorn Andersson
  -1 siblings, 0 replies; 14+ messages in thread
From: Bjorn Andersson @ 2022-03-02  1:29 UTC (permalink / raw)
  To: Rob Clark, Abhinav Kumar, Philipp Zabel, Dmitry Baryshkov, Loic Poulain
  Cc: Rob Herring, Krzysztof Kozlowski, linux-arm-msm, dri-devel,
	freedreno, devicetree, linux-kernel

It's typical for the bootloader to bring up the display for showing a
boot splash or efi framebuffer. But in some cases the kernel driver ends
up only partially configuring (in particular) the DPU, which might
result in e.g. that two different data paths attempts to push data to
the interface - with resulting graphical artifacts.

Naturally the end goal would be to inherit the bootloader's
configuration and provide the user with a glitch free handover from the
boot configuration to a running DPU.

But as implementing seamless transition from the bootloader
configuration to the running OS will be a considerable effort, start by
simply resetting the entire MDSS to its power-on state, to avoid the
partial configuration.

Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
---

Changes since v1:
- Rather than trying to deconfigure individual pieces of the DPU, reset the
  entire block.

 drivers/gpu/drm/msm/disp/dpu1/dpu_mdss.c | 18 ++++++++++++++++++
 drivers/gpu/drm/msm/msm_drv.c            |  4 ++++
 drivers/gpu/drm/msm/msm_kms.h            |  1 +
 3 files changed, 23 insertions(+)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_mdss.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_mdss.c
index b10ca505f9ac..419eaaefe606 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_mdss.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_mdss.c
@@ -7,6 +7,7 @@
 #include <linux/irqchip.h>
 #include <linux/irqdesc.h>
 #include <linux/irqchip/chained_irq.h>
+#include <linux/reset.h>
 #include "dpu_kms.h"
 
 #define to_dpu_mdss(x) container_of(x, struct dpu_mdss, base)
@@ -31,6 +32,7 @@ struct dpu_mdss {
 	void __iomem *mmio;
 	struct clk_bulk_data *clocks;
 	size_t num_clocks;
+	struct reset_control *reset;
 	struct dpu_irq_controller irq_controller;
 };
 
@@ -197,10 +199,18 @@ static void dpu_mdss_destroy(struct msm_mdss *mdss)
 	dpu_mdss->mmio = NULL;
 }
 
+static int dpu_mdss_reset(struct msm_mdss *mdss)
+{
+	struct dpu_mdss *dpu_mdss = to_dpu_mdss(mdss);
+
+	return reset_control_reset(dpu_mdss->reset);
+}
+
 static const struct msm_mdss_funcs mdss_funcs = {
 	.enable	= dpu_mdss_enable,
 	.disable = dpu_mdss_disable,
 	.destroy = dpu_mdss_destroy,
+	.reset = dpu_mdss_reset,
 };
 
 int dpu_mdss_init(struct platform_device *pdev)
@@ -227,6 +237,13 @@ int dpu_mdss_init(struct platform_device *pdev)
 	}
 	dpu_mdss->num_clocks = ret;
 
+	dpu_mdss->reset = devm_reset_control_get_optional_exclusive(&pdev->dev, NULL);
+	if (IS_ERR(dpu_mdss->reset)) {
+		ret = PTR_ERR(dpu_mdss->reset);
+		DPU_ERROR("failed to acquire mdss reset, ret=%d", ret);
+		goto reset_parse_err;
+	}
+
 	dpu_mdss->base.dev = &pdev->dev;
 	dpu_mdss->base.funcs = &mdss_funcs;
 
@@ -252,6 +269,7 @@ int dpu_mdss_init(struct platform_device *pdev)
 irq_error:
 	_dpu_mdss_irq_domain_fini(dpu_mdss);
 irq_domain_error:
+reset_parse_err:
 clk_parse_err:
 	if (dpu_mdss->mmio)
 		devm_iounmap(&pdev->dev, dpu_mdss->mmio);
diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c
index 129fa841ac22..7595f83da3f1 100644
--- a/drivers/gpu/drm/msm/msm_drv.c
+++ b/drivers/gpu/drm/msm/msm_drv.c
@@ -388,6 +388,10 @@ static int msm_drm_init(struct device *dev, const struct drm_driver *drv)
 	if (ret)
 		return ret;
 
+	/* Issue a reset of the entire MDSS */
+	if (priv->mdss && priv->mdss->funcs->reset)
+		priv->mdss->funcs->reset(priv->mdss);
+
 	/* Bind all our sub-components: */
 	ret = component_bind_all(dev, ddev);
 	if (ret)
diff --git a/drivers/gpu/drm/msm/msm_kms.h b/drivers/gpu/drm/msm/msm_kms.h
index 2a4f0526cb98..716a34fca1cd 100644
--- a/drivers/gpu/drm/msm/msm_kms.h
+++ b/drivers/gpu/drm/msm/msm_kms.h
@@ -205,6 +205,7 @@ struct msm_mdss_funcs {
 	int (*enable)(struct msm_mdss *mdss);
 	int (*disable)(struct msm_mdss *mdss);
 	void (*destroy)(struct msm_mdss *mdss);
+	int (*reset)(struct msm_mdss *mdss);
 };
 
 struct msm_mdss {
-- 
2.33.1


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

* [PATCH v2 2/2] drm/msm/dpu: Issue MDSS reset during initialization
@ 2022-03-02  1:29   ` Bjorn Andersson
  0 siblings, 0 replies; 14+ messages in thread
From: Bjorn Andersson @ 2022-03-02  1:29 UTC (permalink / raw)
  To: Rob Clark, Abhinav Kumar, Philipp Zabel, Dmitry Baryshkov, Loic Poulain
  Cc: devicetree, Krzysztof Kozlowski, linux-arm-msm, linux-kernel,
	dri-devel, Rob Herring, freedreno

It's typical for the bootloader to bring up the display for showing a
boot splash or efi framebuffer. But in some cases the kernel driver ends
up only partially configuring (in particular) the DPU, which might
result in e.g. that two different data paths attempts to push data to
the interface - with resulting graphical artifacts.

Naturally the end goal would be to inherit the bootloader's
configuration and provide the user with a glitch free handover from the
boot configuration to a running DPU.

But as implementing seamless transition from the bootloader
configuration to the running OS will be a considerable effort, start by
simply resetting the entire MDSS to its power-on state, to avoid the
partial configuration.

Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
---

Changes since v1:
- Rather than trying to deconfigure individual pieces of the DPU, reset the
  entire block.

 drivers/gpu/drm/msm/disp/dpu1/dpu_mdss.c | 18 ++++++++++++++++++
 drivers/gpu/drm/msm/msm_drv.c            |  4 ++++
 drivers/gpu/drm/msm/msm_kms.h            |  1 +
 3 files changed, 23 insertions(+)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_mdss.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_mdss.c
index b10ca505f9ac..419eaaefe606 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_mdss.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_mdss.c
@@ -7,6 +7,7 @@
 #include <linux/irqchip.h>
 #include <linux/irqdesc.h>
 #include <linux/irqchip/chained_irq.h>
+#include <linux/reset.h>
 #include "dpu_kms.h"
 
 #define to_dpu_mdss(x) container_of(x, struct dpu_mdss, base)
@@ -31,6 +32,7 @@ struct dpu_mdss {
 	void __iomem *mmio;
 	struct clk_bulk_data *clocks;
 	size_t num_clocks;
+	struct reset_control *reset;
 	struct dpu_irq_controller irq_controller;
 };
 
@@ -197,10 +199,18 @@ static void dpu_mdss_destroy(struct msm_mdss *mdss)
 	dpu_mdss->mmio = NULL;
 }
 
+static int dpu_mdss_reset(struct msm_mdss *mdss)
+{
+	struct dpu_mdss *dpu_mdss = to_dpu_mdss(mdss);
+
+	return reset_control_reset(dpu_mdss->reset);
+}
+
 static const struct msm_mdss_funcs mdss_funcs = {
 	.enable	= dpu_mdss_enable,
 	.disable = dpu_mdss_disable,
 	.destroy = dpu_mdss_destroy,
+	.reset = dpu_mdss_reset,
 };
 
 int dpu_mdss_init(struct platform_device *pdev)
@@ -227,6 +237,13 @@ int dpu_mdss_init(struct platform_device *pdev)
 	}
 	dpu_mdss->num_clocks = ret;
 
+	dpu_mdss->reset = devm_reset_control_get_optional_exclusive(&pdev->dev, NULL);
+	if (IS_ERR(dpu_mdss->reset)) {
+		ret = PTR_ERR(dpu_mdss->reset);
+		DPU_ERROR("failed to acquire mdss reset, ret=%d", ret);
+		goto reset_parse_err;
+	}
+
 	dpu_mdss->base.dev = &pdev->dev;
 	dpu_mdss->base.funcs = &mdss_funcs;
 
@@ -252,6 +269,7 @@ int dpu_mdss_init(struct platform_device *pdev)
 irq_error:
 	_dpu_mdss_irq_domain_fini(dpu_mdss);
 irq_domain_error:
+reset_parse_err:
 clk_parse_err:
 	if (dpu_mdss->mmio)
 		devm_iounmap(&pdev->dev, dpu_mdss->mmio);
diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c
index 129fa841ac22..7595f83da3f1 100644
--- a/drivers/gpu/drm/msm/msm_drv.c
+++ b/drivers/gpu/drm/msm/msm_drv.c
@@ -388,6 +388,10 @@ static int msm_drm_init(struct device *dev, const struct drm_driver *drv)
 	if (ret)
 		return ret;
 
+	/* Issue a reset of the entire MDSS */
+	if (priv->mdss && priv->mdss->funcs->reset)
+		priv->mdss->funcs->reset(priv->mdss);
+
 	/* Bind all our sub-components: */
 	ret = component_bind_all(dev, ddev);
 	if (ret)
diff --git a/drivers/gpu/drm/msm/msm_kms.h b/drivers/gpu/drm/msm/msm_kms.h
index 2a4f0526cb98..716a34fca1cd 100644
--- a/drivers/gpu/drm/msm/msm_kms.h
+++ b/drivers/gpu/drm/msm/msm_kms.h
@@ -205,6 +205,7 @@ struct msm_mdss_funcs {
 	int (*enable)(struct msm_mdss *mdss);
 	int (*disable)(struct msm_mdss *mdss);
 	void (*destroy)(struct msm_mdss *mdss);
+	int (*reset)(struct msm_mdss *mdss);
 };
 
 struct msm_mdss {
-- 
2.33.1


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

* Re: [PATCH v2 2/2] drm/msm/dpu: Issue MDSS reset during initialization
  2022-03-02  1:29   ` Bjorn Andersson
@ 2022-03-02  1:47     ` Dmitry Baryshkov
  -1 siblings, 0 replies; 14+ messages in thread
From: Dmitry Baryshkov @ 2022-03-02  1:47 UTC (permalink / raw)
  To: Bjorn Andersson
  Cc: Rob Clark, Abhinav Kumar, Philipp Zabel, Loic Poulain,
	Rob Herring, Krzysztof Kozlowski, linux-arm-msm, dri-devel,
	freedreno, devicetree, linux-kernel

On Wed, 2 Mar 2022 at 04:27, Bjorn Andersson <bjorn.andersson@linaro.org> wrote:
>
> It's typical for the bootloader to bring up the display for showing a
> boot splash or efi framebuffer. But in some cases the kernel driver ends
> up only partially configuring (in particular) the DPU, which might
> result in e.g. that two different data paths attempts to push data to
> the interface - with resulting graphical artifacts.
>
> Naturally the end goal would be to inherit the bootloader's
> configuration and provide the user with a glitch free handover from the
> boot configuration to a running DPU.
>
> But as implementing seamless transition from the bootloader
> configuration to the running OS will be a considerable effort, start by
> simply resetting the entire MDSS to its power-on state, to avoid the
> partial configuration.
>
> Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
> ---
>
> Changes since v1:
> - Rather than trying to deconfigure individual pieces of the DPU, reset the
>   entire block.
>
>  drivers/gpu/drm/msm/disp/dpu1/dpu_mdss.c | 18 ++++++++++++++++++
>  drivers/gpu/drm/msm/msm_drv.c            |  4 ++++
>  drivers/gpu/drm/msm/msm_kms.h            |  1 +
>  3 files changed, 23 insertions(+)
>
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_mdss.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_mdss.c
> index b10ca505f9ac..419eaaefe606 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_mdss.c
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_mdss.c
> @@ -7,6 +7,7 @@
>  #include <linux/irqchip.h>
>  #include <linux/irqdesc.h>
>  #include <linux/irqchip/chained_irq.h>
> +#include <linux/reset.h>
>  #include "dpu_kms.h"
>
>  #define to_dpu_mdss(x) container_of(x, struct dpu_mdss, base)
> @@ -31,6 +32,7 @@ struct dpu_mdss {
>         void __iomem *mmio;
>         struct clk_bulk_data *clocks;
>         size_t num_clocks;
> +       struct reset_control *reset;
>         struct dpu_irq_controller irq_controller;
>  };
>
> @@ -197,10 +199,18 @@ static void dpu_mdss_destroy(struct msm_mdss *mdss)
>         dpu_mdss->mmio = NULL;
>  }
>
> +static int dpu_mdss_reset(struct msm_mdss *mdss)
> +{
> +       struct dpu_mdss *dpu_mdss = to_dpu_mdss(mdss);
> +
> +       return reset_control_reset(dpu_mdss->reset);
> +}
> +
>  static const struct msm_mdss_funcs mdss_funcs = {
>         .enable = dpu_mdss_enable,
>         .disable = dpu_mdss_disable,
>         .destroy = dpu_mdss_destroy,
> +       .reset = dpu_mdss_reset,
>  };
>
>  int dpu_mdss_init(struct platform_device *pdev)
> @@ -227,6 +237,13 @@ int dpu_mdss_init(struct platform_device *pdev)
>         }
>         dpu_mdss->num_clocks = ret;
>
> +       dpu_mdss->reset = devm_reset_control_get_optional_exclusive(&pdev->dev, NULL);
> +       if (IS_ERR(dpu_mdss->reset)) {
> +               ret = PTR_ERR(dpu_mdss->reset);
> +               DPU_ERROR("failed to acquire mdss reset, ret=%d", ret);
> +               goto reset_parse_err;
> +       }
> +
>         dpu_mdss->base.dev = &pdev->dev;
>         dpu_mdss->base.funcs = &mdss_funcs;
>
> @@ -252,6 +269,7 @@ int dpu_mdss_init(struct platform_device *pdev)
>  irq_error:
>         _dpu_mdss_irq_domain_fini(dpu_mdss);
>  irq_domain_error:
> +reset_parse_err:
>  clk_parse_err:
>         if (dpu_mdss->mmio)
>                 devm_iounmap(&pdev->dev, dpu_mdss->mmio);
> diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c
> index 129fa841ac22..7595f83da3f1 100644
> --- a/drivers/gpu/drm/msm/msm_drv.c
> +++ b/drivers/gpu/drm/msm/msm_drv.c
> @@ -388,6 +388,10 @@ static int msm_drm_init(struct device *dev, const struct drm_driver *drv)
>         if (ret)
>                 return ret;
>
> +       /* Issue a reset of the entire MDSS */
> +       if (priv->mdss && priv->mdss->funcs->reset)
> +               priv->mdss->funcs->reset(priv->mdss);
> +

I think this is incorrect. In this way reset happens after all
subdevice are probed. They might have programmed some state of the
corresponding block. The clocks are already registered, so the clock
framework will be out of sync.
I think the reset should happen before calling of_platform_populate(),
so the device state is consistent with the driver.

Also see the https://git.linaro.org/people/dmitry.baryshkov/kernel.git/log/?h=dpu-mdss-rework,
which reworks the mdss driver and mdss probing.

>         /* Bind all our sub-components: */
>         ret = component_bind_all(dev, ddev);
>         if (ret)
> diff --git a/drivers/gpu/drm/msm/msm_kms.h b/drivers/gpu/drm/msm/msm_kms.h
> index 2a4f0526cb98..716a34fca1cd 100644
> --- a/drivers/gpu/drm/msm/msm_kms.h
> +++ b/drivers/gpu/drm/msm/msm_kms.h
> @@ -205,6 +205,7 @@ struct msm_mdss_funcs {
>         int (*enable)(struct msm_mdss *mdss);
>         int (*disable)(struct msm_mdss *mdss);
>         void (*destroy)(struct msm_mdss *mdss);
> +       int (*reset)(struct msm_mdss *mdss);
>  };
>
>  struct msm_mdss {
> --
> 2.33.1
>


-- 
With best wishes
Dmitry

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

* Re: [PATCH v2 2/2] drm/msm/dpu: Issue MDSS reset during initialization
@ 2022-03-02  1:47     ` Dmitry Baryshkov
  0 siblings, 0 replies; 14+ messages in thread
From: Dmitry Baryshkov @ 2022-03-02  1:47 UTC (permalink / raw)
  To: Bjorn Andersson
  Cc: devicetree, Loic Poulain, Krzysztof Kozlowski, linux-arm-msm,
	Abhinav Kumar, dri-devel, linux-kernel, Rob Herring, freedreno

On Wed, 2 Mar 2022 at 04:27, Bjorn Andersson <bjorn.andersson@linaro.org> wrote:
>
> It's typical for the bootloader to bring up the display for showing a
> boot splash or efi framebuffer. But in some cases the kernel driver ends
> up only partially configuring (in particular) the DPU, which might
> result in e.g. that two different data paths attempts to push data to
> the interface - with resulting graphical artifacts.
>
> Naturally the end goal would be to inherit the bootloader's
> configuration and provide the user with a glitch free handover from the
> boot configuration to a running DPU.
>
> But as implementing seamless transition from the bootloader
> configuration to the running OS will be a considerable effort, start by
> simply resetting the entire MDSS to its power-on state, to avoid the
> partial configuration.
>
> Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
> ---
>
> Changes since v1:
> - Rather than trying to deconfigure individual pieces of the DPU, reset the
>   entire block.
>
>  drivers/gpu/drm/msm/disp/dpu1/dpu_mdss.c | 18 ++++++++++++++++++
>  drivers/gpu/drm/msm/msm_drv.c            |  4 ++++
>  drivers/gpu/drm/msm/msm_kms.h            |  1 +
>  3 files changed, 23 insertions(+)
>
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_mdss.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_mdss.c
> index b10ca505f9ac..419eaaefe606 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_mdss.c
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_mdss.c
> @@ -7,6 +7,7 @@
>  #include <linux/irqchip.h>
>  #include <linux/irqdesc.h>
>  #include <linux/irqchip/chained_irq.h>
> +#include <linux/reset.h>
>  #include "dpu_kms.h"
>
>  #define to_dpu_mdss(x) container_of(x, struct dpu_mdss, base)
> @@ -31,6 +32,7 @@ struct dpu_mdss {
>         void __iomem *mmio;
>         struct clk_bulk_data *clocks;
>         size_t num_clocks;
> +       struct reset_control *reset;
>         struct dpu_irq_controller irq_controller;
>  };
>
> @@ -197,10 +199,18 @@ static void dpu_mdss_destroy(struct msm_mdss *mdss)
>         dpu_mdss->mmio = NULL;
>  }
>
> +static int dpu_mdss_reset(struct msm_mdss *mdss)
> +{
> +       struct dpu_mdss *dpu_mdss = to_dpu_mdss(mdss);
> +
> +       return reset_control_reset(dpu_mdss->reset);
> +}
> +
>  static const struct msm_mdss_funcs mdss_funcs = {
>         .enable = dpu_mdss_enable,
>         .disable = dpu_mdss_disable,
>         .destroy = dpu_mdss_destroy,
> +       .reset = dpu_mdss_reset,
>  };
>
>  int dpu_mdss_init(struct platform_device *pdev)
> @@ -227,6 +237,13 @@ int dpu_mdss_init(struct platform_device *pdev)
>         }
>         dpu_mdss->num_clocks = ret;
>
> +       dpu_mdss->reset = devm_reset_control_get_optional_exclusive(&pdev->dev, NULL);
> +       if (IS_ERR(dpu_mdss->reset)) {
> +               ret = PTR_ERR(dpu_mdss->reset);
> +               DPU_ERROR("failed to acquire mdss reset, ret=%d", ret);
> +               goto reset_parse_err;
> +       }
> +
>         dpu_mdss->base.dev = &pdev->dev;
>         dpu_mdss->base.funcs = &mdss_funcs;
>
> @@ -252,6 +269,7 @@ int dpu_mdss_init(struct platform_device *pdev)
>  irq_error:
>         _dpu_mdss_irq_domain_fini(dpu_mdss);
>  irq_domain_error:
> +reset_parse_err:
>  clk_parse_err:
>         if (dpu_mdss->mmio)
>                 devm_iounmap(&pdev->dev, dpu_mdss->mmio);
> diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c
> index 129fa841ac22..7595f83da3f1 100644
> --- a/drivers/gpu/drm/msm/msm_drv.c
> +++ b/drivers/gpu/drm/msm/msm_drv.c
> @@ -388,6 +388,10 @@ static int msm_drm_init(struct device *dev, const struct drm_driver *drv)
>         if (ret)
>                 return ret;
>
> +       /* Issue a reset of the entire MDSS */
> +       if (priv->mdss && priv->mdss->funcs->reset)
> +               priv->mdss->funcs->reset(priv->mdss);
> +

I think this is incorrect. In this way reset happens after all
subdevice are probed. They might have programmed some state of the
corresponding block. The clocks are already registered, so the clock
framework will be out of sync.
I think the reset should happen before calling of_platform_populate(),
so the device state is consistent with the driver.

Also see the https://git.linaro.org/people/dmitry.baryshkov/kernel.git/log/?h=dpu-mdss-rework,
which reworks the mdss driver and mdss probing.

>         /* Bind all our sub-components: */
>         ret = component_bind_all(dev, ddev);
>         if (ret)
> diff --git a/drivers/gpu/drm/msm/msm_kms.h b/drivers/gpu/drm/msm/msm_kms.h
> index 2a4f0526cb98..716a34fca1cd 100644
> --- a/drivers/gpu/drm/msm/msm_kms.h
> +++ b/drivers/gpu/drm/msm/msm_kms.h
> @@ -205,6 +205,7 @@ struct msm_mdss_funcs {
>         int (*enable)(struct msm_mdss *mdss);
>         int (*disable)(struct msm_mdss *mdss);
>         void (*destroy)(struct msm_mdss *mdss);
> +       int (*reset)(struct msm_mdss *mdss);
>  };
>
>  struct msm_mdss {
> --
> 2.33.1
>


-- 
With best wishes
Dmitry

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

* Re: [PATCH v2 2/2] drm/msm/dpu: Issue MDSS reset during initialization
  2022-03-02  1:47     ` Dmitry Baryshkov
@ 2022-03-02  2:44       ` Bjorn Andersson
  -1 siblings, 0 replies; 14+ messages in thread
From: Bjorn Andersson @ 2022-03-02  2:44 UTC (permalink / raw)
  To: Dmitry Baryshkov
  Cc: Rob Clark, Abhinav Kumar, Philipp Zabel, Loic Poulain,
	Rob Herring, Krzysztof Kozlowski, linux-arm-msm, dri-devel,
	freedreno, devicetree, linux-kernel

On Tue 01 Mar 17:47 PST 2022, Dmitry Baryshkov wrote:

> On Wed, 2 Mar 2022 at 04:27, Bjorn Andersson <bjorn.andersson@linaro.org> wrote:
> >
> > It's typical for the bootloader to bring up the display for showing a
> > boot splash or efi framebuffer. But in some cases the kernel driver ends
> > up only partially configuring (in particular) the DPU, which might
> > result in e.g. that two different data paths attempts to push data to
> > the interface - with resulting graphical artifacts.
> >
> > Naturally the end goal would be to inherit the bootloader's
> > configuration and provide the user with a glitch free handover from the
> > boot configuration to a running DPU.
> >
> > But as implementing seamless transition from the bootloader
> > configuration to the running OS will be a considerable effort, start by
> > simply resetting the entire MDSS to its power-on state, to avoid the
> > partial configuration.
> >
> > Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
> > ---
> >
> > Changes since v1:
> > - Rather than trying to deconfigure individual pieces of the DPU, reset the
> >   entire block.
> >
> >  drivers/gpu/drm/msm/disp/dpu1/dpu_mdss.c | 18 ++++++++++++++++++
> >  drivers/gpu/drm/msm/msm_drv.c            |  4 ++++
> >  drivers/gpu/drm/msm/msm_kms.h            |  1 +
> >  3 files changed, 23 insertions(+)
> >
> > diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_mdss.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_mdss.c
> > index b10ca505f9ac..419eaaefe606 100644
> > --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_mdss.c
> > +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_mdss.c
> > @@ -7,6 +7,7 @@
> >  #include <linux/irqchip.h>
> >  #include <linux/irqdesc.h>
> >  #include <linux/irqchip/chained_irq.h>
> > +#include <linux/reset.h>
> >  #include "dpu_kms.h"
> >
> >  #define to_dpu_mdss(x) container_of(x, struct dpu_mdss, base)
> > @@ -31,6 +32,7 @@ struct dpu_mdss {
> >         void __iomem *mmio;
> >         struct clk_bulk_data *clocks;
> >         size_t num_clocks;
> > +       struct reset_control *reset;
> >         struct dpu_irq_controller irq_controller;
> >  };
> >
> > @@ -197,10 +199,18 @@ static void dpu_mdss_destroy(struct msm_mdss *mdss)
> >         dpu_mdss->mmio = NULL;
> >  }
> >
> > +static int dpu_mdss_reset(struct msm_mdss *mdss)
> > +{
> > +       struct dpu_mdss *dpu_mdss = to_dpu_mdss(mdss);
> > +
> > +       return reset_control_reset(dpu_mdss->reset);
> > +}
> > +
> >  static const struct msm_mdss_funcs mdss_funcs = {
> >         .enable = dpu_mdss_enable,
> >         .disable = dpu_mdss_disable,
> >         .destroy = dpu_mdss_destroy,
> > +       .reset = dpu_mdss_reset,
> >  };
> >
> >  int dpu_mdss_init(struct platform_device *pdev)
> > @@ -227,6 +237,13 @@ int dpu_mdss_init(struct platform_device *pdev)
> >         }
> >         dpu_mdss->num_clocks = ret;
> >
> > +       dpu_mdss->reset = devm_reset_control_get_optional_exclusive(&pdev->dev, NULL);
> > +       if (IS_ERR(dpu_mdss->reset)) {
> > +               ret = PTR_ERR(dpu_mdss->reset);
> > +               DPU_ERROR("failed to acquire mdss reset, ret=%d", ret);
> > +               goto reset_parse_err;
> > +       }
> > +
> >         dpu_mdss->base.dev = &pdev->dev;
> >         dpu_mdss->base.funcs = &mdss_funcs;
> >
> > @@ -252,6 +269,7 @@ int dpu_mdss_init(struct platform_device *pdev)
> >  irq_error:
> >         _dpu_mdss_irq_domain_fini(dpu_mdss);
> >  irq_domain_error:
> > +reset_parse_err:
> >  clk_parse_err:
> >         if (dpu_mdss->mmio)
> >                 devm_iounmap(&pdev->dev, dpu_mdss->mmio);
> > diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c
> > index 129fa841ac22..7595f83da3f1 100644
> > --- a/drivers/gpu/drm/msm/msm_drv.c
> > +++ b/drivers/gpu/drm/msm/msm_drv.c
> > @@ -388,6 +388,10 @@ static int msm_drm_init(struct device *dev, const struct drm_driver *drv)
> >         if (ret)
> >                 return ret;
> >
> > +       /* Issue a reset of the entire MDSS */
> > +       if (priv->mdss && priv->mdss->funcs->reset)
> > +               priv->mdss->funcs->reset(priv->mdss);
> > +
> 
> I think this is incorrect. In this way reset happens after all
> subdevice are probed. They might have programmed some state of the
> corresponding block. The clocks are already registered, so the clock
> framework will be out of sync.

I went back and forth through the drivers and I believe at least the
idea is that we probe all the drivers, which will acquire some
resources.

Then in bind() we actually start to access the hardware (and acquire
more resources, for some reason).

> I think the reset should happen before calling of_platform_populate(),
> so the device state is consistent with the driver.
> 

Perhaps I'm misunderstanding the component framework, but I was under
the impression that if any of the subcomponents fails to probe because
of lacking resources, this could be printed on the efifb before we reset
the hardware. Making errors slightly more user friendly.

I.e. in the timeframe between of_platform_populate() and
component_bind_all() below...


But if you believe I'm incorrect on the assumptions about the hardware
not being accessed before this point, I can move the reset before
of_platform_populate() - this is the last piece needed to have
functional eDP on sc8180x.

> Also see the https://git.linaro.org/people/dmitry.baryshkov/kernel.git/log/?h=dpu-mdss-rework,
> which reworks the mdss driver and mdss probing.
> 

There seems to be some room for reducing duplication between the two
drivers, so this seems reasonable.

Regards,
Bjorn

> >         /* Bind all our sub-components: */
> >         ret = component_bind_all(dev, ddev);
> >         if (ret)
> > diff --git a/drivers/gpu/drm/msm/msm_kms.h b/drivers/gpu/drm/msm/msm_kms.h
> > index 2a4f0526cb98..716a34fca1cd 100644
> > --- a/drivers/gpu/drm/msm/msm_kms.h
> > +++ b/drivers/gpu/drm/msm/msm_kms.h
> > @@ -205,6 +205,7 @@ struct msm_mdss_funcs {
> >         int (*enable)(struct msm_mdss *mdss);
> >         int (*disable)(struct msm_mdss *mdss);
> >         void (*destroy)(struct msm_mdss *mdss);
> > +       int (*reset)(struct msm_mdss *mdss);
> >  };
> >
> >  struct msm_mdss {
> > --
> > 2.33.1
> >
> 
> 
> -- 
> With best wishes
> Dmitry

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

* Re: [PATCH v2 2/2] drm/msm/dpu: Issue MDSS reset during initialization
@ 2022-03-02  2:44       ` Bjorn Andersson
  0 siblings, 0 replies; 14+ messages in thread
From: Bjorn Andersson @ 2022-03-02  2:44 UTC (permalink / raw)
  To: Dmitry Baryshkov
  Cc: devicetree, Loic Poulain, Krzysztof Kozlowski, linux-arm-msm,
	Abhinav Kumar, dri-devel, linux-kernel, Rob Herring, freedreno

On Tue 01 Mar 17:47 PST 2022, Dmitry Baryshkov wrote:

> On Wed, 2 Mar 2022 at 04:27, Bjorn Andersson <bjorn.andersson@linaro.org> wrote:
> >
> > It's typical for the bootloader to bring up the display for showing a
> > boot splash or efi framebuffer. But in some cases the kernel driver ends
> > up only partially configuring (in particular) the DPU, which might
> > result in e.g. that two different data paths attempts to push data to
> > the interface - with resulting graphical artifacts.
> >
> > Naturally the end goal would be to inherit the bootloader's
> > configuration and provide the user with a glitch free handover from the
> > boot configuration to a running DPU.
> >
> > But as implementing seamless transition from the bootloader
> > configuration to the running OS will be a considerable effort, start by
> > simply resetting the entire MDSS to its power-on state, to avoid the
> > partial configuration.
> >
> > Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
> > ---
> >
> > Changes since v1:
> > - Rather than trying to deconfigure individual pieces of the DPU, reset the
> >   entire block.
> >
> >  drivers/gpu/drm/msm/disp/dpu1/dpu_mdss.c | 18 ++++++++++++++++++
> >  drivers/gpu/drm/msm/msm_drv.c            |  4 ++++
> >  drivers/gpu/drm/msm/msm_kms.h            |  1 +
> >  3 files changed, 23 insertions(+)
> >
> > diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_mdss.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_mdss.c
> > index b10ca505f9ac..419eaaefe606 100644
> > --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_mdss.c
> > +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_mdss.c
> > @@ -7,6 +7,7 @@
> >  #include <linux/irqchip.h>
> >  #include <linux/irqdesc.h>
> >  #include <linux/irqchip/chained_irq.h>
> > +#include <linux/reset.h>
> >  #include "dpu_kms.h"
> >
> >  #define to_dpu_mdss(x) container_of(x, struct dpu_mdss, base)
> > @@ -31,6 +32,7 @@ struct dpu_mdss {
> >         void __iomem *mmio;
> >         struct clk_bulk_data *clocks;
> >         size_t num_clocks;
> > +       struct reset_control *reset;
> >         struct dpu_irq_controller irq_controller;
> >  };
> >
> > @@ -197,10 +199,18 @@ static void dpu_mdss_destroy(struct msm_mdss *mdss)
> >         dpu_mdss->mmio = NULL;
> >  }
> >
> > +static int dpu_mdss_reset(struct msm_mdss *mdss)
> > +{
> > +       struct dpu_mdss *dpu_mdss = to_dpu_mdss(mdss);
> > +
> > +       return reset_control_reset(dpu_mdss->reset);
> > +}
> > +
> >  static const struct msm_mdss_funcs mdss_funcs = {
> >         .enable = dpu_mdss_enable,
> >         .disable = dpu_mdss_disable,
> >         .destroy = dpu_mdss_destroy,
> > +       .reset = dpu_mdss_reset,
> >  };
> >
> >  int dpu_mdss_init(struct platform_device *pdev)
> > @@ -227,6 +237,13 @@ int dpu_mdss_init(struct platform_device *pdev)
> >         }
> >         dpu_mdss->num_clocks = ret;
> >
> > +       dpu_mdss->reset = devm_reset_control_get_optional_exclusive(&pdev->dev, NULL);
> > +       if (IS_ERR(dpu_mdss->reset)) {
> > +               ret = PTR_ERR(dpu_mdss->reset);
> > +               DPU_ERROR("failed to acquire mdss reset, ret=%d", ret);
> > +               goto reset_parse_err;
> > +       }
> > +
> >         dpu_mdss->base.dev = &pdev->dev;
> >         dpu_mdss->base.funcs = &mdss_funcs;
> >
> > @@ -252,6 +269,7 @@ int dpu_mdss_init(struct platform_device *pdev)
> >  irq_error:
> >         _dpu_mdss_irq_domain_fini(dpu_mdss);
> >  irq_domain_error:
> > +reset_parse_err:
> >  clk_parse_err:
> >         if (dpu_mdss->mmio)
> >                 devm_iounmap(&pdev->dev, dpu_mdss->mmio);
> > diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c
> > index 129fa841ac22..7595f83da3f1 100644
> > --- a/drivers/gpu/drm/msm/msm_drv.c
> > +++ b/drivers/gpu/drm/msm/msm_drv.c
> > @@ -388,6 +388,10 @@ static int msm_drm_init(struct device *dev, const struct drm_driver *drv)
> >         if (ret)
> >                 return ret;
> >
> > +       /* Issue a reset of the entire MDSS */
> > +       if (priv->mdss && priv->mdss->funcs->reset)
> > +               priv->mdss->funcs->reset(priv->mdss);
> > +
> 
> I think this is incorrect. In this way reset happens after all
> subdevice are probed. They might have programmed some state of the
> corresponding block. The clocks are already registered, so the clock
> framework will be out of sync.

I went back and forth through the drivers and I believe at least the
idea is that we probe all the drivers, which will acquire some
resources.

Then in bind() we actually start to access the hardware (and acquire
more resources, for some reason).

> I think the reset should happen before calling of_platform_populate(),
> so the device state is consistent with the driver.
> 

Perhaps I'm misunderstanding the component framework, but I was under
the impression that if any of the subcomponents fails to probe because
of lacking resources, this could be printed on the efifb before we reset
the hardware. Making errors slightly more user friendly.

I.e. in the timeframe between of_platform_populate() and
component_bind_all() below...


But if you believe I'm incorrect on the assumptions about the hardware
not being accessed before this point, I can move the reset before
of_platform_populate() - this is the last piece needed to have
functional eDP on sc8180x.

> Also see the https://git.linaro.org/people/dmitry.baryshkov/kernel.git/log/?h=dpu-mdss-rework,
> which reworks the mdss driver and mdss probing.
> 

There seems to be some room for reducing duplication between the two
drivers, so this seems reasonable.

Regards,
Bjorn

> >         /* Bind all our sub-components: */
> >         ret = component_bind_all(dev, ddev);
> >         if (ret)
> > diff --git a/drivers/gpu/drm/msm/msm_kms.h b/drivers/gpu/drm/msm/msm_kms.h
> > index 2a4f0526cb98..716a34fca1cd 100644
> > --- a/drivers/gpu/drm/msm/msm_kms.h
> > +++ b/drivers/gpu/drm/msm/msm_kms.h
> > @@ -205,6 +205,7 @@ struct msm_mdss_funcs {
> >         int (*enable)(struct msm_mdss *mdss);
> >         int (*disable)(struct msm_mdss *mdss);
> >         void (*destroy)(struct msm_mdss *mdss);
> > +       int (*reset)(struct msm_mdss *mdss);
> >  };
> >
> >  struct msm_mdss {
> > --
> > 2.33.1
> >
> 
> 
> -- 
> With best wishes
> Dmitry

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

* Re: [PATCH v2 2/2] drm/msm/dpu: Issue MDSS reset during initialization
  2022-03-02  2:44       ` Bjorn Andersson
@ 2022-03-02  4:42         ` Dmitry Baryshkov
  -1 siblings, 0 replies; 14+ messages in thread
From: Dmitry Baryshkov @ 2022-03-02  4:42 UTC (permalink / raw)
  To: Bjorn Andersson
  Cc: Rob Clark, Abhinav Kumar, Philipp Zabel, Loic Poulain,
	Rob Herring, Krzysztof Kozlowski, linux-arm-msm, dri-devel,
	freedreno, devicetree, linux-kernel

On 02/03/2022 05:44, Bjorn Andersson wrote:
> On Tue 01 Mar 17:47 PST 2022, Dmitry Baryshkov wrote:
> 
>> On Wed, 2 Mar 2022 at 04:27, Bjorn Andersson <bjorn.andersson@linaro.org> wrote:
>>>
>>> It's typical for the bootloader to bring up the display for showing a
>>> boot splash or efi framebuffer. But in some cases the kernel driver ends
>>> up only partially configuring (in particular) the DPU, which might
>>> result in e.g. that two different data paths attempts to push data to
>>> the interface - with resulting graphical artifacts.
>>>
>>> Naturally the end goal would be to inherit the bootloader's
>>> configuration and provide the user with a glitch free handover from the
>>> boot configuration to a running DPU.
>>>
>>> But as implementing seamless transition from the bootloader
>>> configuration to the running OS will be a considerable effort, start by
>>> simply resetting the entire MDSS to its power-on state, to avoid the
>>> partial configuration.
>>>
>>> Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
>>> ---
>>>
>>> Changes since v1:
>>> - Rather than trying to deconfigure individual pieces of the DPU, reset the
>>>    entire block.
>>>
>>>   drivers/gpu/drm/msm/disp/dpu1/dpu_mdss.c | 18 ++++++++++++++++++
>>>   drivers/gpu/drm/msm/msm_drv.c            |  4 ++++
>>>   drivers/gpu/drm/msm/msm_kms.h            |  1 +
>>>   3 files changed, 23 insertions(+)
>>>
>>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_mdss.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_mdss.c
>>> index b10ca505f9ac..419eaaefe606 100644
>>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_mdss.c
>>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_mdss.c
>>> @@ -7,6 +7,7 @@
>>>   #include <linux/irqchip.h>
>>>   #include <linux/irqdesc.h>
>>>   #include <linux/irqchip/chained_irq.h>
>>> +#include <linux/reset.h>
>>>   #include "dpu_kms.h"
>>>
>>>   #define to_dpu_mdss(x) container_of(x, struct dpu_mdss, base)
>>> @@ -31,6 +32,7 @@ struct dpu_mdss {
>>>          void __iomem *mmio;
>>>          struct clk_bulk_data *clocks;
>>>          size_t num_clocks;
>>> +       struct reset_control *reset;
>>>          struct dpu_irq_controller irq_controller;
>>>   };
>>>
>>> @@ -197,10 +199,18 @@ static void dpu_mdss_destroy(struct msm_mdss *mdss)
>>>          dpu_mdss->mmio = NULL;
>>>   }
>>>
>>> +static int dpu_mdss_reset(struct msm_mdss *mdss)
>>> +{
>>> +       struct dpu_mdss *dpu_mdss = to_dpu_mdss(mdss);
>>> +
>>> +       return reset_control_reset(dpu_mdss->reset);
>>> +}
>>> +
>>>   static const struct msm_mdss_funcs mdss_funcs = {
>>>          .enable = dpu_mdss_enable,
>>>          .disable = dpu_mdss_disable,
>>>          .destroy = dpu_mdss_destroy,
>>> +       .reset = dpu_mdss_reset,
>>>   };
>>>
>>>   int dpu_mdss_init(struct platform_device *pdev)
>>> @@ -227,6 +237,13 @@ int dpu_mdss_init(struct platform_device *pdev)
>>>          }
>>>          dpu_mdss->num_clocks = ret;
>>>
>>> +       dpu_mdss->reset = devm_reset_control_get_optional_exclusive(&pdev->dev, NULL);
>>> +       if (IS_ERR(dpu_mdss->reset)) {
>>> +               ret = PTR_ERR(dpu_mdss->reset);
>>> +               DPU_ERROR("failed to acquire mdss reset, ret=%d", ret);
>>> +               goto reset_parse_err;
>>> +       }
>>> +
>>>          dpu_mdss->base.dev = &pdev->dev;
>>>          dpu_mdss->base.funcs = &mdss_funcs;
>>>
>>> @@ -252,6 +269,7 @@ int dpu_mdss_init(struct platform_device *pdev)
>>>   irq_error:
>>>          _dpu_mdss_irq_domain_fini(dpu_mdss);
>>>   irq_domain_error:
>>> +reset_parse_err:
>>>   clk_parse_err:
>>>          if (dpu_mdss->mmio)
>>>                  devm_iounmap(&pdev->dev, dpu_mdss->mmio);
>>> diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c
>>> index 129fa841ac22..7595f83da3f1 100644
>>> --- a/drivers/gpu/drm/msm/msm_drv.c
>>> +++ b/drivers/gpu/drm/msm/msm_drv.c
>>> @@ -388,6 +388,10 @@ static int msm_drm_init(struct device *dev, const struct drm_driver *drv)
>>>          if (ret)
>>>                  return ret;
>>>
>>> +       /* Issue a reset of the entire MDSS */
>>> +       if (priv->mdss && priv->mdss->funcs->reset)
>>> +               priv->mdss->funcs->reset(priv->mdss);
>>> +
>>
>> I think this is incorrect. In this way reset happens after all
>> subdevice are probed. They might have programmed some state of the
>> corresponding block. The clocks are already registered, so the clock
>> framework will be out of sync.
> 
> I went back and forth through the drivers and I believe at least the
> idea is that we probe all the drivers, which will acquire some
> resources.
> 
> Then in bind() we actually start to access the hardware (and acquire
> more resources, for some reason).

DSI clock init happens in the dsi_clk_init(), called from 
msm_dsi_host_inti(), dsi_init(), dsi_dev_probe(). But it's not the major 
problem.

All the PHYs do not use component framework, be it the DSI PHY or HDMI 
PHY. So at the time you call MDSS reset, the PHYs are already 
initialized, the clocks are registered in the clock subsystem, etc.
Performing a reset will put the hardware out of sync with the Linux kernel.

So, if you'd like to perform a reset in the msm_drm_init(), we'd have to 
modify DSI to perform some parts of init later. And to move PHYs to also 
use the component framework. And I'm not sure if that won't break the 
dispcc, the way it gets the DSI clocks.

> 
>> I think the reset should happen before calling of_platform_populate(),
>> so the device state is consistent with the driver.
>>
> 
> Perhaps I'm misunderstanding the component framework, but I was under
> the impression that if any of the subcomponents fails to probe because
> of lacking resources, this could be printed on the efifb before we reset
> the hardware. Making errors slightly more user friendly.

Yes, I understand why did you place the call in msm_drm_init().

> 
> I.e. in the timeframe between of_platform_populate() and
> component_bind_all() below...
> 
> 
> But if you believe I'm incorrect on the assumptions about the hardware
> not being accessed before this point, I can move the reset before
> of_platform_populate() - this is the last piece needed to have
> functional eDP on sc8180x.
> 
>> Also see the https://git.linaro.org/people/dmitry.baryshkov/kernel.git/log/?h=dpu-mdss-rework,
>> which reworks the mdss driver and mdss probing.
>>
> 
> There seems to be some room for reducing duplication between the two
> drivers, so this seems reasonable.
> 
> Regards,
> Bjorn
> 
>>>          /* Bind all our sub-components: */
>>>          ret = component_bind_all(dev, ddev);
>>>          if (ret)
>>> diff --git a/drivers/gpu/drm/msm/msm_kms.h b/drivers/gpu/drm/msm/msm_kms.h
>>> index 2a4f0526cb98..716a34fca1cd 100644
>>> --- a/drivers/gpu/drm/msm/msm_kms.h
>>> +++ b/drivers/gpu/drm/msm/msm_kms.h
>>> @@ -205,6 +205,7 @@ struct msm_mdss_funcs {
>>>          int (*enable)(struct msm_mdss *mdss);
>>>          int (*disable)(struct msm_mdss *mdss);
>>>          void (*destroy)(struct msm_mdss *mdss);
>>> +       int (*reset)(struct msm_mdss *mdss);
>>>   };
>>>
>>>   struct msm_mdss {
>>> --
>>> 2.33.1
>>>
>>
>>
>> -- 
>> With best wishes
>> Dmitry


-- 
With best wishes
Dmitry

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

* Re: [PATCH v2 2/2] drm/msm/dpu: Issue MDSS reset during initialization
@ 2022-03-02  4:42         ` Dmitry Baryshkov
  0 siblings, 0 replies; 14+ messages in thread
From: Dmitry Baryshkov @ 2022-03-02  4:42 UTC (permalink / raw)
  To: Bjorn Andersson
  Cc: devicetree, Loic Poulain, Krzysztof Kozlowski, linux-arm-msm,
	Abhinav Kumar, dri-devel, linux-kernel, Rob Herring, freedreno

On 02/03/2022 05:44, Bjorn Andersson wrote:
> On Tue 01 Mar 17:47 PST 2022, Dmitry Baryshkov wrote:
> 
>> On Wed, 2 Mar 2022 at 04:27, Bjorn Andersson <bjorn.andersson@linaro.org> wrote:
>>>
>>> It's typical for the bootloader to bring up the display for showing a
>>> boot splash or efi framebuffer. But in some cases the kernel driver ends
>>> up only partially configuring (in particular) the DPU, which might
>>> result in e.g. that two different data paths attempts to push data to
>>> the interface - with resulting graphical artifacts.
>>>
>>> Naturally the end goal would be to inherit the bootloader's
>>> configuration and provide the user with a glitch free handover from the
>>> boot configuration to a running DPU.
>>>
>>> But as implementing seamless transition from the bootloader
>>> configuration to the running OS will be a considerable effort, start by
>>> simply resetting the entire MDSS to its power-on state, to avoid the
>>> partial configuration.
>>>
>>> Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
>>> ---
>>>
>>> Changes since v1:
>>> - Rather than trying to deconfigure individual pieces of the DPU, reset the
>>>    entire block.
>>>
>>>   drivers/gpu/drm/msm/disp/dpu1/dpu_mdss.c | 18 ++++++++++++++++++
>>>   drivers/gpu/drm/msm/msm_drv.c            |  4 ++++
>>>   drivers/gpu/drm/msm/msm_kms.h            |  1 +
>>>   3 files changed, 23 insertions(+)
>>>
>>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_mdss.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_mdss.c
>>> index b10ca505f9ac..419eaaefe606 100644
>>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_mdss.c
>>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_mdss.c
>>> @@ -7,6 +7,7 @@
>>>   #include <linux/irqchip.h>
>>>   #include <linux/irqdesc.h>
>>>   #include <linux/irqchip/chained_irq.h>
>>> +#include <linux/reset.h>
>>>   #include "dpu_kms.h"
>>>
>>>   #define to_dpu_mdss(x) container_of(x, struct dpu_mdss, base)
>>> @@ -31,6 +32,7 @@ struct dpu_mdss {
>>>          void __iomem *mmio;
>>>          struct clk_bulk_data *clocks;
>>>          size_t num_clocks;
>>> +       struct reset_control *reset;
>>>          struct dpu_irq_controller irq_controller;
>>>   };
>>>
>>> @@ -197,10 +199,18 @@ static void dpu_mdss_destroy(struct msm_mdss *mdss)
>>>          dpu_mdss->mmio = NULL;
>>>   }
>>>
>>> +static int dpu_mdss_reset(struct msm_mdss *mdss)
>>> +{
>>> +       struct dpu_mdss *dpu_mdss = to_dpu_mdss(mdss);
>>> +
>>> +       return reset_control_reset(dpu_mdss->reset);
>>> +}
>>> +
>>>   static const struct msm_mdss_funcs mdss_funcs = {
>>>          .enable = dpu_mdss_enable,
>>>          .disable = dpu_mdss_disable,
>>>          .destroy = dpu_mdss_destroy,
>>> +       .reset = dpu_mdss_reset,
>>>   };
>>>
>>>   int dpu_mdss_init(struct platform_device *pdev)
>>> @@ -227,6 +237,13 @@ int dpu_mdss_init(struct platform_device *pdev)
>>>          }
>>>          dpu_mdss->num_clocks = ret;
>>>
>>> +       dpu_mdss->reset = devm_reset_control_get_optional_exclusive(&pdev->dev, NULL);
>>> +       if (IS_ERR(dpu_mdss->reset)) {
>>> +               ret = PTR_ERR(dpu_mdss->reset);
>>> +               DPU_ERROR("failed to acquire mdss reset, ret=%d", ret);
>>> +               goto reset_parse_err;
>>> +       }
>>> +
>>>          dpu_mdss->base.dev = &pdev->dev;
>>>          dpu_mdss->base.funcs = &mdss_funcs;
>>>
>>> @@ -252,6 +269,7 @@ int dpu_mdss_init(struct platform_device *pdev)
>>>   irq_error:
>>>          _dpu_mdss_irq_domain_fini(dpu_mdss);
>>>   irq_domain_error:
>>> +reset_parse_err:
>>>   clk_parse_err:
>>>          if (dpu_mdss->mmio)
>>>                  devm_iounmap(&pdev->dev, dpu_mdss->mmio);
>>> diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c
>>> index 129fa841ac22..7595f83da3f1 100644
>>> --- a/drivers/gpu/drm/msm/msm_drv.c
>>> +++ b/drivers/gpu/drm/msm/msm_drv.c
>>> @@ -388,6 +388,10 @@ static int msm_drm_init(struct device *dev, const struct drm_driver *drv)
>>>          if (ret)
>>>                  return ret;
>>>
>>> +       /* Issue a reset of the entire MDSS */
>>> +       if (priv->mdss && priv->mdss->funcs->reset)
>>> +               priv->mdss->funcs->reset(priv->mdss);
>>> +
>>
>> I think this is incorrect. In this way reset happens after all
>> subdevice are probed. They might have programmed some state of the
>> corresponding block. The clocks are already registered, so the clock
>> framework will be out of sync.
> 
> I went back and forth through the drivers and I believe at least the
> idea is that we probe all the drivers, which will acquire some
> resources.
> 
> Then in bind() we actually start to access the hardware (and acquire
> more resources, for some reason).

DSI clock init happens in the dsi_clk_init(), called from 
msm_dsi_host_inti(), dsi_init(), dsi_dev_probe(). But it's not the major 
problem.

All the PHYs do not use component framework, be it the DSI PHY or HDMI 
PHY. So at the time you call MDSS reset, the PHYs are already 
initialized, the clocks are registered in the clock subsystem, etc.
Performing a reset will put the hardware out of sync with the Linux kernel.

So, if you'd like to perform a reset in the msm_drm_init(), we'd have to 
modify DSI to perform some parts of init later. And to move PHYs to also 
use the component framework. And I'm not sure if that won't break the 
dispcc, the way it gets the DSI clocks.

> 
>> I think the reset should happen before calling of_platform_populate(),
>> so the device state is consistent with the driver.
>>
> 
> Perhaps I'm misunderstanding the component framework, but I was under
> the impression that if any of the subcomponents fails to probe because
> of lacking resources, this could be printed on the efifb before we reset
> the hardware. Making errors slightly more user friendly.

Yes, I understand why did you place the call in msm_drm_init().

> 
> I.e. in the timeframe between of_platform_populate() and
> component_bind_all() below...
> 
> 
> But if you believe I'm incorrect on the assumptions about the hardware
> not being accessed before this point, I can move the reset before
> of_platform_populate() - this is the last piece needed to have
> functional eDP on sc8180x.
> 
>> Also see the https://git.linaro.org/people/dmitry.baryshkov/kernel.git/log/?h=dpu-mdss-rework,
>> which reworks the mdss driver and mdss probing.
>>
> 
> There seems to be some room for reducing duplication between the two
> drivers, so this seems reasonable.
> 
> Regards,
> Bjorn
> 
>>>          /* Bind all our sub-components: */
>>>          ret = component_bind_all(dev, ddev);
>>>          if (ret)
>>> diff --git a/drivers/gpu/drm/msm/msm_kms.h b/drivers/gpu/drm/msm/msm_kms.h
>>> index 2a4f0526cb98..716a34fca1cd 100644
>>> --- a/drivers/gpu/drm/msm/msm_kms.h
>>> +++ b/drivers/gpu/drm/msm/msm_kms.h
>>> @@ -205,6 +205,7 @@ struct msm_mdss_funcs {
>>>          int (*enable)(struct msm_mdss *mdss);
>>>          int (*disable)(struct msm_mdss *mdss);
>>>          void (*destroy)(struct msm_mdss *mdss);
>>> +       int (*reset)(struct msm_mdss *mdss);
>>>   };
>>>
>>>   struct msm_mdss {
>>> --
>>> 2.33.1
>>>
>>
>>
>> -- 
>> With best wishes
>> Dmitry


-- 
With best wishes
Dmitry

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

* Re: [PATCH v2 1/2] dt-bindings: display: msm: Add optional resets
  2022-03-02  1:29 ` Bjorn Andersson
@ 2022-03-02 18:02   ` Rob Herring
  -1 siblings, 0 replies; 14+ messages in thread
From: Rob Herring @ 2022-03-02 18:02 UTC (permalink / raw)
  To: Bjorn Andersson
  Cc: Rob Clark, Abhinav Kumar, Krzysztof Kozlowski, Philipp Zabel,
	Dmitry Baryshkov, Loic Poulain, linux-arm-msm, freedreno,
	linux-kernel, dri-devel, devicetree

On Tue, Mar 01, 2022 at 05:29:30PM -0800, Bjorn Andersson wrote:
> Add an optional reference to the MDSS_CORE reset, which when specified
> can be used by the implementation to reset the hardware blocks.
> 
> Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
> ---
> 
> Changes since v1:
> - New approach/patch
> 
>  .../devicetree/bindings/display/msm/dpu-qcm2290.yaml          | 4 ++++
>  Documentation/devicetree/bindings/display/msm/dpu-sc7180.yaml | 4 ++++
>  Documentation/devicetree/bindings/display/msm/dpu-sc7280.yaml | 4 ++++
>  Documentation/devicetree/bindings/display/msm/dpu-sdm845.yaml | 4 ++++
>  4 files changed, 16 insertions(+)

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


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

* Re: [PATCH v2 1/2] dt-bindings: display: msm: Add optional resets
@ 2022-03-02 18:02   ` Rob Herring
  0 siblings, 0 replies; 14+ messages in thread
From: Rob Herring @ 2022-03-02 18:02 UTC (permalink / raw)
  To: Bjorn Andersson
  Cc: devicetree, Loic Poulain, Krzysztof Kozlowski, linux-arm-msm,
	Abhinav Kumar, dri-devel, linux-kernel, Dmitry Baryshkov,
	freedreno

On Tue, Mar 01, 2022 at 05:29:30PM -0800, Bjorn Andersson wrote:
> Add an optional reference to the MDSS_CORE reset, which when specified
> can be used by the implementation to reset the hardware blocks.
> 
> Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
> ---
> 
> Changes since v1:
> - New approach/patch
> 
>  .../devicetree/bindings/display/msm/dpu-qcm2290.yaml          | 4 ++++
>  Documentation/devicetree/bindings/display/msm/dpu-sc7180.yaml | 4 ++++
>  Documentation/devicetree/bindings/display/msm/dpu-sc7280.yaml | 4 ++++
>  Documentation/devicetree/bindings/display/msm/dpu-sdm845.yaml | 4 ++++
>  4 files changed, 16 insertions(+)

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


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

* [PATCH v2 2/2] drm/msm/dpu: Issue MDSS reset during initialization
  2022-04-08 21:02 Bjorn Andersson
@ 2022-04-08 21:02   ` Bjorn Andersson
  0 siblings, 0 replies; 14+ messages in thread
From: Bjorn Andersson @ 2022-04-08 21:02 UTC (permalink / raw)
  To: Rob Clark, Abhinav Kumar, Rob Herring, Krzysztof Kozlowski,
	Dmitry Baryshkov
  Cc: Sean Paul, David Airlie, Daniel Vetter, Philipp Zabel,
	linux-arm-msm, dri-devel, freedreno, devicetree, linux-kernel

It's typical for the bootloader to bring up the display for showing a
boot splash or efi framebuffer. But in some cases the kernel driver ends
up only partially configuring (in particular) the DPU, which might
result in e.g. that two different data paths attempts to push data to
the interface - with resulting graphical artifacts.

Naturally the end goal would be to inherit the bootloader's
configuration and provide the user with a glitch free handover from the
boot configuration to a running DPU.

But as implementing seamless transition from the bootloader
configuration to the running OS will be a considerable effort, start by
simply resetting the entire MDSS to its power-on state, to avoid the
partial configuration.

Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
---

Changes since v2:
- Move the reset before the probing of the children, to avoid issues if child
  drivers touched hardware at probe time.
- Extend reset assert time as the previous 1us showed reliability issues on
  Lenovo Flex 5G.

 drivers/gpu/drm/msm/disp/dpu1/dpu_mdss.c | 32 ++++++++++++++++++++++++
 1 file changed, 32 insertions(+)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_mdss.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_mdss.c
index b10ca505f9ac..6f921910d0e0 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_mdss.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_mdss.c
@@ -3,10 +3,12 @@
  * Copyright (c) 2018, The Linux Foundation
  */
 
+#include <linux/delay.h>
 #include <linux/irq.h>
 #include <linux/irqchip.h>
 #include <linux/irqdesc.h>
 #include <linux/irqchip/chained_irq.h>
+#include <linux/reset.h>
 #include "dpu_kms.h"
 
 #define to_dpu_mdss(x) container_of(x, struct dpu_mdss, base)
@@ -197,6 +199,32 @@ static void dpu_mdss_destroy(struct msm_mdss *mdss)
 	dpu_mdss->mmio = NULL;
 }
 
+static int dpu_mdss_reset(struct device *dev)
+{
+	struct reset_control *reset;
+
+	reset = reset_control_get_optional_exclusive(dev, NULL);
+	if (!reset) {
+		/* Optional reset not specified */
+		return 0;
+	} else if (IS_ERR(reset)) {
+		DPU_ERROR("failed to acquire mdss reset, ret=%ld", PTR_ERR(reset));
+		return PTR_ERR(reset);
+	}
+
+	reset_control_assert(reset);
+	/*
+	 * Tests indicate that reset has to be held for some period of time,
+	 * make it one frame in a typical system
+	 */
+	msleep(20);
+	reset_control_deassert(reset);
+
+	reset_control_put(reset);
+
+	return 0;
+}
+
 static const struct msm_mdss_funcs mdss_funcs = {
 	.enable	= dpu_mdss_enable,
 	.disable = dpu_mdss_disable,
@@ -210,6 +238,10 @@ int dpu_mdss_init(struct platform_device *pdev)
 	int ret;
 	int irq;
 
+	ret = dpu_mdss_reset(&pdev->dev);
+	if (ret)
+		return ret;
+
 	dpu_mdss = devm_kzalloc(&pdev->dev, sizeof(*dpu_mdss), GFP_KERNEL);
 	if (!dpu_mdss)
 		return -ENOMEM;
-- 
2.35.1


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

* [PATCH v2 2/2] drm/msm/dpu: Issue MDSS reset during initialization
@ 2022-04-08 21:02   ` Bjorn Andersson
  0 siblings, 0 replies; 14+ messages in thread
From: Bjorn Andersson @ 2022-04-08 21:02 UTC (permalink / raw)
  To: Rob Clark, Abhinav Kumar, Rob Herring, Krzysztof Kozlowski,
	Dmitry Baryshkov
  Cc: freedreno, devicetree, David Airlie, linux-arm-msm, linux-kernel,
	dri-devel, Sean Paul

It's typical for the bootloader to bring up the display for showing a
boot splash or efi framebuffer. But in some cases the kernel driver ends
up only partially configuring (in particular) the DPU, which might
result in e.g. that two different data paths attempts to push data to
the interface - with resulting graphical artifacts.

Naturally the end goal would be to inherit the bootloader's
configuration and provide the user with a glitch free handover from the
boot configuration to a running DPU.

But as implementing seamless transition from the bootloader
configuration to the running OS will be a considerable effort, start by
simply resetting the entire MDSS to its power-on state, to avoid the
partial configuration.

Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
---

Changes since v2:
- Move the reset before the probing of the children, to avoid issues if child
  drivers touched hardware at probe time.
- Extend reset assert time as the previous 1us showed reliability issues on
  Lenovo Flex 5G.

 drivers/gpu/drm/msm/disp/dpu1/dpu_mdss.c | 32 ++++++++++++++++++++++++
 1 file changed, 32 insertions(+)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_mdss.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_mdss.c
index b10ca505f9ac..6f921910d0e0 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_mdss.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_mdss.c
@@ -3,10 +3,12 @@
  * Copyright (c) 2018, The Linux Foundation
  */
 
+#include <linux/delay.h>
 #include <linux/irq.h>
 #include <linux/irqchip.h>
 #include <linux/irqdesc.h>
 #include <linux/irqchip/chained_irq.h>
+#include <linux/reset.h>
 #include "dpu_kms.h"
 
 #define to_dpu_mdss(x) container_of(x, struct dpu_mdss, base)
@@ -197,6 +199,32 @@ static void dpu_mdss_destroy(struct msm_mdss *mdss)
 	dpu_mdss->mmio = NULL;
 }
 
+static int dpu_mdss_reset(struct device *dev)
+{
+	struct reset_control *reset;
+
+	reset = reset_control_get_optional_exclusive(dev, NULL);
+	if (!reset) {
+		/* Optional reset not specified */
+		return 0;
+	} else if (IS_ERR(reset)) {
+		DPU_ERROR("failed to acquire mdss reset, ret=%ld", PTR_ERR(reset));
+		return PTR_ERR(reset);
+	}
+
+	reset_control_assert(reset);
+	/*
+	 * Tests indicate that reset has to be held for some period of time,
+	 * make it one frame in a typical system
+	 */
+	msleep(20);
+	reset_control_deassert(reset);
+
+	reset_control_put(reset);
+
+	return 0;
+}
+
 static const struct msm_mdss_funcs mdss_funcs = {
 	.enable	= dpu_mdss_enable,
 	.disable = dpu_mdss_disable,
@@ -210,6 +238,10 @@ int dpu_mdss_init(struct platform_device *pdev)
 	int ret;
 	int irq;
 
+	ret = dpu_mdss_reset(&pdev->dev);
+	if (ret)
+		return ret;
+
 	dpu_mdss = devm_kzalloc(&pdev->dev, sizeof(*dpu_mdss), GFP_KERNEL);
 	if (!dpu_mdss)
 		return -ENOMEM;
-- 
2.35.1


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

end of thread, other threads:[~2022-04-08 21:00 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-03-02  1:29 [PATCH v2 1/2] dt-bindings: display: msm: Add optional resets Bjorn Andersson
2022-03-02  1:29 ` Bjorn Andersson
2022-03-02  1:29 ` [PATCH v2 2/2] drm/msm/dpu: Issue MDSS reset during initialization Bjorn Andersson
2022-03-02  1:29   ` Bjorn Andersson
2022-03-02  1:47   ` Dmitry Baryshkov
2022-03-02  1:47     ` Dmitry Baryshkov
2022-03-02  2:44     ` Bjorn Andersson
2022-03-02  2:44       ` Bjorn Andersson
2022-03-02  4:42       ` Dmitry Baryshkov
2022-03-02  4:42         ` Dmitry Baryshkov
2022-03-02 18:02 ` [PATCH v2 1/2] dt-bindings: display: msm: Add optional resets Rob Herring
2022-03-02 18:02   ` Rob Herring
2022-04-08 21:02 Bjorn Andersson
2022-04-08 21:02 ` [PATCH v2 2/2] drm/msm/dpu: Issue MDSS reset during initialization Bjorn Andersson
2022-04-08 21:02   ` Bjorn Andersson

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.