[PATCH] regulator: core: Stub devm_regulator_bulk_get_const() if !CONFIG_REGULATOR

2024-08-30 Thread Douglas Anderson
When adding devm_regulator_bulk_get_const() I missed adding a stub for
when CONFIG_REGULATOR is not enabled. Under certain conditions (like
randconfig testing) this can cause the compiler to reports errors
like:

  error: implicit declaration of function 'devm_regulator_bulk_get_const';
  did you mean 'devm_regulator_bulk_get_enable'?

Add the stub.

Fixes: 1de452a0edda ("regulator: core: Allow drivers to define their init data 
as const")
Reported-by: kernel test robot 
Closes: 
https://lore.kernel.org/oe-kbuild-all/202408301813.tesfusbh-...@intel.com/
Cc: Neil Armstrong 
Signed-off-by: Douglas Anderson 
---

 include/linux/regulator/consumer.h | 8 
 1 file changed, 8 insertions(+)

diff --git a/include/linux/regulator/consumer.h 
b/include/linux/regulator/consumer.h
index d986ec13092e..b9ce521910a0 100644
--- a/include/linux/regulator/consumer.h
+++ b/include/linux/regulator/consumer.h
@@ -452,6 +452,14 @@ static inline int of_regulator_bulk_get_all(struct device 
*dev, struct device_no
return 0;
 }
 
+static inline int devm_regulator_bulk_get_const(
+   struct device *dev, int num_consumers,
+   const struct regulator_bulk_data *in_consumers,
+   struct regulator_bulk_data **out_consumers)
+{
+   return 0;
+}
+
 static inline int regulator_bulk_enable(int num_consumers,
struct regulator_bulk_data *consumers)
 {
-- 
2.46.0.469.g59c65b2a67-goog



[PATCH] dt-bindings: display: panel: samsung, atna45dc02: Fix indentation

2024-08-08 Thread Douglas Anderson
The yaml had indentation errors:
  
./Documentation/devicetree/bindings/display/panel/samsung,atna33xc20.yaml:21:9:
  [warning] wrong indentation: expected 10 but found 8 (indentation)
  
./Documentation/devicetree/bindings/display/panel/samsung,atna33xc20.yaml:23:11:
  [warning] wrong indentation: expected 12 but found 10 (indentation)

Fix them.

Reported-by: Rob Herring 
Closes: 
https://lore.kernel.org/r/cal_jsqlrtgqrpcfxy4g9hlohmd-uax4_c90bv_ozn4mk+-8...@mail.gmail.com
Fixes: 1c4a057d01f4 ("dt-bindings: display: panel: samsung,atna45dc02: Document 
ATNA45DC02")
Signed-off-by: Douglas Anderson 
---

 .../bindings/display/panel/samsung,atna33xc20.yaml   | 12 ++--
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git 
a/Documentation/devicetree/bindings/display/panel/samsung,atna33xc20.yaml 
b/Documentation/devicetree/bindings/display/panel/samsung,atna33xc20.yaml
index 87c601bcf20a..032f783eefc4 100644
--- a/Documentation/devicetree/bindings/display/panel/samsung,atna33xc20.yaml
+++ b/Documentation/devicetree/bindings/display/panel/samsung,atna33xc20.yaml
@@ -18,12 +18,12 @@ properties:
   # Samsung 13.3" FHD (1920x1080 pixels) eDP AMOLED panel
   - const: samsung,atna33xc20
   - items:
-- enum:
-  # Samsung 14.5" WQXGA+ (2880x1800 pixels) eDP AMOLED panel
-  - samsung,atna45af01
-  # Samsung 14.5" 3K (2944x1840 pixels) eDP AMOLED panel
-  - samsung,atna45dc02
-- const: samsung,atna33xc20
+  - enum:
+  # Samsung 14.5" WQXGA+ (2880x1800 pixels) eDP AMOLED panel
+  - samsung,atna45af01
+  # Samsung 14.5" 3K (2944x1840 pixels) eDP AMOLED panel
+  - samsung,atna45dc02
+  - const: samsung,atna33xc20
 
   enable-gpios: true
   port: true
-- 
2.46.0.76.ge559c4bf1a-goog



[PATCH] drm/panel: sharp-lq101r1sx01: Fixed reversed "if" in remove

2024-07-08 Thread Douglas Anderson
Commit d7d473d8464e ("drm/panel: sharp-lq101r1sx01: Don't call disable
at shutdown/remove") had a subtle bug. We should be calling
sharp_panel_del() when the "sharp" variable is non-NULL, not when it's
NULL. Fix.

Fixes: d7d473d8464e ("drm/panel: sharp-lq101r1sx01: Don't call disable at 
shutdown/remove")
Cc: Thierry Reding 
Reported-by: kernel test robot 
Reported-by: Dan Carpenter 
Closes: https://lore.kernel.org/r/202406261525.skhtm3zv-...@intel.com/
Signed-off-by: Douglas Anderson 
---

 drivers/gpu/drm/panel/panel-sharp-lq101r1sx01.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/panel/panel-sharp-lq101r1sx01.c 
b/drivers/gpu/drm/panel/panel-sharp-lq101r1sx01.c
index edc9425bb143..a0d76d588da1 100644
--- a/drivers/gpu/drm/panel/panel-sharp-lq101r1sx01.c
+++ b/drivers/gpu/drm/panel/panel-sharp-lq101r1sx01.c
@@ -362,7 +362,7 @@ static void sharp_panel_remove(struct mipi_dsi_device *dsi)
dev_err(&dsi->dev, "failed to detach from DSI host: %d\n", err);
 
/* only detach from host for the DSI-LINK2 interface */
-   if (!sharp)
+   if (sharp)
sharp_panel_del(sharp);
 }
 
-- 
2.45.2.803.g4e1b14247a-goog



[PATCH] drm/panel: Avoid warnings w/ panel-simple/panel-edp at shutdown

2024-06-21 Thread Douglas Anderson
At shutdown if you've got a _properly_ coded DRM modeset driver then
you'll get these two warnings at shutdown time:

  Skipping disable of already disabled panel
  Skipping unprepare of already unprepared panel

These warnings are ugly and sound concerning, but they're actually a
sign of a properly working system. That's not great.

We're not ready to get rid of the calls to drm_panel_disable() and
drm_panel_unprepare() because we're not 100% convinced that all DRM
modeset drivers are properly calling drm_atomic_helper_shutdown() or
drm_helper_force_disable_all() at the right times. However, having the
warning show up for correctly working systems is bad.

As a bit of a workaround, add some "if" tests to try to avoid the
warning on correctly working systems. Also add some comments and
update the TODO items in the hopes that future developers won't be too
confused by what's going on here.

Suggested-by: Daniel Vetter 
Signed-off-by: Douglas Anderson 
---
This patch came out of discussion on dri-devel on 2024-06-21
[1]. NOTE: I have put all changes into one patch since it didn't seem
to add anything to break up the updating of the TODO or the comments
in the core into separate patches since the patch is all about one
topic and all code is expected to land in the same tree.

Previous versions:
v0: 
https://lore.kernel.org/r/20240604172305.v3.24.Ieb287c2c3ee3f6d3b0d5f49b29f746b93621749c@changeid/
v1: 
https://lore.kernel.org/r/20240611074846.1.Ieb287c2c3ee3f6d3b0d5f49b29f746b93621749c@changeid

[1] 
https://people.freedesktop.org/~cbrill/dri-log/?channel=dri-devel&date=2024-06-21

 Documentation/gpu/todo.rst   | 35 +---
 drivers/gpu/drm/drm_panel.c  | 18 ++
 drivers/gpu/drm/panel/panel-edp.c| 26 ++---
 drivers/gpu/drm/panel/panel-simple.c | 26 ++---
 4 files changed, 68 insertions(+), 37 deletions(-)

diff --git a/Documentation/gpu/todo.rst b/Documentation/gpu/todo.rst
index 2ea6ffc9b22b..96c453980ab6 100644
--- a/Documentation/gpu/todo.rst
+++ b/Documentation/gpu/todo.rst
@@ -475,25 +475,22 @@ Remove disable/unprepare in remove/shutdown in 
panel-simple and panel-edp
 As of commit d2aacaf07395 ("drm/panel: Check for already prepared/enabled in
 drm_panel"), we have a check in the drm_panel core to make sure nobody
 double-calls prepare/enable/disable/unprepare. Eventually that should probably
-be turned into a WARN_ON() or somehow made louder, but right now we actually
-expect it to trigger and so we don't want it to be too loud.
-
-Specifically, that warning will trigger for panel-edp and panel-simple at
-shutdown time because those panels hardcode a call to drm_panel_disable()
-and drm_panel_unprepare() at shutdown and remove time that they call regardless
-of panel state. On systems with a properly coded DRM modeset driver that
-calls drm_atomic_helper_shutdown() this is pretty much guaranteed to cause
-the warning to fire.
-
-Unfortunately we can't safely remove the calls in panel-edp and panel-simple
-until we're sure that all DRM modeset drivers that are used with those panels
-properly call drm_atomic_helper_shutdown(). This TODO item is to validate
-that all DRM modeset drivers used with panel-edp and panel-simple properly
-call drm_atomic_helper_shutdown() and then remove the calls to
-disable/unprepare from those panels. Alternatively, this TODO item could be
-removed by convincing stakeholders that those calls are fine and downgrading
-the error message in drm_panel_disable() / drm_panel_unprepare() to a
-debug-level message.
+be turned into a WARN_ON() or somehow made louder.
+
+At the moment, we expect that we may still encounter the warnings in the
+drm_panel core when using panel-simple and panel-edp. Since those panel
+drivers are used with a lot of different DRM modeset drivers they still
+make an extra effort to disable/unprepare the panel themsevles at shutdown
+time. Specifically we could still encounter those warnings if the panel
+driver gets shutdown() _before_ the DRM modeset driver and the DRM modeset
+driver properly calls drm_atomic_helper_shutdown() in its own shutdown()
+callback. Warnings could be avoided in such a case by using something like
+device links to ensure that the panel gets shutdown() after the DRM modeset
+driver.
+
+Once all DRM modeset drivers are known to shutdown properly, the extra
+calls to disable/unprepare in remove/shutdown in panel-simple and panel-edp
+should be removed and this TODO item marked complete.
 
 Contact: Douglas Anderson 
 
diff --git a/drivers/gpu/drm/drm_panel.c b/drivers/gpu/drm/drm_panel.c
index cfbe020de54e..19ab0a794add 100644
--- a/drivers/gpu/drm/drm_panel.c
+++ b/drivers/gpu/drm/drm_panel.c
@@ -161,6 +161,15 @@ int drm_panel_unprepare(struct drm_panel *panel)
if (!panel)
return -EINVAL;
 
+   /*
+* If you are seeing 

Re: [PATCH v3] drm/panel: truly-nt35521: transition to mipi_dsi wrapped functions

2024-06-20 Thread Douglas Anderson


On Wed, 12 Jun 2024 22:09:42 +0530, Tejas Vipin wrote:
> Use functions introduced in commit 966e397e4f60 ("drm/mipi-dsi: Introduce
> mipi_dsi_*_write_seq_multi()") and commit f79d6d28d8fe
> ("drm/mipi-dsi: wrap more functions for streamline handling") for the
> sony tulip truly nt35521 panel.
> 
> 

Applied, thanks!

[1/1] drm/panel: truly-nt35521: transition to mipi_dsi wrapped functions
  commit: c62b4fc4b9b86ab35e5c4236f2053ce21ee81ebc

Best regards,
-- 
Douglas Anderson 



[PATCH v2 8/8] drm/amdgpu: Call drm_atomic_helper_shutdown() at shutdown time

2024-06-12 Thread Douglas Anderson
Based on grepping through the source code this driver appears to be
missing a call to drm_atomic_helper_shutdown() at system shutdown
time. Among other things, this means that if a panel is in use that it
won't be cleanly powered off at system shutdown time.

The fact that we should call drm_atomic_helper_shutdown() in the case
of OS shutdown/restart comes straight out of the kernel doc "driver
instance overview" in drm_drv.c.

Suggested-by: Maxime Ripard 
Cc: Alex Deucher 
Cc: Christian König 
Cc: Xinhui Pan 
Signed-off-by: Douglas Anderson 
---
This commit is only compile-time tested.

...and further, I'd say that this patch is more of a plea for help
than a patch I think is actually right. I'm _fairly_ certain that
drm/amdgpu needs this call at shutdown time but the logic is a bit
hard for me to follow. I'd appreciate if anyone who actually knows
what this should look like could illuminate me, or perhaps even just
post a patch themselves!

(no changes since v1)

 drivers/gpu/drm/amd/amdgpu/amdgpu.h|  1 +
 drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 10 ++
 drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c|  2 ++
 3 files changed, 13 insertions(+)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h 
b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
index f87d53e183c3..c202a1d5ff5f 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
@@ -1197,6 +1197,7 @@ static inline struct amdgpu_device 
*amdgpu_ttm_adev(struct ttm_device *bdev)
 int amdgpu_device_init(struct amdgpu_device *adev,
   uint32_t flags);
 void amdgpu_device_fini_hw(struct amdgpu_device *adev);
+void amdgpu_device_shutdown_hw(struct amdgpu_device *adev);
 void amdgpu_device_fini_sw(struct amdgpu_device *adev);
 
 int amdgpu_gpu_wait_for_idle(struct amdgpu_device *adev);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
index 861ccff78af9..a8c4b8412e04 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
@@ -4531,6 +4531,16 @@ void amdgpu_device_fini_hw(struct amdgpu_device *adev)
 
 }
 
+void amdgpu_device_shutdown_hw(struct amdgpu_device *adev)
+{
+   if (adev->mode_info.mode_config_initialized) {
+   if (!drm_drv_uses_atomic_modeset(adev_to_drm(adev)))
+   drm_helper_force_disable_all(adev_to_drm(adev));
+   else
+   drm_atomic_helper_shutdown(adev_to_drm(adev));
+   }
+}
+
 void amdgpu_device_fini_sw(struct amdgpu_device *adev)
 {
int idx;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
index ea14f1c8f430..b34bf9259d5c 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
@@ -2409,6 +2409,8 @@ amdgpu_pci_shutdown(struct pci_dev *pdev)
struct drm_device *dev = pci_get_drvdata(pdev);
struct amdgpu_device *adev = drm_to_adev(dev);
 
+   amdgpu_device_shutdown_hw(adev);
+
if (amdgpu_ras_intr_triggered())
return;
 
-- 
2.45.2.505.gda0bf45e8d-goog



[PATCH v2 7/8] drm/radeon: Call drm_helper_force_disable_all() at shutdown/remove time

2024-06-12 Thread Douglas Anderson
Based on grepping through the source code, this driver appears to be
missing a call to drm_atomic_helper_shutdown(), or in this case the
non-atomic equivalent drm_helper_force_disable_all(), at system
shutdown time and at driver remove time. This is important because
drm_helper_force_disable_all() will cause panels to get disabled
cleanly which may be important for their power sequencing. Future
changes will remove any custom powering off in individual panel
drivers so the DRM drivers need to start getting this right.

The fact that we should call drm_atomic_helper_shutdown(), or in this
case the non-atomic equivalent drm_helper_force_disable_all(), in the
case of OS shutdown/restart comes straight out of the kernel doc
"driver instance overview" in drm_drv.c.

NOTE: in order to get things inserted in the right place, I had to
replace the old/deprecated drm_put_dev() function with the equivalent
new calls.

Suggested-by: Maxime Ripard 
Reviewed-by: Maxime Ripard 
Cc: Alex Deucher 
Cc: Christian König 
Cc: Xinhui Pan 
Signed-off-by: Douglas Anderson 
---
I honestly have no idea if I got this patch right. The shutdown()
function already had some special case logic for PPC, Loongson, and
VMs and I don't 100% for sure know how this interacts with
those. Everything here is just compile tested.

(no changes since v1)

 drivers/gpu/drm/radeon/radeon_drv.c | 7 ++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/radeon/radeon_drv.c 
b/drivers/gpu/drm/radeon/radeon_drv.c
index 7bf08164140e..9ea7f163a731 100644
--- a/drivers/gpu/drm/radeon/radeon_drv.c
+++ b/drivers/gpu/drm/radeon/radeon_drv.c
@@ -38,6 +38,7 @@
 #include 
 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -330,7 +331,9 @@ radeon_pci_remove(struct pci_dev *pdev)
 {
struct drm_device *dev = pci_get_drvdata(pdev);
 
-   drm_put_dev(dev);
+   drm_dev_unregister(dev);
+   drm_helper_force_disable_all(dev);
+   drm_dev_put(dev);
 }
 
 static void
@@ -341,6 +344,8 @@ radeon_pci_shutdown(struct pci_dev *pdev)
 */
if (radeon_device_is_virtual())
radeon_pci_remove(pdev);
+   else
+   drm_helper_force_disable_all(pci_get_drvdata(pdev));
 
 #if defined(CONFIG_PPC64) || defined(CONFIG_MACH_LOONGSON64)
/*
-- 
2.45.2.505.gda0bf45e8d-goog



[PATCH v2 6/8] drm/gma500: Call drm_helper_force_disable_all() at shutdown/remove time

2024-06-12 Thread Douglas Anderson
Based on grepping through the source code, this driver appears to be
missing a call to drm_atomic_helper_shutdown(), or in this case the
non-atomic equivalent drm_helper_force_disable_all(), at system
shutdown time and at driver remove time. This is important because
drm_helper_force_disable_all() will cause panels to get disabled
cleanly which may be important for their power sequencing. Future
changes will remove any custom powering off in individual panel
drivers so the DRM drivers need to start getting this right.

The fact that we should call drm_atomic_helper_shutdown(), or in this
case the non-atomic equivalent drm_helper_force_disable_all(), in the
case of OS shutdown/restart comes straight out of the kernel doc
"driver instance overview" in drm_drv.c.

Suggested-by: Maxime Ripard 
Reviewed-by: Maxime Ripard 
Signed-off-by: Douglas Anderson 
---
This commit is only compile-time tested.

(no changes since v1)

 drivers/gpu/drm/gma500/psb_drv.c | 8 
 1 file changed, 8 insertions(+)

diff --git a/drivers/gpu/drm/gma500/psb_drv.c b/drivers/gpu/drm/gma500/psb_drv.c
index 8b64f61ffaf9..a5a399bbe8f5 100644
--- a/drivers/gpu/drm/gma500/psb_drv.c
+++ b/drivers/gpu/drm/gma500/psb_drv.c
@@ -20,6 +20,7 @@
 #include 
 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -485,6 +486,12 @@ static void psb_pci_remove(struct pci_dev *pdev)
struct drm_device *dev = pci_get_drvdata(pdev);
 
drm_dev_unregister(dev);
+   drm_helper_force_disable_all(dev);
+}
+
+static void psb_pci_shutdown(struct pci_dev *pdev)
+{
+   drm_helper_force_disable_all(pci_get_drvdata(pdev));
 }
 
 static DEFINE_RUNTIME_DEV_PM_OPS(psb_pm_ops, gma_power_suspend, 
gma_power_resume, NULL);
@@ -521,6 +528,7 @@ static struct pci_driver psb_pci_driver = {
.id_table = pciidlist,
.probe = psb_pci_probe,
.remove = psb_pci_remove,
+   .shutdown = psb_pci_shutdown,
.driver.pm = &psb_pm_ops,
 };
 
-- 
2.45.2.505.gda0bf45e8d-goog



[PATCH v2 3/8] drm/tegra: Call drm_atomic_helper_shutdown() at shutdown time

2024-06-12 Thread Douglas Anderson
Based on grepping through the source code this driver appears to be
missing a call to drm_atomic_helper_shutdown() at system shutdown
time. Among other things, this means that if a panel is in use that it
won't be cleanly powered off at system shutdown time.

The fact that we should call drm_atomic_helper_shutdown() in the case
of OS shutdown/restart comes straight out of the kernel doc "driver
instance overview" in drm_drv.c.

Suggested-by: Maxime Ripard 
Reviewed-by: Maxime Ripard 
Signed-off-by: Douglas Anderson 
---
This commit is only compile-time tested.

(no changes since v1)

 drivers/gpu/drm/tegra/drm.c | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/drivers/gpu/drm/tegra/drm.c b/drivers/gpu/drm/tegra/drm.c
index 03d1c76aec2d..d9f0728c3afd 100644
--- a/drivers/gpu/drm/tegra/drm.c
+++ b/drivers/gpu/drm/tegra/drm.c
@@ -1330,6 +1330,11 @@ static int host1x_drm_remove(struct host1x_device *dev)
return 0;
 }
 
+static void host1x_drm_shutdown(struct host1x_device *dev)
+{
+   drm_atomic_helper_shutdown(dev_get_drvdata(&dev->dev));
+}
+
 #ifdef CONFIG_PM_SLEEP
 static int host1x_drm_suspend(struct device *dev)
 {
@@ -1398,6 +1403,7 @@ static struct host1x_driver host1x_drm_driver = {
},
.probe = host1x_drm_probe,
.remove = host1x_drm_remove,
+   .shutdown = host1x_drm_shutdown,
.subdevs = host1x_drm_subdevs,
 };
 
-- 
2.45.2.505.gda0bf45e8d-goog



[PATCH v2 4/8] drm/arcpgu: Call drm_atomic_helper_shutdown() at shutdown time

2024-06-12 Thread Douglas Anderson
Based on grepping through the source code this driver appears to be
missing a call to drm_atomic_helper_shutdown() at system shutdown
time. Among other things, this means that if a panel is in use that it
won't be cleanly powered off at system shutdown time.

The fact that we should call drm_atomic_helper_shutdown() in the case
of OS shutdown/restart comes straight out of the kernel doc "driver
instance overview" in drm_drv.c.

Suggested-by: Maxime Ripard 
Reviewed-by: Maxime Ripard 
Signed-off-by: Douglas Anderson 
---
This commit is only compile-time tested.

(no changes since v1)

 drivers/gpu/drm/tiny/arcpgu.c | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/drivers/gpu/drm/tiny/arcpgu.c b/drivers/gpu/drm/tiny/arcpgu.c
index 4f8f3172379e..85b21f5aac55 100644
--- a/drivers/gpu/drm/tiny/arcpgu.c
+++ b/drivers/gpu/drm/tiny/arcpgu.c
@@ -412,6 +412,11 @@ static void arcpgu_remove(struct platform_device *pdev)
arcpgu_unload(drm);
 }
 
+static void arcpgu_shutdown(struct platform_device *pdev)
+{
+   drm_atomic_helper_shutdown(platform_get_drvdata(pdev));
+}
+
 static const struct of_device_id arcpgu_of_table[] = {
{.compatible = "snps,arcpgu"},
{}
@@ -422,6 +427,7 @@ MODULE_DEVICE_TABLE(of, arcpgu_of_table);
 static struct platform_driver arcpgu_platform_driver = {
.probe = arcpgu_probe,
.remove_new = arcpgu_remove,
+   .shutdown = arcpgu_shutdown,
.driver = {
   .name = "arcpgu",
   .of_match_table = arcpgu_of_table,
-- 
2.45.2.505.gda0bf45e8d-goog



[PATCH v2 5/8] drm/sprd: Call drm_atomic_helper_shutdown() at remove time

2024-06-12 Thread Douglas Anderson
Based on grepping through the source code, this driver appears to be
missing a call to drm_atomic_helper_shutdown() at remove time. Let's
add it.

The fact that we should call drm_atomic_helper_shutdown() in the case
of OS driver remove comes straight out of the kernel doc "driver
instance overview" in drm_drv.c.

While at it, let's also fix it so that if the driver's bind fails or
if a driver gets unbound that the drvdata gets set to NULL. This will
make sure we can't get confused during a later shutdown().

Suggested-by: Maxime Ripard 
Reviewed-by: Maxime Ripard 
Signed-off-by: Douglas Anderson 
---
This commit is only compile-time tested.

While making this patch, I noticed that the bind() function of this
driver is using "devm". That's probably a bug. As per kernel docs [1]
"the lifetime of the aggregate driver does not align with any of the
underlying struct device instances. Therefore devm cannot be used and
all resources acquired or allocated in this callback must be
explicitly released in the unbind callback". Fixing that is outside
the scope of this commit.

[1] https://docs.kernel.org/driver-api/component.html

(no changes since v1)

 drivers/gpu/drm/sprd/sprd_drm.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/sprd/sprd_drm.c b/drivers/gpu/drm/sprd/sprd_drm.c
index a74cd0caf645..d4453430dd1f 100644
--- a/drivers/gpu/drm/sprd/sprd_drm.c
+++ b/drivers/gpu/drm/sprd/sprd_drm.c
@@ -114,6 +114,7 @@ static int sprd_drm_bind(struct device *dev)
drm_kms_helper_poll_fini(drm);
 err_unbind_all:
component_unbind_all(drm->dev, drm);
+   platform_set_drvdata(pdev, NULL);
return ret;
 }
 
@@ -122,10 +123,11 @@ static void sprd_drm_unbind(struct device *dev)
struct drm_device *drm = dev_get_drvdata(dev);
 
drm_dev_unregister(drm);
-
drm_kms_helper_poll_fini(drm);
+   drm_atomic_helper_shutdown(drm);
 
component_unbind_all(drm->dev, drm);
+   dev_set_drvdata(dev, NULL);
 }
 
 static const struct component_master_ops drm_component_ops = {
-- 
2.45.2.505.gda0bf45e8d-goog



[PATCH v2 2/8] drm/nouveau: Call drm_atomic_helper_shutdown() or equiv at shutdown time

2024-06-12 Thread Douglas Anderson
Based on grepping through the source code this driver appears to be
missing a call to drm_atomic_helper_shutdown() (or
drm_helper_force_disable_all() if not using atomic) at system shutdown
time. Among other things, this means that if a panel is in use that it
won't be cleanly powered off at system shutdown time.

The fact that we should call drm_atomic_helper_shutdown() in the case
of OS shutdown/restart comes straight out of the kernel doc "driver
instance overview" in drm_drv.c.

Suggested-by: Maxime Ripard 
Reviewed-by: Maxime Ripard 
Signed-off-by: Douglas Anderson 
---
This commit is only compile-time tested. I made my best guess about
how to fit this into the existing code. If someone wishes a different
style, please yell.

(no changes since v1)

 drivers/gpu/drm/nouveau/nouveau_display.c  |  9 +
 drivers/gpu/drm/nouveau/nouveau_display.h  |  1 +
 drivers/gpu/drm/nouveau/nouveau_drm.c  | 13 +
 drivers/gpu/drm/nouveau/nouveau_drv.h  |  1 +
 drivers/gpu/drm/nouveau/nouveau_platform.c |  6 ++
 5 files changed, 30 insertions(+)

diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c 
b/drivers/gpu/drm/nouveau/nouveau_display.c
index d4725a968827..15da55c382f1 100644
--- a/drivers/gpu/drm/nouveau/nouveau_display.c
+++ b/drivers/gpu/drm/nouveau/nouveau_display.c
@@ -645,6 +645,15 @@ nouveau_display_fini(struct drm_device *dev, bool suspend, 
bool runtime)
disp->fini(dev, runtime, suspend);
 }
 
+void
+nouveau_display_shutdown(struct drm_device *dev)
+{
+   if (drm_drv_uses_atomic_modeset(dev))
+   drm_atomic_helper_shutdown(dev);
+   else
+   drm_helper_force_disable_all(dev);
+}
+
 static void
 nouveau_display_create_properties(struct drm_device *dev)
 {
diff --git a/drivers/gpu/drm/nouveau/nouveau_display.h 
b/drivers/gpu/drm/nouveau/nouveau_display.h
index 2ab2ddb1eadf..9df62e833cda 100644
--- a/drivers/gpu/drm/nouveau/nouveau_display.h
+++ b/drivers/gpu/drm/nouveau/nouveau_display.h
@@ -47,6 +47,7 @@ void nouveau_display_destroy(struct drm_device *dev);
 int  nouveau_display_init(struct drm_device *dev, bool resume, bool runtime);
 void nouveau_display_hpd_resume(struct drm_device *dev);
 void nouveau_display_fini(struct drm_device *dev, bool suspend, bool runtime);
+void nouveau_display_shutdown(struct drm_device *dev);
 int  nouveau_display_suspend(struct drm_device *dev, bool runtime);
 void nouveau_display_resume(struct drm_device *dev, bool runtime);
 int  nouveau_display_vblank_enable(struct drm_crtc *crtc);
diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.c 
b/drivers/gpu/drm/nouveau/nouveau_drm.c
index a947e1d5f309..b41154c9b9cc 100644
--- a/drivers/gpu/drm/nouveau/nouveau_drm.c
+++ b/drivers/gpu/drm/nouveau/nouveau_drm.c
@@ -894,6 +894,18 @@ nouveau_drm_remove(struct pci_dev *pdev)
pci_disable_device(pdev);
 }
 
+void
+nouveau_drm_device_shutdown(struct drm_device *dev)
+{
+   nouveau_display_shutdown(dev);
+}
+
+static void
+nouveau_drm_shutdown(struct pci_dev *pdev)
+{
+   nouveau_drm_device_shutdown(pci_get_drvdata(pdev));
+}
+
 static int
 nouveau_do_suspend(struct drm_device *dev, bool runtime)
 {
@@ -1361,6 +1373,7 @@ nouveau_drm_pci_driver = {
.id_table = nouveau_drm_pci_table,
.probe = nouveau_drm_probe,
.remove = nouveau_drm_remove,
+   .shutdown = nouveau_drm_shutdown,
.driver.pm = &nouveau_pm_ops,
 };
 
diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h 
b/drivers/gpu/drm/nouveau/nouveau_drv.h
index 25fca98a20bc..78a91686006b 100644
--- a/drivers/gpu/drm/nouveau/nouveau_drv.h
+++ b/drivers/gpu/drm/nouveau/nouveau_drv.h
@@ -327,6 +327,7 @@ struct drm_device *
 nouveau_platform_device_create(const struct nvkm_device_tegra_func *,
   struct platform_device *, struct nvkm_device **);
 void nouveau_drm_device_remove(struct drm_device *dev);
+void nouveau_drm_device_shutdown(struct drm_device *dev);
 
 #define NV_PRINTK(l,c,f,a...) do { 
\
struct nouveau_cli *_cli = (c);\
diff --git a/drivers/gpu/drm/nouveau/nouveau_platform.c 
b/drivers/gpu/drm/nouveau/nouveau_platform.c
index bf2dc7567ea4..511f3a0c6ee9 100644
--- a/drivers/gpu/drm/nouveau/nouveau_platform.c
+++ b/drivers/gpu/drm/nouveau/nouveau_platform.c
@@ -49,6 +49,11 @@ static void nouveau_platform_remove(struct platform_device 
*pdev)
nouveau_drm_device_remove(dev);
 }
 
+static void nouveau_platform_shutdown(struct platform_device *pdev)
+{
+   nouveau_drm_device_shutdown(platform_get_drvdata(pdev));
+}
+
 #if IS_ENABLED(CONFIG_OF)
 static const struct nvkm_device_tegra_func gk20a_platform_data = {
.iommu_bit = 34,
@@ -93,4 +98,5 @@ struct platform_driver nouveau_platform_driver = {
},
.probe = nouveau_platform_probe,
.remove_new = nouveau_platform_remove,
+   .shutdown = nouveau_platform_shutdown,
 };
-- 
2.45.2.505.gda0bf45e8d-goog



[PATCH v2 1/8] drm/kmb: Call drm_atomic_helper_shutdown() at shutdown time

2024-06-12 Thread Douglas Anderson
Based on grepping through the source code this driver appears to be
missing a call to drm_atomic_helper_shutdown() at system shutdown
time. Among other things, this means that if a panel is in use that it
won't be cleanly powered off at system shutdown time.

The fact that we should call drm_atomic_helper_shutdown() in the case
of OS shutdown/restart comes straight out of the kernel doc "driver
instance overview" in drm_drv.c.

Suggested-by: Maxime Ripard 
Reviewed-by: Maxime Ripard 
Signed-off-by: Douglas Anderson 
---
This commit is only compile-time tested.

(no changes since v1)

 drivers/gpu/drm/kmb/kmb_drv.c | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/drivers/gpu/drm/kmb/kmb_drv.c b/drivers/gpu/drm/kmb/kmb_drv.c
index 169b83987ce2..73d82b4d33e7 100644
--- a/drivers/gpu/drm/kmb/kmb_drv.c
+++ b/drivers/gpu/drm/kmb/kmb_drv.c
@@ -475,6 +475,11 @@ static void kmb_remove(struct platform_device *pdev)
drm_atomic_helper_shutdown(drm);
 }
 
+static void kmb_shutdown(struct platform_device *pdev)
+{
+   drm_atomic_helper_shutdown(platform_get_drvdata(pdev));
+}
+
 static int kmb_probe(struct platform_device *pdev)
 {
struct device *dev = get_device(&pdev->dev);
@@ -621,6 +626,7 @@ static SIMPLE_DEV_PM_OPS(kmb_pm_ops, kmb_pm_suspend, 
kmb_pm_resume);
 static struct platform_driver kmb_platform_driver = {
.probe = kmb_probe,
.remove_new = kmb_remove,
+   .shutdown = kmb_shutdown,
.driver = {
.name = "kmb-drm",
.pm = &kmb_pm_ops,
-- 
2.45.2.505.gda0bf45e8d-goog



[PATCH v2 0/8] drm: make leftover drivers call drm_atomic_helper_shutdown() at the right times

2024-06-12 Thread Douglas Anderson


This patch series is the leftovers of a patch series sent in September
2023 [1] in an attempt to get some of the patches landed finally.

This patch series originally came about after a _long_ discussion
between me and Maxime Ripard in response to a different patch I sent
out [2]. As part of that discussion, we realized that it would be good
if DRM drivers consistently called drm_atomic_helper_shutdown()
properly at shutdown and driver remove time as it's documented that
they should do. The eventual goal of this would be to enable removing
some hacky code from panel drivers where they had to hook into
shutdown themselves because the DRM driver wasn't calling them.

It turns out that quite a lot of drivers seemed to be missing
drm_atomic_helper_shutdown() in one or both places that it was
supposed to be. This patch series attempts to fix all the drivers that
I was able to identify.

NOTE: fixing this wasn't exactly cookie cutter. Each driver has its
own unique way of setting itself up and tearing itself down. Some
drivers also use the component model, which adds extra fun. I've made
my best guess at solving this and I've run a bunch of compile tests
(specifically, allmodconfig for amd64, arm64, and powerpc). That being
said, these code changes are not totally trivial and I've done zero
real testing on them. Making these patches was also a little mind
numbing and I'm certain my eyes glazed over at several points when
writing them. What I'm trying to say is to please double-check that I
didn't do anything too silly, like cast your driver's drvdata to the
wrong type. Even better, test these patches!

Apparently most of these drivers now land through drm-misc [3], so
hopefully they can land. The two that don't (amdgpu and radeon) are
the ones I'm most ucertain about anyway so I've stuck them at the end.
If I've totally buggered those up feel free to take my patch as a bug
report and submit your own proper fix. ...or if there's some reason
that we don't need to do anything for those drivers then let me know
and we can drop them.

I'd like to call out a few drivers that I _didn't_ fix in this series
and why. If any of these drivers should be fixed then please yell.
- DRM drivers backed by usb_driver (like gud, gm12u320, udl): I didn't
  add the call to drm_atomic_helper_shutdown() at shutdown time
  because there's no ".shutdown" callback for them USB drivers. Given
  that USB is hotpluggable, I'm assuming that they are robust against
  this and the special shutdown callback isn't needed.
- ofdrm and simpledrm: These didn't have drm_atomic_helper_shutdown()
  in either shutdown or remove, but I didn't add it. I think that's OK
  since they're sorta special and not really directly controlling
  hardware power sequencing.
- virtio, vkms, vmwgfx, xen: I believe these are all virtual (thus
  they wouldn't directly drive a panel) and adding the shutdown
  didn't look straightforward, so I skipped them.

I've let each patch in the series get CCed straight from
get_maintainer. That means not everyone will have received every patch
but everyone should be on the cover letter. I know some people dislike
this but when touching this many drivers there's not much
choice. dri-devel and lkml have been CCed and lore/lei exist, so
hopefully that's enough for folks. I'm happy to add people to the
whole series for future posts.

[1] https://lore.kernel.org/r/20230901234202.566951-1-diand...@chromium.org
[2] 
https://lore.kernel.org/r/20230804140605.RFC.4.I930069a32baab6faf46d6b234f89613b5cec0f14@changeid
[3] https://lore.kernel.org/r/Zmm6_27GikpmT3HQ@phenom.ffwll.local

Changes in v2:
- Gathered whatever hadn't landed, rebased, and reposted.

Douglas Anderson (8):
  drm/kmb: Call drm_atomic_helper_shutdown() at shutdown time
  drm/nouveau: Call drm_atomic_helper_shutdown() or equiv at shutdown
time
  drm/tegra: Call drm_atomic_helper_shutdown() at shutdown time
  drm/arcpgu: Call drm_atomic_helper_shutdown() at shutdown time
  drm/sprd: Call drm_atomic_helper_shutdown() at remove time
  drm/gma500: Call drm_helper_force_disable_all() at shutdown/remove
time
  drm/radeon: Call drm_helper_force_disable_all() at shutdown/remove
time
  drm/amdgpu: Call drm_atomic_helper_shutdown() at shutdown time

 drivers/gpu/drm/amd/amdgpu/amdgpu.h|  1 +
 drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 10 ++
 drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c|  2 ++
 drivers/gpu/drm/gma500/psb_drv.c   |  8 
 drivers/gpu/drm/kmb/kmb_drv.c  |  6 ++
 drivers/gpu/drm/nouveau/nouveau_display.c  |  9 +
 drivers/gpu/drm/nouveau/nouveau_display.h  |  1 +
 drivers/gpu/drm/nouveau/nouveau_drm.c  | 13 +
 drivers/gpu/drm/nouveau/nouveau_drv.h  |  1 +
 drivers/gpu/drm/nouveau/nouveau_platform.c |  6 ++
 dri

[PATCH v2] drm/mediatek: Call drm_atomic_helper_shutdown() at shutdown time

2024-06-11 Thread Douglas Anderson
Based on grepping through the source code this driver appears to be
missing a call to drm_atomic_helper_shutdown() at system shutdown
time. Among other things, this means that if a panel is in use that it
won't be cleanly powered off at system shutdown time.

The fact that we should call drm_atomic_helper_shutdown() in the case
of OS shutdown/restart comes straight out of the kernel doc "driver
instance overview" in drm_drv.c.

This driver users the component model and shutdown happens in the base
driver. The "drvdata" for this driver will always be valid if
shutdown() is called and as of commit 2a073968289d
("drm/atomic-helper: drm_atomic_helper_shutdown(NULL) should be a
noop") we don't need to confirm that "drm" is non-NULL.

Suggested-by: Maxime Ripard 
Reviewed-by: Maxime Ripard 
Reviewed-by: Fei Shao 
Tested-by: Fei Shao 
Signed-off-by: Douglas Anderson 
---
v1 of this patch was part of a series [1]. It got tested and reviewed
but never landed. Reposting separately in the hopes that Mediatek DRM
folks will land it. If, instead, Mediatek DRM folks want to Ack it I'm
happy to land through drm-misc.

I noticed that this was missing when I failed to add "mediatek" to my
patch series IDing which DRM modeset drivers did this properly [2].
Assuming my patch lands, that means that Mediatek devices will start
getting more warnings printed.

[1] 
https://lore.kernel.org/r/20230901164111.RFT.5.I2b014f90afc4729b6ecc7b5ddd1f6dedcea4625b@changeid
[2] 
https://lore.kernel.org/r/20240611074846.1.Ieb287c2c3ee3f6d3b0d5f49b29f746b93621749c@changeid

Changes in v2:
- Removed NULL check since it's not needed since 6.7
- Rebased on ToT.

 drivers/gpu/drm/mediatek/mtk_drm_drv.c | 8 
 1 file changed, 8 insertions(+)

diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.c 
b/drivers/gpu/drm/mediatek/mtk_drm_drv.c
index b5f605751b0a..de811e2265da 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_drv.c
+++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.c
@@ -952,6 +952,13 @@ static void mtk_drm_remove(struct platform_device *pdev)
of_node_put(private->comp_node[i]);
 }
 
+static void mtk_drm_shutdown(struct platform_device *pdev)
+{
+   struct mtk_drm_private *private = platform_get_drvdata(pdev);
+
+   drm_atomic_helper_shutdown(private->drm);
+}
+
 static int mtk_drm_sys_prepare(struct device *dev)
 {
struct mtk_drm_private *private = dev_get_drvdata(dev);
@@ -983,6 +990,7 @@ static const struct dev_pm_ops mtk_drm_pm_ops = {
 static struct platform_driver mtk_drm_platform_driver = {
.probe  = mtk_drm_probe,
.remove_new = mtk_drm_remove,
+   .shutdown = mtk_drm_shutdown,
.driver = {
.name   = "mediatek-drm",
.pm = &mtk_drm_pm_ops,
-- 
2.45.2.505.gda0bf45e8d-goog



[PATCH] drm/panel: Avoid warnings w/ panel-simple/panel-edp at shutdown

2024-06-11 Thread Douglas Anderson
At shutdown if you've got a _properly_ coded DRM modeset driver then
you'll get these two warnings at shutdown time:

  Skipping disable of already disabled panel
  Skipping unprepare of already unprepared panel

These warnings are ugly and sound concerning, but they're actually a
sign of a properly working system. That's not great.

It's not easy to get rid of these warnings. Until we know that all DRM
modeset drivers used with panel-simple and panel-edp are properly
calling drm_atomic_helper_shutdown() or drm_helper_force_disable_all()
then the panel drivers _need_ to disable/unprepare themselves in order
to power off the panel cleanly. However, there are lots of DRM modeset
drivers used with panel-edp and panel-simple and it's hard to know
when we've got them all. Since the warning happens only on the drivers
that _are_ updated there's nothing to encourage broken DRM modeset
drivers to get fixed.

In order to flip the warning to the proper place, we need to know
which modeset drivers are going to shutdown properly. Though ugly, do
this by creating a list of everyone that shuts down properly. This
allows us to generate a warning for the correct case and also lets us
get rid of the warning for drivers that are shutting down properly.

Maintaining this list is ugly, but the idea is that it's only short
term. Once everyone is converted we can delete the list and call it
done. The list is ugly enough and adding to it is annoying enough that
people should push to make this happen.

Implement this all in a shared "header" file included by the two panel
drivers that need it. This avoids us adding an new exports while still
allowing the panel drivers to be modules. The code waste should be
small and, as per above, the whole solution is temporary.

Signed-off-by: Douglas Anderson 
---
I came up with this idea to help us move forward since otherwise I
couldn't see how we were ever going to fix panel-simple and panel-edp
since they're used by so many DRM Modeset drivers. It's a bit ugly but
I don't hate it. What do others think?

This is at the end of the series so even if folks hate it we could
still land the rest of the series.
This was a "bonus" extra patch I added at the end of v3 of the series
("drm/panel: Remove most store/double-check of prepared/enabled
state") [1]. There, I had the note: "I came up with this idea to help
us move forward since otherwise I couldn't see how we were ever going
to fix panel-simple and panel-edp since they're used by so many DRM
Modeset drivers. It's a bit ugly but I don't hate it. What do others
think?"

As requested by Neil, now that the rest of the series has landed I'm
sending this as a standalone patch so it can get more attention. I'm
starting it back at "v1". There is no change between v1 and the one
sent previously except for a typo fix in an error message: Can't't =>
Can't

[1] https://lore.kernel.org/r/20240605002401.2848541-1-diand...@chromium.org

 drivers/gpu/drm/drm_panel.c   |  12 ++
 .../gpu/drm/panel/panel-drm-shutdown-check.h  | 151 ++
 drivers/gpu/drm/panel/panel-edp.c |  19 +--
 drivers/gpu/drm/panel/panel-simple.c  |  19 +--
 4 files changed, 169 insertions(+), 32 deletions(-)
 create mode 100644 drivers/gpu/drm/panel/panel-drm-shutdown-check.h

diff --git a/drivers/gpu/drm/drm_panel.c b/drivers/gpu/drm/drm_panel.c
index cfbe020de54e..df3f15f4625e 100644
--- a/drivers/gpu/drm/drm_panel.c
+++ b/drivers/gpu/drm/drm_panel.c
@@ -161,6 +161,12 @@ int drm_panel_unprepare(struct drm_panel *panel)
if (!panel)
return -EINVAL;
 
+   /*
+* If you're seeing this warning, you either need to add your driver
+* to "drm_drivers_that_shutdown" (if you're seeing it with panel-edp
+* or panel-simple) or you need to remove the manual call to
+* drm_panel_unprepare() in your panel driver.
+*/
if (!panel->prepared) {
dev_warn(panel->dev, "Skipping unprepare of already unprepared 
panel\n");
return 0;
@@ -245,6 +251,12 @@ int drm_panel_disable(struct drm_panel *panel)
if (!panel)
return -EINVAL;
 
+   /*
+* If you're seeing this warning, you either need to add your driver
+* to "drm_drivers_that_shutdown" (if you're seeing it with panel-edp
+* or panel-simple) or you need to remove the manual call to
+* drm_panel_disable() in your panel driver.
+*/
if (!panel->enabled) {
dev_warn(panel->dev, "Skipping disable of already disabled 
panel\n");
return 0;
diff --git a/drivers/gpu/drm/panel/panel-drm-shutdown-check.h 
b/drivers/gpu/drm/panel/panel-drm-shutdown-check.h
new file mode 100644
ind

[PATCH v3 21/24] drm/panel: raydium-rm67191: Stop tracking enabled

2024-06-04 Thread Douglas Anderson
As talked about in commit d2aacaf07395 ("drm/panel: Check for already
prepared/enabled in drm_panel"), we want to remove needless code from
panel drivers that was storing and double-checking the
prepared/enabled state. Even if someone was relying on the
double-check before, that double-check is now in the core and not
needed in individual drivers.

The conversion of the rm67191 panel driver follows many of the other
panel drivers but has a few differences that need to be called out.

Like in commit 1e0465eb16a4 ("drm/panel: otm8009a: Don't double check
prepared/enabled"), this panel also uses the "prepared" flag to
prevent the backlight functions from running when the panel is powered
off. This is probably not the safest thing to do but the old behavior
was preserved. See the discussion in the otm8009a patch. Because of
this, I've left the driver tracking "prepared" but removed its
tracking of "enabled".

NOTE: as part of this, transition the panel's direct calls to its
disable/unprepare functions in shutdown to call through DRM panel.

Cc: Robert Chiras 
Acked-by: Linus Walleij 
Acked-by: Maxime Ripard 
Signed-off-by: Douglas Anderson 
---

(no changes since v2)

Changes in v2:
- Split removal of prepared/enabled from handling of remove/shutdown.

 drivers/gpu/drm/panel/panel-raydium-rm67191.c | 21 ++-
 1 file changed, 2 insertions(+), 19 deletions(-)

diff --git a/drivers/gpu/drm/panel/panel-raydium-rm67191.c 
b/drivers/gpu/drm/panel/panel-raydium-rm67191.c
index dbb1ed4efbed..fa9bf89d3bb5 100644
--- a/drivers/gpu/drm/panel/panel-raydium-rm67191.c
+++ b/drivers/gpu/drm/panel/panel-raydium-rm67191.c
@@ -205,7 +205,6 @@ struct rad_panel {
unsigned int num_supplies;
 
bool prepared;
-   bool enabled;
 };
 
 static const struct drm_display_mode default_mode = {
@@ -267,9 +266,6 @@ static int rad_panel_prepare(struct drm_panel *panel)
struct rad_panel *rad = to_rad_panel(panel);
int ret;
 
-   if (rad->prepared)
-   return 0;
-
ret = regulator_bulk_enable(rad->num_supplies, rad->supplies);
if (ret)
return ret;
@@ -291,9 +287,6 @@ static int rad_panel_unprepare(struct drm_panel *panel)
struct rad_panel *rad = to_rad_panel(panel);
int ret;
 
-   if (!rad->prepared)
-   return 0;
-
/*
 * Right after asserting the reset, we need to release it, so that the
 * touch driver can have an active connection with the touch controller
@@ -322,9 +315,6 @@ static int rad_panel_enable(struct drm_panel *panel)
int color_format = color_format_from_dsi_format(dsi->format);
int ret;
 
-   if (rad->enabled)
-   return 0;
-
dsi->mode_flags |= MIPI_DSI_MODE_LPM;
 
ret = rad_panel_push_cmd_list(dsi);
@@ -389,8 +379,6 @@ static int rad_panel_enable(struct drm_panel *panel)
 
backlight_enable(rad->backlight);
 
-   rad->enabled = true;
-
return 0;
 
 fail:
@@ -406,9 +394,6 @@ static int rad_panel_disable(struct drm_panel *panel)
struct device *dev = &dsi->dev;
int ret;
 
-   if (!rad->enabled)
-   return 0;
-
dsi->mode_flags |= MIPI_DSI_MODE_LPM;
 
backlight_disable(rad->backlight);
@@ -429,8 +414,6 @@ static int rad_panel_disable(struct drm_panel *panel)
return ret;
}
 
-   rad->enabled = false;
-
return 0;
 }
 
@@ -633,8 +616,8 @@ static void rad_panel_shutdown(struct mipi_dsi_device *dsi)
 {
struct rad_panel *rad = mipi_dsi_get_drvdata(dsi);
 
-   rad_panel_disable(&rad->panel);
-   rad_panel_unprepare(&rad->panel);
+   drm_panel_disable(&rad->panel);
+   drm_panel_unprepare(&rad->panel);
 }
 
 static const struct of_device_id rad_of_match[] = {
-- 
2.45.1.288.g0e0cd299f1-goog



[PATCH v3 23/24] drm/panel: Update TODO list item for cleaning up prepared/enabled tracking

2024-06-04 Thread Douglas Anderson
Now that most panels have been updated not to track/double-check their
prepared/enabled state update the TODO with next steps.

Acked-by: Linus Walleij 
Acked-by: Maxime Ripard 
Signed-off-by: Douglas Anderson 
---

(no changes since v1)

 Documentation/gpu/todo.rst | 47 +-
 1 file changed, 26 insertions(+), 21 deletions(-)

diff --git a/Documentation/gpu/todo.rst b/Documentation/gpu/todo.rst
index 2734b8a34541..2ea6ffc9b22b 100644
--- a/Documentation/gpu/todo.rst
+++ b/Documentation/gpu/todo.rst
@@ -469,30 +469,35 @@ Contact: Thomas Zimmermann 
 
 Level: Starter
 
-Clean up checks for already prepared/enabled in panels
---
-
-In a whole pile of panel drivers, we have code to make the
-prepare/unprepare/enable/disable callbacks behave as no-ops if they've already
-been called. To get some idea of the duplicated code, try::
-
-  git grep 'if.*>prepared' -- drivers/gpu/drm/panel
-  git grep 'if.*>enabled' -- drivers/gpu/drm/panel
-
-In the patch ("drm/panel: Check for already prepared/enabled in drm_panel")
-we've moved this check to the core. Now we can most definitely remove the
-check from the individual panels and save a pile of code.
-
-In adition to removing the check from the individual panels, it is believed
-that even the core shouldn't need this check and that should be considered
-an error if other code ever relies on this check. The check in the core
-currently prints a warning whenever something is relying on this check with
-dev_warn(). After a little while, we likely want to promote this to a
-WARN(1) to help encourage folks not to rely on this behavior.
+Remove disable/unprepare in remove/shutdown in panel-simple and panel-edp
+-
+
+As of commit d2aacaf07395 ("drm/panel: Check for already prepared/enabled in
+drm_panel"), we have a check in the drm_panel core to make sure nobody
+double-calls prepare/enable/disable/unprepare. Eventually that should probably
+be turned into a WARN_ON() or somehow made louder, but right now we actually
+expect it to trigger and so we don't want it to be too loud.
+
+Specifically, that warning will trigger for panel-edp and panel-simple at
+shutdown time because those panels hardcode a call to drm_panel_disable()
+and drm_panel_unprepare() at shutdown and remove time that they call regardless
+of panel state. On systems with a properly coded DRM modeset driver that
+calls drm_atomic_helper_shutdown() this is pretty much guaranteed to cause
+the warning to fire.
+
+Unfortunately we can't safely remove the calls in panel-edp and panel-simple
+until we're sure that all DRM modeset drivers that are used with those panels
+properly call drm_atomic_helper_shutdown(). This TODO item is to validate
+that all DRM modeset drivers used with panel-edp and panel-simple properly
+call drm_atomic_helper_shutdown() and then remove the calls to
+disable/unprepare from those panels. Alternatively, this TODO item could be
+removed by convincing stakeholders that those calls are fine and downgrading
+the error message in drm_panel_disable() / drm_panel_unprepare() to a
+debug-level message.
 
 Contact: Douglas Anderson 
 
-Level: Starter/Intermediate
+Level: Intermediate
 
 Transition away from using mipi_dsi_*_write_seq()
 -
-- 
2.45.1.288.g0e0cd299f1-goog



[PATCH v3 22/24] drm/panel: raydium-rm67191: Don't call unprepare+disable at shutdown

2024-06-04 Thread Douglas Anderson
It's the responsibility of a correctly written DRM modeset driver to
call drm_atomic_helper_shutdown() at shutdown time and that should be
disabling / unpreparing the panel if needed. Panel drivers shouldn't
be calling these functions themselves.

A recent effort was made to fix as many DRM modeset drivers as
possible [1] [2] [3] and most drivers are fixed now.

A grep through mainline for compatible strings used by this driver
indicates that it is used by IMX boards. The IMX driver appears to be
correctly calling drm_atomic_helper_shutdown() so we can remove the
calls.

[1] https://lore.kernel.org/r/20230901234015.566018-1-diand...@chromium.org
[2] https://lore.kernel.org/r/20230901234202.566951-1-diand...@chromium.org
[3] https://lore.kernel.org/r/20230921192749.1542462-1-diand...@chromium.org

Cc: Robert Chiras 
Acked-by: Linus Walleij 
Acked-by: Maxime Ripard 
Signed-off-by: Douglas Anderson 
---

(no changes since v2)

Changes in v2:
- Split removal of prepared/enabled from handling of remove/shutdown.

 drivers/gpu/drm/panel/panel-raydium-rm67191.c | 9 -
 1 file changed, 9 deletions(-)

diff --git a/drivers/gpu/drm/panel/panel-raydium-rm67191.c 
b/drivers/gpu/drm/panel/panel-raydium-rm67191.c
index fa9bf89d3bb5..b2029e035635 100644
--- a/drivers/gpu/drm/panel/panel-raydium-rm67191.c
+++ b/drivers/gpu/drm/panel/panel-raydium-rm67191.c
@@ -612,14 +612,6 @@ static void rad_panel_remove(struct mipi_dsi_device *dsi)
drm_panel_remove(&rad->panel);
 }
 
-static void rad_panel_shutdown(struct mipi_dsi_device *dsi)
-{
-   struct rad_panel *rad = mipi_dsi_get_drvdata(dsi);
-
-   drm_panel_disable(&rad->panel);
-   drm_panel_unprepare(&rad->panel);
-}
-
 static const struct of_device_id rad_of_match[] = {
{ .compatible = "raydium,rm67191", },
{ /* sentinel */ }
@@ -633,7 +625,6 @@ static struct mipi_dsi_driver rad_panel_driver = {
},
.probe = rad_panel_probe,
.remove = rad_panel_remove,
-   .shutdown = rad_panel_shutdown,
 };
 module_mipi_dsi_driver(rad_panel_driver);
 
-- 
2.45.1.288.g0e0cd299f1-goog



[PATCH v3 24/24] drm/panel: Avoid warnings w/ panel-simple/panel-edp at shutdown

2024-06-04 Thread Douglas Anderson
At shutdown if you've got a _properly_ coded DRM modeset driver then
you'll get these two warnings at shutdown time:

  Skipping disable of already disabled panel
  Skipping unprepare of already unprepared panel

These warnings are ugly and sound concerning, but they're actually a
sign of a properly working system. That's not great.

It's not easy to get rid of these warnings. Until we know that all DRM
modeset drivers used with panel-simple and panel-edp are properly
calling drm_atomic_helper_shutdown() or drm_helper_force_disable_all()
then the panel drivers _need_ to disable/unprepare themselves in order
to power off the panel cleanly. However, there are lots of DRM modeset
drivers used with panel-edp and panel-simple and it's hard to know
when we've got them all. Since the warning happens only on the drivers
that _are_ updated there's nothing to encourage broken DRM modeset
drivers to get fixed.

In order to flip the warning to the proper place, we need to know
which modeset drivers are going to shutdown properly. Though ugly, do
this by creating a list of everyone that shuts down properly. This
allows us to generate a warning for the correct case and also lets us
get rid of the warning for drivers that are shutting down properly.

Maintaining this list is ugly, but the idea is that it's only short
term. Once everyone is converted we can delete the list and call it
done. The list is ugly enough and adding to it is annoying enough that
people should push to make this happen.

Implement this all in a shared "header" file included by the two panel
drivers that need it. This avoids us adding an new exports while still
allowing the panel drivers to be modules. The code waste should be
small and, as per above, the whole solution is temporary.

Signed-off-by: Douglas Anderson 
---
I came up with this idea to help us move forward since otherwise I
couldn't see how we were ever going to fix panel-simple and panel-edp
since they're used by so many DRM Modeset drivers. It's a bit ugly but
I don't hate it. What do others think?

This is at the end of the series so even if folks hate it we could
still land the rest of the series.

Changes in v3:
- New

 drivers/gpu/drm/drm_panel.c   |  12 ++
 .../gpu/drm/panel/panel-drm-shutdown-check.h  | 151 ++
 drivers/gpu/drm/panel/panel-edp.c |  19 +--
 drivers/gpu/drm/panel/panel-simple.c  |  19 +--
 4 files changed, 169 insertions(+), 32 deletions(-)
 create mode 100644 drivers/gpu/drm/panel/panel-drm-shutdown-check.h

diff --git a/drivers/gpu/drm/drm_panel.c b/drivers/gpu/drm/drm_panel.c
index cfbe020de54e..df3f15f4625e 100644
--- a/drivers/gpu/drm/drm_panel.c
+++ b/drivers/gpu/drm/drm_panel.c
@@ -161,6 +161,12 @@ int drm_panel_unprepare(struct drm_panel *panel)
if (!panel)
return -EINVAL;
 
+   /*
+* If you're seeing this warning, you either need to add your driver
+* to "drm_drivers_that_shutdown" (if you're seeing it with panel-edp
+* or panel-simple) or you need to remove the manual call to
+* drm_panel_unprepare() in your panel driver.
+*/
if (!panel->prepared) {
dev_warn(panel->dev, "Skipping unprepare of already unprepared 
panel\n");
return 0;
@@ -245,6 +251,12 @@ int drm_panel_disable(struct drm_panel *panel)
if (!panel)
return -EINVAL;
 
+   /*
+* If you're seeing this warning, you either need to add your driver
+* to "drm_drivers_that_shutdown" (if you're seeing it with panel-edp
+* or panel-simple) or you need to remove the manual call to
+* drm_panel_disable() in your panel driver.
+*/
if (!panel->enabled) {
dev_warn(panel->dev, "Skipping disable of already disabled 
panel\n");
return 0;
diff --git a/drivers/gpu/drm/panel/panel-drm-shutdown-check.h 
b/drivers/gpu/drm/panel/panel-drm-shutdown-check.h
new file mode 100644
index ..b5164490d6e7
--- /dev/null
+++ b/drivers/gpu/drm/panel/panel-drm-shutdown-check.h
@@ -0,0 +1,151 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright 2024 Google Inc.
+ *
+ * This header is a temporary solution and is intended to be included
+ * directly by panel-edp.c and panel-simple.c.
+ *
+ * This header is needed because panel-edp and panel-simple are used by a
+ * wide variety of DRM drivers and it's hard to know for sure if all of the
+ * DRM drivers used by those panel drivers are properly calling
+ * drm_atomic_helper_shutdown() or drm_helper_force_disable_all() at
+ * shutdown/remove time.
+ *
+ * The plan for this header file:
+ * - Land it and hope that the warning print will encourage DRM drivers to
+ *   get fixed.
+ * - Eventually move to a WARN() splat for extra encouragement.
+ * -

[PATCH v3 20/24] drm/panel: sharp-ls043t1le01: Don't call disable at shutdown/remove

2024-06-04 Thread Douglas Anderson
It's the responsibility of a correctly written DRM modeset driver to
call drm_atomic_helper_shutdown() at shutdown time and that should be
disabling / unpreparing the panel if needed. Panel drivers shouldn't
be calling these functions themselves.

A recent effort was made to fix as many DRM modeset drivers as
possible [1] [2] [3] and most drivers are fixed now.

A grep through mainline for compatible strings used by this driver
indicates that it is used by Qualcomm boards. The Qualcomm driver
appears to be correctly calling drm_atomic_helper_shutdown() so we can
remove the calls.

[1] https://lore.kernel.org/r/20230901234015.566018-1-diand...@chromium.org
[2] https://lore.kernel.org/r/20230901234202.566951-1-diand...@chromium.org
[3] https://lore.kernel.org/r/20230921192749.1542462-1-diand...@chromium.org

Cc: Werner Johansson 
Cc: Dmitry Baryshkov 
Acked-by: Linus Walleij 
Acked-by: Maxime Ripard 
Signed-off-by: Douglas Anderson 
---

(no changes since v2)

Changes in v2:
- Only handle 1 panel per patch.
- Split removal of prepared/enabled from handling of remove/shutdown.

 drivers/gpu/drm/panel/panel-sharp-ls043t1le01.c | 12 
 1 file changed, 12 deletions(-)

diff --git a/drivers/gpu/drm/panel/panel-sharp-ls043t1le01.c 
b/drivers/gpu/drm/panel/panel-sharp-ls043t1le01.c
index c86337954ad7..729cbb0d8403 100644
--- a/drivers/gpu/drm/panel/panel-sharp-ls043t1le01.c
+++ b/drivers/gpu/drm/panel/panel-sharp-ls043t1le01.c
@@ -267,10 +267,6 @@ static void sharp_nt_panel_remove(struct mipi_dsi_device 
*dsi)
struct sharp_nt_panel *sharp_nt = mipi_dsi_get_drvdata(dsi);
int ret;
 
-   ret = drm_panel_disable(&sharp_nt->base);
-   if (ret < 0)
-   dev_err(&dsi->dev, "failed to disable panel: %d\n", ret);
-
ret = mipi_dsi_detach(dsi);
if (ret < 0)
dev_err(&dsi->dev, "failed to detach from DSI host: %d\n", ret);
@@ -278,13 +274,6 @@ static void sharp_nt_panel_remove(struct mipi_dsi_device 
*dsi)
sharp_nt_panel_del(sharp_nt);
 }
 
-static void sharp_nt_panel_shutdown(struct mipi_dsi_device *dsi)
-{
-   struct sharp_nt_panel *sharp_nt = mipi_dsi_get_drvdata(dsi);
-
-   drm_panel_disable(&sharp_nt->base);
-}
-
 static const struct of_device_id sharp_nt_of_match[] = {
{ .compatible = "sharp,ls043t1le01-qhd", },
{ }
@@ -298,7 +287,6 @@ static struct mipi_dsi_driver sharp_nt_panel_driver = {
},
.probe = sharp_nt_panel_probe,
.remove = sharp_nt_panel_remove,
-   .shutdown = sharp_nt_panel_shutdown,
 };
 module_mipi_dsi_driver(sharp_nt_panel_driver);
 
-- 
2.45.1.288.g0e0cd299f1-goog



[PATCH v3 19/24] drm/panel: sharp-ls043t1le01: Stop tracking prepared

2024-06-04 Thread Douglas Anderson
As talked about in commit d2aacaf07395 ("drm/panel: Check for already
prepared/enabled in drm_panel"), we want to remove needless code from
panel drivers that was storing and double-checking the
prepared/enabled state. Even if someone was relying on the
double-check before, that double-check is now in the core and not
needed in individual drivers.

Cc: Werner Johansson 
Cc: Dmitry Baryshkov 
Acked-by: Linus Walleij 
Acked-by: Maxime Ripard 
Signed-off-by: Douglas Anderson 
---

(no changes since v2)

Changes in v2:
- Only handle 1 panel per patch.
- Split removal of prepared/enabled from handling of remove/shutdown.

 drivers/gpu/drm/panel/panel-sharp-ls043t1le01.c | 12 
 1 file changed, 12 deletions(-)

diff --git a/drivers/gpu/drm/panel/panel-sharp-ls043t1le01.c 
b/drivers/gpu/drm/panel/panel-sharp-ls043t1le01.c
index 855e6daa..c86337954ad7 100644
--- a/drivers/gpu/drm/panel/panel-sharp-ls043t1le01.c
+++ b/drivers/gpu/drm/panel/panel-sharp-ls043t1le01.c
@@ -26,8 +26,6 @@ struct sharp_nt_panel {
 
struct regulator *supply;
struct gpio_desc *reset_gpio;
-
-   bool prepared;
 };
 
 static inline struct sharp_nt_panel *to_sharp_nt_panel(struct drm_panel *panel)
@@ -99,9 +97,6 @@ static int sharp_nt_panel_unprepare(struct drm_panel *panel)
struct sharp_nt_panel *sharp_nt = to_sharp_nt_panel(panel);
int ret;
 
-   if (!sharp_nt->prepared)
-   return 0;
-
ret = sharp_nt_panel_off(sharp_nt);
if (ret < 0) {
dev_err(panel->dev, "failed to set panel off: %d\n", ret);
@@ -112,8 +107,6 @@ static int sharp_nt_panel_unprepare(struct drm_panel *panel)
if (sharp_nt->reset_gpio)
gpiod_set_value(sharp_nt->reset_gpio, 0);
 
-   sharp_nt->prepared = false;
-
return 0;
 }
 
@@ -122,9 +115,6 @@ static int sharp_nt_panel_prepare(struct drm_panel *panel)
struct sharp_nt_panel *sharp_nt = to_sharp_nt_panel(panel);
int ret;
 
-   if (sharp_nt->prepared)
-   return 0;
-
ret = regulator_enable(sharp_nt->supply);
if (ret < 0)
return ret;
@@ -152,8 +142,6 @@ static int sharp_nt_panel_prepare(struct drm_panel *panel)
goto poweroff;
}
 
-   sharp_nt->prepared = true;
-
return 0;
 
 poweroff:
-- 
2.45.1.288.g0e0cd299f1-goog



[PATCH v3 17/24] drm/panel: sharp-lq101r1sx01: Stop tracking prepared/enabled

2024-06-04 Thread Douglas Anderson
As talked about in commit d2aacaf07395 ("drm/panel: Check for already
prepared/enabled in drm_panel"), we want to remove needless code from
panel drivers that was storing and double-checking the
prepared/enabled state. Even if someone was relying on the
double-check before, that double-check is now in the core and not
needed in individual drivers.

Cc: Thierry Reding 
Acked-by: Linus Walleij 
Acked-by: Maxime Ripard 
Signed-off-by: Douglas Anderson 
---

(no changes since v2)

Changes in v2:
- Only handle 1 panel per patch.
- Split removal of prepared/enabled from handling of remove/shutdown.

 .../gpu/drm/panel/panel-sharp-lq101r1sx01.c   | 39 ---
 1 file changed, 39 deletions(-)

diff --git a/drivers/gpu/drm/panel/panel-sharp-lq101r1sx01.c 
b/drivers/gpu/drm/panel/panel-sharp-lq101r1sx01.c
index 14851408a5e1..8f6c21b99522 100644
--- a/drivers/gpu/drm/panel/panel-sharp-lq101r1sx01.c
+++ b/drivers/gpu/drm/panel/panel-sharp-lq101r1sx01.c
@@ -24,9 +24,6 @@ struct sharp_panel {
 
struct regulator *supply;
 
-   bool prepared;
-   bool enabled;
-
const struct drm_display_mode *mode;
 };
 
@@ -85,26 +82,11 @@ static __maybe_unused int sharp_panel_read(struct 
sharp_panel *sharp,
return err;
 }
 
-static int sharp_panel_disable(struct drm_panel *panel)
-{
-   struct sharp_panel *sharp = to_sharp_panel(panel);
-
-   if (!sharp->enabled)
-   return 0;
-
-   sharp->enabled = false;
-
-   return 0;
-}
-
 static int sharp_panel_unprepare(struct drm_panel *panel)
 {
struct sharp_panel *sharp = to_sharp_panel(panel);
int err;
 
-   if (!sharp->prepared)
-   return 0;
-
sharp_wait_frames(sharp, 4);
 
err = mipi_dsi_dcs_set_display_off(sharp->link1);
@@ -119,8 +101,6 @@ static int sharp_panel_unprepare(struct drm_panel *panel)
 
regulator_disable(sharp->supply);
 
-   sharp->prepared = false;
-
return 0;
 }
 
@@ -164,9 +144,6 @@ static int sharp_panel_prepare(struct drm_panel *panel)
u8 format = MIPI_DCS_PIXEL_FMT_24BIT;
int err;
 
-   if (sharp->prepared)
-   return 0;
-
err = regulator_enable(sharp->supply);
if (err < 0)
return err;
@@ -235,8 +212,6 @@ static int sharp_panel_prepare(struct drm_panel *panel)
goto poweroff;
}
 
-   sharp->prepared = true;
-
/* wait for 6 frames before continuing */
sharp_wait_frames(sharp, 6);
 
@@ -247,18 +222,6 @@ static int sharp_panel_prepare(struct drm_panel *panel)
return err;
 }
 
-static int sharp_panel_enable(struct drm_panel *panel)
-{
-   struct sharp_panel *sharp = to_sharp_panel(panel);
-
-   if (sharp->enabled)
-   return 0;
-
-   sharp->enabled = true;
-
-   return 0;
-}
-
 static const struct drm_display_mode default_mode = {
.clock = 278000,
.hdisplay = 2560,
@@ -295,10 +258,8 @@ static int sharp_panel_get_modes(struct drm_panel *panel,
 }
 
 static const struct drm_panel_funcs sharp_panel_funcs = {
-   .disable = sharp_panel_disable,
.unprepare = sharp_panel_unprepare,
.prepare = sharp_panel_prepare,
-   .enable = sharp_panel_enable,
.get_modes = sharp_panel_get_modes,
 };
 
-- 
2.45.1.288.g0e0cd299f1-goog



[PATCH v3 18/24] drm/panel: sharp-lq101r1sx01: Don't call disable at shutdown/remove

2024-06-04 Thread Douglas Anderson
It's the responsibility of a correctly written DRM modeset driver to
call drm_atomic_helper_shutdown() at shutdown time and that should be
disabling / unpreparing the panel if needed. Panel drivers shouldn't
be calling these functions themselves.

A recent effort was made to fix as many DRM modeset drivers as
possible [1] [2] [3] and most drivers are fixed now.

A grep through mainline for compatible strings used by this driver
indicates that it is used by Tegra boards. The Tegra driver appears to
be correctly calling drm_atomic_helper_shutdown() so we can remove the
calls.

[1] https://lore.kernel.org/r/20230901234015.566018-1-diand...@chromium.org
[2] https://lore.kernel.org/r/20230901234202.566951-1-diand...@chromium.org
[3] https://lore.kernel.org/r/20230921192749.1542462-1-diand...@chromium.org

Cc: Thierry Reding 
Acked-by: Linus Walleij 
Acked-by: Maxime Ripard 
Signed-off-by: Douglas Anderson 
---

(no changes since v2)

Changes in v2:
- Only handle 1 panel per patch.
- Split removal of prepared/enabled from handling of remove/shutdown.

 .../gpu/drm/panel/panel-sharp-lq101r1sx01.c   | 24 ++-
 1 file changed, 2 insertions(+), 22 deletions(-)

diff --git a/drivers/gpu/drm/panel/panel-sharp-lq101r1sx01.c 
b/drivers/gpu/drm/panel/panel-sharp-lq101r1sx01.c
index 8f6c21b99522..edc9425bb143 100644
--- a/drivers/gpu/drm/panel/panel-sharp-lq101r1sx01.c
+++ b/drivers/gpu/drm/panel/panel-sharp-lq101r1sx01.c
@@ -357,32 +357,13 @@ static void sharp_panel_remove(struct mipi_dsi_device 
*dsi)
struct sharp_panel *sharp = mipi_dsi_get_drvdata(dsi);
int err;
 
-   /* only detach from host for the DSI-LINK2 interface */
-   if (!sharp) {
-   mipi_dsi_detach(dsi);
-   return;
-   }
-
-   err = drm_panel_disable(&sharp->base);
-   if (err < 0)
-   dev_err(&dsi->dev, "failed to disable panel: %d\n", err);
-
err = mipi_dsi_detach(dsi);
if (err < 0)
dev_err(&dsi->dev, "failed to detach from DSI host: %d\n", err);
 
-   sharp_panel_del(sharp);
-}
-
-static void sharp_panel_shutdown(struct mipi_dsi_device *dsi)
-{
-   struct sharp_panel *sharp = mipi_dsi_get_drvdata(dsi);
-
-   /* nothing to do for DSI-LINK2 */
+   /* only detach from host for the DSI-LINK2 interface */
if (!sharp)
-   return;
-
-   drm_panel_disable(&sharp->base);
+   sharp_panel_del(sharp);
 }
 
 static struct mipi_dsi_driver sharp_panel_driver = {
@@ -392,7 +373,6 @@ static struct mipi_dsi_driver sharp_panel_driver = {
},
.probe = sharp_panel_probe,
.remove = sharp_panel_remove,
-   .shutdown = sharp_panel_shutdown,
 };
 module_mipi_dsi_driver(sharp_panel_driver);
 
-- 
2.45.1.288.g0e0cd299f1-goog



[PATCH v3 13/24] drm/panel: panasonic-vvx10f034n00: Stop tracking prepared/enabled

2024-06-04 Thread Douglas Anderson
As talked about in commit d2aacaf07395 ("drm/panel: Check for already
prepared/enabled in drm_panel"), we want to remove needless code from
panel drivers that was storing and double-checking the
prepared/enabled state. Even if someone was relying on the
double-check before, that double-check is now in the core and not
needed in individual drivers.

Cc: Werner Johansson 
Acked-by: Linus Walleij 
Acked-by: Maxime Ripard 
Signed-off-by: Douglas Anderson 
---

(no changes since v2)

Changes in v2:
- Only handle 1 panel per patch.
- Split removal of prepared/enabled from handling of remove/shutdown.

 .../drm/panel/panel-panasonic-vvx10f034n00.c  | 35 +--
 1 file changed, 1 insertion(+), 34 deletions(-)

diff --git a/drivers/gpu/drm/panel/panel-panasonic-vvx10f034n00.c 
b/drivers/gpu/drm/panel/panel-panasonic-vvx10f034n00.c
index 8ba6d8287938..822ca2f971eb 100644
--- a/drivers/gpu/drm/panel/panel-panasonic-vvx10f034n00.c
+++ b/drivers/gpu/drm/panel/panel-panasonic-vvx10f034n00.c
@@ -32,9 +32,6 @@ struct wuxga_nt_panel {
 
struct regulator *supply;
 
-   bool prepared;
-   bool enabled;
-
ktime_t earliest_wake;
 
const struct drm_display_mode *mode;
@@ -53,28 +50,16 @@ static int wuxga_nt_panel_on(struct wuxga_nt_panel 
*wuxga_nt)
 static int wuxga_nt_panel_disable(struct drm_panel *panel)
 {
struct wuxga_nt_panel *wuxga_nt = to_wuxga_nt_panel(panel);
-   int mipi_ret, bl_ret = 0;
-
-   if (!wuxga_nt->enabled)
-   return 0;
-
-   mipi_ret = mipi_dsi_shutdown_peripheral(wuxga_nt->dsi);
-
-   wuxga_nt->enabled = false;
 
-   return mipi_ret ? mipi_ret : bl_ret;
+   return mipi_dsi_shutdown_peripheral(wuxga_nt->dsi);
 }
 
 static int wuxga_nt_panel_unprepare(struct drm_panel *panel)
 {
struct wuxga_nt_panel *wuxga_nt = to_wuxga_nt_panel(panel);
 
-   if (!wuxga_nt->prepared)
-   return 0;
-
regulator_disable(wuxga_nt->supply);
wuxga_nt->earliest_wake = ktime_add_ms(ktime_get_real(), MIN_POFF_MS);
-   wuxga_nt->prepared = false;
 
return 0;
 }
@@ -85,9 +70,6 @@ static int wuxga_nt_panel_prepare(struct drm_panel *panel)
int ret;
s64 enablewait;
 
-   if (wuxga_nt->prepared)
-   return 0;
-
/*
 * If the user re-enabled the panel before the required off-time then
 * we need to wait the remaining period before re-enabling regulator
@@ -117,8 +99,6 @@ static int wuxga_nt_panel_prepare(struct drm_panel *panel)
goto poweroff;
}
 
-   wuxga_nt->prepared = true;
-
return 0;
 
 poweroff:
@@ -127,18 +107,6 @@ static int wuxga_nt_panel_prepare(struct drm_panel *panel)
return ret;
 }
 
-static int wuxga_nt_panel_enable(struct drm_panel *panel)
-{
-   struct wuxga_nt_panel *wuxga_nt = to_wuxga_nt_panel(panel);
-
-   if (wuxga_nt->enabled)
-   return 0;
-
-   wuxga_nt->enabled = true;
-
-   return 0;
-}
-
 static const struct drm_display_mode default_mode = {
.clock = 164402,
.hdisplay = 1920,
@@ -178,7 +146,6 @@ static const struct drm_panel_funcs wuxga_nt_panel_funcs = {
.disable = wuxga_nt_panel_disable,
.unprepare = wuxga_nt_panel_unprepare,
.prepare = wuxga_nt_panel_prepare,
-   .enable = wuxga_nt_panel_enable,
.get_modes = wuxga_nt_panel_get_modes,
 };
 
-- 
2.45.1.288.g0e0cd299f1-goog



[PATCH v3 16/24] drm/panel: seiko-43wvf1g: Don't call disable at shutdown/remove

2024-06-04 Thread Douglas Anderson
It's the responsibility of a correctly written DRM modeset driver to
call drm_atomic_helper_shutdown() at shutdown time and that should be
disabling / unpreparing the panel if needed. Panel drivers shouldn't
be calling these functions themselves.

A recent effort was made to fix as many DRM modeset drivers as
possible [1] [2] [3] and most drivers are fixed now.

A grep through mainline for compatible strings used by this driver
indicates that it is used by IMX boards. As far as I can tell, all IMX
boards are now correctly calling drm_atomic_helper_shutdown() so we
can remove the calls.

[1] https://lore.kernel.org/r/20230901234015.566018-1-diand...@chromium.org
[2] https://lore.kernel.org/r/20230901234202.566951-1-diand...@chromium.org
[3] https://lore.kernel.org/r/20230921192749.1542462-1-diand...@chromium.org

Cc: Marco Franchi 
Cc: Fabio Estevam 
Cc: Laurentiu Palcu 
Cc: Pengutronix Kernel Team 
Cc: i...@lists.linux.dev
Acked-by: Linus Walleij 
Acked-by: Maxime Ripard 
Signed-off-by: Douglas Anderson 
---

(no changes since v2)

Changes in v2:
- Only handle 1 panel per patch.
- Split removal of prepared/enabled from handling of remove/shutdown.

 drivers/gpu/drm/panel/panel-seiko-43wvf1g.c | 9 -
 1 file changed, 9 deletions(-)

diff --git a/drivers/gpu/drm/panel/panel-seiko-43wvf1g.c 
b/drivers/gpu/drm/panel/panel-seiko-43wvf1g.c
index 98480904126c..8a3fe531c641 100644
--- a/drivers/gpu/drm/panel/panel-seiko-43wvf1g.c
+++ b/drivers/gpu/drm/panel/panel-seiko-43wvf1g.c
@@ -243,14 +243,6 @@ static void seiko_panel_remove(struct platform_device 
*pdev)
struct seiko_panel *panel = platform_get_drvdata(pdev);
 
drm_panel_remove(&panel->base);
-   drm_panel_disable(&panel->base);
-}
-
-static void seiko_panel_shutdown(struct platform_device *pdev)
-{
-   struct seiko_panel *panel = platform_get_drvdata(pdev);
-
-   drm_panel_disable(&panel->base);
 }
 
 static const struct display_timing seiko_43wvf1g_timing = {
@@ -306,7 +298,6 @@ static struct platform_driver seiko_panel_platform_driver = 
{
},
.probe = seiko_panel_platform_probe,
.remove_new = seiko_panel_remove,
-   .shutdown = seiko_panel_shutdown,
 };
 module_platform_driver(seiko_panel_platform_driver);
 
-- 
2.45.1.288.g0e0cd299f1-goog



[PATCH v3 14/24] drm/panel: panasonic-vvx10f034n00: Don't call disable at shutdown/remove

2024-06-04 Thread Douglas Anderson
It's the responsibility of a correctly written DRM modeset driver to
call drm_atomic_helper_shutdown() at shutdown time and that should be
disabling / unpreparing the panel if needed. Panel drivers shouldn't
be calling these functions themselves.

A recent effort was made to fix as many DRM modeset drivers as
possible [1] [2] [3] and most drivers are fixed now.

Unfortunately, grepping mainline for this panel's compatible string
shows no hits, so we can't be 100% sure if the DRM modeset driver used
with this panel has been fixed. If it is found that the DRM modeset
driver hasn't been fixed then this patch could be temporarily reverted
until it is.

[1] https://lore.kernel.org/r/20230901234015.566018-1-diand...@chromium.org
[2] https://lore.kernel.org/r/20230901234202.566951-1-diand...@chromium.org
[3] https://lore.kernel.org/r/20230921192749.1542462-1-diand...@chromium.org

Cc: Werner Johansson 
Acked-by: Linus Walleij 
Acked-by: Maxime Ripard 
Signed-off-by: Douglas Anderson 
---

(no changes since v2)

Changes in v2:
- Only handle 1 panel per patch.
- Split removal of prepared/enabled from handling of remove/shutdown.

 drivers/gpu/drm/panel/panel-panasonic-vvx10f034n00.c | 12 
 1 file changed, 12 deletions(-)

diff --git a/drivers/gpu/drm/panel/panel-panasonic-vvx10f034n00.c 
b/drivers/gpu/drm/panel/panel-panasonic-vvx10f034n00.c
index 822ca2f971eb..d1c5c9bc3c56 100644
--- a/drivers/gpu/drm/panel/panel-panasonic-vvx10f034n00.c
+++ b/drivers/gpu/drm/panel/panel-panasonic-vvx10f034n00.c
@@ -222,10 +222,6 @@ static void wuxga_nt_panel_remove(struct mipi_dsi_device 
*dsi)
struct wuxga_nt_panel *wuxga_nt = mipi_dsi_get_drvdata(dsi);
int ret;
 
-   ret = drm_panel_disable(&wuxga_nt->base);
-   if (ret < 0)
-   dev_err(&dsi->dev, "failed to disable panel: %d\n", ret);
-
ret = mipi_dsi_detach(dsi);
if (ret < 0)
dev_err(&dsi->dev, "failed to detach from DSI host: %d\n", ret);
@@ -233,13 +229,6 @@ static void wuxga_nt_panel_remove(struct mipi_dsi_device 
*dsi)
wuxga_nt_panel_del(wuxga_nt);
 }
 
-static void wuxga_nt_panel_shutdown(struct mipi_dsi_device *dsi)
-{
-   struct wuxga_nt_panel *wuxga_nt = mipi_dsi_get_drvdata(dsi);
-
-   drm_panel_disable(&wuxga_nt->base);
-}
-
 static struct mipi_dsi_driver wuxga_nt_panel_driver = {
.driver = {
.name = "panel-panasonic-vvx10f034n00",
@@ -247,7 +236,6 @@ static struct mipi_dsi_driver wuxga_nt_panel_driver = {
},
.probe = wuxga_nt_panel_probe,
.remove = wuxga_nt_panel_remove,
-   .shutdown = wuxga_nt_panel_shutdown,
 };
 module_mipi_dsi_driver(wuxga_nt_panel_driver);
 
-- 
2.45.1.288.g0e0cd299f1-goog



[PATCH v3 12/24] drm/panel: jdi-lt070me05000: Don't call disable at shutdown/remove

2024-06-04 Thread Douglas Anderson
It's the responsibility of a correctly written DRM modeset driver to
call drm_atomic_helper_shutdown() at shutdown time and that should be
disabling / unpreparing the panel if needed. Panel drivers shouldn't
be calling these functions themselves.

A recent effort was made to fix as many DRM modeset drivers as
possible [1] [2] [3] and most drivers are fixed now.

A grep through mainline for compatible strings used by this driver
indicates that it is used by Qualcomm boards. The Qualcomm driver
appears to be correctly calling drm_atomic_helper_shutdown() so we can
remove the calls.

[1] https://lore.kernel.org/r/20230901234015.566018-1-diand...@chromium.org
[2] https://lore.kernel.org/r/20230901234202.566951-1-diand...@chromium.org
[3] https://lore.kernel.org/r/20230921192749.1542462-1-diand...@chromium.org

Cc: Vinay Simha BN 
Cc: Sumit Semwal 
Acked-by: Linus Walleij 
Acked-by: Maxime Ripard 
Signed-off-by: Douglas Anderson 
---

(no changes since v2)

Changes in v2:
- Only handle 1 panel per patch.
- Split removal of prepared/enabled from handling of remove/shutdown.

 drivers/gpu/drm/panel/panel-jdi-lt070me05000.c | 12 
 1 file changed, 12 deletions(-)

diff --git a/drivers/gpu/drm/panel/panel-jdi-lt070me05000.c 
b/drivers/gpu/drm/panel/panel-jdi-lt070me05000.c
index 4ee6fa1e..b1ce186de261 100644
--- a/drivers/gpu/drm/panel/panel-jdi-lt070me05000.c
+++ b/drivers/gpu/drm/panel/panel-jdi-lt070me05000.c
@@ -452,10 +452,6 @@ static void jdi_panel_remove(struct mipi_dsi_device *dsi)
struct jdi_panel *jdi = mipi_dsi_get_drvdata(dsi);
int ret;
 
-   ret = drm_panel_disable(&jdi->base);
-   if (ret < 0)
-   dev_err(&dsi->dev, "failed to disable panel: %d\n", ret);
-
ret = mipi_dsi_detach(dsi);
if (ret < 0)
dev_err(&dsi->dev, "failed to detach from DSI host: %d\n",
@@ -464,13 +460,6 @@ static void jdi_panel_remove(struct mipi_dsi_device *dsi)
jdi_panel_del(jdi);
 }
 
-static void jdi_panel_shutdown(struct mipi_dsi_device *dsi)
-{
-   struct jdi_panel *jdi = mipi_dsi_get_drvdata(dsi);
-
-   drm_panel_disable(&jdi->base);
-}
-
 static struct mipi_dsi_driver jdi_panel_driver = {
.driver = {
.name = "panel-jdi-lt070me05000",
@@ -478,7 +467,6 @@ static struct mipi_dsi_driver jdi_panel_driver = {
},
.probe = jdi_panel_probe,
.remove = jdi_panel_remove,
-   .shutdown = jdi_panel_shutdown,
 };
 module_mipi_dsi_driver(jdi_panel_driver);
 
-- 
2.45.1.288.g0e0cd299f1-goog



[PATCH v3 15/24] drm/panel: seiko-43wvf1g: Stop tracking prepared/enabled

2024-06-04 Thread Douglas Anderson
As talked about in commit d2aacaf07395 ("drm/panel: Check for already
prepared/enabled in drm_panel"), we want to remove needless code from
panel drivers that was storing and double-checking the
prepared/enabled state. Even if someone was relying on the
double-check before, that double-check is now in the core and not
needed in individual drivers.

Cc: Marco Franchi 
Cc: Fabio Estevam 
Cc: Laurentiu Palcu 
Cc: Pengutronix Kernel Team 
Cc: i...@lists.linux.dev
Acked-by: Linus Walleij 
Acked-by: Maxime Ripard 
Signed-off-by: Douglas Anderson 
---

(no changes since v2)

Changes in v2:
- Only handle 1 panel per patch.
- Split removal of prepared/enabled from handling of remove/shutdown.

 drivers/gpu/drm/panel/panel-seiko-43wvf1g.c | 40 -
 1 file changed, 40 deletions(-)

diff --git a/drivers/gpu/drm/panel/panel-seiko-43wvf1g.c 
b/drivers/gpu/drm/panel/panel-seiko-43wvf1g.c
index 658c7c040570..98480904126c 100644
--- a/drivers/gpu/drm/panel/panel-seiko-43wvf1g.c
+++ b/drivers/gpu/drm/panel/panel-seiko-43wvf1g.c
@@ -44,8 +44,6 @@ struct seiko_panel_desc {
 
 struct seiko_panel {
struct drm_panel base;
-   bool prepared;
-   bool enabled;
const struct seiko_panel_desc *desc;
struct regulator *dvdd;
struct regulator *avdd;
@@ -122,25 +120,10 @@ static int seiko_panel_get_fixed_modes(struct seiko_panel 
*panel,
return num;
 }
 
-static int seiko_panel_disable(struct drm_panel *panel)
-{
-   struct seiko_panel *p = to_seiko_panel(panel);
-
-   if (!p->enabled)
-   return 0;
-
-   p->enabled = false;
-
-   return 0;
-}
-
 static int seiko_panel_unprepare(struct drm_panel *panel)
 {
struct seiko_panel *p = to_seiko_panel(panel);
 
-   if (!p->prepared)
-   return 0;
-
gpiod_set_value_cansleep(p->enable_gpio, 0);
 
regulator_disable(p->avdd);
@@ -150,8 +133,6 @@ static int seiko_panel_unprepare(struct drm_panel *panel)
 
regulator_disable(p->dvdd);
 
-   p->prepared = false;
-
return 0;
 }
 
@@ -160,9 +141,6 @@ static int seiko_panel_prepare(struct drm_panel *panel)
struct seiko_panel *p = to_seiko_panel(panel);
int err;
 
-   if (p->prepared)
-   return 0;
-
err = regulator_enable(p->dvdd);
if (err < 0) {
dev_err(panel->dev, "failed to enable dvdd: %d\n", err);
@@ -180,8 +158,6 @@ static int seiko_panel_prepare(struct drm_panel *panel)
 
gpiod_set_value_cansleep(p->enable_gpio, 1);
 
-   p->prepared = true;
-
return 0;
 
 disable_dvdd:
@@ -189,18 +165,6 @@ static int seiko_panel_prepare(struct drm_panel *panel)
return err;
 }
 
-static int seiko_panel_enable(struct drm_panel *panel)
-{
-   struct seiko_panel *p = to_seiko_panel(panel);
-
-   if (p->enabled)
-   return 0;
-
-   p->enabled = true;
-
-   return 0;
-}
-
 static int seiko_panel_get_modes(struct drm_panel *panel,
 struct drm_connector *connector)
 {
@@ -228,10 +192,8 @@ static int seiko_panel_get_timings(struct drm_panel *panel,
 }
 
 static const struct drm_panel_funcs seiko_panel_funcs = {
-   .disable = seiko_panel_disable,
.unprepare = seiko_panel_unprepare,
.prepare = seiko_panel_prepare,
-   .enable = seiko_panel_enable,
.get_modes = seiko_panel_get_modes,
.get_timings = seiko_panel_get_timings,
 };
@@ -246,8 +208,6 @@ static int seiko_panel_probe(struct device *dev,
if (!panel)
return -ENOMEM;
 
-   panel->enabled = false;
-   panel->prepared = false;
panel->desc = desc;
 
panel->dvdd = devm_regulator_get(dev, "dvdd");
-- 
2.45.1.288.g0e0cd299f1-goog



[PATCH v3 09/24] drm/panel: tdo-tl070wsh30: Stop tracking prepared

2024-06-04 Thread Douglas Anderson
As talked about in commit d2aacaf07395 ("drm/panel: Check for already
prepared/enabled in drm_panel"), we want to remove needless code from
panel drivers that was storing and double-checking the
prepared/enabled state. Even if someone was relying on the
double-check before, that double-check is now in the core and not
needed in individual drivers.

Cc: Neil Armstrong 
Acked-by: Linus Walleij 
Acked-by: Maxime Ripard 
Signed-off-by: Douglas Anderson 
---

(no changes since v2)

Changes in v2:
- Only handle 1 panel per patch.
- Split removal of prepared/enabled from handling of remove/shutdown.

 drivers/gpu/drm/panel/panel-tdo-tl070wsh30.c | 12 
 1 file changed, 12 deletions(-)

diff --git a/drivers/gpu/drm/panel/panel-tdo-tl070wsh30.c 
b/drivers/gpu/drm/panel/panel-tdo-tl070wsh30.c
index d8487bc6d611..36f27c664b69 100644
--- a/drivers/gpu/drm/panel/panel-tdo-tl070wsh30.c
+++ b/drivers/gpu/drm/panel/panel-tdo-tl070wsh30.c
@@ -24,8 +24,6 @@ struct tdo_tl070wsh30_panel {
 
struct regulator *supply;
struct gpio_desc *reset_gpio;
-
-   bool prepared;
 };
 
 static inline
@@ -39,9 +37,6 @@ static int tdo_tl070wsh30_panel_prepare(struct drm_panel 
*panel)
struct tdo_tl070wsh30_panel *tdo_tl070wsh30 = 
to_tdo_tl070wsh30_panel(panel);
int err;
 
-   if (tdo_tl070wsh30->prepared)
-   return 0;
-
err = regulator_enable(tdo_tl070wsh30->supply);
if (err < 0)
return err;
@@ -74,8 +69,6 @@ static int tdo_tl070wsh30_panel_prepare(struct drm_panel 
*panel)
 
msleep(20);
 
-   tdo_tl070wsh30->prepared = true;
-
return 0;
 }
 
@@ -84,9 +77,6 @@ static int tdo_tl070wsh30_panel_unprepare(struct drm_panel 
*panel)
struct tdo_tl070wsh30_panel *tdo_tl070wsh30 = 
to_tdo_tl070wsh30_panel(panel);
int err;
 
-   if (!tdo_tl070wsh30->prepared)
-   return 0;
-
err = mipi_dsi_dcs_set_display_off(tdo_tl070wsh30->link);
if (err < 0)
dev_err(panel->dev, "failed to set display off: %d\n", err);
@@ -103,8 +93,6 @@ static int tdo_tl070wsh30_panel_unprepare(struct drm_panel 
*panel)
 
regulator_disable(tdo_tl070wsh30->supply);
 
-   tdo_tl070wsh30->prepared = false;
-
return 0;
 }
 
-- 
2.45.1.288.g0e0cd299f1-goog



[PATCH v3 11/24] drm/panel: jdi-lt070me05000: Stop tracking prepared/enabled

2024-06-04 Thread Douglas Anderson
As talked about in commit d2aacaf07395 ("drm/panel: Check for already
prepared/enabled in drm_panel"), we want to remove needless code from
panel drivers that was storing and double-checking the
prepared/enabled state. Even if someone was relying on the
double-check before, that double-check is now in the core and not
needed in individual drivers.

NOTE: as part of this, transition the panel's direct calls to its
disable function in shutdown/remove to call through DRM panel.

Cc: Vinay Simha BN 
Cc: Sumit Semwal 
Acked-by: Linus Walleij 
Acked-by: Maxime Ripard 
Signed-off-by: Douglas Anderson 
---
Note: since we are able to identify that this panel only appears to be
used on Qualcomm boards and we have to touch the shutdown/remove path
in this patch anyway, we could possibly squash this with the next
patch that removes the disable call in shutdown/remove. For now I'm
keeping them separate just to keep the concepts separate.

(no changes since v2)

Changes in v2:
- Only handle 1 panel per patch.
- Split removal of prepared/enabled from handling of remove/shutdown.

 .../gpu/drm/panel/panel-jdi-lt070me05000.c| 27 ++-
 1 file changed, 2 insertions(+), 25 deletions(-)

diff --git a/drivers/gpu/drm/panel/panel-jdi-lt070me05000.c 
b/drivers/gpu/drm/panel/panel-jdi-lt070me05000.c
index f9a69f347068..4ee6fa1e 100644
--- a/drivers/gpu/drm/panel/panel-jdi-lt070me05000.c
+++ b/drivers/gpu/drm/panel/panel-jdi-lt070me05000.c
@@ -37,9 +37,6 @@ struct jdi_panel {
struct gpio_desc *dcdc_en_gpio;
struct backlight_device *backlight;
 
-   bool prepared;
-   bool enabled;
-
const struct drm_display_mode *mode;
 };
 
@@ -176,13 +173,8 @@ static int jdi_panel_disable(struct drm_panel *panel)
 {
struct jdi_panel *jdi = to_jdi_panel(panel);
 
-   if (!jdi->enabled)
-   return 0;
-
backlight_disable(jdi->backlight);
 
-   jdi->enabled = false;
-
return 0;
 }
 
@@ -192,9 +184,6 @@ static int jdi_panel_unprepare(struct drm_panel *panel)
struct device *dev = &jdi->dsi->dev;
int ret;
 
-   if (!jdi->prepared)
-   return 0;
-
jdi_panel_off(jdi);
 
ret = regulator_bulk_disable(ARRAY_SIZE(jdi->supplies), jdi->supplies);
@@ -207,8 +196,6 @@ static int jdi_panel_unprepare(struct drm_panel *panel)
 
gpiod_set_value(jdi->dcdc_en_gpio, 0);
 
-   jdi->prepared = false;
-
return 0;
 }
 
@@ -218,9 +205,6 @@ static int jdi_panel_prepare(struct drm_panel *panel)
struct device *dev = &jdi->dsi->dev;
int ret;
 
-   if (jdi->prepared)
-   return 0;
-
ret = regulator_bulk_enable(ARRAY_SIZE(jdi->supplies), jdi->supplies);
if (ret < 0) {
dev_err(dev, "regulator enable failed, %d\n", ret);
@@ -250,8 +234,6 @@ static int jdi_panel_prepare(struct drm_panel *panel)
goto poweroff;
}
 
-   jdi->prepared = true;
-
return 0;
 
 poweroff:
@@ -272,13 +254,8 @@ static int jdi_panel_enable(struct drm_panel *panel)
 {
struct jdi_panel *jdi = to_jdi_panel(panel);
 
-   if (jdi->enabled)
-   return 0;
-
backlight_enable(jdi->backlight);
 
-   jdi->enabled = true;
-
return 0;
 }
 
@@ -475,7 +452,7 @@ static void jdi_panel_remove(struct mipi_dsi_device *dsi)
struct jdi_panel *jdi = mipi_dsi_get_drvdata(dsi);
int ret;
 
-   ret = jdi_panel_disable(&jdi->base);
+   ret = drm_panel_disable(&jdi->base);
if (ret < 0)
dev_err(&dsi->dev, "failed to disable panel: %d\n", ret);
 
@@ -491,7 +468,7 @@ static void jdi_panel_shutdown(struct mipi_dsi_device *dsi)
 {
struct jdi_panel *jdi = mipi_dsi_get_drvdata(dsi);
 
-   jdi_panel_disable(&jdi->base);
+   drm_panel_disable(&jdi->base);
 }
 
 static struct mipi_dsi_driver jdi_panel_driver = {
-- 
2.45.1.288.g0e0cd299f1-goog



[PATCH v3 08/24] drm/panel: osd-osd101t2587-53ts: Don't call unprepare+disable at shutdown/remove

2024-06-04 Thread Douglas Anderson
It's the responsibility of a correctly written DRM modeset driver to
call drm_atomic_helper_shutdown() at shutdown time and that should be
disabling / unpreparing the panel if needed. Panel drivers shouldn't
be calling these functions themselves.

A recent effort was made to fix as many DRM modeset drivers as
possible [1] [2] [3] and most drivers are fixed now.

A grep through mainline for compatible strings used by this driver
indicates that it is used by TI OMAP boards. The OMAP driver appears
to be correctly calling drm_atomic_helper_shutdown() so we can remove
the calls.

[1] https://lore.kernel.org/r/20230901234015.566018-1-diand...@chromium.org
[2] https://lore.kernel.org/r/20230901234202.566951-1-diand...@chromium.org
[3] https://lore.kernel.org/r/20230921192749.1542462-1-diand...@chromium.org

Cc: Peter Ujfalusi 
Acked-by: Linus Walleij 
Acked-by: Maxime Ripard 
Signed-off-by: Douglas Anderson 
---

(no changes since v2)

Changes in v2:
- Only handle 1 panel per patch.
- Split removal of prepared/enabled from handling of remove/shutdown.

 drivers/gpu/drm/panel/panel-osd-osd101t2587-53ts.c | 14 --
 1 file changed, 14 deletions(-)

diff --git a/drivers/gpu/drm/panel/panel-osd-osd101t2587-53ts.c 
b/drivers/gpu/drm/panel/panel-osd-osd101t2587-53ts.c
index c0da7d9512e8..dbea84f51514 100644
--- a/drivers/gpu/drm/panel/panel-osd-osd101t2587-53ts.c
+++ b/drivers/gpu/drm/panel/panel-osd-osd101t2587-53ts.c
@@ -186,11 +186,6 @@ static void osd101t2587_panel_remove(struct 
mipi_dsi_device *dsi)
struct osd101t2587_panel *osd101t2587 = mipi_dsi_get_drvdata(dsi);
int ret;
 
-   ret = drm_panel_disable(&osd101t2587->base);
-   if (ret < 0)
-   dev_warn(&dsi->dev, "failed to disable panel: %d\n", ret);
-
-   drm_panel_unprepare(&osd101t2587->base);
drm_panel_remove(&osd101t2587->base);
 
ret = mipi_dsi_detach(dsi);
@@ -198,14 +193,6 @@ static void osd101t2587_panel_remove(struct 
mipi_dsi_device *dsi)
dev_err(&dsi->dev, "failed to detach from DSI host: %d\n", ret);
 }
 
-static void osd101t2587_panel_shutdown(struct mipi_dsi_device *dsi)
-{
-   struct osd101t2587_panel *osd101t2587 = mipi_dsi_get_drvdata(dsi);
-
-   drm_panel_disable(&osd101t2587->base);
-   drm_panel_unprepare(&osd101t2587->base);
-}
-
 static struct mipi_dsi_driver osd101t2587_panel_driver = {
.driver = {
.name = "panel-osd-osd101t2587-53ts",
@@ -213,7 +200,6 @@ static struct mipi_dsi_driver osd101t2587_panel_driver = {
},
.probe = osd101t2587_panel_probe,
.remove = osd101t2587_panel_remove,
-   .shutdown = osd101t2587_panel_shutdown,
 };
 module_mipi_dsi_driver(osd101t2587_panel_driver);
 
-- 
2.45.1.288.g0e0cd299f1-goog



[PATCH v3 10/24] drm/panel: tdo-tl070wsh30: Don't call unprepare+disable at shutdown/remove

2024-06-04 Thread Douglas Anderson
It's the responsibility of a correctly written DRM modeset driver to
call drm_atomic_helper_shutdown() at shutdown time and that should be
disabling / unpreparing the panel if needed. Panel drivers shouldn't
be calling these functions themselves.

A recent effort was made to fix as many DRM modeset drivers as
possible [1] [2] [3] and most drivers are fixed now.

Unfortunately, grepping mainline for this panel's compatible string
shows no hits, so we can't be 100% sure if the DRM modeset driver used
with this panel has been fixed. If it is found that the DRM modeset
driver hasn't been fixed then this patch could be temporarily reverted
until it is.

[1] https://lore.kernel.org/r/20230901234015.566018-1-diand...@chromium.org
[2] https://lore.kernel.org/r/20230901234202.566951-1-diand...@chromium.org
[3] https://lore.kernel.org/r/20230921192749.1542462-1-diand...@chromium.org

Cc: Neil Armstrong 
Acked-by: Linus Walleij 
Acked-by: Maxime Ripard 
Signed-off-by: Douglas Anderson 
---

(no changes since v2)

Changes in v2:
- Only handle 1 panel per patch.
- Split removal of prepared/enabled from handling of remove/shutdown.

 drivers/gpu/drm/panel/panel-tdo-tl070wsh30.c | 11 ---
 1 file changed, 11 deletions(-)

diff --git a/drivers/gpu/drm/panel/panel-tdo-tl070wsh30.c 
b/drivers/gpu/drm/panel/panel-tdo-tl070wsh30.c
index 36f27c664b69..227f97f9b136 100644
--- a/drivers/gpu/drm/panel/panel-tdo-tl070wsh30.c
+++ b/drivers/gpu/drm/panel/panel-tdo-tl070wsh30.c
@@ -208,16 +208,6 @@ static void tdo_tl070wsh30_panel_remove(struct 
mipi_dsi_device *dsi)
dev_err(&dsi->dev, "failed to detach from DSI host: %d\n", err);
 
drm_panel_remove(&tdo_tl070wsh30->base);
-   drm_panel_disable(&tdo_tl070wsh30->base);
-   drm_panel_unprepare(&tdo_tl070wsh30->base);
-}
-
-static void tdo_tl070wsh30_panel_shutdown(struct mipi_dsi_device *dsi)
-{
-   struct tdo_tl070wsh30_panel *tdo_tl070wsh30 = mipi_dsi_get_drvdata(dsi);
-
-   drm_panel_disable(&tdo_tl070wsh30->base);
-   drm_panel_unprepare(&tdo_tl070wsh30->base);
 }
 
 static struct mipi_dsi_driver tdo_tl070wsh30_panel_driver = {
@@ -227,7 +217,6 @@ static struct mipi_dsi_driver tdo_tl070wsh30_panel_driver = 
{
},
.probe = tdo_tl070wsh30_panel_probe,
.remove = tdo_tl070wsh30_panel_remove,
-   .shutdown = tdo_tl070wsh30_panel_shutdown,
 };
 module_mipi_dsi_driver(tdo_tl070wsh30_panel_driver);
 
-- 
2.45.1.288.g0e0cd299f1-goog



[PATCH v3 07/24] drm/panel: osd-osd101t2587-53ts: Stop tracking prepared/enabled

2024-06-04 Thread Douglas Anderson
As talked about in commit d2aacaf07395 ("drm/panel: Check for already
prepared/enabled in drm_panel"), we want to remove needless code from
panel drivers that was storing and double-checking the
prepared/enabled state. Even if someone was relying on the
double-check before, that double-check is now in the core and not
needed in individual drivers.

Cc: Peter Ujfalusi 
Acked-by: Linus Walleij 
Acked-by: Maxime Ripard 
Signed-off-by: Douglas Anderson 
---

(no changes since v2)

Changes in v2:
- Only handle 1 panel per patch.
- Split removal of prepared/enabled from handling of remove/shutdown.

 .../drm/panel/panel-osd-osd101t2587-53ts.c| 27 +--
 1 file changed, 1 insertion(+), 26 deletions(-)

diff --git a/drivers/gpu/drm/panel/panel-osd-osd101t2587-53ts.c 
b/drivers/gpu/drm/panel/panel-osd-osd101t2587-53ts.c
index 493e0504f6f7..c0da7d9512e8 100644
--- a/drivers/gpu/drm/panel/panel-osd-osd101t2587-53ts.c
+++ b/drivers/gpu/drm/panel/panel-osd-osd101t2587-53ts.c
@@ -21,9 +21,6 @@ struct osd101t2587_panel {
 
struct regulator *supply;
 
-   bool prepared;
-   bool enabled;
-
const struct drm_display_mode *default_mode;
 };
 
@@ -37,13 +34,8 @@ static int osd101t2587_panel_disable(struct drm_panel *panel)
struct osd101t2587_panel *osd101t2587 = ti_osd_panel(panel);
int ret;
 
-   if (!osd101t2587->enabled)
-   return 0;
-
ret = mipi_dsi_shutdown_peripheral(osd101t2587->dsi);
 
-   osd101t2587->enabled = false;
-
return ret;
 }
 
@@ -51,11 +43,7 @@ static int osd101t2587_panel_unprepare(struct drm_panel 
*panel)
 {
struct osd101t2587_panel *osd101t2587 = ti_osd_panel(panel);
 
-   if (!osd101t2587->prepared)
-   return 0;
-
regulator_disable(osd101t2587->supply);
-   osd101t2587->prepared = false;
 
return 0;
 }
@@ -63,16 +51,8 @@ static int osd101t2587_panel_unprepare(struct drm_panel 
*panel)
 static int osd101t2587_panel_prepare(struct drm_panel *panel)
 {
struct osd101t2587_panel *osd101t2587 = ti_osd_panel(panel);
-   int ret;
 
-   if (osd101t2587->prepared)
-   return 0;
-
-   ret = regulator_enable(osd101t2587->supply);
-   if (!ret)
-   osd101t2587->prepared = true;
-
-   return ret;
+   return regulator_enable(osd101t2587->supply);
 }
 
 static int osd101t2587_panel_enable(struct drm_panel *panel)
@@ -80,15 +60,10 @@ static int osd101t2587_panel_enable(struct drm_panel *panel)
struct osd101t2587_panel *osd101t2587 = ti_osd_panel(panel);
int ret;
 
-   if (osd101t2587->enabled)
-   return 0;
-
ret = mipi_dsi_turn_on_peripheral(osd101t2587->dsi);
if (ret)
return ret;
 
-   osd101t2587->enabled = true;
-
return ret;
 }
 
-- 
2.45.1.288.g0e0cd299f1-goog



[PATCH v3 06/24] drm/panel: olimex-lcd-olinuxino: Don't call unprepare+disable at remove

2024-06-04 Thread Douglas Anderson
It's the responsibility of a correctly written DRM modeset driver to
call drm_atomic_helper_shutdown() at shutdown time and that should be
disabling / unpreparing the panel if needed. Panel drivers shouldn't
be calling these functions themselves.

A recent effort was made to fix as many DRM modeset drivers as
possible [1] [2] [3] and most drivers are fixed now.

Unfortunately, grepping mainline for this panel's compatible string
shows no hits, so we can't be 100% sure if the DRM modeset driver used
with this panel has been fixed. If it is found that the DRM modeset
driver hasn't been fixed then this patch could be temporarily reverted
until it is.

[1] https://lore.kernel.org/r/20230901234015.566018-1-diand...@chromium.org
[2] https://lore.kernel.org/r/20230901234202.566951-1-diand...@chromium.org
[3] https://lore.kernel.org/r/20230921192749.1542462-1-diand...@chromium.org

Acked-by: Linus Walleij 
Acked-by: Maxime Ripard 
Signed-off-by: Douglas Anderson 
---

(no changes since v2)

Changes in v2:
- Only handle 1 panel per patch.
- Split removal of prepared/enabled from handling of remove/shutdown.

 drivers/gpu/drm/panel/panel-olimex-lcd-olinuxino.c | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/drivers/gpu/drm/panel/panel-olimex-lcd-olinuxino.c 
b/drivers/gpu/drm/panel/panel-olimex-lcd-olinuxino.c
index 8a687d3ba236..94ae8c8270b8 100644
--- a/drivers/gpu/drm/panel/panel-olimex-lcd-olinuxino.c
+++ b/drivers/gpu/drm/panel/panel-olimex-lcd-olinuxino.c
@@ -251,9 +251,6 @@ static void lcd_olinuxino_remove(struct i2c_client *client)
struct lcd_olinuxino *panel = i2c_get_clientdata(client);
 
drm_panel_remove(&panel->panel);
-
-   drm_panel_disable(&panel->panel);
-   drm_panel_unprepare(&panel->panel);
 }
 
 static const struct of_device_id lcd_olinuxino_of_ids[] = {
-- 
2.45.1.288.g0e0cd299f1-goog



[PATCH v3 05/24] drm/panel: olimex-lcd-olinuxino: Stop tracking prepared/enabled

2024-06-04 Thread Douglas Anderson
As talked about in commit d2aacaf07395 ("drm/panel: Check for already
prepared/enabled in drm_panel"), we want to remove needless code from
panel drivers that was storing and double-checking the
prepared/enabled state. Even if someone was relying on the
double-check before, that double-check is now in the core and not
needed in individual drivers.

Acked-by: Linus Walleij 
Acked-by: Maxime Ripard 
Signed-off-by: Douglas Anderson 
---

(no changes since v2)

Changes in v2:
- Only handle 1 panel per patch.
- Split removal of prepared/enabled from handling of remove/shutdown.

 .../drm/panel/panel-olimex-lcd-olinuxino.c| 41 ---
 1 file changed, 41 deletions(-)

diff --git a/drivers/gpu/drm/panel/panel-olimex-lcd-olinuxino.c 
b/drivers/gpu/drm/panel/panel-olimex-lcd-olinuxino.c
index 4819ada69482..8a687d3ba236 100644
--- a/drivers/gpu/drm/panel/panel-olimex-lcd-olinuxino.c
+++ b/drivers/gpu/drm/panel/panel-olimex-lcd-olinuxino.c
@@ -64,9 +64,6 @@ struct lcd_olinuxino {
struct i2c_client *client;
struct mutex mutex;
 
-   bool prepared;
-   bool enabled;
-
struct regulator *supply;
struct gpio_desc *enable_gpio;
 
@@ -78,30 +75,13 @@ static inline struct lcd_olinuxino *to_lcd_olinuxino(struct 
drm_panel *panel)
return container_of(panel, struct lcd_olinuxino, panel);
 }
 
-static int lcd_olinuxino_disable(struct drm_panel *panel)
-{
-   struct lcd_olinuxino *lcd = to_lcd_olinuxino(panel);
-
-   if (!lcd->enabled)
-   return 0;
-
-   lcd->enabled = false;
-
-   return 0;
-}
-
 static int lcd_olinuxino_unprepare(struct drm_panel *panel)
 {
struct lcd_olinuxino *lcd = to_lcd_olinuxino(panel);
 
-   if (!lcd->prepared)
-   return 0;
-
gpiod_set_value_cansleep(lcd->enable_gpio, 0);
regulator_disable(lcd->supply);
 
-   lcd->prepared = false;
-
return 0;
 }
 
@@ -110,27 +90,11 @@ static int lcd_olinuxino_prepare(struct drm_panel *panel)
struct lcd_olinuxino *lcd = to_lcd_olinuxino(panel);
int ret;
 
-   if (lcd->prepared)
-   return 0;
-
ret = regulator_enable(lcd->supply);
if (ret < 0)
return ret;
 
gpiod_set_value_cansleep(lcd->enable_gpio, 1);
-   lcd->prepared = true;
-
-   return 0;
-}
-
-static int lcd_olinuxino_enable(struct drm_panel *panel)
-{
-   struct lcd_olinuxino *lcd = to_lcd_olinuxino(panel);
-
-   if (lcd->enabled)
-   return 0;
-
-   lcd->enabled = true;
 
return 0;
 }
@@ -195,10 +159,8 @@ static int lcd_olinuxino_get_modes(struct drm_panel *panel,
 }
 
 static const struct drm_panel_funcs lcd_olinuxino_funcs = {
-   .disable = lcd_olinuxino_disable,
.unprepare = lcd_olinuxino_unprepare,
.prepare = lcd_olinuxino_prepare,
-   .enable = lcd_olinuxino_enable,
.get_modes = lcd_olinuxino_get_modes,
 };
 
@@ -264,9 +226,6 @@ static int lcd_olinuxino_probe(struct i2c_client *client)
lcd->eeprom.num_modes = 4;
}
 
-   lcd->enabled = false;
-   lcd->prepared = false;
-
lcd->supply = devm_regulator_get(dev, "power");
if (IS_ERR(lcd->supply))
return PTR_ERR(lcd->supply);
-- 
2.45.1.288.g0e0cd299f1-goog



[PATCH v3 03/24] drm/panel: khadas-ts050: Stop tracking prepared/enabled

2024-06-04 Thread Douglas Anderson
As talked about in commit d2aacaf07395 ("drm/panel: Check for already
prepared/enabled in drm_panel"), we want to remove needless code from
panel drivers that was storing and double-checking the
prepared/enabled state. Even if someone was relying on the
double-check before, that double-check is now in the core and not
needed in individual drivers.

Cc: Jacobe Zang 
Cc: Nicolas Belin 
Cc: Neil Armstrong 
Acked-by: Linus Walleij 
Acked-by: Maxime Ripard 
Signed-off-by: Douglas Anderson 
---

(no changes since v2)

Changes in v2:
- Only handle 1 panel per patch.
- Split removal of prepared/enabled from handling of remove/shutdown.

 drivers/gpu/drm/panel/panel-khadas-ts050.c | 28 --
 1 file changed, 28 deletions(-)

diff --git a/drivers/gpu/drm/panel/panel-khadas-ts050.c 
b/drivers/gpu/drm/panel/panel-khadas-ts050.c
index c54be0cc3f08..e35762ebdbd1 100644
--- a/drivers/gpu/drm/panel/panel-khadas-ts050.c
+++ b/drivers/gpu/drm/panel/panel-khadas-ts050.c
@@ -26,9 +26,6 @@ struct khadas_ts050_panel {
struct gpio_desc *reset_gpio;
struct gpio_desc *enable_gpio;
struct khadas_ts050_panel_data *panel_data;
-
-   bool prepared;
-   bool enabled;
 };
 
 struct khadas_ts050_panel_cmd {
@@ -642,9 +639,6 @@ static int khadas_ts050_panel_prepare(struct drm_panel 
*panel)
unsigned int i;
int err;
 
-   if (khadas_ts050->prepared)
-   return 0;
-
gpiod_set_value_cansleep(khadas_ts050->enable_gpio, 0);
 
err = regulator_enable(khadas_ts050->supply);
@@ -708,8 +702,6 @@ static int khadas_ts050_panel_prepare(struct drm_panel 
*panel)
 
usleep_range(1, 11000);
 
-   khadas_ts050->prepared = true;
-
return 0;
 
 poweroff:
@@ -726,11 +718,6 @@ static int khadas_ts050_panel_unprepare(struct drm_panel 
*panel)
struct khadas_ts050_panel *khadas_ts050 = to_khadas_ts050_panel(panel);
int err;
 
-   if (!khadas_ts050->prepared)
-   return 0;
-
-   khadas_ts050->prepared = false;
-
err = mipi_dsi_dcs_enter_sleep_mode(khadas_ts050->link);
if (err < 0)
dev_err(panel->dev, "failed to enter sleep mode: %d\n", err);
@@ -747,31 +734,17 @@ static int khadas_ts050_panel_unprepare(struct drm_panel 
*panel)
return 0;
 }
 
-static int khadas_ts050_panel_enable(struct drm_panel *panel)
-{
-   struct khadas_ts050_panel *khadas_ts050 = to_khadas_ts050_panel(panel);
-
-   khadas_ts050->enabled = true;
-
-   return 0;
-}
-
 static int khadas_ts050_panel_disable(struct drm_panel *panel)
 {
struct khadas_ts050_panel *khadas_ts050 = to_khadas_ts050_panel(panel);
int err;
 
-   if (!khadas_ts050->enabled)
-   return 0;
-
err = mipi_dsi_dcs_set_display_off(khadas_ts050->link);
if (err < 0)
dev_err(panel->dev, "failed to set display off: %d\n", err);
 
usleep_range(1, 11000);
 
-   khadas_ts050->enabled = false;
-
return 0;
 }
 
@@ -815,7 +788,6 @@ static int khadas_ts050_panel_get_modes(struct drm_panel 
*panel,
 static const struct drm_panel_funcs khadas_ts050_panel_funcs = {
.prepare = khadas_ts050_panel_prepare,
.unprepare = khadas_ts050_panel_unprepare,
-   .enable = khadas_ts050_panel_enable,
.disable = khadas_ts050_panel_disable,
.get_modes = khadas_ts050_panel_get_modes,
 };
-- 
2.45.1.288.g0e0cd299f1-goog



[PATCH v3 04/24] drm/panel: khadas-ts050: Don't call unprepare+disable at shutdown/remove

2024-06-04 Thread Douglas Anderson
It's the responsibility of a correctly written DRM modeset driver to
call drm_atomic_helper_shutdown() at shutdown time and that should be
disabling / unpreparing the panel if needed. Panel drivers shouldn't
be calling these functions themselves.

A recent effort was made to fix as many DRM modeset drivers as
possible [1] [2] [3] and most drivers are fixed now.

Unfortunately, grepping mainline for this panel's compatible string
shows no hits, so we can't be 100% sure if the DRM modeset driver used
with this panel has been fixed. If it is found that the DRM modeset
driver hasn't been fixed then this patch could be temporarily reverted
until it is.

[1] https://lore.kernel.org/r/20230901234015.566018-1-diand...@chromium.org
[2] https://lore.kernel.org/r/20230901234202.566951-1-diand...@chromium.org
[3] https://lore.kernel.org/r/20230921192749.1542462-1-diand...@chromium.org

Cc: Jacobe Zang 
Cc: Nicolas Belin 
Cc: Neil Armstrong 
Acked-by: Linus Walleij 
Acked-by: Maxime Ripard 
Signed-off-by: Douglas Anderson 
---

(no changes since v2)

Changes in v2:
- Only handle 1 panel per patch.
- Split removal of prepared/enabled from handling of remove/shutdown.

 drivers/gpu/drm/panel/panel-khadas-ts050.c | 11 ---
 1 file changed, 11 deletions(-)

diff --git a/drivers/gpu/drm/panel/panel-khadas-ts050.c 
b/drivers/gpu/drm/panel/panel-khadas-ts050.c
index e35762ebdbd1..14932cb3defc 100644
--- a/drivers/gpu/drm/panel/panel-khadas-ts050.c
+++ b/drivers/gpu/drm/panel/panel-khadas-ts050.c
@@ -880,16 +880,6 @@ static void khadas_ts050_panel_remove(struct 
mipi_dsi_device *dsi)
dev_err(&dsi->dev, "failed to detach from DSI host: %d\n", err);
 
drm_panel_remove(&khadas_ts050->base);
-   drm_panel_disable(&khadas_ts050->base);
-   drm_panel_unprepare(&khadas_ts050->base);
-}
-
-static void khadas_ts050_panel_shutdown(struct mipi_dsi_device *dsi)
-{
-   struct khadas_ts050_panel *khadas_ts050 = mipi_dsi_get_drvdata(dsi);
-
-   drm_panel_disable(&khadas_ts050->base);
-   drm_panel_unprepare(&khadas_ts050->base);
 }
 
 static struct mipi_dsi_driver khadas_ts050_panel_driver = {
@@ -899,7 +889,6 @@ static struct mipi_dsi_driver khadas_ts050_panel_driver = {
},
.probe = khadas_ts050_panel_probe,
.remove = khadas_ts050_panel_remove,
-   .shutdown = khadas_ts050_panel_shutdown,
 };
 module_mipi_dsi_driver(khadas_ts050_panel_driver);
 
-- 
2.45.1.288.g0e0cd299f1-goog



[PATCH v3 02/24] drm/panel: boe-himax8279d: Don't call unprepare+disable at shutdown/remove

2024-06-04 Thread Douglas Anderson
It's the responsibility of a correctly written DRM modeset driver to
call drm_atomic_helper_shutdown() at shutdown time and that should be
disabling / unpreparing the panel if needed. Panel drivers shouldn't
be calling these functions themselves.

A recent effort was made to fix as many DRM modeset drivers as
possible [1] [2] [3] and most drivers are fixed now.

Unfortunately, grepping mainline for this panel's compatible string
shows no hits, so we can't be 100% sure if the DRM modeset driver used
with this panel has been fixed. If it is found that the DRM modeset
driver hasn't been fixed then this patch could be temporarily reverted
until it is.

[1] https://lore.kernel.org/r/20230901234015.566018-1-diand...@chromium.org
[2] https://lore.kernel.org/r/20230901234202.566951-1-diand...@chromium.org
[3] https://lore.kernel.org/r/20230921192749.1542462-1-diand...@chromium.org

Cc: Jerry Han 
Cc: Jitao Shi 
Cc: Rock Wang 
Acked-by: Linus Walleij 
Acked-by: Maxime Ripard 
Signed-off-by: Douglas Anderson 
---

(no changes since v2)

Changes in v2:
- Only handle 1 panel per patch.
- Split removal of prepared/enabled from handling of remove/shutdown.

 drivers/gpu/drm/panel/panel-boe-himax8279d.c | 17 -
 1 file changed, 17 deletions(-)

diff --git a/drivers/gpu/drm/panel/panel-boe-himax8279d.c 
b/drivers/gpu/drm/panel/panel-boe-himax8279d.c
index 12e14615298b..df746baae301 100644
--- a/drivers/gpu/drm/panel/panel-boe-himax8279d.c
+++ b/drivers/gpu/drm/panel/panel-boe-himax8279d.c
@@ -894,14 +894,6 @@ static void panel_remove(struct mipi_dsi_device *dsi)
struct panel_info *pinfo = mipi_dsi_get_drvdata(dsi);
int err;
 
-   err = drm_panel_disable(&pinfo->base);
-   if (err < 0)
-   dev_err(&dsi->dev, "failed to disable panel: %d\n", err);
-
-   err = drm_panel_unprepare(&pinfo->base);
-   if (err < 0)
-   dev_err(&dsi->dev, "failed to unprepare panel: %d\n", err);
-
err = mipi_dsi_detach(dsi);
if (err < 0)
dev_err(&dsi->dev, "failed to detach from DSI host: %d\n", err);
@@ -909,14 +901,6 @@ static void panel_remove(struct mipi_dsi_device *dsi)
drm_panel_remove(&pinfo->base);
 }
 
-static void panel_shutdown(struct mipi_dsi_device *dsi)
-{
-   struct panel_info *pinfo = mipi_dsi_get_drvdata(dsi);
-
-   drm_panel_disable(&pinfo->base);
-   drm_panel_unprepare(&pinfo->base);
-}
-
 static struct mipi_dsi_driver panel_driver = {
.driver = {
.name = "panel-boe-himax8279d",
@@ -924,7 +908,6 @@ static struct mipi_dsi_driver panel_driver = {
},
.probe = panel_probe,
.remove = panel_remove,
-   .shutdown = panel_shutdown,
 };
 module_mipi_dsi_driver(panel_driver);
 
-- 
2.45.1.288.g0e0cd299f1-goog



[PATCH v3 01/24] drm/panel: boe-himax8279d: Stop tracking prepared/enabled

2024-06-04 Thread Douglas Anderson
As talked about in commit d2aacaf07395 ("drm/panel: Check for already
prepared/enabled in drm_panel"), we want to remove needless code from
panel drivers that was storing and double-checking the
prepared/enabled state. Even if someone was relying on the
double-check before, that double-check is now in the core and not
needed in individual drivers.

NOTE: as part of this, transition the panel's direct calls to its
disable/unprepare functions in shutdown/remove to call through DRM
panel.

Cc: Jerry Han 
Cc: Jitao Shi 
Cc: Rock Wang 
Acked-by: Linus Walleij 
Acked-by: Maxime Ripard 
Signed-off-by: Douglas Anderson 
---

(no changes since v2)

Changes in v2:
- Only handle 1 panel per patch.
- Split removal of prepared/enabled from handling of remove/shutdown.

 drivers/gpu/drm/panel/panel-boe-himax8279d.c | 31 +++-
 1 file changed, 4 insertions(+), 27 deletions(-)

diff --git a/drivers/gpu/drm/panel/panel-boe-himax8279d.c 
b/drivers/gpu/drm/panel/panel-boe-himax8279d.c
index e225840b0d67..12e14615298b 100644
--- a/drivers/gpu/drm/panel/panel-boe-himax8279d.c
+++ b/drivers/gpu/drm/panel/panel-boe-himax8279d.c
@@ -47,9 +47,6 @@ struct panel_info {
struct gpio_desc *enable_gpio;
struct gpio_desc *pp33_gpio;
struct gpio_desc *pp18_gpio;
-
-   bool prepared;
-   bool enabled;
 };
 
 static inline struct panel_info *to_panel_info(struct drm_panel *panel)
@@ -86,17 +83,12 @@ static int boe_panel_disable(struct drm_panel *panel)
struct panel_info *pinfo = to_panel_info(panel);
int err;
 
-   if (!pinfo->enabled)
-   return 0;
-
err = mipi_dsi_dcs_set_display_off(pinfo->link);
if (err < 0) {
dev_err(panel->dev, "failed to set display off: %d\n", err);
return err;
}
 
-   pinfo->enabled = false;
-
return 0;
 }
 
@@ -105,9 +97,6 @@ static int boe_panel_unprepare(struct drm_panel *panel)
struct panel_info *pinfo = to_panel_info(panel);
int err;
 
-   if (!pinfo->prepared)
-   return 0;
-
err = mipi_dsi_dcs_set_display_off(pinfo->link);
if (err < 0)
dev_err(panel->dev, "failed to set display off: %d\n", err);
@@ -121,8 +110,6 @@ static int boe_panel_unprepare(struct drm_panel *panel)
 
disable_gpios(pinfo);
 
-   pinfo->prepared = false;
-
return 0;
 }
 
@@ -131,9 +118,6 @@ static int boe_panel_prepare(struct drm_panel *panel)
struct panel_info *pinfo = to_panel_info(panel);
int err;
 
-   if (pinfo->prepared)
-   return 0;
-
gpiod_set_value(pinfo->pp18_gpio, 1);
/* T1: 5ms - 6ms */
usleep_range(5000, 6000);
@@ -180,8 +164,6 @@ static int boe_panel_prepare(struct drm_panel *panel)
/* T7: 20ms - 21ms */
usleep_range(2, 21000);
 
-   pinfo->prepared = true;
-
return 0;
 
 poweroff:
@@ -194,9 +176,6 @@ static int boe_panel_enable(struct drm_panel *panel)
struct panel_info *pinfo = to_panel_info(panel);
int ret;
 
-   if (pinfo->enabled)
-   return 0;
-
usleep_range(12, 121000);
 
ret = mipi_dsi_dcs_set_display_on(pinfo->link);
@@ -205,8 +184,6 @@ static int boe_panel_enable(struct drm_panel *panel)
return ret;
}
 
-   pinfo->enabled = true;
-
return 0;
 }
 
@@ -917,11 +894,11 @@ static void panel_remove(struct mipi_dsi_device *dsi)
struct panel_info *pinfo = mipi_dsi_get_drvdata(dsi);
int err;
 
-   err = boe_panel_disable(&pinfo->base);
+   err = drm_panel_disable(&pinfo->base);
if (err < 0)
dev_err(&dsi->dev, "failed to disable panel: %d\n", err);
 
-   err = boe_panel_unprepare(&pinfo->base);
+   err = drm_panel_unprepare(&pinfo->base);
if (err < 0)
dev_err(&dsi->dev, "failed to unprepare panel: %d\n", err);
 
@@ -936,8 +913,8 @@ static void panel_shutdown(struct mipi_dsi_device *dsi)
 {
struct panel_info *pinfo = mipi_dsi_get_drvdata(dsi);
 
-   boe_panel_disable(&pinfo->base);
-   boe_panel_unprepare(&pinfo->base);
+   drm_panel_disable(&pinfo->base);
+   drm_panel_unprepare(&pinfo->base);
 }
 
 static struct mipi_dsi_driver panel_driver = {
-- 
2.45.1.288.g0e0cd299f1-goog



[PATCH v3 00/24] drm/panel: Remove most store/double-check of prepared/enabled state

2024-06-04 Thread Douglas Anderson


As talked about in commit d2aacaf07395 ("drm/panel: Check for already
prepared/enabled in drm_panel"), we want to remove needless code from
panel drivers that was storing and double-checking the
prepared/enabled state. Even if someone was relying on the
double-check before, that double-check is now in the core and not
needed in individual drivers.

This series attempts to do just that. While the original grep, AKA:
  git grep 'if.*>prepared' -- drivers/gpu/drm/panel
  git grep 'if.*>enabled' -- drivers/gpu/drm/panel
...still produces a few hits after my series, they are _mostly_ all
gone. The ones that are left are less trivial to fix.

One of the main reasons that many panels probably needed to store and
double-check their prepared/enabled appears to have been to handle
shutdown and/or remove. Panels drivers often wanted to force the power
off for panels in these cases and this was a good reason for the
double-check.

In response to my V1 series [1] we had much discussion of what to
do. The conclusion was that as long as DRM modeset drivers properly
called drm_atomic_helper_shutdown() that we should be able to remove
the explicit shutdown/remove handling in the panel drivers. Most of
the patches to improve DRM modeset drivers [2] [3] [4] have now
landed.

In contrast to my V1 series, I broke the V2 series up a lot
more. Since a few of the panel drivers in V1 already landed, we had
fewer total drivers and so we could devote a patch to each panel.
Also, since we were now relying on DRM modeset drivers I felt like we
should split the patches for each panel into two: one that's
definitely safe and one that could be reverted if we found a
problematic DRM modeset driver that we couldn't fix.

Many of the patches in the V2 series [5] landed, so this V3 series is
the patches that are left plus one new bonus patch. At this point, we
may want to just land the patches that are left since it seems like
nobody is going to test/review them and they've all been Acked by
Linus and Maxime.

NOTE: this touches _a lot_ of drivers, is repetitive, and is not
really possible to generate automatically. That means it's entirely
possible that my eyes glazed over and I did something wrong. Please
double-check me and don't assume that I got everything perfect, though
I did my best. I have at least confirmed that "allmodconfig" for arm64
doesn't fall on its face with this series. I haven't done a ton of
other testing.

[1] 
https://lore.kernel.org/r/20230804140605.RFC.4.I930069a32baab6faf46d6b234f89613b5cec0f14@changeid
[2] https://lore.kernel.org/r/20230901234015.566018-1-diand...@chromium.org
[3] https://lore.kernel.org/r/20230901234202.566951-1-diand...@chromium.org
[4] https://lore.kernel.org/r/20230921192749.1542462-1-diand...@chromium.org
[5] https://lore.kernel.org/r/20240503213441.177109-1-diand...@chromium.org/

Changes in v3:
- drm/panel: Avoid warnings w/ panel-simple/panel-edp at shutdown

Changes in v2:
- Only handle 1 panel per patch.
- Split removal of prepared/enabled from handling of remove/shutdown.

Douglas Anderson (24):
  drm/panel: boe-himax8279d: Stop tracking prepared/enabled
  drm/panel: boe-himax8279d: Don't call unprepare+disable at
shutdown/remove
  drm/panel: khadas-ts050: Stop tracking prepared/enabled
  drm/panel: khadas-ts050: Don't call unprepare+disable at
shutdown/remove
  drm/panel: olimex-lcd-olinuxino: Stop tracking prepared/enabled
  drm/panel: olimex-lcd-olinuxino: Don't call unprepare+disable at
remove
  drm/panel: osd-osd101t2587-53ts: Stop tracking prepared/enabled
  drm/panel: osd-osd101t2587-53ts: Don't call unprepare+disable at
shutdown/remove
  drm/panel: tdo-tl070wsh30: Stop tracking prepared
  drm/panel: tdo-tl070wsh30: Don't call unprepare+disable at
shutdown/remove
  drm/panel: jdi-lt070me05000: Stop tracking prepared/enabled
  drm/panel: jdi-lt070me05000: Don't call disable at shutdown/remove
  drm/panel: panasonic-vvx10f034n00: Stop tracking prepared/enabled
  drm/panel: panasonic-vvx10f034n00: Don't call disable at
shutdown/remove
  drm/panel: seiko-43wvf1g: Stop tracking prepared/enabled
  drm/panel: seiko-43wvf1g: Don't call disable at shutdown/remove
  drm/panel: sharp-lq101r1sx01: Stop tracking prepared/enabled
  drm/panel: sharp-lq101r1sx01: Don't call disable at shutdown/remove
  drm/panel: sharp-ls043t1le01: Stop tracking prepared
  drm/panel: sharp-ls043t1le01: Don't call disable at shutdown/remove
  drm/panel: raydium-rm67191: Stop tracking enabled
  drm/panel: raydium-rm67191: Don't call unprepare+disable at shutdown
  drm/panel: Update TODO list item for cleaning up prepared/enabled
tracking
  drm/panel: Avoid warnings w/ panel-simple/panel-edp at shutdown

 Documentation/gpu/todo.rst|  47 +++---
 drivers/gpu/drm/drm_panel.c   |  12 ++
 drivers/gpu/drm/panel/panel-

Re: (subset) [PATCH 2/2] drm/panel-edp: Add more panels with conservative timings

2024-05-28 Thread Douglas Anderson


On Mon, 27 May 2024 17:54:50 +0800, Pin-yen Lin wrote:
> Same as commit 7c8690d8fc80 ("drm/panel-edp: Add some panels with
> conservative timings"), the 3 panels added in this patch are used by
> Mediatek MT8173 Chromebooks and they used to work with the downstream
> v4.19 kernel without any specified delay.
> 
> These panel IDs were found from in-field reports, but their datahseets
> are not available. For BOE 0x0623 and SHP 0x153a, their product names
> are retrieved from the EDIDs. The EDID of AUO 0x1999 does not contain
> such information, so list as "Unknown" in this patch.
> 
> [...]

Applied, thanks!

[2/2] drm/panel-edp: Add more panels with conservative timings
  commit: 336dca397dcefc5d7436be1fee3c814ed6512996

Best regards,
-- 
Douglas Anderson 



Re: (subset) [PATCH 1/2] drm/panel-edp: Add support for several panels

2024-05-28 Thread Douglas Anderson


On Mon, 27 May 2024 17:54:49 +0800, Pin-yen Lin wrote:
> Add support for the following models:
> AUO B140HTN02.0
> BOE NT116WHM-N21 V4.1
> BOE NT116WHM-N21
> 
> 

Applied, thanks!

[1/2] drm/panel-edp: Add support for several panels
  commit: e4f9fd9edbc22faceb4c9c57242440bb9e17924b

Best regards,
-- 
Douglas Anderson 



Re: [PATCH] drm/dp: Fix documentation warning

2024-05-28 Thread Douglas Anderson


On Sun, 19 May 2024 00:10:27 -0300, MarileneGarcia wrote:
> It fixes the following warnings when
> the kernel documentation is generated:
> 
> ./include/drm/display/drm_dp_helper.h:126:
> warning: Function parameter or struct member
> 'mode' not described in 'drm_dp_as_sdp'
> 
> [...]

Applied, thanks!

[1/1] drm/dp: Fix documentation warning
  commit: c7ce956bb6d0f32ab921b6ffba1a6a834df96f21

Best regards,
-- 
Douglas Anderson 



Re: [PATCH] drm/panel-edp: Add CMN N116BCJ-EAK

2024-05-22 Thread Douglas Anderson


On Wed, 22 May 2024 19:39:24 +0800, Haikun Zhou wrote:
> Add support for the CMN N116BCJ-EAK, place the raw EDID here for
> subsequent reference.
> 00 ff ff ff ff ff ff 00 0d ae 60 11 00 00 00 00
> 04 22 01 04 95 1a 0e 78 02 67 75 98 59 53 90 27
> 1c 50 54 00 00 00 01 01 01 01 01 01 01 01 01 01
> 01 01 01 01 01 01 da 1d 56 e2 50 00 20 30 30 20
> a6 00 00 90 10 00 00 18 00 00 00 fe 00 4e 31 31
> 36 42 43 4a 2d 45 41 4b 0a 20 00 00 00 fe 00 43
> 4d 4e 0a 20 20 20 20 20 20 20 20 20 00 00 00 fe
> 00 4e 31 31 36 42 43 4a 2d 45 41 4b 0a 20 00 98
> 
> [...]

Applied, thanks!

[1/1] drm/panel-edp: Add CMN N116BCJ-EAK
  commit: 7acacca1b157fcb258cfd781603425f73bc7370b

Best regards,
-- 
Douglas Anderson 



[PATCH] dt-bindings: display: Reorganize legacy eDP panel bindings

2024-05-20 Thread Douglas Anderson
Back in the day, we used to need to list the exact panel in dts for
eDP panels. This led to all sorts of problems including a large number
of cases where people listed a bogus panel in their device tree
because of the needs of second sourcing (and third sourcing, and
fourth sourcing, ...). Back when we needed to add eDP panels to dts
files we used to list them in "panel-simple.yaml".

These days we have the new way of doing things as documented in
"panel-edp.yaml". We can just list the compatible "edp-panel", add
some timing info to the source code, and we're good to go. There's not
really good reasons not to use this new method.

To try to make it obvious that we shouldn't add new compatible strings
for eDP panels, let's move them all out of the old "panel-simple.yaml"
file to their own file: "panel-edp-legacy.yaml". This new file will
have a description that makes it obvious that we shouldn't use it for
new panels.

While we're doing this:
- We can remove eDP-specific properties from panel-simple.yaml since
  there are no more panels there.
- We don't need to copy non-eDP properties to the
  "panel-edp-legacy.yaml".
- We'll fork off a separate yaml file for "samsung,atna33xc20.yaml".
  This is an eDP panel which isn't _quite_ handled by the generic
  "edp-panel" compatible since it's not allowed to have an external
  backlight (it has one builtin) and it absolutely requires an
  "enable" GPIO.
- We'll un-fork the "sharp,ld-d5116z01b.yaml" and put it in
  "panel-edp-legacy.yaml" since there doesn't appear to be any reason
  for it to be separate.

Suggested-by: Dmitry Baryshkov 
Signed-off-by: Douglas Anderson 
---

 .../display/panel/panel-edp-legacy.yaml   | 127 ++
 .../bindings/display/panel/panel-simple.yaml  |  58 
 .../display/panel/samsung,atna33xc20.yaml |  95 +
 .../display/panel/sharp,ld-d5116z01b.yaml |  30 -
 4 files changed, 222 insertions(+), 88 deletions(-)
 create mode 100644 
Documentation/devicetree/bindings/display/panel/panel-edp-legacy.yaml
 create mode 100644 
Documentation/devicetree/bindings/display/panel/samsung,atna33xc20.yaml
 delete mode 100644 
Documentation/devicetree/bindings/display/panel/sharp,ld-d5116z01b.yaml

diff --git 
a/Documentation/devicetree/bindings/display/panel/panel-edp-legacy.yaml 
b/Documentation/devicetree/bindings/display/panel/panel-edp-legacy.yaml
new file mode 100644
index ..9e5864de49e7
--- /dev/null
+++ b/Documentation/devicetree/bindings/display/panel/panel-edp-legacy.yaml
@@ -0,0 +1,127 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/display/panel/panel-edp-legacy.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Legacy eDP panels from before the "edp-panel" compatible
+
+maintainers:
+  - Douglas Anderson 
+
+description: |
+  This binding file is a collection of eDP panels from before the generic
+  "edp-panel" compatible was introduced. It is kept around to support old
+  dts files. The only reason one might add a new panel here instead of using
+  the generic "edp-panel" is if it needed to be used on an eDP controller
+  that doesn't support the generic "edp-panel" compatible, but it should be
+  a strong preference to add the generic "edp-panel" compatible instead.
+
+allOf:
+  - $ref: panel-common.yaml#
+
+properties:
+  compatible:
+enum:
+# compatible must be listed in alphabetical order, ordered by compatible.
+# The description in the comment is mandatory for each compatible.
+
+# AU Optronics Corporation 10.1" WSVGA TFT LCD panel
+  - auo,b101ean01
+# AUO B116XAK01 eDP TFT LCD panel
+  - auo,b116xa01
+# AU Optronics Corporation 13.3" FHD (1920x1080) color TFT-LCD panel
+  - auo,b133han05
+# AU Optronics Corporation 13.3" FHD (1920x1080) color TFT-LCD panel
+  - auo,b133htn01
+# AU Optronics Corporation 13.3" WXGA (1366x768) TFT LCD panel
+  - auo,b133xtn01
+# AU Optronics Corporation 14.0" FHD (1920x1080) color TFT-LCD panel
+  - auo,b140han06
+# BOE OPTOELECTRONICS TECHNOLOGY 10.1" WXGA TFT LCD panel
+  - boe,nv101wxmn51
+# BOE NV133FHM-N61 13.3" FHD (1920x1080) TFT LCD Panel
+  - boe,nv110wtm-n61
+# BOE NV110WTM-N61 11.0" 2160x1440 TFT LCD Panel
+  - boe,nv133fhm-n61
+# BOE NV133FHM-N62 13.3" FHD (1920x1080) TFT LCD Panel
+  - boe,nv133fhm-n62
+# BOE NV140FHM-N49 14.0" FHD a-Si FT panel
+  - boe,nv140fhmn49
+# Innolux Corporation 11.6" WXGA (1366x768) TFT LCD panel
+  - innolux,n116bca-ea1
+# Innolux Corporation 11.6" WXGA (1366x768) TFT LCD p

[PATCH 6/8] drm/panel: himax-hx83102: If prepare fails, disable GPIO before regulators

2024-05-17 Thread Douglas Anderson
The enable GPIO should clearly be set low before turning off
regulators. That matches both the inverse order that things were
enabled and also the order in unprepare().

Fixes: 0ef94554dc40 ("drm/panel: himax-hx83102: Break out as separate driver")
Signed-off-by: Douglas Anderson 
---

 drivers/gpu/drm/panel/panel-himax-hx83102.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/panel/panel-himax-hx83102.c 
b/drivers/gpu/drm/panel/panel-himax-hx83102.c
index 1a6975937f30..4ac7f9d8b232 100644
--- a/drivers/gpu/drm/panel/panel-himax-hx83102.c
+++ b/drivers/gpu/drm/panel/panel-himax-hx83102.c
@@ -578,13 +578,13 @@ static int hx83102_prepare(struct drm_panel *panel)
return 0;
 
 poweroff:
+   gpiod_set_value(ctx->enable_gpio, 0);
regulator_disable(ctx->avee);
 poweroffavdd:
regulator_disable(ctx->avdd);
 poweroff1v8:
usleep_range(5000, 7000);
regulator_disable(ctx->pp1800);
-   gpiod_set_value(ctx->enable_gpio, 0);
 
return ret;
 }
-- 
2.45.0.rc1.225.g2a3ae87e7f-goog



[PATCH 7/8] drm/panel: himax-hx83102: Check for errors on the NOP in prepare()

2024-05-17 Thread Douglas Anderson
The mipi_dsi_dcs_nop() function returns an error but we weren't
checking it in hx83102_prepare(). Add a check. This is highly unlikely
to matter in practice. If the NOP failed then likely later MIPI
commands would fail too.

Found by code inspection.

Fixes: 0ef94554dc40 ("drm/panel: himax-hx83102: Break out as separate driver")
Signed-off-by: Douglas Anderson 
---

 drivers/gpu/drm/panel/panel-himax-hx83102.c | 6 +-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/panel/panel-himax-hx83102.c 
b/drivers/gpu/drm/panel/panel-himax-hx83102.c
index 4ac7f9d8b232..1ba623e41924 100644
--- a/drivers/gpu/drm/panel/panel-himax-hx83102.c
+++ b/drivers/gpu/drm/panel/panel-himax-hx83102.c
@@ -547,7 +547,11 @@ static int hx83102_prepare(struct drm_panel *panel)
 
usleep_range(1, 11000);
 
-   mipi_dsi_dcs_nop(ctx->dsi);
+   ret = mipi_dsi_dcs_nop(ctx->dsi);
+   if (ret < 0) {
+   dev_err(dev, "Failed to send NOP: %d\n", ret);
+   goto poweroff;
+   }
usleep_range(1000, 2000);
 
gpiod_set_value(ctx->enable_gpio, 1);
-- 
2.45.0.rc1.225.g2a3ae87e7f-goog



[PATCH 8/8] drm/panel: himax-hx83102: use wrapped MIPI DCS functions

2024-05-17 Thread Douglas Anderson
Take advantage of some of the new wrapped routines introduced by
commit f79d6d28d8fe ("drm/mipi-dsi: wrap more functions for streamline
handling") to simplify the himax-hx83102 driver a bit more. This gets
rid of some extra error prints (since the _multi functions all print
errors for you) and simplifies the code a bit.

One thing here that isn't just refactoring is that in a few places we
now check with errors with "if (err)" instead of "if (err < 0)". All
errors are expected to be negative so this is not expected to have any
impact. The _multi code internally considers anything non-zero to be
an error so this just makes things consistent.

It can also be noted that hx83102_prepare() has a mix of things that
can take advantage of _multi calls and things that can't. The cleanest
seemed to be to use the multi_ctx still but consistently use the
"accum_err" variable for error returns, though that's definitely a
style decision with pros and cons.

Signed-off-by: Douglas Anderson 
---

 drivers/gpu/drm/panel/panel-himax-hx83102.c | 92 +++--
 1 file changed, 28 insertions(+), 64 deletions(-)

diff --git a/drivers/gpu/drm/panel/panel-himax-hx83102.c 
b/drivers/gpu/drm/panel/panel-himax-hx83102.c
index 1ba623e41924..6009a3fe1b8f 100644
--- a/drivers/gpu/drm/panel/panel-himax-hx83102.c
+++ b/drivers/gpu/drm/panel/panel-himax-hx83102.c
@@ -285,12 +285,10 @@ static int boe_nv110wum_init(struct hx83102 *ctx)
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0x3f);
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETBANK, 0x00);
hx83102_enable_extended_cmds(&dsi_ctx, false);
-   if (dsi_ctx.accum_err)
-   return dsi_ctx.accum_err;
 
-   msleep(50);
+   mipi_dsi_msleep(dsi_ctx, 50);
 
-   return 0;
+   return dsi_ctx.accum_err;
 };
 
 static int ivo_t109nw41_init(struct hx83102 *ctx)
@@ -392,12 +390,10 @@ static int ivo_t109nw41_init(struct hx83102 *ctx)
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0x3f);
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETBANK, 0x00);
hx83102_enable_extended_cmds(&dsi_ctx, false);
-   if (dsi_ctx.accum_err)
-   return dsi_ctx.accum_err;
 
-   msleep(60);
+   mipi_dsi_msleep(dsi_ctx, 60);
 
-   return 0;
+   return dsi_ctx.accum_err;
 };
 
 static const struct drm_display_mode starry_mode = {
@@ -472,40 +468,20 @@ static int hx83102_enable(struct drm_panel *panel)
return 0;
 }
 
-static int hx83102_panel_enter_sleep_mode(struct hx83102 *ctx)
-{
-   struct mipi_dsi_device *dsi = ctx->dsi;
-   int ret;
-
-   dsi->mode_flags &= ~MIPI_DSI_MODE_LPM;
-
-   ret = mipi_dsi_dcs_set_display_off(dsi);
-   if (ret < 0)
-   return ret;
-
-   ret = mipi_dsi_dcs_enter_sleep_mode(dsi);
-   if (ret < 0)
-   return ret;
-
-   return 0;
-}
-
 static int hx83102_disable(struct drm_panel *panel)
 {
struct hx83102 *ctx = panel_to_hx83102(panel);
struct mipi_dsi_device *dsi = ctx->dsi;
-   struct device *dev = &dsi->dev;
-   int ret;
+   struct mipi_dsi_multi_context dsi_ctx = { .dsi = dsi };
 
-   ret = hx83102_panel_enter_sleep_mode(ctx);
-   if (ret < 0) {
-   dev_err(dev, "failed to set panel off: %d\n", ret);
-   return ret;
-   }
+   dsi->mode_flags &= ~MIPI_DSI_MODE_LPM;
 
-   msleep(150);
+   mipi_dsi_dcs_set_display_off_multi(&dsi_ctx);
+   mipi_dsi_dcs_enter_sleep_mode_multi(&dsi_ctx);
 
-   return 0;
+   mipi_dsi_msleep(&dsi_ctx, 150);
+
+   return dsi_ctx.accum_err;
 }
 
 static int hx83102_unprepare(struct drm_panel *panel)
@@ -526,32 +502,30 @@ static int hx83102_prepare(struct drm_panel *panel)
 {
struct hx83102 *ctx = panel_to_hx83102(panel);
struct mipi_dsi_device *dsi = ctx->dsi;
-   struct device *dev = &dsi->dev;
-   int ret;
+   struct mipi_dsi_multi_context dsi_ctx = { .dsi = dsi };
 
gpiod_set_value(ctx->enable_gpio, 0);
usleep_range(1000, 1500);
 
-   ret = regulator_enable(ctx->pp1800);
-   if (ret < 0)
-   return ret;
+   dsi_ctx.accum_err = regulator_enable(ctx->pp1800);
+   if (dsi_ctx.accum_err)
+   return dsi_ctx.accum_err;
 
usleep_range(3000, 5000);
 
-   ret = regulator_enable(ctx->avdd);
-   if (ret < 0)
+   dsi_ctx.accum_err = regulator_enable(ctx->avdd);
+   if (dsi_ctx.accum_err)
goto poweroff1v8;
-   ret = regulator_enable(ctx->avee);
-   if (ret < 0)
+   dsi_ctx.accum_err = regulator_enable(ctx->avee);
+   if (dsi_ctx.accum_err)
goto poweroffavdd;
 
usleep_range(1, 11000);
 
-   ret = mipi_dsi_dcs_nop(ctx->dsi);
-

[PATCH 3/8] drm/panel: boe-tv101wum-nl6: Check for errors on the NOP in prepare()

2024-05-17 Thread Douglas Anderson
The mipi_dsi_dcs_nop() function returns an error but we weren't
checking it in boe_panel_prepare(). Add a check. This is highly
unlikely to matter in practice. If the NOP failed then likely later
MIPI commands would fail too.

Found by code inspection.

Fixes: 812562b8d881 ("drm/panel: boe-tv101wum-nl6: Fine tune the panel power 
sequence")
Signed-off-by: Douglas Anderson 
---

 drivers/gpu/drm/panel/panel-boe-tv101wum-nl6.c | 6 +-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/panel/panel-boe-tv101wum-nl6.c 
b/drivers/gpu/drm/panel/panel-boe-tv101wum-nl6.c
index 028625d2d37d..f7beace455c3 100644
--- a/drivers/gpu/drm/panel/panel-boe-tv101wum-nl6.c
+++ b/drivers/gpu/drm/panel/panel-boe-tv101wum-nl6.c
@@ -1456,7 +1456,11 @@ static int boe_panel_prepare(struct drm_panel *panel)
usleep_range(1, 11000);
 
if (boe->desc->lp11_before_reset) {
-   mipi_dsi_dcs_nop(boe->dsi);
+   ret = mipi_dsi_dcs_nop(boe->dsi);
+   if (ret < 0) {
+   dev_err(&boe->dsi->dev, "Failed to send NOP: %d\n", 
ret);
+   goto poweroff;
+   }
usleep_range(1000, 2000);
}
gpiod_set_value(boe->enable_gpio, 1);
-- 
2.45.0.rc1.225.g2a3ae87e7f-goog



[PATCH 5/8] drm/panel: ilitek-ili9882t: Check for errors on the NOP in prepare()

2024-05-17 Thread Douglas Anderson
The mipi_dsi_dcs_nop() function returns an error but we weren't
checking it in ili9882t_prepare(). Add a check. This is highly
unlikely to matter in practice. If the NOP failed then likely later
MIPI commands would fail too.

Found by code inspection.

Fixes: e2450d32e5fb ("drm/panel: ili9882t: Break out as separate driver")
Signed-off-by: Douglas Anderson 
---

 drivers/gpu/drm/panel/panel-ilitek-ili9882t.c | 6 +-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/panel/panel-ilitek-ili9882t.c 
b/drivers/gpu/drm/panel/panel-ilitek-ili9882t.c
index a2ea25bb6624..266a087fe14c 100644
--- a/drivers/gpu/drm/panel/panel-ilitek-ili9882t.c
+++ b/drivers/gpu/drm/panel/panel-ilitek-ili9882t.c
@@ -478,7 +478,11 @@ static int ili9882t_prepare(struct drm_panel *panel)
usleep_range(1, 11000);
 
// MIPI needs to keep the LP11 state before the lcm_reset pin is pulled 
high
-   mipi_dsi_dcs_nop(ili->dsi);
+   ret = mipi_dsi_dcs_nop(ili->dsi);
+   if (ret < 0) {
+   dev_err(&ili->dsi->dev, "Failed to send NOP: %d\n", ret);
+   goto poweroff;
+   }
usleep_range(1000, 2000);
 
gpiod_set_value(ili->enable_gpio, 1);
-- 
2.45.0.rc1.225.g2a3ae87e7f-goog



[PATCH 4/8] drm/panel: ilitek-ili9882t: If prepare fails, disable GPIO before regulators

2024-05-17 Thread Douglas Anderson
The enable GPIO should clearly be set low before turning off
regulators. That matches both the inverse order that things were
enabled and also the order in unprepare().

Fixes: e2450d32e5fb ("drm/panel: ili9882t: Break out as separate driver")
Signed-off-by: Douglas Anderson 
---

 drivers/gpu/drm/panel/panel-ilitek-ili9882t.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/panel/panel-ilitek-ili9882t.c 
b/drivers/gpu/drm/panel/panel-ilitek-ili9882t.c
index 830d7cfbe857..a2ea25bb6624 100644
--- a/drivers/gpu/drm/panel/panel-ilitek-ili9882t.c
+++ b/drivers/gpu/drm/panel/panel-ilitek-ili9882t.c
@@ -495,13 +495,13 @@ static int ili9882t_prepare(struct drm_panel *panel)
return 0;
 
 poweroff:
+   gpiod_set_value(ili->enable_gpio, 0);
regulator_disable(ili->avee);
 poweroffavdd:
regulator_disable(ili->avdd);
 poweroff1v8:
usleep_range(5000, 7000);
regulator_disable(ili->pp1800);
-   gpiod_set_value(ili->enable_gpio, 0);
 
return ret;
 }
-- 
2.45.0.rc1.225.g2a3ae87e7f-goog



[PATCH 2/8] drm/panel: boe-tv101wum-nl6: If prepare fails, disable GPIO before regulators

2024-05-17 Thread Douglas Anderson
The enable GPIO should clearly be set low before turning off
regulators. That matches both the inverse order that things were
enabled and also the order in unprepare().

Fixes: a869b9db7adf ("drm/panel: support for boe tv101wum-nl6 wuxga dsi video 
mode panel")
Signed-off-by: Douglas Anderson 
---

 drivers/gpu/drm/panel/panel-boe-tv101wum-nl6.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/panel/panel-boe-tv101wum-nl6.c 
b/drivers/gpu/drm/panel/panel-boe-tv101wum-nl6.c
index 8e839a1749e4..028625d2d37d 100644
--- a/drivers/gpu/drm/panel/panel-boe-tv101wum-nl6.c
+++ b/drivers/gpu/drm/panel/panel-boe-tv101wum-nl6.c
@@ -1475,13 +1475,13 @@ static int boe_panel_prepare(struct drm_panel *panel)
return 0;
 
 poweroff:
+   gpiod_set_value(boe->enable_gpio, 0);
regulator_disable(boe->avee);
 poweroffavdd:
regulator_disable(boe->avdd);
 poweroff1v8:
usleep_range(5000, 7000);
regulator_disable(boe->pp1800);
-   gpiod_set_value(boe->enable_gpio, 0);
 
return ret;
 }
-- 
2.45.0.rc1.225.g2a3ae87e7f-goog



[PATCH 1/8] drm/panel: himax-hx8394: Handle errors from mipi_dsi_dcs_set_display_on() better

2024-05-17 Thread Douglas Anderson
If mipi_dsi_dcs_set_display_on() returned an error then we'd store
that in the "ret" variable and jump to error handling. We'd then
attempt an orderly poweroff. Unfortunately we then blew away the value
stored in "ret". That means that if the orderly poweroff actually
worked then we're return 0 (no error) from hx8394_enable() even though
the panel wasn't enabled.

Fix this by not blowing away "ret".

Found by code inspection.

Fixes: 65dc9360f741 ("drm: panel: Add Himax HX8394 panel controller driver")
Signed-off-by: Douglas Anderson 
---

 drivers/gpu/drm/panel/panel-himax-hx8394.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/panel/panel-himax-hx8394.c 
b/drivers/gpu/drm/panel/panel-himax-hx8394.c
index ff0dc08b9829..cb9f46e853de 100644
--- a/drivers/gpu/drm/panel/panel-himax-hx8394.c
+++ b/drivers/gpu/drm/panel/panel-himax-hx8394.c
@@ -370,8 +370,7 @@ static int hx8394_enable(struct drm_panel *panel)
 
 sleep_in:
/* This will probably fail, but let's try orderly power off anyway. */
-   ret = mipi_dsi_dcs_enter_sleep_mode(dsi);
-   if (!ret)
+   if (!mipi_dsi_dcs_enter_sleep_mode(dsi))
msleep(50);
 
return ret;
-- 
2.45.0.rc1.225.g2a3ae87e7f-goog



[PATCH 0/8] drm/panel: Some very minor err handling fixes + more _multi

2024-05-17 Thread Douglas Anderson


This series is pretty much just addressing a few minor error handling
bugs that I noticed recently while reviewing some panel patches. For
the most part these are all old issues.

This also adjusts the new himax-hx83102 in a similar way that Dmitry
did in his recent series that included commit f79d6d28d8fe
("drm/mipi-dsi: wrap more functions for streamline handling"). His
series handled the panel driver that himax-hx83102 forked from but not
himax-hx83102.


Douglas Anderson (8):
  drm/panel: himax-hx8394: Handle errors from
mipi_dsi_dcs_set_display_on() better
  drm/panel: boe-tv101wum-nl6: If prepare fails, disable GPIO before
regulators
  drm/panel: boe-tv101wum-nl6: Check for errors on the NOP in prepare()
  drm/panel: ilitek-ili9882t: If prepare fails, disable GPIO before
regulators
  drm/panel: ilitek-ili9882t: Check for errors on the NOP in prepare()
  drm/panel: himax-hx83102: If prepare fails, disable GPIO before
regulators
  drm/panel: himax-hx83102: Check for errors on the NOP in prepare()
  drm/panel: himax-hx83102: use wrapped MIPI DCS functions

 .../gpu/drm/panel/panel-boe-tv101wum-nl6.c|  8 +-
 drivers/gpu/drm/panel/panel-himax-hx83102.c   | 92 ++-
 drivers/gpu/drm/panel/panel-himax-hx8394.c|  3 +-
 drivers/gpu/drm/panel/panel-ilitek-ili9882t.c |  8 +-
 4 files changed, 43 insertions(+), 68 deletions(-)

-- 
2.45.0.rc1.225.g2a3ae87e7f-goog



[PATCH v5 7/9] drm/panel: boe-tv101wum-nl6: Don't use a table for initting panels

2024-05-14 Thread Douglas Anderson
Consensus on the mailing lists is that panels shouldn't use a table of
init commands but should instead use init functions. With the recently
introduced mipi_dsi_dcs_write_seq_multi() this is not only clean/easy
but also saves space. Measuring before/after this change:

$ scripts/bloat-o-meter \
  .../before/panel-boe-tv101wum-nl6.ko \
  .../after/panel-boe-tv101wum-nl6.ko
add/remove: 14/8 grow/shrink: 0/1 up/down: 27062/-31433 (-4371)
Function old new   delta
inx_hj110iz_init   -7040   +7040
boe_tv110c9m_init  -6440   +6440
boe_init   -5916   +5916
starry_qfh032011_53g_init  -1944   +1944
starry_himax83102_j02_init -1228   +1228
inx_hj110iz_init.d -1040   +1040
boe_tv110c9m_init.d- 982+982
auo_b101uan08_3_init   - 944+944
boe_init.d - 580+580
starry_himax83102_j02_init.d   - 512+512
starry_qfh032011_53g_init.d- 180+180
auo_kd101n80_45na_init - 172+172
auo_b101uan08_3_init.d -  82 +82
auo_kd101n80_45na_init.d   -   2  +2
auo_kd101n80_45na_init_cmd   144   --144
boe_panel_prepare592 440-152
auo_b101uan08_3_init_cmd1056   -   -1056
starry_himax83102_j02_init_cmd  1392   -   -1392
starry_qfh032011_53g_init_cmd   2256   -   -2256
.compoundliteral3393   -   -3393
boe_init_cmd7008   -   -7008
boe_tv110c9m_init_cmd   7656   -   -7656
inx_hj110iz_init_cmd8376   -   -8376
Total: Before=37297, After=32926, chg -11.72%

Let's do the conversion.

Since we're touching all the tables, let's also convert hex numbers to
lower case as per kernel conventions.

Reviewed-by: Linus Walleij 
Signed-off-by: Douglas Anderson 
---

(no changes since v3)

Changes in v3:
- Fix spacing of init function.
- Remove an unneeded error print.
- Squash boe-tv101wum-nl6 lowercase patch into main patch

Changes in v2:
- New

 .../gpu/drm/panel/panel-boe-tv101wum-nl6.c| 2792 +
 1 file changed, 1442 insertions(+), 1350 deletions(-)

diff --git a/drivers/gpu/drm/panel/panel-boe-tv101wum-nl6.c 
b/drivers/gpu/drm/panel/panel-boe-tv101wum-nl6.c
index 0ffe8f8c01de..aab60cec0603 100644
--- a/drivers/gpu/drm/panel/panel-boe-tv101wum-nl6.c
+++ b/drivers/gpu/drm/panel/panel-boe-tv101wum-nl6.c
@@ -17,6 +17,8 @@
 
 #include 
 
+struct boe_panel;
+
 struct panel_desc {
const struct drm_display_mode *modes;
unsigned int bpc;
@@ -32,7 +34,7 @@ struct panel_desc {
 
unsigned long mode_flags;
enum mipi_dsi_pixel_format format;
-   const struct panel_init_cmd *init_cmds;
+   int (*init)(struct boe_panel *boe);
unsigned int lanes;
bool discharge_on_disable;
bool lp11_before_reset;
@@ -54,1318 +56,1449 @@ struct boe_panel {
bool prepared;
 };
 
-enum dsi_cmd_type {
-   INIT_DCS_CMD,
-   DELAY_CMD,
-};
+static int boe_tv110c9m_init(struct boe_panel *boe)
+{
+   struct mipi_dsi_multi_context ctx = { .dsi = boe->dsi };
+
+   mipi_dsi_dcs_write_seq_multi(&ctx, 0xff, 0x20);
+   mipi_dsi_dcs_write_seq_multi(&ctx, 0xfb, 0x01);
+   mipi_dsi_dcs_write_seq_multi(&ctx, 0x05, 0xd9);
+   mipi_dsi_dcs_write_seq_multi(&ctx, 0x07, 0x78);
+   mipi_dsi_dcs_write_seq_multi(&ctx, 0x08, 0x5a);
+   mipi_dsi_dcs_write_seq_multi(&ctx, 0x0d, 0x63);
+   mipi_dsi_dcs_write_seq_multi(&ctx, 0x0e, 0x91);
+   mipi_dsi_dcs_write_seq_multi(&ctx, 0x0f, 0x73);
+   mipi_dsi_dcs_write_seq_multi(&ctx, 0x95, 0xe6);
+   mipi_dsi_dcs_write_seq_multi(&ctx, 0x96, 0xf0);
+   mipi_dsi_dcs_write_seq_multi(&ctx, 0x30, 0x00);
+   mipi_dsi_dcs_write_seq_multi(&ctx, 0x6d, 0x66);
+   mipi_dsi_dcs_write_seq_multi(&ctx, 0x75, 0xa2);
+   mipi_dsi_dcs_write_seq_multi(&ctx, 0x77, 0x3b);
+
+   mipi_dsi_dcs_write_seq_multi(&ctx, 0xb0, 0x00, 0x08, 0x00, 0x23, 0x00, 
0x4d, 0x00, 0x6d,
+0x00, 0x89, 0x00, 0xa1, 0x00, 0xb6, 0x00, 
0xc9);
+   mipi_dsi_dcs_write_seq_multi(&ctx, 0xb1, 0x00, 0xda, 0x01, 0x13, 0x01, 
0x3c, 0x01, 0x7e,
+0x01, 0xab, 0x01, 0xf7, 0x02, 0x2f, 0x02, 
0x31);
+   mipi_dsi_dcs_write_seq_multi(&ctx, 0xb2, 0x02, 0x67, 0x02, 0xa6, 0x02, 
0xd1, 0x03, 0x08,
+0x03, 0x2e, 0x03, 0x5b, 0x03, 0x6b, 0x03, 
0x7b);
+

[PATCH v5 9/9] drm/panel: innolux-p079zca: Don't use a table for initting panels

2024-05-14 Thread Douglas Anderson
Consensus on the mailing lists is that panels shouldn't use a table of
init commands but should instead use init functions. We'll use the
same concepts as the recently introduced
mipi_dsi_generic_write_seq_multi() to make this clean/easy and also
not bloat the driver too much. Measuring before/after this change:

$ scripts/bloat-o-meter \
  .../before/panel-innolux-p079zca.ko \
  .../after/panel-innolux-p079zca.ko
add/remove: 3/2 grow/shrink: 0/1 up/down: 2356/-1944 (412)
Function old new   delta
innolux_p097pfg_init   -1772   +1772
innolux_p097pfg_init.d - 480+480
innolux_panel_write_multi  - 104+104
innolux_panel_prepare412 308-104
.compoundliteral 480   --480
innolux_p097pfg_init_cmds   1360   -   -1360
Total: Before=5802, After=6214, chg +7.10%

Note that, unlike some other drivers, we actually make this panel
driver _bigger_ by using the new functions. This is because the
innolux-p079zca panel driver didn't have as complex of a table and
thus the old table was more efficient than the code. The bloat is
still not giant (only 412 bytes).

Also note that we can't direclty use
mipi_dsi_generic_write_seq_multi() here because we need to deal with
the crazy "nop" that this driver sends after all commands. This means
that we have to write code that is "inspired" by the new macros.

Since we're touching all the tables, let's also convert hex numbers to
lower case as per kernel conventions.

Reviewed-by: Linus Walleij 
Signed-off-by: Douglas Anderson 
---

(no changes since v4)

Changes in v4:
- Test to see if init is non-NULL before using it.

Changes in v3:
- New

 drivers/gpu/drm/panel/panel-innolux-p079zca.c | 284 +-
 1 file changed, 140 insertions(+), 144 deletions(-)

diff --git a/drivers/gpu/drm/panel/panel-innolux-p079zca.c 
b/drivers/gpu/drm/panel/panel-innolux-p079zca.c
index 485178a99910..ade8bf7491ee 100644
--- a/drivers/gpu/drm/panel/panel-innolux-p079zca.c
+++ b/drivers/gpu/drm/panel/panel-innolux-p079zca.c
@@ -17,14 +17,7 @@
 #include 
 #include 
 
-struct panel_init_cmd {
-   size_t len;
-   const char *data;
-};
-
-#define _INIT_CMD(...) { \
-   .len = sizeof((char[]){__VA_ARGS__}), \
-   .data = (char[]){__VA_ARGS__} }
+struct innolux_panel;
 
 struct panel_desc {
const struct drm_display_mode *mode;
@@ -36,7 +29,7 @@ struct panel_desc {
 
unsigned long flags;
enum mipi_dsi_pixel_format format;
-   const struct panel_init_cmd *init_cmds;
+   int (*init)(struct innolux_panel *innolux);
unsigned int lanes;
const char * const *supply_names;
unsigned int num_supplies;
@@ -132,32 +125,10 @@ static int innolux_panel_prepare(struct drm_panel *panel)
/* p079zca: t4, p097pfg: t5 */
usleep_range(2, 21000);
 
-   if (innolux->desc->init_cmds) {
-   const struct panel_init_cmd *cmds =
-   innolux->desc->init_cmds;
-   unsigned int i;
-
-   for (i = 0; cmds[i].len != 0; i++) {
-   const struct panel_init_cmd *cmd = &cmds[i];
-
-   err = mipi_dsi_generic_write(innolux->link, cmd->data,
-cmd->len);
-   if (err < 0) {
-   dev_err(panel->dev, "failed to write command 
%u\n", i);
-   goto poweroff;
-   }
-
-   /*
-* Included by random guessing, because without this
-* (or at least, some delay), the panel sometimes
-* didn't appear to pick up the command sequence.
-*/
-   err = mipi_dsi_dcs_nop(innolux->link);
-   if (err < 0) {
-   dev_err(panel->dev, "failed to send DCS nop: 
%d\n", err);
-   goto poweroff;
-   }
-   }
+   if (innolux->desc->init) {
+   err = innolux->desc->init(innolux);
+   if (err < 0)
+   goto poweroff;
}
 
err = mipi_dsi_dcs_exit_sleep_mode(innolux->link);
@@ -250,119 +221,144 @@ static const struct drm_display_mode 
innolux_p097pfg_mode = {
.vtotal = 2048 + 100 + 2 + 18,
 };
 
+static void innolux_panel_write_multi(struct mipi_dsi_multi_context *ctx,
+ const void *payload, size_t size)
+{
+   struct mipi_dsi_device *dsi = ctx->dsi;
+   struct device *dev = &dsi->dev;
+
+   mipi_dsi_generic_write_multi(ctx

[PATCH v5 8/9] drm/panel: ili9882t: Don't use a table for initting panels

2024-05-14 Thread Douglas Anderson
Consensus on the mailing lists is that panels shouldn't use a table of
init commands but should instead use init functions. With the recently
introduced mipi_dsi_dcs_write_seq_multi() this is not only clean/easy
but also saves space. Measuring before/after this change:

$ scripts/bloat-o-meter \
  .../before/panel-ilitek-ili9882t.ko \
  .../after/panel-ilitek-ili9882t.ko
add/remove: 3/2 grow/shrink: 0/2 up/down: 6834/-8177 (-1343)
Function old new   delta
starry_ili9882t_init   -6152   +6152
starry_ili9882t_init.d - 678+678
ili9882t_disable.d -   4  +4
ili9882t_disable 260 228 -32
ili9882t_prepare 540 396-144
.compoundliteral 681   --681
starry_ili9882t_init_cmd7320   -   -7320
Total: Before=11928, After=10585, chg -11.26%

Let's do the conversion.

Since we're touching all the tables, let's also convert hex numbers to
lower case as per kernel conventions.

Reviewed-by: Linus Walleij 
Signed-off-by: Douglas Anderson 
---

(no changes since v3)

Changes in v3:
- New

 drivers/gpu/drm/panel/panel-ilitek-ili9882t.c | 794 --
 1 file changed, 368 insertions(+), 426 deletions(-)

diff --git a/drivers/gpu/drm/panel/panel-ilitek-ili9882t.c 
b/drivers/gpu/drm/panel/panel-ilitek-ili9882t.c
index 267a5307041c..58fc1d799371 100644
--- a/drivers/gpu/drm/panel/panel-ilitek-ili9882t.c
+++ b/drivers/gpu/drm/panel/panel-ilitek-ili9882t.c
@@ -15,6 +15,8 @@
 
 #include 
 
+struct ili9882t;
+
 /*
  * Use this descriptor struct to describe different panels using the
  * Ilitek ILI9882T display controller.
@@ -34,7 +36,7 @@ struct panel_desc {
 
unsigned long mode_flags;
enum mipi_dsi_pixel_format format;
-   const struct panel_init_cmd *init_cmds;
+   int (*init)(struct ili9882t *boe);
unsigned int lanes;
 };
 
@@ -52,433 +54,372 @@ struct ili9882t {
struct gpio_desc *enable_gpio;
 };
 
-enum dsi_cmd_type {
-   INIT_DCS_CMD,
-   DELAY_CMD,
-};
-
-struct panel_init_cmd {
-   enum dsi_cmd_type type;
-   size_t len;
-   const char *data;
-};
-
-#define _INIT_DCS_CMD(...) { \
-   .type = INIT_DCS_CMD, \
-   .len = sizeof((char[]){__VA_ARGS__}), \
-   .data = (char[]){__VA_ARGS__} }
-
-#define _INIT_DELAY_CMD(...) { \
-   .type = DELAY_CMD,\
-   .len = sizeof((char[]){__VA_ARGS__}), \
-   .data = (char[]){__VA_ARGS__} }
-
 /* ILI9882-specific commands, add new commands as you decode them */
 #define ILI9882T_DCS_SWITCH_PAGE   0xFF
 
-#define _INIT_SWITCH_PAGE_CMD(page) \
-   _INIT_DCS_CMD(ILI9882T_DCS_SWITCH_PAGE, 0x98, 0x82, (page))
-
-static const struct panel_init_cmd starry_ili9882t_init_cmd[] = {
-   _INIT_DELAY_CMD(5),
-   _INIT_SWITCH_PAGE_CMD(0x01),
-   _INIT_DCS_CMD(0x00, 0x42),
-   _INIT_DCS_CMD(0x01, 0x11),
-   _INIT_DCS_CMD(0x02, 0x00),
-   _INIT_DCS_CMD(0x03, 0x00),
-
-   _INIT_DCS_CMD(0x04, 0x01),
-   _INIT_DCS_CMD(0x05, 0x11),
-   _INIT_DCS_CMD(0x06, 0x00),
-   _INIT_DCS_CMD(0x07, 0x00),
-
-   _INIT_DCS_CMD(0x08, 0x80),
-   _INIT_DCS_CMD(0x09, 0x81),
-   _INIT_DCS_CMD(0x0A, 0x71),
-   _INIT_DCS_CMD(0x0B, 0x00),
-
-   _INIT_DCS_CMD(0x0C, 0x00),
-   _INIT_DCS_CMD(0x0E, 0x1A),
-
-   _INIT_DCS_CMD(0x24, 0x00),
-   _INIT_DCS_CMD(0x25, 0x00),
-   _INIT_DCS_CMD(0x26, 0x00),
-   _INIT_DCS_CMD(0x27, 0x00),
-
-   _INIT_DCS_CMD(0x2C, 0xD4),
-   _INIT_DCS_CMD(0xB9, 0x40),
-
-   _INIT_DCS_CMD(0xB0, 0x11),
-
-   _INIT_DCS_CMD(0xE6, 0x32),
-   _INIT_DCS_CMD(0xD1, 0x30),
-
-   _INIT_DCS_CMD(0xD6, 0x55),
-
-   _INIT_DCS_CMD(0xD0, 0x01),
-   _INIT_DCS_CMD(0xE3, 0x93),
-   _INIT_DCS_CMD(0xE4, 0x00),
-   _INIT_DCS_CMD(0xE5, 0x80),
-
-   _INIT_DCS_CMD(0x31, 0x07),
-   _INIT_DCS_CMD(0x32, 0x07),
-   _INIT_DCS_CMD(0x33, 0x07),
-   _INIT_DCS_CMD(0x34, 0x07),
-   _INIT_DCS_CMD(0x35, 0x07),
-   _INIT_DCS_CMD(0x36, 0x01),
-   _INIT_DCS_CMD(0x37, 0x00),
-   _INIT_DCS_CMD(0x38, 0x28),
-   _INIT_DCS_CMD(0x39, 0x29),
-   _INIT_DCS_CMD(0x3A, 0x11),
-   _INIT_DCS_CMD(0x3B, 0x13),
-   _INIT_DCS_CMD(0x3C, 0x15),
-   _INIT_DCS_CMD(0x3D, 0x17),
-   _INIT_DCS_CMD(0x3E, 0x09),
-   _INIT_DCS_CMD(0x3F, 0x0D),
-   _INIT_DCS_CMD(0x40, 0x02),
-   _INIT_DCS_CMD(0x41, 0x02),
-   _INIT_DCS_CMD(0x42, 0x02),
-   _INIT_DCS_CMD(0x43, 0x02),
-   _INIT_DCS_CMD(0x44, 0x02),
-   _INIT_DCS_CMD(0x45, 0x02),
-   _INIT_DCS_CMD(0x46, 0x02),
-
-   _INIT_DCS_CMD(0x47, 0x07),
-   _INIT_DCS_CMD(0x48, 0x07),
-   _INIT_DCS_CMD(0x49, 0x07),
-   _INIT_DCS_CMD(0x4A, 0x07),
-   _INIT_DCS_CMD(0x4B, 0x07),
-   _INIT_DCS_CMD(0x4C, 0x01),
-   _INI

[PATCH v5 6/9] drm/panel: novatek-nt36672e: Switch to mipi_dsi_dcs_write_seq_multi()

2024-05-14 Thread Douglas Anderson
This is a mechanical conversion of the novatek-nt36672e driver to use
the new mipi_dsi_dcs_write_seq_multi(). The new function is easier for
clients to understand and using it also causes smaller code to be
generated. Specifically:

$ scripts/bloat-o-meter \
  ...after/panel-novatek-nt36672e.ko \
  ...ctx/panel-novatek-nt36672e.ko
add/remove: 0/0 grow/shrink: 0/1 up/down: 0/-988 (-988)
Function old new   delta
nt36672e_1080x2408_60hz_init62365248-988
Total: Before=10651, After=9663, chg -9.28%

Cc: Ritesh Kumar 
Reviewed-by: Dmitry Baryshkov 
Reviewed-by: Linus Walleij 
Signed-off-by: Douglas Anderson 
---
This change is only compile tested. I don't use this panel myself but
arbitrarily picked it as an example to look at when working on the
MIPI DSI macros.

(no changes since v3)

Changes in v3:
- Fix spacing of init function.

Changes in v2:
- New

 .../gpu/drm/panel/panel-novatek-nt36672e.c| 576 +-
 1 file changed, 289 insertions(+), 287 deletions(-)

diff --git a/drivers/gpu/drm/panel/panel-novatek-nt36672e.c 
b/drivers/gpu/drm/panel/panel-novatek-nt36672e.c
index 20b7bfe4aa12..9ce8df455232 100644
--- a/drivers/gpu/drm/panel/panel-novatek-nt36672e.c
+++ b/drivers/gpu/drm/panel/panel-novatek-nt36672e.c
@@ -51,293 +51,295 @@ static inline struct nt36672e_panel 
*to_nt36672e_panel(struct drm_panel *panel)
 
 static int nt36672e_1080x2408_60hz_init(struct mipi_dsi_device *dsi)
 {
-   mipi_dsi_dcs_write_seq(dsi, 0xff, 0x10);
-   mipi_dsi_dcs_write_seq(dsi, 0xfb, 0x01);
-   mipi_dsi_dcs_write_seq(dsi, 0xb0, 0x00);
-   mipi_dsi_dcs_write_seq(dsi, 0xc0, 0x00);
-   mipi_dsi_dcs_write_seq(dsi, 0xc1, 0x89, 0x28, 0x00, 0x08, 0x00, 0xaa, 
0x02,
-   0x0e, 0x00, 0x2b, 0x00, 0x07, 0x0d, 0xb7, 0x0c, 
0xb7);
-
-   mipi_dsi_dcs_write_seq(dsi, 0xc2, 0x1b, 0xa0);
-   mipi_dsi_dcs_write_seq(dsi, 0xff, 0x20);
-   mipi_dsi_dcs_write_seq(dsi, 0xfb, 0x01);
-   mipi_dsi_dcs_write_seq(dsi, 0x01, 0x66);
-   mipi_dsi_dcs_write_seq(dsi, 0x06, 0x40);
-   mipi_dsi_dcs_write_seq(dsi, 0x07, 0x38);
-   mipi_dsi_dcs_write_seq(dsi, 0x2f, 0x83);
-   mipi_dsi_dcs_write_seq(dsi, 0x69, 0x91);
-   mipi_dsi_dcs_write_seq(dsi, 0x95, 0xd1);
-   mipi_dsi_dcs_write_seq(dsi, 0x96, 0xd1);
-   mipi_dsi_dcs_write_seq(dsi, 0xf2, 0x64);
-   mipi_dsi_dcs_write_seq(dsi, 0xf3, 0x54);
-   mipi_dsi_dcs_write_seq(dsi, 0xf4, 0x64);
-   mipi_dsi_dcs_write_seq(dsi, 0xf5, 0x54);
-   mipi_dsi_dcs_write_seq(dsi, 0xf6, 0x64);
-   mipi_dsi_dcs_write_seq(dsi, 0xf7, 0x54);
-   mipi_dsi_dcs_write_seq(dsi, 0xf8, 0x64);
-   mipi_dsi_dcs_write_seq(dsi, 0xf9, 0x54);
-   mipi_dsi_dcs_write_seq(dsi, 0xff, 0x24);
-   mipi_dsi_dcs_write_seq(dsi, 0xfb, 0x01);
-   mipi_dsi_dcs_write_seq(dsi, 0x01, 0x0f);
-   mipi_dsi_dcs_write_seq(dsi, 0x03, 0x0c);
-   mipi_dsi_dcs_write_seq(dsi, 0x05, 0x1d);
-   mipi_dsi_dcs_write_seq(dsi, 0x08, 0x2f);
-   mipi_dsi_dcs_write_seq(dsi, 0x09, 0x2e);
-   mipi_dsi_dcs_write_seq(dsi, 0x0a, 0x2d);
-   mipi_dsi_dcs_write_seq(dsi, 0x0b, 0x2c);
-   mipi_dsi_dcs_write_seq(dsi, 0x11, 0x17);
-   mipi_dsi_dcs_write_seq(dsi, 0x12, 0x13);
-   mipi_dsi_dcs_write_seq(dsi, 0x13, 0x15);
-   mipi_dsi_dcs_write_seq(dsi, 0x15, 0x14);
-   mipi_dsi_dcs_write_seq(dsi, 0x16, 0x16);
-   mipi_dsi_dcs_write_seq(dsi, 0x17, 0x18);
-   mipi_dsi_dcs_write_seq(dsi, 0x1b, 0x01);
-   mipi_dsi_dcs_write_seq(dsi, 0x1d, 0x1d);
-   mipi_dsi_dcs_write_seq(dsi, 0x20, 0x2f);
-   mipi_dsi_dcs_write_seq(dsi, 0x21, 0x2e);
-   mipi_dsi_dcs_write_seq(dsi, 0x22, 0x2d);
-   mipi_dsi_dcs_write_seq(dsi, 0x23, 0x2c);
-   mipi_dsi_dcs_write_seq(dsi, 0x29, 0x17);
-   mipi_dsi_dcs_write_seq(dsi, 0x2a, 0x13);
-   mipi_dsi_dcs_write_seq(dsi, 0x2b, 0x15);
-   mipi_dsi_dcs_write_seq(dsi, 0x2f, 0x14);
-   mipi_dsi_dcs_write_seq(dsi, 0x30, 0x16);
-   mipi_dsi_dcs_write_seq(dsi, 0x31, 0x18);
-   mipi_dsi_dcs_write_seq(dsi, 0x32, 0x04);
-   mipi_dsi_dcs_write_seq(dsi, 0x34, 0x10);
-   mipi_dsi_dcs_write_seq(dsi, 0x35, 0x1f);
-   mipi_dsi_dcs_write_seq(dsi, 0x36, 0x1f);
-   mipi_dsi_dcs_write_seq(dsi, 0x4d, 0x14);
-   mipi_dsi_dcs_write_seq(dsi, 0x4e, 0x36);
-   mipi_dsi_dcs_write_seq(dsi, 0x4f, 0x36);
-   mipi_dsi_dcs_write_seq(dsi, 0x53, 0x36);
-   mipi_dsi_dcs_write_seq(dsi, 0x71, 0x30);
-   mipi_dsi_dcs_write_seq(dsi, 0x79, 0x11);
-   mipi_dsi_dcs_write_seq(dsi, 0x7a, 0x82);
-   mipi_dsi_dcs_write_seq(dsi, 0x7b, 0x8f);
-   mipi_dsi_dcs_write_seq(dsi, 0x7d, 0x04);
-   mipi_dsi_dcs_write_seq(dsi, 0x80, 0x04);
-   mipi_dsi_dcs_write_seq(dsi, 0x81, 0x04);
-   mipi_dsi_dcs_write_seq(dsi, 0x82, 0x13);
-   mipi_dsi_dcs_write_seq(dsi, 0x84, 0x31);
-   mipi_dsi_dcs_write_seq(dsi, 0x85, 0x00);
-   mipi_dsi_dcs_write_seq(dsi, 0x86,

[PATCH v5 5/9] drm/mipi-dsi: Introduce mipi_dsi_*_write_seq_multi()

2024-05-14 Thread Douglas Anderson
The current mipi_dsi_*_write_seq() macros are non-intutitive because
they contain a hidden "return" statement that will return out of the
_caller_ of the macro. Let's mark them as deprecated and instead
introduce some new macros that are more intuitive.

These new macros are less optimal when an error occurs but should
behave more optimally when there is no error. Specifically these new
macros cause smaller code to get generated and the code size savings
(less to fetch from RAM, less cache space used, less RAM used) are
important. Since the error case isn't something we need to optimize
for and these new macros are easier to understand and more flexible,
they should be used.

After converting to use these new functions, one example shows some
nice savings while also being easier to understand.

$ scripts/bloat-o-meter \
  ...after/panel-novatek-nt36672e.ko \
  ...ctx/panel-novatek-nt36672e.ko
add/remove: 0/0 grow/shrink: 0/1 up/down: 0/-988 (-988)
Function old new   delta
nt36672e_1080x2408_60hz_init62365248-988
Total: Before=10651, After=9663, chg -9.28%

Reviewed-by: Neil Armstrong 
Reviewed-by: Linus Walleij 
Signed-off-by: Douglas Anderson 
---
Right now this patch introduces two new functions in drm_mipi_dsi.c.
Alternatively we could have changed the prototype of the "chatty"
functions and made the deprecated macros adapt to the new prototype.
While this sounds nice, it bloated callers of the deprecated functioin
a bit because it caused the compiler to emit less optimal code. It
doesn't seem terrible to add two more functions, so I went that
way. There may be cases where callers who aren't writing many
sequences prefer to use the "chatty" versions anyway.

(no changes since v3)

Changes in v3:
- Add a TODO item for cleaning up the deprecated macros/functions.
- Inline kerneldoc comments for struct mipi_dsi_multi_context.

Changes in v2:
- New

 Documentation/gpu/todo.rst | 18 ++
 drivers/gpu/drm/drm_mipi_dsi.c | 56 ++
 include/drm/drm_mipi_dsi.h | 62 ++
 3 files changed, 136 insertions(+)

diff --git a/Documentation/gpu/todo.rst b/Documentation/gpu/todo.rst
index e2a0585915b3..2734b8a34541 100644
--- a/Documentation/gpu/todo.rst
+++ b/Documentation/gpu/todo.rst
@@ -494,6 +494,24 @@ Contact: Douglas Anderson 
 
 Level: Starter/Intermediate
 
+Transition away from using mipi_dsi_*_write_seq()
+-
+
+The macros mipi_dsi_generic_write_seq() and mipi_dsi_dcs_write_seq() are
+non-intuitive because, if there are errors, they return out of the *caller's*
+function. We should move all callers to use mipi_dsi_generic_write_seq_multi()
+and mipi_dsi_dcs_write_seq_multi() macros instead.
+
+Once all callers are transitioned, the macros and the functions that they call,
+mipi_dsi_generic_write_chatty() and mipi_dsi_dcs_write_buffer_chatty(), can
+probably be removed. Alternatively, if people feel like the _multi() variants
+are overkill for some use cases, we could keep the mipi_dsi_*_write_seq()
+variants but change them not to return out of the caller.
+
+Contact: Douglas Anderson 
+
+Level: Starter
+
 
 Core refactorings
 =
diff --git a/drivers/gpu/drm/drm_mipi_dsi.c b/drivers/gpu/drm/drm_mipi_dsi.c
index 4d2685d5a6e0..26c7383406c1 100644
--- a/drivers/gpu/drm/drm_mipi_dsi.c
+++ b/drivers/gpu/drm/drm_mipi_dsi.c
@@ -792,6 +792,34 @@ int mipi_dsi_generic_write_chatty(struct mipi_dsi_device 
*dsi,
 }
 EXPORT_SYMBOL(mipi_dsi_generic_write_chatty);
 
+/**
+ * mipi_dsi_generic_write_multi() - mipi_dsi_generic_write_chatty() w/ 
accum_err
+ * @ctx: Context for multiple DSI transactions
+ * @payload: buffer containing the payload
+ * @size: size of payload buffer
+ *
+ * Like mipi_dsi_generic_write_chatty() but deals with errors in a way that
+ * makes it convenient to make several calls in a row.
+ */
+void mipi_dsi_generic_write_multi(struct mipi_dsi_multi_context *ctx,
+ const void *payload, size_t size)
+{
+   struct mipi_dsi_device *dsi = ctx->dsi;
+   struct device *dev = &dsi->dev;
+   ssize_t ret;
+
+   if (ctx->accum_err)
+   return;
+
+   ret = mipi_dsi_generic_write(dsi, payload, size);
+   if (ret < 0) {
+   ctx->accum_err = ret;
+   dev_err(dev, "sending generic data %*ph failed: %d\n",
+   (int)size, payload, ctx->accum_err);
+   }
+}
+EXPORT_SYMBOL(mipi_dsi_generic_write_multi);
+
 /**
  * mipi_dsi_generic_read() - receive data using a generic read packet
  * @dsi: DSI peripheral device
@@ -908,6 +936,34 @@ int mipi_dsi_dcs_write_buffer_chatty(struct 
mipi_dsi_device *dsi,
 }
 EXPORT_SYMBOL(mipi_dsi_dcs_write_buffer_chatty);
 
+/**
+ * mipi_dsi_dcs_write_buffer_multi - mipi_dsi_dcs_write_buffer_c

[PATCH v5 3/9] drm/mipi-dsi: mipi_dsi_*_write functions don't need to ratelimit prints

2024-05-14 Thread Douglas Anderson
We really don't expect these errors to be printed over and over
again. When a driver hits the error it should bail out. Just use a
normal error print.

This gives a nice space savings for users of these functions:

$ scripts/bloat-o-meter \
  .../before/panel-novatek-nt36672e.ko \
  .../after/panel-novatek-nt36672e.ko
add/remove: 0/1 grow/shrink: 0/1 up/down: 0/-16760 (-16760)
Function old new   delta
nt36672e_1080x2408_60hz_init   17080   10640   -6440
nt36672e_1080x2408_60hz_init._rs   10320   -  -10320
Total: Before=31815, After=15055, chg -52.68%

Reviewed-by: Neil Armstrong 
Reviewed-by: Linus Walleij 
Signed-off-by: Douglas Anderson 
---

(no changes since v3)

Changes in v3:
- ("mipi_dsi_*_write functions don't need to ratelimit...") moved earlier.

Changes in v2:
- New

 include/drm/drm_mipi_dsi.h | 24 +++-
 1 file changed, 11 insertions(+), 13 deletions(-)

diff --git a/include/drm/drm_mipi_dsi.h b/include/drm/drm_mipi_dsi.h
index e0f56564bf97..67967be48dbd 100644
--- a/include/drm/drm_mipi_dsi.h
+++ b/include/drm/drm_mipi_dsi.h
@@ -314,17 +314,16 @@ int mipi_dsi_dcs_get_display_brightness_large(struct 
mipi_dsi_device *dsi,
  * @dsi: DSI peripheral device
  * @seq: buffer containing the payload
  */
-#define mipi_dsi_generic_write_seq(dsi, seq...)
 \
-   do {
\
-   static const u8 d[] = { seq };  
\
-   struct device *dev = &dsi->dev; 
\
-   ssize_t ret;
\
-   ret = mipi_dsi_generic_write(dsi, d, ARRAY_SIZE(d));
\
-   if (ret < 0) {  
\
-   dev_err_ratelimited(dev, "transmit data failed: %zd\n", 
\
-   ret);   
\
-   return ret; 
\
-   }   
\
+#define mipi_dsi_generic_write_seq(dsi, seq...)   \
+   do {  \
+   static const u8 d[] = { seq };\
+   struct device *dev = &dsi->dev;   \
+   ssize_t ret;  \
+   ret = mipi_dsi_generic_write(dsi, d, ARRAY_SIZE(d));  \
+   if (ret < 0) {\
+   dev_err(dev, "transmit data failed: %zd\n", ret); \
+   return ret;   \
+   } \
} while (0)
 
 /**
@@ -340,8 +339,7 @@ int mipi_dsi_dcs_get_display_brightness_large(struct 
mipi_dsi_device *dsi,
ssize_t ret;\
ret = mipi_dsi_dcs_write_buffer(dsi, d, ARRAY_SIZE(d)); \
if (ret < 0) {  \
-   dev_err_ratelimited(\
-   dev, "sending command %#02x failed: %zd\n", \
+   dev_err(dev, "sending command %#02x failed: %zd\n", \
cmd, ret);  \
return ret; \
}   \
-- 
2.45.0.rc1.225.g2a3ae87e7f-goog



[PATCH v5 4/9] drm/mipi-dsi: Reduce driver bloat of mipi_dsi_*_write_seq()

2024-05-14 Thread Douglas Anderson
Through a cooperative effort between Hsin-Yi Wang and Dmitry
Baryshkov, we have realized the dev_err() in the
mipi_dsi_*_write_seq() macros was causing quite a bit of bloat to the
kernel. Let's hoist this call into drm_mipi_dsi.c by adding a "chatty"
version of the functions that includes the print. While doing this,
add a bit more comments to these macros making it clear that they
print errors and also that they return out of _the caller's_ function.

Without any changes to clients this gives a nice savings. Specifically
the macro was inlined and thus the error report call was inlined into
every call to mipi_dsi_dcs_write_seq() and
mipi_dsi_generic_write_seq(). By using a call to a "chatty" function,
the usage is reduced to one call in the chatty function and a function
call at the invoking site.

Building with my build system shows one example:

$ scripts/bloat-o-meter \
  .../before/panel-novatek-nt36672e.ko \
  .../after/panel-novatek-nt36672e.ko
add/remove: 0/0 grow/shrink: 0/1 up/down: 0/-4404 (-4404)
Function old new   delta
nt36672e_1080x2408_60hz_init   106406236   -4404
Total: Before=15055, After=10651, chg -29.25%

Note that given the change in location of the print it's harder to
include the "cmd" in the printout for mipi_dsi_dcs_write_seq() since,
theoretically, someone could call the new chatty function with a
zero-size array and it would be illegal to dereference data[0].
There's a printk format to print the whole buffer and this is probably
more useful for debugging anyway. Given that we're doing this for
mipi_dsi_dcs_write_seq(), let's also print the buffer for
mipi_dsi_generic_write_seq() in the error case.

It should be noted that the current consensus of DRM folks is that the
mipi_dsi_*_write_seq() should be deprecated due to the non-intuitive
return behavior. A future patch will formally mark them as deprecated
and provide an alternative.

Reviewed-by: Dmitry Baryshkov 
Reviewed-by: Neil Armstrong 
Reviewed-by: Linus Walleij 
Signed-off-by: Douglas Anderson 
---

Changes in v5:
- Fix comment dev_err_ratelimited() => dev_err().

Changes in v4:
- Update wording as per Linus W.

Changes in v3:
- Rebased upon patch to remove ratelimit of prints.

Changes in v2:
- Add some comments to the macros about printing and returning.
- Change the way err value is handled in prep for next patch.
- Modify commit message now that this is part of a series.
- Rebased upon patches to avoid theoretical int overflow.

 drivers/gpu/drm/drm_mipi_dsi.c | 56 ++
 include/drm/drm_mipi_dsi.h | 47 +++-
 2 files changed, 82 insertions(+), 21 deletions(-)

diff --git a/drivers/gpu/drm/drm_mipi_dsi.c b/drivers/gpu/drm/drm_mipi_dsi.c
index 795001bb7ff1..4d2685d5a6e0 100644
--- a/drivers/gpu/drm/drm_mipi_dsi.c
+++ b/drivers/gpu/drm/drm_mipi_dsi.c
@@ -764,6 +764,34 @@ ssize_t mipi_dsi_generic_write(struct mipi_dsi_device 
*dsi, const void *payload,
 }
 EXPORT_SYMBOL(mipi_dsi_generic_write);
 
+/**
+ * mipi_dsi_generic_write_chatty() - mipi_dsi_generic_write() w/ an error log
+ * @dsi: DSI peripheral device
+ * @payload: buffer containing the payload
+ * @size: size of payload buffer
+ *
+ * Like mipi_dsi_generic_write() but includes a dev_err()
+ * call for you and returns 0 upon success, not the number of bytes sent.
+ *
+ * Return: 0 on success or a negative error code on failure.
+ */
+int mipi_dsi_generic_write_chatty(struct mipi_dsi_device *dsi,
+ const void *payload, size_t size)
+{
+   struct device *dev = &dsi->dev;
+   ssize_t ret;
+
+   ret = mipi_dsi_generic_write(dsi, payload, size);
+   if (ret < 0) {
+   dev_err(dev, "sending generic data %*ph failed: %zd\n",
+   (int)size, payload, ret);
+   return ret;
+   }
+
+   return 0;
+}
+EXPORT_SYMBOL(mipi_dsi_generic_write_chatty);
+
 /**
  * mipi_dsi_generic_read() - receive data using a generic read packet
  * @dsi: DSI peripheral device
@@ -852,6 +880,34 @@ ssize_t mipi_dsi_dcs_write_buffer(struct mipi_dsi_device 
*dsi,
 }
 EXPORT_SYMBOL(mipi_dsi_dcs_write_buffer);
 
+/**
+ * mipi_dsi_dcs_write_buffer_chatty - mipi_dsi_dcs_write_buffer() w/ an error 
log
+ * @dsi: DSI peripheral device
+ * @data: buffer containing data to be transmitted
+ * @len: size of transmission buffer
+ *
+ * Like mipi_dsi_dcs_write_buffer() but includes a dev_err()
+ * call for you and returns 0 upon success, not the number of bytes sent.
+ *
+ * Return: 0 on success or a negative error code on failure.
+ */
+int mipi_dsi_dcs_write_buffer_chatty(struct mipi_dsi_device *dsi,
+const void *data, size_t len)
+{
+   struct device *dev = &dsi->dev;
+   ssize_t ret;
+
+   ret = mipi_dsi_dcs_write_buffer(dsi, data, len)

[PATCH v5 2/9] drm/mipi-dsi: Fix theoretical int overflow in mipi_dsi_generic_write_seq()

2024-05-14 Thread Douglas Anderson
The mipi_dsi_generic_write_seq() macro makes a call to
mipi_dsi_generic_write() which returns a type ssize_t. The macro then
stores it in an int and checks to see if it's negative. This could
theoretically be a problem if "ssize_t" is larger than "int".

To see the issue, imagine that "ssize_t" is 32-bits and "int" is
16-bits, you could see a problem if there was some code out there that
looked like:

  mipi_dsi_generic_write_seq(dsi, <32768 bytes as arguments>);

...since we'd get back that 32768 bytes were transferred and 32768
stored in a 16-bit int would look negative.

Though there are no callsites where we'd actually hit this (even if
"int" was only 16-bit), it's cleaner to make the types match so let's
fix it.

Fixes: a9015ce59320 ("drm/mipi-dsi: Add a mipi_dsi_dcs_write_seq() macro")
Reviewed-by: Neil Armstrong 
Reviewed-by: Linus Walleij 
Signed-off-by: Douglas Anderson 
---

(no changes since v3)

Changes in v3:
- Use %zd in print instead of casting errors to int.

Changes in v2:
- New

 include/drm/drm_mipi_dsi.h | 22 +++---
 1 file changed, 11 insertions(+), 11 deletions(-)

diff --git a/include/drm/drm_mipi_dsi.h b/include/drm/drm_mipi_dsi.h
index 70ce0b8cbc68..e0f56564bf97 100644
--- a/include/drm/drm_mipi_dsi.h
+++ b/include/drm/drm_mipi_dsi.h
@@ -314,17 +314,17 @@ int mipi_dsi_dcs_get_display_brightness_large(struct 
mipi_dsi_device *dsi,
  * @dsi: DSI peripheral device
  * @seq: buffer containing the payload
  */
-#define mipi_dsi_generic_write_seq(dsi, seq...)
\
-   do {   \
-   static const u8 d[] = { seq }; \
-   struct device *dev = &dsi->dev;\
-   int ret;   \
-   ret = mipi_dsi_generic_write(dsi, d, ARRAY_SIZE(d));   \
-   if (ret < 0) { \
-   dev_err_ratelimited(dev, "transmit data failed: %d\n", \
-   ret);  \
-   return ret;\
-   }  \
+#define mipi_dsi_generic_write_seq(dsi, seq...)
 \
+   do {
\
+   static const u8 d[] = { seq };  
\
+   struct device *dev = &dsi->dev; 
\
+   ssize_t ret;
\
+   ret = mipi_dsi_generic_write(dsi, d, ARRAY_SIZE(d));
\
+   if (ret < 0) {  
\
+   dev_err_ratelimited(dev, "transmit data failed: %zd\n", 
\
+   ret);   
\
+   return ret; 
\
+   }   
\
} while (0)
 
 /**
-- 
2.45.0.rc1.225.g2a3ae87e7f-goog



[PATCH v5 1/9] drm/mipi-dsi: Fix theoretical int overflow in mipi_dsi_dcs_write_seq()

2024-05-14 Thread Douglas Anderson
The mipi_dsi_dcs_write_seq() macro makes a call to
mipi_dsi_dcs_write_buffer() which returns a type ssize_t. The macro
then stores it in an int and checks to see if it's negative. This
could theoretically be a problem if "ssize_t" is larger than "int".

To see the issue, imagine that "ssize_t" is 32-bits and "int" is
16-bits, you could see a problem if there was some code out there that
looked like:

  mipi_dsi_dcs_write_seq(dsi, cmd, <32767 bytes as arguments>);

...since we'd get back that 32768 bytes were transferred and 32768
stored in a 16-bit int would look negative.

Though there are no callsites where we'd actually hit this (even if
"int" was only 16-bit), it's cleaner to make the types match so let's
fix it.

Fixes: 2a9e9daf7523 ("drm/mipi-dsi: Introduce mipi_dsi_dcs_write_seq macro")
Reviewed-by: Neil Armstrong 
Reviewed-by: Linus Walleij 
Signed-off-by: Douglas Anderson 
---

(no changes since v3)

Changes in v3:
- Use %zd in print instead of casting errors to int.

Changes in v2:
- New

 include/drm/drm_mipi_dsi.h | 24 
 1 file changed, 12 insertions(+), 12 deletions(-)

diff --git a/include/drm/drm_mipi_dsi.h b/include/drm/drm_mipi_dsi.h
index 82b1cc434ea3..70ce0b8cbc68 100644
--- a/include/drm/drm_mipi_dsi.h
+++ b/include/drm/drm_mipi_dsi.h
@@ -333,18 +333,18 @@ int mipi_dsi_dcs_get_display_brightness_large(struct 
mipi_dsi_device *dsi,
  * @cmd: Command
  * @seq: buffer containing data to be transmitted
  */
-#define mipi_dsi_dcs_write_seq(dsi, cmd, seq...)   \
-   do {   \
-   static const u8 d[] = { cmd, seq };\
-   struct device *dev = &dsi->dev;\
-   int ret;   \
-   ret = mipi_dsi_dcs_write_buffer(dsi, d, ARRAY_SIZE(d));\
-   if (ret < 0) { \
-   dev_err_ratelimited(   \
-   dev, "sending command %#02x failed: %d\n", \
-   cmd, ret); \
-   return ret;\
-   }  \
+#define mipi_dsi_dcs_write_seq(dsi, cmd, seq...)\
+   do {\
+   static const u8 d[] = { cmd, seq }; \
+   struct device *dev = &dsi->dev; \
+   ssize_t ret;\
+   ret = mipi_dsi_dcs_write_buffer(dsi, d, ARRAY_SIZE(d)); \
+   if (ret < 0) {  \
+   dev_err_ratelimited(\
+   dev, "sending command %#02x failed: %zd\n", \
+   cmd, ret);  \
+   return ret; \
+   }   \
} while (0)
 
 /**
-- 
2.45.0.rc1.225.g2a3ae87e7f-goog



[PATCH v5 0/9] drm/mipi-dsi: Reduce bloat and add funcs for cleaner init seqs

2024-05-14 Thread Douglas Anderson
The consensus of many DRM folks is that we want to move away from DSI
drivers defining tables of init commands. Instead, we want to move to
init functions that can use common DRM functions. The issue thus far
has been that using the macros mipi_dsi_generic_write_seq() and
mipi_dsi_dcs_write_seq() bloats the driver using them.

While trying to solve bloat, we realized that the majority of the it
was easy to solve. This series solves the bloat for existing drivers
by moving the printout outside of the macro.

During discussion of my v1 patch to fix the bloat [1], we also decided
that we really want to change the way that drivers deal with init
sequences to make it clearer. In addition to being cleaner, a side
effect of moving drivers to the new style reduces bloat _even more_.

This series also contains a few minor fixes / cleanups that I found
along the way.

This series converts four drivers over to the new
mipi_dsi_dcs_write_seq_multi() function. Not all conversions have been
tested, but hopefully they are straightforward enough. I'd appreciate
testing.

NOTE: In v3 I tried to incorporate the feedback from v2. I also
converted the other two panels I could find that used table-based
initialization.

v4 just has a tiny bugfix and collects tags. v5 has another tiny
bugfix. Assuming no other problems are found the plan is to land this
series sometime roughly around May 16 [2].

[1] 
https://lore.kernel.org/r/20240424172017.1.Id15fae80582bc74a0d4f1338987fa375738f45b9@changeid
[2] https://lore.kernel.org/r/35b899d2-fb47-403a-83d2-204c0800d...@linaro.org

Changes in v5:
- Fix comment dev_err_ratelimited() => dev_err().

Changes in v4:
- Test to see if init is non-NULL before using it.
- Update wording as per Linus W.

Changes in v3:
- ("mipi_dsi_*_write functions don't need to ratelimit...") moved earlier.
- Add a TODO item for cleaning up the deprecated macros/functions.
- Fix spacing of init function.
- Inline kerneldoc comments for struct mipi_dsi_multi_context.
- Rebased upon patch to remove ratelimit of prints.
- Remove an unneeded error print.
- Squash boe-tv101wum-nl6 lowercase patch into main patch
- Use %zd in print instead of casting errors to int.
- drm/panel: ili9882t: Don't use a table for initting panels
- drm/panel: innolux-p079zca: Don't use a table for initting panels

Changes in v2:
- Add some comments to the macros about printing and returning.
- Change the way err value is handled in prep for next patch.
- Modify commit message now that this is part of a series.
- Rebased upon patches to avoid theoretical int overflow.
- drm/mipi-dsi: Fix theoretical int overflow in mipi_dsi_dcs_write_seq()
- drm/mipi-dsi: Fix theoretical int overflow in mipi_dsi_generic_write_seq()
- drm/mipi-dsi: Introduce mipi_dsi_*_write_seq_multi()
- drm/mipi-dsi: mipi_dsi_*_write functions don't need to ratelimit prints
- drm/panel: boe-tv101wum-nl6: Convert hex to lowercase
- drm/panel: boe-tv101wum-nl6: Don't use a table for initting commands
- drm/panel: novatek-nt36672e: Switch to mipi_dsi_dcs_write_seq_multi()

Douglas Anderson (9):
  drm/mipi-dsi: Fix theoretical int overflow in mipi_dsi_dcs_write_seq()
  drm/mipi-dsi: Fix theoretical int overflow in
mipi_dsi_generic_write_seq()
  drm/mipi-dsi: mipi_dsi_*_write functions don't need to ratelimit
prints
  drm/mipi-dsi: Reduce driver bloat of mipi_dsi_*_write_seq()
  drm/mipi-dsi: Introduce mipi_dsi_*_write_seq_multi()
  drm/panel: novatek-nt36672e: Switch to mipi_dsi_dcs_write_seq_multi()
  drm/panel: boe-tv101wum-nl6: Don't use a table for initting panels
  drm/panel: ili9882t: Don't use a table for initting panels
  drm/panel: innolux-p079zca: Don't use a table for initting panels

 Documentation/gpu/todo.rst|   18 +
 drivers/gpu/drm/drm_mipi_dsi.c|  112 +
 .../gpu/drm/panel/panel-boe-tv101wum-nl6.c| 2792 +
 drivers/gpu/drm/panel/panel-ilitek-ili9882t.c |  794 +++--
 drivers/gpu/drm/panel/panel-innolux-p079zca.c |  284 +-
 .../gpu/drm/panel/panel-novatek-nt36672e.c|  576 ++--
 include/drm/drm_mipi_dsi.h|  101 +-
 7 files changed, 2452 insertions(+), 2225 deletions(-)

-- 
2.45.0.rc1.225.g2a3ae87e7f-goog



[PATCH v4 8/9] drm/panel: ili9882t: Don't use a table for initting panels

2024-05-08 Thread Douglas Anderson
Consensus on the mailing lists is that panels shouldn't use a table of
init commands but should instead use init functions. With the recently
introduced mipi_dsi_dcs_write_seq_multi() this is not only clean/easy
but also saves space. Measuring before/after this change:

$ scripts/bloat-o-meter \
  .../before/panel-ilitek-ili9882t.ko \
  .../after/panel-ilitek-ili9882t.ko
add/remove: 3/2 grow/shrink: 0/2 up/down: 6834/-8177 (-1343)
Function old new   delta
starry_ili9882t_init   -6152   +6152
starry_ili9882t_init.d - 678+678
ili9882t_disable.d -   4  +4
ili9882t_disable 260 228 -32
ili9882t_prepare 540 396-144
.compoundliteral 681   --681
starry_ili9882t_init_cmd7320   -   -7320
Total: Before=11928, After=10585, chg -11.26%

Let's do the conversion.

Since we're touching all the tables, let's also convert hex numbers to
lower case as per kernel conventions.

Reviewed-by: Linus Walleij 
Signed-off-by: Douglas Anderson 
---

(no changes since v3)

Changes in v3:
- New

 drivers/gpu/drm/panel/panel-ilitek-ili9882t.c | 794 --
 1 file changed, 368 insertions(+), 426 deletions(-)

diff --git a/drivers/gpu/drm/panel/panel-ilitek-ili9882t.c 
b/drivers/gpu/drm/panel/panel-ilitek-ili9882t.c
index 267a5307041c..58fc1d799371 100644
--- a/drivers/gpu/drm/panel/panel-ilitek-ili9882t.c
+++ b/drivers/gpu/drm/panel/panel-ilitek-ili9882t.c
@@ -15,6 +15,8 @@
 
 #include 
 
+struct ili9882t;
+
 /*
  * Use this descriptor struct to describe different panels using the
  * Ilitek ILI9882T display controller.
@@ -34,7 +36,7 @@ struct panel_desc {
 
unsigned long mode_flags;
enum mipi_dsi_pixel_format format;
-   const struct panel_init_cmd *init_cmds;
+   int (*init)(struct ili9882t *boe);
unsigned int lanes;
 };
 
@@ -52,433 +54,372 @@ struct ili9882t {
struct gpio_desc *enable_gpio;
 };
 
-enum dsi_cmd_type {
-   INIT_DCS_CMD,
-   DELAY_CMD,
-};
-
-struct panel_init_cmd {
-   enum dsi_cmd_type type;
-   size_t len;
-   const char *data;
-};
-
-#define _INIT_DCS_CMD(...) { \
-   .type = INIT_DCS_CMD, \
-   .len = sizeof((char[]){__VA_ARGS__}), \
-   .data = (char[]){__VA_ARGS__} }
-
-#define _INIT_DELAY_CMD(...) { \
-   .type = DELAY_CMD,\
-   .len = sizeof((char[]){__VA_ARGS__}), \
-   .data = (char[]){__VA_ARGS__} }
-
 /* ILI9882-specific commands, add new commands as you decode them */
 #define ILI9882T_DCS_SWITCH_PAGE   0xFF
 
-#define _INIT_SWITCH_PAGE_CMD(page) \
-   _INIT_DCS_CMD(ILI9882T_DCS_SWITCH_PAGE, 0x98, 0x82, (page))
-
-static const struct panel_init_cmd starry_ili9882t_init_cmd[] = {
-   _INIT_DELAY_CMD(5),
-   _INIT_SWITCH_PAGE_CMD(0x01),
-   _INIT_DCS_CMD(0x00, 0x42),
-   _INIT_DCS_CMD(0x01, 0x11),
-   _INIT_DCS_CMD(0x02, 0x00),
-   _INIT_DCS_CMD(0x03, 0x00),
-
-   _INIT_DCS_CMD(0x04, 0x01),
-   _INIT_DCS_CMD(0x05, 0x11),
-   _INIT_DCS_CMD(0x06, 0x00),
-   _INIT_DCS_CMD(0x07, 0x00),
-
-   _INIT_DCS_CMD(0x08, 0x80),
-   _INIT_DCS_CMD(0x09, 0x81),
-   _INIT_DCS_CMD(0x0A, 0x71),
-   _INIT_DCS_CMD(0x0B, 0x00),
-
-   _INIT_DCS_CMD(0x0C, 0x00),
-   _INIT_DCS_CMD(0x0E, 0x1A),
-
-   _INIT_DCS_CMD(0x24, 0x00),
-   _INIT_DCS_CMD(0x25, 0x00),
-   _INIT_DCS_CMD(0x26, 0x00),
-   _INIT_DCS_CMD(0x27, 0x00),
-
-   _INIT_DCS_CMD(0x2C, 0xD4),
-   _INIT_DCS_CMD(0xB9, 0x40),
-
-   _INIT_DCS_CMD(0xB0, 0x11),
-
-   _INIT_DCS_CMD(0xE6, 0x32),
-   _INIT_DCS_CMD(0xD1, 0x30),
-
-   _INIT_DCS_CMD(0xD6, 0x55),
-
-   _INIT_DCS_CMD(0xD0, 0x01),
-   _INIT_DCS_CMD(0xE3, 0x93),
-   _INIT_DCS_CMD(0xE4, 0x00),
-   _INIT_DCS_CMD(0xE5, 0x80),
-
-   _INIT_DCS_CMD(0x31, 0x07),
-   _INIT_DCS_CMD(0x32, 0x07),
-   _INIT_DCS_CMD(0x33, 0x07),
-   _INIT_DCS_CMD(0x34, 0x07),
-   _INIT_DCS_CMD(0x35, 0x07),
-   _INIT_DCS_CMD(0x36, 0x01),
-   _INIT_DCS_CMD(0x37, 0x00),
-   _INIT_DCS_CMD(0x38, 0x28),
-   _INIT_DCS_CMD(0x39, 0x29),
-   _INIT_DCS_CMD(0x3A, 0x11),
-   _INIT_DCS_CMD(0x3B, 0x13),
-   _INIT_DCS_CMD(0x3C, 0x15),
-   _INIT_DCS_CMD(0x3D, 0x17),
-   _INIT_DCS_CMD(0x3E, 0x09),
-   _INIT_DCS_CMD(0x3F, 0x0D),
-   _INIT_DCS_CMD(0x40, 0x02),
-   _INIT_DCS_CMD(0x41, 0x02),
-   _INIT_DCS_CMD(0x42, 0x02),
-   _INIT_DCS_CMD(0x43, 0x02),
-   _INIT_DCS_CMD(0x44, 0x02),
-   _INIT_DCS_CMD(0x45, 0x02),
-   _INIT_DCS_CMD(0x46, 0x02),
-
-   _INIT_DCS_CMD(0x47, 0x07),
-   _INIT_DCS_CMD(0x48, 0x07),
-   _INIT_DCS_CMD(0x49, 0x07),
-   _INIT_DCS_CMD(0x4A, 0x07),
-   _INIT_DCS_CMD(0x4B, 0x07),
-   _INIT_DCS_CMD(0x4C, 0x01),
-   _INI

[PATCH v4 9/9] drm/panel: innolux-p079zca: Don't use a table for initting panels

2024-05-08 Thread Douglas Anderson
Consensus on the mailing lists is that panels shouldn't use a table of
init commands but should instead use init functions. We'll use the
same concepts as the recently introduced
mipi_dsi_generic_write_seq_multi() to make this clean/easy and also
not bloat the driver too much. Measuring before/after this change:

$ scripts/bloat-o-meter \
  .../before/panel-innolux-p079zca.ko \
  .../after/panel-innolux-p079zca.ko
add/remove: 3/2 grow/shrink: 0/1 up/down: 2356/-1944 (412)
Function old new   delta
innolux_p097pfg_init   -1772   +1772
innolux_p097pfg_init.d - 480+480
innolux_panel_write_multi  - 104+104
innolux_panel_prepare412 308-104
.compoundliteral 480   --480
innolux_p097pfg_init_cmds   1360   -   -1360
Total: Before=5802, After=6214, chg +7.10%

Note that, unlike some other drivers, we actually make this panel
driver _bigger_ by using the new functions. This is because the
innolux-p079zca panel driver didn't have as complex of a table and
thus the old table was more efficient than the code. The bloat is
still not giant (only 412 bytes).

Also note that we can't direclty use
mipi_dsi_generic_write_seq_multi() here because we need to deal with
the crazy "nop" that this driver sends after all commands. This means
that we have to write code that is "inspired" by the new macros.

Since we're touching all the tables, let's also convert hex numbers to
lower case as per kernel conventions.

Reviewed-by: Linus Walleij 
Signed-off-by: Douglas Anderson 
---

Changes in v4:
- Test to see if init is non-NULL before using it.

Changes in v3:
- New

 drivers/gpu/drm/panel/panel-innolux-p079zca.c | 284 +-
 1 file changed, 140 insertions(+), 144 deletions(-)

diff --git a/drivers/gpu/drm/panel/panel-innolux-p079zca.c 
b/drivers/gpu/drm/panel/panel-innolux-p079zca.c
index 485178a99910..ade8bf7491ee 100644
--- a/drivers/gpu/drm/panel/panel-innolux-p079zca.c
+++ b/drivers/gpu/drm/panel/panel-innolux-p079zca.c
@@ -17,14 +17,7 @@
 #include 
 #include 
 
-struct panel_init_cmd {
-   size_t len;
-   const char *data;
-};
-
-#define _INIT_CMD(...) { \
-   .len = sizeof((char[]){__VA_ARGS__}), \
-   .data = (char[]){__VA_ARGS__} }
+struct innolux_panel;
 
 struct panel_desc {
const struct drm_display_mode *mode;
@@ -36,7 +29,7 @@ struct panel_desc {
 
unsigned long flags;
enum mipi_dsi_pixel_format format;
-   const struct panel_init_cmd *init_cmds;
+   int (*init)(struct innolux_panel *innolux);
unsigned int lanes;
const char * const *supply_names;
unsigned int num_supplies;
@@ -132,32 +125,10 @@ static int innolux_panel_prepare(struct drm_panel *panel)
/* p079zca: t4, p097pfg: t5 */
usleep_range(2, 21000);
 
-   if (innolux->desc->init_cmds) {
-   const struct panel_init_cmd *cmds =
-   innolux->desc->init_cmds;
-   unsigned int i;
-
-   for (i = 0; cmds[i].len != 0; i++) {
-   const struct panel_init_cmd *cmd = &cmds[i];
-
-   err = mipi_dsi_generic_write(innolux->link, cmd->data,
-cmd->len);
-   if (err < 0) {
-   dev_err(panel->dev, "failed to write command 
%u\n", i);
-   goto poweroff;
-   }
-
-   /*
-* Included by random guessing, because without this
-* (or at least, some delay), the panel sometimes
-* didn't appear to pick up the command sequence.
-*/
-   err = mipi_dsi_dcs_nop(innolux->link);
-   if (err < 0) {
-   dev_err(panel->dev, "failed to send DCS nop: 
%d\n", err);
-   goto poweroff;
-   }
-   }
+   if (innolux->desc->init) {
+   err = innolux->desc->init(innolux);
+   if (err < 0)
+   goto poweroff;
}
 
err = mipi_dsi_dcs_exit_sleep_mode(innolux->link);
@@ -250,119 +221,144 @@ static const struct drm_display_mode 
innolux_p097pfg_mode = {
.vtotal = 2048 + 100 + 2 + 18,
 };
 
+static void innolux_panel_write_multi(struct mipi_dsi_multi_context *ctx,
+ const void *payload, size_t size)
+{
+   struct mipi_dsi_device *dsi = ctx->dsi;
+   struct device *dev = &dsi->dev;
+
+   mipi_dsi_generic_write_multi(ctx, payload, size);
+   if (

[PATCH v4 7/9] drm/panel: boe-tv101wum-nl6: Don't use a table for initting panels

2024-05-08 Thread Douglas Anderson
Consensus on the mailing lists is that panels shouldn't use a table of
init commands but should instead use init functions. With the recently
introduced mipi_dsi_dcs_write_seq_multi() this is not only clean/easy
but also saves space. Measuring before/after this change:

$ scripts/bloat-o-meter \
  .../before/panel-boe-tv101wum-nl6.ko \
  .../after/panel-boe-tv101wum-nl6.ko
add/remove: 14/8 grow/shrink: 0/1 up/down: 27062/-31433 (-4371)
Function old new   delta
inx_hj110iz_init   -7040   +7040
boe_tv110c9m_init  -6440   +6440
boe_init   -5916   +5916
starry_qfh032011_53g_init  -1944   +1944
starry_himax83102_j02_init -1228   +1228
inx_hj110iz_init.d -1040   +1040
boe_tv110c9m_init.d- 982+982
auo_b101uan08_3_init   - 944+944
boe_init.d - 580+580
starry_himax83102_j02_init.d   - 512+512
starry_qfh032011_53g_init.d- 180+180
auo_kd101n80_45na_init - 172+172
auo_b101uan08_3_init.d -  82 +82
auo_kd101n80_45na_init.d   -   2  +2
auo_kd101n80_45na_init_cmd   144   --144
boe_panel_prepare592 440-152
auo_b101uan08_3_init_cmd1056   -   -1056
starry_himax83102_j02_init_cmd  1392   -   -1392
starry_qfh032011_53g_init_cmd   2256   -   -2256
.compoundliteral3393   -   -3393
boe_init_cmd7008   -   -7008
boe_tv110c9m_init_cmd   7656   -   -7656
inx_hj110iz_init_cmd8376   -   -8376
Total: Before=37297, After=32926, chg -11.72%

Let's do the conversion.

Since we're touching all the tables, let's also convert hex numbers to
lower case as per kernel conventions.

Reviewed-by: Linus Walleij 
Signed-off-by: Douglas Anderson 
---

(no changes since v3)

Changes in v3:
- Fix spacing of init function.
- Remove an unneeded error print.
- Squash boe-tv101wum-nl6 lowercase patch into main patch

Changes in v2:
- New

 .../gpu/drm/panel/panel-boe-tv101wum-nl6.c| 2792 +
 1 file changed, 1442 insertions(+), 1350 deletions(-)

diff --git a/drivers/gpu/drm/panel/panel-boe-tv101wum-nl6.c 
b/drivers/gpu/drm/panel/panel-boe-tv101wum-nl6.c
index 0ffe8f8c01de..aab60cec0603 100644
--- a/drivers/gpu/drm/panel/panel-boe-tv101wum-nl6.c
+++ b/drivers/gpu/drm/panel/panel-boe-tv101wum-nl6.c
@@ -17,6 +17,8 @@
 
 #include 
 
+struct boe_panel;
+
 struct panel_desc {
const struct drm_display_mode *modes;
unsigned int bpc;
@@ -32,7 +34,7 @@ struct panel_desc {
 
unsigned long mode_flags;
enum mipi_dsi_pixel_format format;
-   const struct panel_init_cmd *init_cmds;
+   int (*init)(struct boe_panel *boe);
unsigned int lanes;
bool discharge_on_disable;
bool lp11_before_reset;
@@ -54,1318 +56,1449 @@ struct boe_panel {
bool prepared;
 };
 
-enum dsi_cmd_type {
-   INIT_DCS_CMD,
-   DELAY_CMD,
-};
+static int boe_tv110c9m_init(struct boe_panel *boe)
+{
+   struct mipi_dsi_multi_context ctx = { .dsi = boe->dsi };
+
+   mipi_dsi_dcs_write_seq_multi(&ctx, 0xff, 0x20);
+   mipi_dsi_dcs_write_seq_multi(&ctx, 0xfb, 0x01);
+   mipi_dsi_dcs_write_seq_multi(&ctx, 0x05, 0xd9);
+   mipi_dsi_dcs_write_seq_multi(&ctx, 0x07, 0x78);
+   mipi_dsi_dcs_write_seq_multi(&ctx, 0x08, 0x5a);
+   mipi_dsi_dcs_write_seq_multi(&ctx, 0x0d, 0x63);
+   mipi_dsi_dcs_write_seq_multi(&ctx, 0x0e, 0x91);
+   mipi_dsi_dcs_write_seq_multi(&ctx, 0x0f, 0x73);
+   mipi_dsi_dcs_write_seq_multi(&ctx, 0x95, 0xe6);
+   mipi_dsi_dcs_write_seq_multi(&ctx, 0x96, 0xf0);
+   mipi_dsi_dcs_write_seq_multi(&ctx, 0x30, 0x00);
+   mipi_dsi_dcs_write_seq_multi(&ctx, 0x6d, 0x66);
+   mipi_dsi_dcs_write_seq_multi(&ctx, 0x75, 0xa2);
+   mipi_dsi_dcs_write_seq_multi(&ctx, 0x77, 0x3b);
+
+   mipi_dsi_dcs_write_seq_multi(&ctx, 0xb0, 0x00, 0x08, 0x00, 0x23, 0x00, 
0x4d, 0x00, 0x6d,
+0x00, 0x89, 0x00, 0xa1, 0x00, 0xb6, 0x00, 
0xc9);
+   mipi_dsi_dcs_write_seq_multi(&ctx, 0xb1, 0x00, 0xda, 0x01, 0x13, 0x01, 
0x3c, 0x01, 0x7e,
+0x01, 0xab, 0x01, 0xf7, 0x02, 0x2f, 0x02, 
0x31);
+   mipi_dsi_dcs_write_seq_multi(&ctx, 0xb2, 0x02, 0x67, 0x02, 0xa6, 0x02, 
0xd1, 0x03, 0x08,
+0x03, 0x2e, 0x03, 0x5b, 0x03, 0x6b, 0x03, 
0x7b);
+

[PATCH v4 6/9] drm/panel: novatek-nt36672e: Switch to mipi_dsi_dcs_write_seq_multi()

2024-05-08 Thread Douglas Anderson
This is a mechanical conversion of the novatek-nt36672e driver to use
the new mipi_dsi_dcs_write_seq_multi(). The new function is easier for
clients to understand and using it also causes smaller code to be
generated. Specifically:

$ scripts/bloat-o-meter \
  ...after/panel-novatek-nt36672e.ko \
  ...ctx/panel-novatek-nt36672e.ko
add/remove: 0/0 grow/shrink: 0/1 up/down: 0/-988 (-988)
Function old new   delta
nt36672e_1080x2408_60hz_init62365248-988
Total: Before=10651, After=9663, chg -9.28%

Cc: Ritesh Kumar 
Signed-off-by: Douglas Anderson 
---
This change is only compile tested. I don't use this panel myself but
arbitrarily picked it as an example to look at when working on the
MIPI DSI macros.

NOTE: as of the posting of v4 this change still has no tags. Without
any tags (Reviewed-by/Tested-by/Acked-by) I won't actually land this
change even if the rest of the series lands.

(no changes since v3)

Changes in v3:
- Fix spacing of init function.

Changes in v2:
- New

 .../gpu/drm/panel/panel-novatek-nt36672e.c| 576 +-
 1 file changed, 289 insertions(+), 287 deletions(-)

diff --git a/drivers/gpu/drm/panel/panel-novatek-nt36672e.c 
b/drivers/gpu/drm/panel/panel-novatek-nt36672e.c
index 20b7bfe4aa12..9ce8df455232 100644
--- a/drivers/gpu/drm/panel/panel-novatek-nt36672e.c
+++ b/drivers/gpu/drm/panel/panel-novatek-nt36672e.c
@@ -51,293 +51,295 @@ static inline struct nt36672e_panel 
*to_nt36672e_panel(struct drm_panel *panel)
 
 static int nt36672e_1080x2408_60hz_init(struct mipi_dsi_device *dsi)
 {
-   mipi_dsi_dcs_write_seq(dsi, 0xff, 0x10);
-   mipi_dsi_dcs_write_seq(dsi, 0xfb, 0x01);
-   mipi_dsi_dcs_write_seq(dsi, 0xb0, 0x00);
-   mipi_dsi_dcs_write_seq(dsi, 0xc0, 0x00);
-   mipi_dsi_dcs_write_seq(dsi, 0xc1, 0x89, 0x28, 0x00, 0x08, 0x00, 0xaa, 
0x02,
-   0x0e, 0x00, 0x2b, 0x00, 0x07, 0x0d, 0xb7, 0x0c, 
0xb7);
-
-   mipi_dsi_dcs_write_seq(dsi, 0xc2, 0x1b, 0xa0);
-   mipi_dsi_dcs_write_seq(dsi, 0xff, 0x20);
-   mipi_dsi_dcs_write_seq(dsi, 0xfb, 0x01);
-   mipi_dsi_dcs_write_seq(dsi, 0x01, 0x66);
-   mipi_dsi_dcs_write_seq(dsi, 0x06, 0x40);
-   mipi_dsi_dcs_write_seq(dsi, 0x07, 0x38);
-   mipi_dsi_dcs_write_seq(dsi, 0x2f, 0x83);
-   mipi_dsi_dcs_write_seq(dsi, 0x69, 0x91);
-   mipi_dsi_dcs_write_seq(dsi, 0x95, 0xd1);
-   mipi_dsi_dcs_write_seq(dsi, 0x96, 0xd1);
-   mipi_dsi_dcs_write_seq(dsi, 0xf2, 0x64);
-   mipi_dsi_dcs_write_seq(dsi, 0xf3, 0x54);
-   mipi_dsi_dcs_write_seq(dsi, 0xf4, 0x64);
-   mipi_dsi_dcs_write_seq(dsi, 0xf5, 0x54);
-   mipi_dsi_dcs_write_seq(dsi, 0xf6, 0x64);
-   mipi_dsi_dcs_write_seq(dsi, 0xf7, 0x54);
-   mipi_dsi_dcs_write_seq(dsi, 0xf8, 0x64);
-   mipi_dsi_dcs_write_seq(dsi, 0xf9, 0x54);
-   mipi_dsi_dcs_write_seq(dsi, 0xff, 0x24);
-   mipi_dsi_dcs_write_seq(dsi, 0xfb, 0x01);
-   mipi_dsi_dcs_write_seq(dsi, 0x01, 0x0f);
-   mipi_dsi_dcs_write_seq(dsi, 0x03, 0x0c);
-   mipi_dsi_dcs_write_seq(dsi, 0x05, 0x1d);
-   mipi_dsi_dcs_write_seq(dsi, 0x08, 0x2f);
-   mipi_dsi_dcs_write_seq(dsi, 0x09, 0x2e);
-   mipi_dsi_dcs_write_seq(dsi, 0x0a, 0x2d);
-   mipi_dsi_dcs_write_seq(dsi, 0x0b, 0x2c);
-   mipi_dsi_dcs_write_seq(dsi, 0x11, 0x17);
-   mipi_dsi_dcs_write_seq(dsi, 0x12, 0x13);
-   mipi_dsi_dcs_write_seq(dsi, 0x13, 0x15);
-   mipi_dsi_dcs_write_seq(dsi, 0x15, 0x14);
-   mipi_dsi_dcs_write_seq(dsi, 0x16, 0x16);
-   mipi_dsi_dcs_write_seq(dsi, 0x17, 0x18);
-   mipi_dsi_dcs_write_seq(dsi, 0x1b, 0x01);
-   mipi_dsi_dcs_write_seq(dsi, 0x1d, 0x1d);
-   mipi_dsi_dcs_write_seq(dsi, 0x20, 0x2f);
-   mipi_dsi_dcs_write_seq(dsi, 0x21, 0x2e);
-   mipi_dsi_dcs_write_seq(dsi, 0x22, 0x2d);
-   mipi_dsi_dcs_write_seq(dsi, 0x23, 0x2c);
-   mipi_dsi_dcs_write_seq(dsi, 0x29, 0x17);
-   mipi_dsi_dcs_write_seq(dsi, 0x2a, 0x13);
-   mipi_dsi_dcs_write_seq(dsi, 0x2b, 0x15);
-   mipi_dsi_dcs_write_seq(dsi, 0x2f, 0x14);
-   mipi_dsi_dcs_write_seq(dsi, 0x30, 0x16);
-   mipi_dsi_dcs_write_seq(dsi, 0x31, 0x18);
-   mipi_dsi_dcs_write_seq(dsi, 0x32, 0x04);
-   mipi_dsi_dcs_write_seq(dsi, 0x34, 0x10);
-   mipi_dsi_dcs_write_seq(dsi, 0x35, 0x1f);
-   mipi_dsi_dcs_write_seq(dsi, 0x36, 0x1f);
-   mipi_dsi_dcs_write_seq(dsi, 0x4d, 0x14);
-   mipi_dsi_dcs_write_seq(dsi, 0x4e, 0x36);
-   mipi_dsi_dcs_write_seq(dsi, 0x4f, 0x36);
-   mipi_dsi_dcs_write_seq(dsi, 0x53, 0x36);
-   mipi_dsi_dcs_write_seq(dsi, 0x71, 0x30);
-   mipi_dsi_dcs_write_seq(dsi, 0x79, 0x11);
-   mipi_dsi_dcs_write_seq(dsi, 0x7a, 0x82);
-   mipi_dsi_dcs_write_seq(dsi, 0x7b, 0x8f);
-   mipi_dsi_dcs_write_seq(dsi, 0x7d, 0x04);
-   mipi_dsi_dcs_write_seq(dsi, 0x80, 0x04);
-   mipi_dsi_dcs_write_seq(dsi, 0x81, 0x04);
-   mipi_dsi_dcs_write_seq(dsi, 

[PATCH v4 5/9] drm/mipi-dsi: Introduce mipi_dsi_*_write_seq_multi()

2024-05-08 Thread Douglas Anderson
The current mipi_dsi_*_write_seq() macros are non-intutitive because
they contain a hidden "return" statement that will return out of the
_caller_ of the macro. Let's mark them as deprecated and instead
introduce some new macros that are more intuitive.

These new macros are less optimal when an error occurs but should
behave more optimally when there is no error. Specifically these new
macros cause smaller code to get generated and the code size savings
(less to fetch from RAM, less cache space used, less RAM used) are
important. Since the error case isn't something we need to optimize
for and these new macros are easier to understand and more flexible,
they should be used.

After converting to use these new functions, one example shows some
nice savings while also being easier to understand.

$ scripts/bloat-o-meter \
  ...after/panel-novatek-nt36672e.ko \
  ...ctx/panel-novatek-nt36672e.ko
add/remove: 0/0 grow/shrink: 0/1 up/down: 0/-988 (-988)
Function old new   delta
nt36672e_1080x2408_60hz_init62365248-988
Total: Before=10651, After=9663, chg -9.28%

Reviewed-by: Neil Armstrong 
Reviewed-by: Linus Walleij 
Signed-off-by: Douglas Anderson 
---
Right now this patch introduces two new functions in drm_mipi_dsi.c.
Alternatively we could have changed the prototype of the "chatty"
functions and made the deprecated macros adapt to the new prototype.
While this sounds nice, it bloated callers of the deprecated functioin
a bit because it caused the compiler to emit less optimal code. It
doesn't seem terrible to add two more functions, so I went that
way. There may be cases where callers who aren't writing many
sequences prefer to use the "chatty" versions anyway.

(no changes since v3)

Changes in v3:
- Add a TODO item for cleaning up the deprecated macros/functions.
- Inline kerneldoc comments for struct mipi_dsi_multi_context.

Changes in v2:
- New

 Documentation/gpu/todo.rst | 18 ++
 drivers/gpu/drm/drm_mipi_dsi.c | 56 ++
 include/drm/drm_mipi_dsi.h | 62 ++
 3 files changed, 136 insertions(+)

diff --git a/Documentation/gpu/todo.rst b/Documentation/gpu/todo.rst
index e2a0585915b3..2734b8a34541 100644
--- a/Documentation/gpu/todo.rst
+++ b/Documentation/gpu/todo.rst
@@ -494,6 +494,24 @@ Contact: Douglas Anderson 
 
 Level: Starter/Intermediate
 
+Transition away from using mipi_dsi_*_write_seq()
+-
+
+The macros mipi_dsi_generic_write_seq() and mipi_dsi_dcs_write_seq() are
+non-intuitive because, if there are errors, they return out of the *caller's*
+function. We should move all callers to use mipi_dsi_generic_write_seq_multi()
+and mipi_dsi_dcs_write_seq_multi() macros instead.
+
+Once all callers are transitioned, the macros and the functions that they call,
+mipi_dsi_generic_write_chatty() and mipi_dsi_dcs_write_buffer_chatty(), can
+probably be removed. Alternatively, if people feel like the _multi() variants
+are overkill for some use cases, we could keep the mipi_dsi_*_write_seq()
+variants but change them not to return out of the caller.
+
+Contact: Douglas Anderson 
+
+Level: Starter
+
 
 Core refactorings
 =
diff --git a/drivers/gpu/drm/drm_mipi_dsi.c b/drivers/gpu/drm/drm_mipi_dsi.c
index 8593d9ed5891..d2957cb692d3 100644
--- a/drivers/gpu/drm/drm_mipi_dsi.c
+++ b/drivers/gpu/drm/drm_mipi_dsi.c
@@ -792,6 +792,34 @@ int mipi_dsi_generic_write_chatty(struct mipi_dsi_device 
*dsi,
 }
 EXPORT_SYMBOL(mipi_dsi_generic_write_chatty);
 
+/**
+ * mipi_dsi_generic_write_multi() - mipi_dsi_generic_write_chatty() w/ 
accum_err
+ * @ctx: Context for multiple DSI transactions
+ * @payload: buffer containing the payload
+ * @size: size of payload buffer
+ *
+ * Like mipi_dsi_generic_write_chatty() but deals with errors in a way that
+ * makes it convenient to make several calls in a row.
+ */
+void mipi_dsi_generic_write_multi(struct mipi_dsi_multi_context *ctx,
+ const void *payload, size_t size)
+{
+   struct mipi_dsi_device *dsi = ctx->dsi;
+   struct device *dev = &dsi->dev;
+   ssize_t ret;
+
+   if (ctx->accum_err)
+   return;
+
+   ret = mipi_dsi_generic_write(dsi, payload, size);
+   if (ret < 0) {
+   ctx->accum_err = ret;
+   dev_err(dev, "sending generic data %*ph failed: %d\n",
+   (int)size, payload, ctx->accum_err);
+   }
+}
+EXPORT_SYMBOL(mipi_dsi_generic_write_multi);
+
 /**
  * mipi_dsi_generic_read() - receive data using a generic read packet
  * @dsi: DSI peripheral device
@@ -908,6 +936,34 @@ int mipi_dsi_dcs_write_buffer_chatty(struct 
mipi_dsi_device *dsi,
 }
 EXPORT_SYMBOL(mipi_dsi_dcs_write_buffer_chatty);
 
+/**
+ * mipi_dsi_dcs_write_buffer_multi - mipi_dsi_dcs_write_buffer_c

[PATCH v4 4/9] drm/mipi-dsi: Reduce driver bloat of mipi_dsi_*_write_seq()

2024-05-08 Thread Douglas Anderson
Through a cooperative effort between Hsin-Yi Wang and Dmitry
Baryshkov, we have realized the dev_err() in the
mipi_dsi_*_write_seq() macros was causing quite a bit of bloat to the
kernel. Let's hoist this call into drm_mipi_dsi.c by adding a "chatty"
version of the functions that includes the print. While doing this,
add a bit more comments to these macros making it clear that they
print errors and also that they return out of _the caller's_ function.

Without any changes to clients this gives a nice savings. Specifically
the macro was inlined and thus the error report call was inlined into
every call to mipi_dsi_dcs_write_seq() and
mipi_dsi_generic_write_seq(). By using a call to a "chatty" function,
the usage is reduced to one call in the chatty function and a function
call at the invoking site.

Building with my build system shows one example:

$ scripts/bloat-o-meter \
  .../before/panel-novatek-nt36672e.ko \
  .../after/panel-novatek-nt36672e.ko
add/remove: 0/0 grow/shrink: 0/1 up/down: 0/-4404 (-4404)
Function old new   delta
nt36672e_1080x2408_60hz_init   106406236   -4404
Total: Before=15055, After=10651, chg -29.25%

Note that given the change in location of the print it's harder to
include the "cmd" in the printout for mipi_dsi_dcs_write_seq() since,
theoretically, someone could call the new chatty function with a
zero-size array and it would be illegal to dereference data[0].
There's a printk format to print the whole buffer and this is probably
more useful for debugging anyway. Given that we're doing this for
mipi_dsi_dcs_write_seq(), let's also print the buffer for
mipi_dsi_generic_write_seq() in the error case.

It should be noted that the current consensus of DRM folks is that the
mipi_dsi_*_write_seq() should be deprecated due to the non-intuitive
return behavior. A future patch will formally mark them as deprecated
and provide an alternative.

Reviewed-by: Dmitry Baryshkov 
Reviewed-by: Neil Armstrong 
Reviewed-by: Linus Walleij 
Signed-off-by: Douglas Anderson 
---

Changes in v4:
- Update wording as per Linus W.

Changes in v3:
- Rebased upon patch to remove ratelimit of prints.

Changes in v2:
- Add some comments to the macros about printing and returning.
- Change the way err value is handled in prep for next patch.
- Modify commit message now that this is part of a series.
- Rebased upon patches to avoid theoretical int overflow.

 drivers/gpu/drm/drm_mipi_dsi.c | 56 ++
 include/drm/drm_mipi_dsi.h | 47 +++-
 2 files changed, 82 insertions(+), 21 deletions(-)

diff --git a/drivers/gpu/drm/drm_mipi_dsi.c b/drivers/gpu/drm/drm_mipi_dsi.c
index 795001bb7ff1..8593d9ed5891 100644
--- a/drivers/gpu/drm/drm_mipi_dsi.c
+++ b/drivers/gpu/drm/drm_mipi_dsi.c
@@ -764,6 +764,34 @@ ssize_t mipi_dsi_generic_write(struct mipi_dsi_device 
*dsi, const void *payload,
 }
 EXPORT_SYMBOL(mipi_dsi_generic_write);
 
+/**
+ * mipi_dsi_generic_write_chatty() - mipi_dsi_generic_write() w/ an error log
+ * @dsi: DSI peripheral device
+ * @payload: buffer containing the payload
+ * @size: size of payload buffer
+ *
+ * Like mipi_dsi_generic_write() but includes a dev_err_ratelimited()
+ * call for you and returns 0 upon success, not the number of bytes sent.
+ *
+ * Return: 0 on success or a negative error code on failure.
+ */
+int mipi_dsi_generic_write_chatty(struct mipi_dsi_device *dsi,
+ const void *payload, size_t size)
+{
+   struct device *dev = &dsi->dev;
+   ssize_t ret;
+
+   ret = mipi_dsi_generic_write(dsi, payload, size);
+   if (ret < 0) {
+   dev_err(dev, "sending generic data %*ph failed: %zd\n",
+   (int)size, payload, ret);
+   return ret;
+   }
+
+   return 0;
+}
+EXPORT_SYMBOL(mipi_dsi_generic_write_chatty);
+
 /**
  * mipi_dsi_generic_read() - receive data using a generic read packet
  * @dsi: DSI peripheral device
@@ -852,6 +880,34 @@ ssize_t mipi_dsi_dcs_write_buffer(struct mipi_dsi_device 
*dsi,
 }
 EXPORT_SYMBOL(mipi_dsi_dcs_write_buffer);
 
+/**
+ * mipi_dsi_dcs_write_buffer_chatty - mipi_dsi_dcs_write_buffer() w/ an error 
log
+ * @dsi: DSI peripheral device
+ * @data: buffer containing data to be transmitted
+ * @len: size of transmission buffer
+ *
+ * Like mipi_dsi_dcs_write_buffer() but includes a dev_err_ratelimited()
+ * call for you and returns 0 upon success, not the number of bytes sent.
+ *
+ * Return: 0 on success or a negative error code on failure.
+ */
+int mipi_dsi_dcs_write_buffer_chatty(struct mipi_dsi_device *dsi,
+const void *data, size_t len)
+{
+   struct device *dev = &dsi->dev;
+   ssize_t ret;
+
+   ret = mipi_dsi_dcs_write_buffer(dsi, data, len);
+   if (ret < 0) {
+   dev_e

[PATCH v4 3/9] drm/mipi-dsi: mipi_dsi_*_write functions don't need to ratelimit prints

2024-05-08 Thread Douglas Anderson
We really don't expect these errors to be printed over and over
again. When a driver hits the error it should bail out. Just use a
normal error print.

This gives a nice space savings for users of these functions:

$ scripts/bloat-o-meter \
  .../before/panel-novatek-nt36672e.ko \
  .../after/panel-novatek-nt36672e.ko
add/remove: 0/1 grow/shrink: 0/1 up/down: 0/-16760 (-16760)
Function old new   delta
nt36672e_1080x2408_60hz_init   17080   10640   -6440
nt36672e_1080x2408_60hz_init._rs   10320   -  -10320
Total: Before=31815, After=15055, chg -52.68%

Reviewed-by: Neil Armstrong 
Reviewed-by: Linus Walleij 
Signed-off-by: Douglas Anderson 
---

(no changes since v3)

Changes in v3:
- ("mipi_dsi_*_write functions don't need to ratelimit...") moved earlier.

Changes in v2:
- New

 include/drm/drm_mipi_dsi.h | 24 +++-
 1 file changed, 11 insertions(+), 13 deletions(-)

diff --git a/include/drm/drm_mipi_dsi.h b/include/drm/drm_mipi_dsi.h
index e0f56564bf97..67967be48dbd 100644
--- a/include/drm/drm_mipi_dsi.h
+++ b/include/drm/drm_mipi_dsi.h
@@ -314,17 +314,16 @@ int mipi_dsi_dcs_get_display_brightness_large(struct 
mipi_dsi_device *dsi,
  * @dsi: DSI peripheral device
  * @seq: buffer containing the payload
  */
-#define mipi_dsi_generic_write_seq(dsi, seq...)
 \
-   do {
\
-   static const u8 d[] = { seq };  
\
-   struct device *dev = &dsi->dev; 
\
-   ssize_t ret;
\
-   ret = mipi_dsi_generic_write(dsi, d, ARRAY_SIZE(d));
\
-   if (ret < 0) {  
\
-   dev_err_ratelimited(dev, "transmit data failed: %zd\n", 
\
-   ret);   
\
-   return ret; 
\
-   }   
\
+#define mipi_dsi_generic_write_seq(dsi, seq...)   \
+   do {  \
+   static const u8 d[] = { seq };\
+   struct device *dev = &dsi->dev;   \
+   ssize_t ret;  \
+   ret = mipi_dsi_generic_write(dsi, d, ARRAY_SIZE(d));  \
+   if (ret < 0) {\
+   dev_err(dev, "transmit data failed: %zd\n", ret); \
+   return ret;   \
+   } \
} while (0)
 
 /**
@@ -340,8 +339,7 @@ int mipi_dsi_dcs_get_display_brightness_large(struct 
mipi_dsi_device *dsi,
ssize_t ret;\
ret = mipi_dsi_dcs_write_buffer(dsi, d, ARRAY_SIZE(d)); \
if (ret < 0) {  \
-   dev_err_ratelimited(\
-   dev, "sending command %#02x failed: %zd\n", \
+   dev_err(dev, "sending command %#02x failed: %zd\n", \
cmd, ret);  \
return ret; \
}   \
-- 
2.45.0.rc1.225.g2a3ae87e7f-goog



[PATCH v4 2/9] drm/mipi-dsi: Fix theoretical int overflow in mipi_dsi_generic_write_seq()

2024-05-08 Thread Douglas Anderson
The mipi_dsi_generic_write_seq() macro makes a call to
mipi_dsi_generic_write() which returns a type ssize_t. The macro then
stores it in an int and checks to see if it's negative. This could
theoretically be a problem if "ssize_t" is larger than "int".

To see the issue, imagine that "ssize_t" is 32-bits and "int" is
16-bits, you could see a problem if there was some code out there that
looked like:

  mipi_dsi_generic_write_seq(dsi, <32768 bytes as arguments>);

...since we'd get back that 32768 bytes were transferred and 32768
stored in a 16-bit int would look negative.

Though there are no callsites where we'd actually hit this (even if
"int" was only 16-bit), it's cleaner to make the types match so let's
fix it.

Fixes: a9015ce59320 ("drm/mipi-dsi: Add a mipi_dsi_dcs_write_seq() macro")
Reviewed-by: Neil Armstrong 
Reviewed-by: Linus Walleij 
Signed-off-by: Douglas Anderson 
---

(no changes since v3)

Changes in v3:
- Use %zd in print instead of casting errors to int.

Changes in v2:
- New

 include/drm/drm_mipi_dsi.h | 22 +++---
 1 file changed, 11 insertions(+), 11 deletions(-)

diff --git a/include/drm/drm_mipi_dsi.h b/include/drm/drm_mipi_dsi.h
index 70ce0b8cbc68..e0f56564bf97 100644
--- a/include/drm/drm_mipi_dsi.h
+++ b/include/drm/drm_mipi_dsi.h
@@ -314,17 +314,17 @@ int mipi_dsi_dcs_get_display_brightness_large(struct 
mipi_dsi_device *dsi,
  * @dsi: DSI peripheral device
  * @seq: buffer containing the payload
  */
-#define mipi_dsi_generic_write_seq(dsi, seq...)
\
-   do {   \
-   static const u8 d[] = { seq }; \
-   struct device *dev = &dsi->dev;\
-   int ret;   \
-   ret = mipi_dsi_generic_write(dsi, d, ARRAY_SIZE(d));   \
-   if (ret < 0) { \
-   dev_err_ratelimited(dev, "transmit data failed: %d\n", \
-   ret);  \
-   return ret;\
-   }  \
+#define mipi_dsi_generic_write_seq(dsi, seq...)
 \
+   do {
\
+   static const u8 d[] = { seq };  
\
+   struct device *dev = &dsi->dev; 
\
+   ssize_t ret;
\
+   ret = mipi_dsi_generic_write(dsi, d, ARRAY_SIZE(d));
\
+   if (ret < 0) {  
\
+   dev_err_ratelimited(dev, "transmit data failed: %zd\n", 
\
+   ret);   
\
+   return ret; 
\
+   }   
\
} while (0)
 
 /**
-- 
2.45.0.rc1.225.g2a3ae87e7f-goog



[PATCH v4 1/9] drm/mipi-dsi: Fix theoretical int overflow in mipi_dsi_dcs_write_seq()

2024-05-08 Thread Douglas Anderson
The mipi_dsi_dcs_write_seq() macro makes a call to
mipi_dsi_dcs_write_buffer() which returns a type ssize_t. The macro
then stores it in an int and checks to see if it's negative. This
could theoretically be a problem if "ssize_t" is larger than "int".

To see the issue, imagine that "ssize_t" is 32-bits and "int" is
16-bits, you could see a problem if there was some code out there that
looked like:

  mipi_dsi_dcs_write_seq(dsi, cmd, <32767 bytes as arguments>);

...since we'd get back that 32768 bytes were transferred and 32768
stored in a 16-bit int would look negative.

Though there are no callsites where we'd actually hit this (even if
"int" was only 16-bit), it's cleaner to make the types match so let's
fix it.

Fixes: 2a9e9daf7523 ("drm/mipi-dsi: Introduce mipi_dsi_dcs_write_seq macro")
Reviewed-by: Neil Armstrong 
Reviewed-by: Linus Walleij 
Signed-off-by: Douglas Anderson 
---

(no changes since v3)

Changes in v3:
- Use %zd in print instead of casting errors to int.

Changes in v2:
- New

 include/drm/drm_mipi_dsi.h | 24 
 1 file changed, 12 insertions(+), 12 deletions(-)

diff --git a/include/drm/drm_mipi_dsi.h b/include/drm/drm_mipi_dsi.h
index 82b1cc434ea3..70ce0b8cbc68 100644
--- a/include/drm/drm_mipi_dsi.h
+++ b/include/drm/drm_mipi_dsi.h
@@ -333,18 +333,18 @@ int mipi_dsi_dcs_get_display_brightness_large(struct 
mipi_dsi_device *dsi,
  * @cmd: Command
  * @seq: buffer containing data to be transmitted
  */
-#define mipi_dsi_dcs_write_seq(dsi, cmd, seq...)   \
-   do {   \
-   static const u8 d[] = { cmd, seq };\
-   struct device *dev = &dsi->dev;\
-   int ret;   \
-   ret = mipi_dsi_dcs_write_buffer(dsi, d, ARRAY_SIZE(d));\
-   if (ret < 0) { \
-   dev_err_ratelimited(   \
-   dev, "sending command %#02x failed: %d\n", \
-   cmd, ret); \
-   return ret;\
-   }  \
+#define mipi_dsi_dcs_write_seq(dsi, cmd, seq...)\
+   do {\
+   static const u8 d[] = { cmd, seq }; \
+   struct device *dev = &dsi->dev; \
+   ssize_t ret;\
+   ret = mipi_dsi_dcs_write_buffer(dsi, d, ARRAY_SIZE(d)); \
+   if (ret < 0) {  \
+   dev_err_ratelimited(\
+   dev, "sending command %#02x failed: %zd\n", \
+   cmd, ret);  \
+   return ret; \
+   }   \
} while (0)
 
 /**
-- 
2.45.0.rc1.225.g2a3ae87e7f-goog



[PATCH v4 0/9] drm/mipi-dsi: Reduce bloat and add funcs for cleaner init seqs

2024-05-08 Thread Douglas Anderson
The consensus of many DRM folks is that we want to move away from DSI
drivers defining tables of init commands. Instead, we want to move to
init functions that can use common DRM functions. The issue thus far
has been that using the macros mipi_dsi_generic_write_seq() and
mipi_dsi_dcs_write_seq() bloats the driver using them.

While trying to solve bloat, we realized that the majority of the it
was easy to solve. This series solves the bloat for existing drivers
by moving the printout outside of the macro.

During discussion of my v1 patch to fix the bloat [1], we also decided
that we really want to change the way that drivers deal with init
sequences to make it clearer. In addition to being cleaner, a side
effect of moving drivers to the new style reduces bloat _even more_.

This series also contains a few minor fixes / cleanups that I found
along the way.

This series converts four drivers over to the new
mipi_dsi_dcs_write_seq_multi() function. Not all conversions have been
tested, but hopefully they are straightforward enough. I'd appreciate
testing.

NOTE: In v3 I tried to incorporate the feedback from v2. I also
converted the other two panels I could find that used table-based
initialization.

v4 just has a tiny bugfix and collects tags. Assuming no other
problems are found the plan is to land this series sometime roughly
around May 16 [2]. Note that unless I get a review/Ack for the patch
("drm/panel: novatek-nt36672e: Switch to
mipi_dsi_dcs_write_seq_multi()") then I'll land the series without
that patch.

[1] 
https://lore.kernel.org/r/20240424172017.1.Id15fae80582bc74a0d4f1338987fa375738f45b9@changeid
[2] https://lore.kernel.org/r/35b899d2-fb47-403a-83d2-204c0800d...@linaro.org

Changes in v4:
- Test to see if init is non-NULL before using it.
- Update wording as per Linus W.

Changes in v3:
- ("mipi_dsi_*_write functions don't need to ratelimit...") moved earlier.
- Add a TODO item for cleaning up the deprecated macros/functions.
- Fix spacing of init function.
- Inline kerneldoc comments for struct mipi_dsi_multi_context.
- Rebased upon patch to remove ratelimit of prints.
- Remove an unneeded error print.
- Squash boe-tv101wum-nl6 lowercase patch into main patch
- Use %zd in print instead of casting errors to int.
- drm/panel: ili9882t: Don't use a table for initting panels
- drm/panel: innolux-p079zca: Don't use a table for initting panels

Changes in v2:
- Add some comments to the macros about printing and returning.
- Change the way err value is handled in prep for next patch.
- Modify commit message now that this is part of a series.
- Rebased upon patches to avoid theoretical int overflow.
- drm/mipi-dsi: Fix theoretical int overflow in mipi_dsi_dcs_write_seq()
- drm/mipi-dsi: Fix theoretical int overflow in mipi_dsi_generic_write_seq()
- drm/mipi-dsi: Introduce mipi_dsi_*_write_seq_multi()
- drm/mipi-dsi: mipi_dsi_*_write functions don't need to ratelimit prints
- drm/panel: boe-tv101wum-nl6: Convert hex to lowercase
- drm/panel: boe-tv101wum-nl6: Don't use a table for initting commands
- drm/panel: novatek-nt36672e: Switch to mipi_dsi_dcs_write_seq_multi()

Douglas Anderson (9):
  drm/mipi-dsi: Fix theoretical int overflow in mipi_dsi_dcs_write_seq()
  drm/mipi-dsi: Fix theoretical int overflow in
mipi_dsi_generic_write_seq()
  drm/mipi-dsi: mipi_dsi_*_write functions don't need to ratelimit
prints
  drm/mipi-dsi: Reduce driver bloat of mipi_dsi_*_write_seq()
  drm/mipi-dsi: Introduce mipi_dsi_*_write_seq_multi()
  drm/panel: novatek-nt36672e: Switch to mipi_dsi_dcs_write_seq_multi()
  drm/panel: boe-tv101wum-nl6: Don't use a table for initting panels
  drm/panel: ili9882t: Don't use a table for initting panels
  drm/panel: innolux-p079zca: Don't use a table for initting panels

 Documentation/gpu/todo.rst|   18 +
 drivers/gpu/drm/drm_mipi_dsi.c|  112 +
 .../gpu/drm/panel/panel-boe-tv101wum-nl6.c| 2792 +
 drivers/gpu/drm/panel/panel-ilitek-ili9882t.c |  794 +++--
 drivers/gpu/drm/panel/panel-innolux-p079zca.c |  284 +-
 .../gpu/drm/panel/panel-novatek-nt36672e.c|  576 ++--
 include/drm/drm_mipi_dsi.h|  101 +-
 7 files changed, 2452 insertions(+), 2225 deletions(-)

-- 
2.45.0.rc1.225.g2a3ae87e7f-goog



[RFT PATCH v2 48/48] drm/panel: Update TODO list item for cleaning up prepared/enabled tracking

2024-05-03 Thread Douglas Anderson
Now that most panels have been updated not to track/double-check their
prepared/enabled state update the TODO with next steps.

Signed-off-by: Douglas Anderson 
---

(no changes since v1)

 Documentation/gpu/todo.rst | 47 +-
 1 file changed, 26 insertions(+), 21 deletions(-)

diff --git a/Documentation/gpu/todo.rst b/Documentation/gpu/todo.rst
index e2a0585915b3..4063bc45bbd3 100644
--- a/Documentation/gpu/todo.rst
+++ b/Documentation/gpu/todo.rst
@@ -469,30 +469,35 @@ Contact: Thomas Zimmermann 
 
 Level: Starter
 
-Clean up checks for already prepared/enabled in panels
---
-
-In a whole pile of panel drivers, we have code to make the
-prepare/unprepare/enable/disable callbacks behave as no-ops if they've already
-been called. To get some idea of the duplicated code, try::
-
-  git grep 'if.*>prepared' -- drivers/gpu/drm/panel
-  git grep 'if.*>enabled' -- drivers/gpu/drm/panel
-
-In the patch ("drm/panel: Check for already prepared/enabled in drm_panel")
-we've moved this check to the core. Now we can most definitely remove the
-check from the individual panels and save a pile of code.
-
-In adition to removing the check from the individual panels, it is believed
-that even the core shouldn't need this check and that should be considered
-an error if other code ever relies on this check. The check in the core
-currently prints a warning whenever something is relying on this check with
-dev_warn(). After a little while, we likely want to promote this to a
-WARN(1) to help encourage folks not to rely on this behavior.
+Remove disable/unprepare in remove/shutdown in panel-simple and panel-edp
+-
+
+As of commit d2aacaf07395 ("drm/panel: Check for already prepared/enabled in
+drm_panel"), we have a check in the drm_panel core to make sure nobody
+double-calls prepare/enable/disable/unprepare. Eventually that should probably
+be turned into a WARN_ON() or somehow made louder, but right now we actually
+expect it to trigger and so we don't want it to be too loud.
+
+Specifically, that warning will trigger for panel-edp and panel-simple at
+shutdown time because those panels hardcode a call to drm_panel_disable()
+and drm_panel_unprepare() at shutdown and remove time that they call regardless
+of panel state. On systems with a properly coded DRM modeset driver that
+calls drm_atomic_helper_shutdown() this is pretty much guaranteed to cause
+the warning to fire.
+
+Unfortunately we can't safely remove the calls in panel-edp and panel-simple
+until we're sure that all DRM modeset drivers that are used with those panels
+properly call drm_atomic_helper_shutdown(). This TODO item is to validate
+that all DRM modeset drivers used with panel-edp and panel-simple properly
+call drm_atomic_helper_shutdown() and then remove the calls to
+disable/unprepare from those panels. Alternatively, this TODO item could be
+removed by convincing stakeholders that those calls are fine and downgrading
+the error message in drm_panel_disable() / drm_panel_unprepare() to a
+debug-level message.
 
 Contact: Douglas Anderson 
 
-Level: Starter/Intermediate
+Level: Intermediate
 
 
 Core refactorings
-- 
2.45.0.rc1.225.g2a3ae87e7f-goog



[RFT PATCH v2 47/48] drm/panel: sony-acx565akm: Don't call disable at remove

2024-05-03 Thread Douglas Anderson
It's the responsibility of a correctly written DRM modeset driver to
call drm_atomic_helper_shutdown() at shutdown time and that should be
disabling / unpreparing the panel if needed. Panel drivers shouldn't
be calling these functions themselves.

A recent effort was made to fix as many DRM modeset drivers as
possible [1] [2] [3] and most drivers are fixed now.

A grep through mainline for compatible strings used by this driver
indicates that it is used by TI OMAP boards. The TI OMAP driver
appears to be correctly calling drm_atomic_helper_shutdown() so we can
remove the calls.

[1] https://lore.kernel.org/r/20230901234015.566018-1-diand...@chromium.org
[2] https://lore.kernel.org/r/20230901234202.566951-1-diand...@chromium.org
[3] https://lore.kernel.org/r/20230921192749.1542462-1-diand...@chromium.org

Cc: Laurent Pinchart 
Cc: Sebastian Reichel 
Signed-off-by: Douglas Anderson 
---

Changes in v2:
- Split removal of prepared/enabled from handling of remove/shutdown.

 drivers/gpu/drm/panel/panel-sony-acx565akm.c | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/drivers/gpu/drm/panel/panel-sony-acx565akm.c 
b/drivers/gpu/drm/panel/panel-sony-acx565akm.c
index a9a545a56404..73ba93ff00fe 100644
--- a/drivers/gpu/drm/panel/panel-sony-acx565akm.c
+++ b/drivers/gpu/drm/panel/panel-sony-acx565akm.c
@@ -652,9 +652,6 @@ static void acx565akm_remove(struct spi_device *spi)
 
if (lcd->has_bc)
acx565akm_backlight_cleanup(lcd);
-
-   drm_panel_disable(&lcd->panel);
-   drm_panel_unprepare(&lcd->panel);
 }
 
 static const struct of_device_id acx565akm_of_match[] = {
-- 
2.45.0.rc1.225.g2a3ae87e7f-goog



[RFT PATCH v2 46/48] drm/panel: sony-acx565akm: Don't double-check enabled state in disable

2024-05-03 Thread Douglas Anderson
As talked about in commit d2aacaf07395 ("drm/panel: Check for already
prepared/enabled in drm_panel"), we want to remove needless code from
panel drivers that was storing and double-checking the
prepared/enabled state. Even if someone was relying on the
double-check before, that double-check is now in the core and not
needed in individual drivers.

The acx565akm seems to do some unique stuff with the "enabled"
state. Specifically:
1. It seems to detect the enabled state based on how the bootloader
   left the panel.
2. It uses the enabled state to prevent certain sysfs files from
   accessing a disabled panel.

We'll leave the "enabled" state tracking for this. However, we can at
least get rid of the double-check when trying to disable.

Cc: Laurent Pinchart 
Cc: Sebastian Reichel 
Signed-off-by: Douglas Anderson 
---

Changes in v2:
- Split removal of prepared/enabled from handling of remove/shutdown.

 drivers/gpu/drm/panel/panel-sony-acx565akm.c | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/drivers/gpu/drm/panel/panel-sony-acx565akm.c 
b/drivers/gpu/drm/panel/panel-sony-acx565akm.c
index 3d6a286056a0..a9a545a56404 100644
--- a/drivers/gpu/drm/panel/panel-sony-acx565akm.c
+++ b/drivers/gpu/drm/panel/panel-sony-acx565akm.c
@@ -454,9 +454,6 @@ static int acx565akm_power_on(struct acx565akm_panel *lcd)
 
 static void acx565akm_power_off(struct acx565akm_panel *lcd)
 {
-   if (!lcd->enabled)
-   return;
-
acx565akm_set_display_state(lcd, 0);
acx565akm_set_sleep_mode(lcd, 1);
lcd->enabled = false;
-- 
2.45.0.rc1.225.g2a3ae87e7f-goog



[RFT PATCH v2 45/48] drm/panel: raydium-rm67191: Don't call unprepare+disable at shutdown

2024-05-03 Thread Douglas Anderson
It's the responsibility of a correctly written DRM modeset driver to
call drm_atomic_helper_shutdown() at shutdown time and that should be
disabling / unpreparing the panel if needed. Panel drivers shouldn't
be calling these functions themselves.

A recent effort was made to fix as many DRM modeset drivers as
possible [1] [2] [3] and most drivers are fixed now.

A grep through mainline for compatible strings used by this driver
indicates that it is used by IMX boards. The IMX driver appears to be
correctly calling drm_atomic_helper_shutdown() so we can remove the
calls.

[1] https://lore.kernel.org/r/20230901234015.566018-1-diand...@chromium.org
[2] https://lore.kernel.org/r/20230901234202.566951-1-diand...@chromium.org
[3] https://lore.kernel.org/r/20230921192749.1542462-1-diand...@chromium.org

Cc: Robert Chiras 
Signed-off-by: Douglas Anderson 
---

Changes in v2:
- Split removal of prepared/enabled from handling of remove/shutdown.

 drivers/gpu/drm/panel/panel-raydium-rm67191.c | 9 -
 1 file changed, 9 deletions(-)

diff --git a/drivers/gpu/drm/panel/panel-raydium-rm67191.c 
b/drivers/gpu/drm/panel/panel-raydium-rm67191.c
index fa9bf89d3bb5..b2029e035635 100644
--- a/drivers/gpu/drm/panel/panel-raydium-rm67191.c
+++ b/drivers/gpu/drm/panel/panel-raydium-rm67191.c
@@ -612,14 +612,6 @@ static void rad_panel_remove(struct mipi_dsi_device *dsi)
drm_panel_remove(&rad->panel);
 }
 
-static void rad_panel_shutdown(struct mipi_dsi_device *dsi)
-{
-   struct rad_panel *rad = mipi_dsi_get_drvdata(dsi);
-
-   drm_panel_disable(&rad->panel);
-   drm_panel_unprepare(&rad->panel);
-}
-
 static const struct of_device_id rad_of_match[] = {
{ .compatible = "raydium,rm67191", },
{ /* sentinel */ }
@@ -633,7 +625,6 @@ static struct mipi_dsi_driver rad_panel_driver = {
},
.probe = rad_panel_probe,
.remove = rad_panel_remove,
-   .shutdown = rad_panel_shutdown,
 };
 module_mipi_dsi_driver(rad_panel_driver);
 
-- 
2.45.0.rc1.225.g2a3ae87e7f-goog



[RFT PATCH v2 44/48] drm/panel: raydium-rm67191: Stop tracking enabled

2024-05-03 Thread Douglas Anderson
As talked about in commit d2aacaf07395 ("drm/panel: Check for already
prepared/enabled in drm_panel"), we want to remove needless code from
panel drivers that was storing and double-checking the
prepared/enabled state. Even if someone was relying on the
double-check before, that double-check is now in the core and not
needed in individual drivers.

The conversion of the rm67191 panel driver follows many of the other
panel drivers but has a few differences that need to be called out.

Like in commit 1e0465eb16a4 ("drm/panel: otm8009a: Don't double check
prepared/enabled"), this panel also uses the "prepared" flag to
prevent the backlight functions from running when the panel is powered
off. This is probably not the safest thing to do but the old behavior
was preserved. See the discussion in the otm8009a patch. Because of
this, I've left the driver tracking "prepared" but removed its
tracking of "enabled".

NOTE: as part of this, transition the panel's direct calls to its
disable/unprepare functions in shutdown to call through DRM panel.

Cc: Robert Chiras 
Signed-off-by: Douglas Anderson 
---

Changes in v2:
- Split removal of prepared/enabled from handling of remove/shutdown.

 drivers/gpu/drm/panel/panel-raydium-rm67191.c | 21 ++-
 1 file changed, 2 insertions(+), 19 deletions(-)

diff --git a/drivers/gpu/drm/panel/panel-raydium-rm67191.c 
b/drivers/gpu/drm/panel/panel-raydium-rm67191.c
index dbb1ed4efbed..fa9bf89d3bb5 100644
--- a/drivers/gpu/drm/panel/panel-raydium-rm67191.c
+++ b/drivers/gpu/drm/panel/panel-raydium-rm67191.c
@@ -205,7 +205,6 @@ struct rad_panel {
unsigned int num_supplies;
 
bool prepared;
-   bool enabled;
 };
 
 static const struct drm_display_mode default_mode = {
@@ -267,9 +266,6 @@ static int rad_panel_prepare(struct drm_panel *panel)
struct rad_panel *rad = to_rad_panel(panel);
int ret;
 
-   if (rad->prepared)
-   return 0;
-
ret = regulator_bulk_enable(rad->num_supplies, rad->supplies);
if (ret)
return ret;
@@ -291,9 +287,6 @@ static int rad_panel_unprepare(struct drm_panel *panel)
struct rad_panel *rad = to_rad_panel(panel);
int ret;
 
-   if (!rad->prepared)
-   return 0;
-
/*
 * Right after asserting the reset, we need to release it, so that the
 * touch driver can have an active connection with the touch controller
@@ -322,9 +315,6 @@ static int rad_panel_enable(struct drm_panel *panel)
int color_format = color_format_from_dsi_format(dsi->format);
int ret;
 
-   if (rad->enabled)
-   return 0;
-
dsi->mode_flags |= MIPI_DSI_MODE_LPM;
 
ret = rad_panel_push_cmd_list(dsi);
@@ -389,8 +379,6 @@ static int rad_panel_enable(struct drm_panel *panel)
 
backlight_enable(rad->backlight);
 
-   rad->enabled = true;
-
return 0;
 
 fail:
@@ -406,9 +394,6 @@ static int rad_panel_disable(struct drm_panel *panel)
struct device *dev = &dsi->dev;
int ret;
 
-   if (!rad->enabled)
-   return 0;
-
dsi->mode_flags |= MIPI_DSI_MODE_LPM;
 
backlight_disable(rad->backlight);
@@ -429,8 +414,6 @@ static int rad_panel_disable(struct drm_panel *panel)
return ret;
}
 
-   rad->enabled = false;
-
return 0;
 }
 
@@ -633,8 +616,8 @@ static void rad_panel_shutdown(struct mipi_dsi_device *dsi)
 {
struct rad_panel *rad = mipi_dsi_get_drvdata(dsi);
 
-   rad_panel_disable(&rad->panel);
-   rad_panel_unprepare(&rad->panel);
+   drm_panel_disable(&rad->panel);
+   drm_panel_unprepare(&rad->panel);
 }
 
 static const struct of_device_id rad_of_match[] = {
-- 
2.45.0.rc1.225.g2a3ae87e7f-goog



[RFT PATCH v2 43/48] drm/panel: sitronix-st7703: Don't call disable at shutdown/remove

2024-05-03 Thread Douglas Anderson
It's the responsibility of a correctly written DRM modeset driver to
call drm_atomic_helper_shutdown() at shutdown time and that should be
disabling / unpreparing the panel if needed. Panel drivers shouldn't
be calling these functions themselves.

A recent effort was made to fix as many DRM modeset drivers as
possible [1] [2] [3] and most drivers are fixed now.

The compatible strings used by this driver seem to show up across
boards using a variety of DRM drivers. It appears that the relevant
drivers have been converted, but at least one compatible string
doesn't seem to be found in any mainline dts files so we can't be 100%
sure. If it is found that the DRM modeset driver hasn't been fixed
then this patch could be temporarily reverted until it is.

[1] https://lore.kernel.org/r/20230901234015.566018-1-diand...@chromium.org
[2] https://lore.kernel.org/r/20230901234202.566951-1-diand...@chromium.org
[3] https://lore.kernel.org/r/20230921192749.1542462-1-diand...@chromium.org

Cc: "Guido Günther" 
Cc: "Ondřej Jirman" 
Cc: Chris Morgan 
Cc: Frank Oltmanns 
Signed-off-by: Douglas Anderson 
---

Changes in v2:
- Split removal of prepared/enabled from handling of remove/shutdown.

 drivers/gpu/drm/panel/panel-sitronix-st7703.c | 17 -
 1 file changed, 17 deletions(-)

diff --git a/drivers/gpu/drm/panel/panel-sitronix-st7703.c 
b/drivers/gpu/drm/panel/panel-sitronix-st7703.c
index 6b2d940640ca..77b30e045a57 100644
--- a/drivers/gpu/drm/panel/panel-sitronix-st7703.c
+++ b/drivers/gpu/drm/panel/panel-sitronix-st7703.c
@@ -937,27 +937,11 @@ static int st7703_probe(struct mipi_dsi_device *dsi)
return 0;
 }
 
-static void st7703_shutdown(struct mipi_dsi_device *dsi)
-{
-   struct st7703 *ctx = mipi_dsi_get_drvdata(dsi);
-   int ret;
-
-   ret = drm_panel_unprepare(&ctx->panel);
-   if (ret < 0)
-   dev_err(&dsi->dev, "Failed to unprepare panel: %d\n", ret);
-
-   ret = drm_panel_disable(&ctx->panel);
-   if (ret < 0)
-   dev_err(&dsi->dev, "Failed to disable panel: %d\n", ret);
-}
-
 static void st7703_remove(struct mipi_dsi_device *dsi)
 {
struct st7703 *ctx = mipi_dsi_get_drvdata(dsi);
int ret;
 
-   st7703_shutdown(dsi);
-
ret = mipi_dsi_detach(dsi);
if (ret < 0)
dev_err(&dsi->dev, "Failed to detach from DSI host: %d\n", ret);
@@ -981,7 +965,6 @@ MODULE_DEVICE_TABLE(of, st7703_of_match);
 static struct mipi_dsi_driver st7703_driver = {
.probe  = st7703_probe,
.remove = st7703_remove,
-   .shutdown = st7703_shutdown,
.driver = {
.name = DRV_NAME,
.of_match_table = st7703_of_match,
-- 
2.45.0.rc1.225.g2a3ae87e7f-goog



[RFT PATCH v2 42/48] drm/panel: sitronix-st7703: Stop tracking prepared

2024-05-03 Thread Douglas Anderson
As talked about in commit d2aacaf07395 ("drm/panel: Check for already
prepared/enabled in drm_panel"), we want to remove needless code from
panel drivers that was storing and double-checking the
prepared/enabled state. Even if someone was relying on the
double-check before, that double-check is now in the core and not
needed in individual drivers.

One thing to note for st7703 is that it has a special "allpixelson"
debugfs file. When this file is written the driver hacks a
disable/unprepare and then a prepare/enable to try to reset the
panel. Potentially that might have been relying on the old booleans we
removed. It'll still "work" because of the checks in the core but it
deserves a comment. This debugfs file didn't appear to be particularly
safe to use even before this patch since it would cause a
disabled/unprepared panel to become prepared/enabled.

Cc: "Guido Günther" 
Cc: "Ondřej Jirman" 
Cc: Chris Morgan 
Cc: Frank Oltmanns 
Signed-off-by: Douglas Anderson 
---

Changes in v2:
- Split removal of prepared/enabled from handling of remove/shutdown.

 drivers/gpu/drm/panel/panel-sitronix-st7703.c | 18 +++---
 1 file changed, 7 insertions(+), 11 deletions(-)

diff --git a/drivers/gpu/drm/panel/panel-sitronix-st7703.c 
b/drivers/gpu/drm/panel/panel-sitronix-st7703.c
index 7d8302cca091..6b2d940640ca 100644
--- a/drivers/gpu/drm/panel/panel-sitronix-st7703.c
+++ b/drivers/gpu/drm/panel/panel-sitronix-st7703.c
@@ -58,7 +58,6 @@ struct st7703 {
struct gpio_desc *reset_gpio;
struct regulator *vcc;
struct regulator *iovcc;
-   bool prepared;
 
struct dentry *debugfs;
const struct st7703_panel_desc *desc;
@@ -752,13 +751,9 @@ static int st7703_unprepare(struct drm_panel *panel)
 {
struct st7703 *ctx = panel_to_st7703(panel);
 
-   if (!ctx->prepared)
-   return 0;
-
gpiod_set_value_cansleep(ctx->reset_gpio, 1);
regulator_disable(ctx->iovcc);
regulator_disable(ctx->vcc);
-   ctx->prepared = false;
 
return 0;
 }
@@ -768,9 +763,6 @@ static int st7703_prepare(struct drm_panel *panel)
struct st7703 *ctx = panel_to_st7703(panel);
int ret;
 
-   if (ctx->prepared)
-   return 0;
-
dev_dbg(ctx->dev, "Resetting the panel\n");
gpiod_set_value_cansleep(ctx->reset_gpio, 1);
 
@@ -793,8 +785,6 @@ static int st7703_prepare(struct drm_panel *panel)
gpiod_set_value_cansleep(ctx->reset_gpio, 0);
usleep_range(15000, 2);
 
-   ctx->prepared = true;
-
return 0;
 }
 
@@ -854,7 +844,13 @@ static int allpixelson_set(void *data, u64 val)
dev_dbg(ctx->dev, "Setting all pixels on\n");
mipi_dsi_generic_write_seq(dsi, ST7703_CMD_ALL_PIXEL_ON);
msleep(val * 1000);
-   /* Reset the panel to get video back */
+
+   /*
+* Reset the panel to get video back. NOTE: This isn't a
+* particularly safe thing to do in general because it assumes
+* that the screen was on to begin with, but this is just a
+* debugfs file so it's not a huge deal.
+*/
drm_panel_disable(&ctx->panel);
drm_panel_unprepare(&ctx->panel);
drm_panel_prepare(&ctx->panel);
-- 
2.45.0.rc1.225.g2a3ae87e7f-goog



[RFT PATCH v2 41/48] drm/panel: sharp-ls043t1le01: Don't call disable at shutdown/remove

2024-05-03 Thread Douglas Anderson
It's the responsibility of a correctly written DRM modeset driver to
call drm_atomic_helper_shutdown() at shutdown time and that should be
disabling / unpreparing the panel if needed. Panel drivers shouldn't
be calling these functions themselves.

A recent effort was made to fix as many DRM modeset drivers as
possible [1] [2] [3] and most drivers are fixed now.

A grep through mainline for compatible strings used by this driver
indicates that it is used by Qualcomm boards. The Qualcomm driver
appears to be correctly calling drm_atomic_helper_shutdown() so we can
remove the calls.

[1] https://lore.kernel.org/r/20230901234015.566018-1-diand...@chromium.org
[2] https://lore.kernel.org/r/20230901234202.566951-1-diand...@chromium.org
[3] https://lore.kernel.org/r/20230921192749.1542462-1-diand...@chromium.org

Cc: Werner Johansson 
Cc: Dmitry Baryshkov 
Signed-off-by: Douglas Anderson 
---

Changes in v2:
- Only handle 1 panel per patch.
- Split removal of prepared/enabled from handling of remove/shutdown.

 drivers/gpu/drm/panel/panel-sharp-ls043t1le01.c | 12 
 1 file changed, 12 deletions(-)

diff --git a/drivers/gpu/drm/panel/panel-sharp-ls043t1le01.c 
b/drivers/gpu/drm/panel/panel-sharp-ls043t1le01.c
index c86337954ad7..729cbb0d8403 100644
--- a/drivers/gpu/drm/panel/panel-sharp-ls043t1le01.c
+++ b/drivers/gpu/drm/panel/panel-sharp-ls043t1le01.c
@@ -267,10 +267,6 @@ static void sharp_nt_panel_remove(struct mipi_dsi_device 
*dsi)
struct sharp_nt_panel *sharp_nt = mipi_dsi_get_drvdata(dsi);
int ret;
 
-   ret = drm_panel_disable(&sharp_nt->base);
-   if (ret < 0)
-   dev_err(&dsi->dev, "failed to disable panel: %d\n", ret);
-
ret = mipi_dsi_detach(dsi);
if (ret < 0)
dev_err(&dsi->dev, "failed to detach from DSI host: %d\n", ret);
@@ -278,13 +274,6 @@ static void sharp_nt_panel_remove(struct mipi_dsi_device 
*dsi)
sharp_nt_panel_del(sharp_nt);
 }
 
-static void sharp_nt_panel_shutdown(struct mipi_dsi_device *dsi)
-{
-   struct sharp_nt_panel *sharp_nt = mipi_dsi_get_drvdata(dsi);
-
-   drm_panel_disable(&sharp_nt->base);
-}
-
 static const struct of_device_id sharp_nt_of_match[] = {
{ .compatible = "sharp,ls043t1le01-qhd", },
{ }
@@ -298,7 +287,6 @@ static struct mipi_dsi_driver sharp_nt_panel_driver = {
},
.probe = sharp_nt_panel_probe,
.remove = sharp_nt_panel_remove,
-   .shutdown = sharp_nt_panel_shutdown,
 };
 module_mipi_dsi_driver(sharp_nt_panel_driver);
 
-- 
2.45.0.rc1.225.g2a3ae87e7f-goog



[RFT PATCH v2 40/48] drm/panel: sharp-ls043t1le01: Stop tracking prepared

2024-05-03 Thread Douglas Anderson
As talked about in commit d2aacaf07395 ("drm/panel: Check for already
prepared/enabled in drm_panel"), we want to remove needless code from
panel drivers that was storing and double-checking the
prepared/enabled state. Even if someone was relying on the
double-check before, that double-check is now in the core and not
needed in individual drivers.

Cc: Werner Johansson 
Cc: Dmitry Baryshkov 
Signed-off-by: Douglas Anderson 
---

Changes in v2:
- Only handle 1 panel per patch.
- Split removal of prepared/enabled from handling of remove/shutdown.

 drivers/gpu/drm/panel/panel-sharp-ls043t1le01.c | 12 
 1 file changed, 12 deletions(-)

diff --git a/drivers/gpu/drm/panel/panel-sharp-ls043t1le01.c 
b/drivers/gpu/drm/panel/panel-sharp-ls043t1le01.c
index 855e6daa..c86337954ad7 100644
--- a/drivers/gpu/drm/panel/panel-sharp-ls043t1le01.c
+++ b/drivers/gpu/drm/panel/panel-sharp-ls043t1le01.c
@@ -26,8 +26,6 @@ struct sharp_nt_panel {
 
struct regulator *supply;
struct gpio_desc *reset_gpio;
-
-   bool prepared;
 };
 
 static inline struct sharp_nt_panel *to_sharp_nt_panel(struct drm_panel *panel)
@@ -99,9 +97,6 @@ static int sharp_nt_panel_unprepare(struct drm_panel *panel)
struct sharp_nt_panel *sharp_nt = to_sharp_nt_panel(panel);
int ret;
 
-   if (!sharp_nt->prepared)
-   return 0;
-
ret = sharp_nt_panel_off(sharp_nt);
if (ret < 0) {
dev_err(panel->dev, "failed to set panel off: %d\n", ret);
@@ -112,8 +107,6 @@ static int sharp_nt_panel_unprepare(struct drm_panel *panel)
if (sharp_nt->reset_gpio)
gpiod_set_value(sharp_nt->reset_gpio, 0);
 
-   sharp_nt->prepared = false;
-
return 0;
 }
 
@@ -122,9 +115,6 @@ static int sharp_nt_panel_prepare(struct drm_panel *panel)
struct sharp_nt_panel *sharp_nt = to_sharp_nt_panel(panel);
int ret;
 
-   if (sharp_nt->prepared)
-   return 0;
-
ret = regulator_enable(sharp_nt->supply);
if (ret < 0)
return ret;
@@ -152,8 +142,6 @@ static int sharp_nt_panel_prepare(struct drm_panel *panel)
goto poweroff;
}
 
-   sharp_nt->prepared = true;
-
return 0;
 
 poweroff:
-- 
2.45.0.rc1.225.g2a3ae87e7f-goog



[RFT PATCH v2 39/48] drm/panel: sharp-lq101r1sx01: Don't call disable at shutdown/remove

2024-05-03 Thread Douglas Anderson
It's the responsibility of a correctly written DRM modeset driver to
call drm_atomic_helper_shutdown() at shutdown time and that should be
disabling / unpreparing the panel if needed. Panel drivers shouldn't
be calling these functions themselves.

A recent effort was made to fix as many DRM modeset drivers as
possible [1] [2] [3] and most drivers are fixed now.

A grep through mainline for compatible strings used by this driver
indicates that it is used by Tegra boards. The Tegra driver appears to
be correctly calling drm_atomic_helper_shutdown() so we can remove the
calls.

[1] https://lore.kernel.org/r/20230901234015.566018-1-diand...@chromium.org
[2] https://lore.kernel.org/r/20230901234202.566951-1-diand...@chromium.org
[3] https://lore.kernel.org/r/20230921192749.1542462-1-diand...@chromium.org

Cc: Thierry Reding 
Signed-off-by: Douglas Anderson 
---

Changes in v2:
- Only handle 1 panel per patch.
- Split removal of prepared/enabled from handling of remove/shutdown.

 .../gpu/drm/panel/panel-sharp-lq101r1sx01.c   | 24 ++-
 1 file changed, 2 insertions(+), 22 deletions(-)

diff --git a/drivers/gpu/drm/panel/panel-sharp-lq101r1sx01.c 
b/drivers/gpu/drm/panel/panel-sharp-lq101r1sx01.c
index 8f6c21b99522..edc9425bb143 100644
--- a/drivers/gpu/drm/panel/panel-sharp-lq101r1sx01.c
+++ b/drivers/gpu/drm/panel/panel-sharp-lq101r1sx01.c
@@ -357,32 +357,13 @@ static void sharp_panel_remove(struct mipi_dsi_device 
*dsi)
struct sharp_panel *sharp = mipi_dsi_get_drvdata(dsi);
int err;
 
-   /* only detach from host for the DSI-LINK2 interface */
-   if (!sharp) {
-   mipi_dsi_detach(dsi);
-   return;
-   }
-
-   err = drm_panel_disable(&sharp->base);
-   if (err < 0)
-   dev_err(&dsi->dev, "failed to disable panel: %d\n", err);
-
err = mipi_dsi_detach(dsi);
if (err < 0)
dev_err(&dsi->dev, "failed to detach from DSI host: %d\n", err);
 
-   sharp_panel_del(sharp);
-}
-
-static void sharp_panel_shutdown(struct mipi_dsi_device *dsi)
-{
-   struct sharp_panel *sharp = mipi_dsi_get_drvdata(dsi);
-
-   /* nothing to do for DSI-LINK2 */
+   /* only detach from host for the DSI-LINK2 interface */
if (!sharp)
-   return;
-
-   drm_panel_disable(&sharp->base);
+   sharp_panel_del(sharp);
 }
 
 static struct mipi_dsi_driver sharp_panel_driver = {
@@ -392,7 +373,6 @@ static struct mipi_dsi_driver sharp_panel_driver = {
},
.probe = sharp_panel_probe,
.remove = sharp_panel_remove,
-   .shutdown = sharp_panel_shutdown,
 };
 module_mipi_dsi_driver(sharp_panel_driver);
 
-- 
2.45.0.rc1.225.g2a3ae87e7f-goog



[RFT PATCH v2 38/48] drm/panel: sharp-lq101r1sx01: Stop tracking prepared/enabled

2024-05-03 Thread Douglas Anderson
As talked about in commit d2aacaf07395 ("drm/panel: Check for already
prepared/enabled in drm_panel"), we want to remove needless code from
panel drivers that was storing and double-checking the
prepared/enabled state. Even if someone was relying on the
double-check before, that double-check is now in the core and not
needed in individual drivers.

Cc: Thierry Reding 
Signed-off-by: Douglas Anderson 
---

Changes in v2:
- Only handle 1 panel per patch.
- Split removal of prepared/enabled from handling of remove/shutdown.

 .../gpu/drm/panel/panel-sharp-lq101r1sx01.c   | 39 ---
 1 file changed, 39 deletions(-)

diff --git a/drivers/gpu/drm/panel/panel-sharp-lq101r1sx01.c 
b/drivers/gpu/drm/panel/panel-sharp-lq101r1sx01.c
index 14851408a5e1..8f6c21b99522 100644
--- a/drivers/gpu/drm/panel/panel-sharp-lq101r1sx01.c
+++ b/drivers/gpu/drm/panel/panel-sharp-lq101r1sx01.c
@@ -24,9 +24,6 @@ struct sharp_panel {
 
struct regulator *supply;
 
-   bool prepared;
-   bool enabled;
-
const struct drm_display_mode *mode;
 };
 
@@ -85,26 +82,11 @@ static __maybe_unused int sharp_panel_read(struct 
sharp_panel *sharp,
return err;
 }
 
-static int sharp_panel_disable(struct drm_panel *panel)
-{
-   struct sharp_panel *sharp = to_sharp_panel(panel);
-
-   if (!sharp->enabled)
-   return 0;
-
-   sharp->enabled = false;
-
-   return 0;
-}
-
 static int sharp_panel_unprepare(struct drm_panel *panel)
 {
struct sharp_panel *sharp = to_sharp_panel(panel);
int err;
 
-   if (!sharp->prepared)
-   return 0;
-
sharp_wait_frames(sharp, 4);
 
err = mipi_dsi_dcs_set_display_off(sharp->link1);
@@ -119,8 +101,6 @@ static int sharp_panel_unprepare(struct drm_panel *panel)
 
regulator_disable(sharp->supply);
 
-   sharp->prepared = false;
-
return 0;
 }
 
@@ -164,9 +144,6 @@ static int sharp_panel_prepare(struct drm_panel *panel)
u8 format = MIPI_DCS_PIXEL_FMT_24BIT;
int err;
 
-   if (sharp->prepared)
-   return 0;
-
err = regulator_enable(sharp->supply);
if (err < 0)
return err;
@@ -235,8 +212,6 @@ static int sharp_panel_prepare(struct drm_panel *panel)
goto poweroff;
}
 
-   sharp->prepared = true;
-
/* wait for 6 frames before continuing */
sharp_wait_frames(sharp, 6);
 
@@ -247,18 +222,6 @@ static int sharp_panel_prepare(struct drm_panel *panel)
return err;
 }
 
-static int sharp_panel_enable(struct drm_panel *panel)
-{
-   struct sharp_panel *sharp = to_sharp_panel(panel);
-
-   if (sharp->enabled)
-   return 0;
-
-   sharp->enabled = true;
-
-   return 0;
-}
-
 static const struct drm_display_mode default_mode = {
.clock = 278000,
.hdisplay = 2560,
@@ -295,10 +258,8 @@ static int sharp_panel_get_modes(struct drm_panel *panel,
 }
 
 static const struct drm_panel_funcs sharp_panel_funcs = {
-   .disable = sharp_panel_disable,
.unprepare = sharp_panel_unprepare,
.prepare = sharp_panel_prepare,
-   .enable = sharp_panel_enable,
.get_modes = sharp_panel_get_modes,
 };
 
-- 
2.45.0.rc1.225.g2a3ae87e7f-goog



[RFT PATCH v2 37/48] drm/panel: seiko-43wvf1g: Don't call disable at shutdown/remove

2024-05-03 Thread Douglas Anderson
It's the responsibility of a correctly written DRM modeset driver to
call drm_atomic_helper_shutdown() at shutdown time and that should be
disabling / unpreparing the panel if needed. Panel drivers shouldn't
be calling these functions themselves.

A recent effort was made to fix as many DRM modeset drivers as
possible [1] [2] [3] and most drivers are fixed now.

A grep through mainline for compatible strings used by this driver
indicates that it is used by IMX boards. As far as I can tell, all IMX
boards are now correctly calling drm_atomic_helper_shutdown() so we
can remove the calls.

[1] https://lore.kernel.org/r/20230901234015.566018-1-diand...@chromium.org
[2] https://lore.kernel.org/r/20230901234202.566951-1-diand...@chromium.org
[3] https://lore.kernel.org/r/20230921192749.1542462-1-diand...@chromium.org

Cc: Marco Franchi 
Cc: Fabio Estevam 
Cc: Laurentiu Palcu 
Cc: Pengutronix Kernel Team 
Cc: i...@lists.linux.dev
Signed-off-by: Douglas Anderson 
---

Changes in v2:
- Only handle 1 panel per patch.
- Split removal of prepared/enabled from handling of remove/shutdown.

 drivers/gpu/drm/panel/panel-seiko-43wvf1g.c | 9 -
 1 file changed, 9 deletions(-)

diff --git a/drivers/gpu/drm/panel/panel-seiko-43wvf1g.c 
b/drivers/gpu/drm/panel/panel-seiko-43wvf1g.c
index 98480904126c..8a3fe531c641 100644
--- a/drivers/gpu/drm/panel/panel-seiko-43wvf1g.c
+++ b/drivers/gpu/drm/panel/panel-seiko-43wvf1g.c
@@ -243,14 +243,6 @@ static void seiko_panel_remove(struct platform_device 
*pdev)
struct seiko_panel *panel = platform_get_drvdata(pdev);
 
drm_panel_remove(&panel->base);
-   drm_panel_disable(&panel->base);
-}
-
-static void seiko_panel_shutdown(struct platform_device *pdev)
-{
-   struct seiko_panel *panel = platform_get_drvdata(pdev);
-
-   drm_panel_disable(&panel->base);
 }
 
 static const struct display_timing seiko_43wvf1g_timing = {
@@ -306,7 +298,6 @@ static struct platform_driver seiko_panel_platform_driver = 
{
},
.probe = seiko_panel_platform_probe,
.remove_new = seiko_panel_remove,
-   .shutdown = seiko_panel_shutdown,
 };
 module_platform_driver(seiko_panel_platform_driver);
 
-- 
2.45.0.rc1.225.g2a3ae87e7f-goog



[RFT PATCH v2 36/48] drm/panel: seiko-43wvf1g: Stop tracking prepared/enabled

2024-05-03 Thread Douglas Anderson
As talked about in commit d2aacaf07395 ("drm/panel: Check for already
prepared/enabled in drm_panel"), we want to remove needless code from
panel drivers that was storing and double-checking the
prepared/enabled state. Even if someone was relying on the
double-check before, that double-check is now in the core and not
needed in individual drivers.

Cc: Marco Franchi 
Cc: Fabio Estevam 
Cc: Laurentiu Palcu 
Cc: Pengutronix Kernel Team 
Cc: i...@lists.linux.dev
Signed-off-by: Douglas Anderson 
---

Changes in v2:
- Only handle 1 panel per patch.
- Split removal of prepared/enabled from handling of remove/shutdown.

 drivers/gpu/drm/panel/panel-seiko-43wvf1g.c | 40 -
 1 file changed, 40 deletions(-)

diff --git a/drivers/gpu/drm/panel/panel-seiko-43wvf1g.c 
b/drivers/gpu/drm/panel/panel-seiko-43wvf1g.c
index 658c7c040570..98480904126c 100644
--- a/drivers/gpu/drm/panel/panel-seiko-43wvf1g.c
+++ b/drivers/gpu/drm/panel/panel-seiko-43wvf1g.c
@@ -44,8 +44,6 @@ struct seiko_panel_desc {
 
 struct seiko_panel {
struct drm_panel base;
-   bool prepared;
-   bool enabled;
const struct seiko_panel_desc *desc;
struct regulator *dvdd;
struct regulator *avdd;
@@ -122,25 +120,10 @@ static int seiko_panel_get_fixed_modes(struct seiko_panel 
*panel,
return num;
 }
 
-static int seiko_panel_disable(struct drm_panel *panel)
-{
-   struct seiko_panel *p = to_seiko_panel(panel);
-
-   if (!p->enabled)
-   return 0;
-
-   p->enabled = false;
-
-   return 0;
-}
-
 static int seiko_panel_unprepare(struct drm_panel *panel)
 {
struct seiko_panel *p = to_seiko_panel(panel);
 
-   if (!p->prepared)
-   return 0;
-
gpiod_set_value_cansleep(p->enable_gpio, 0);
 
regulator_disable(p->avdd);
@@ -150,8 +133,6 @@ static int seiko_panel_unprepare(struct drm_panel *panel)
 
regulator_disable(p->dvdd);
 
-   p->prepared = false;
-
return 0;
 }
 
@@ -160,9 +141,6 @@ static int seiko_panel_prepare(struct drm_panel *panel)
struct seiko_panel *p = to_seiko_panel(panel);
int err;
 
-   if (p->prepared)
-   return 0;
-
err = regulator_enable(p->dvdd);
if (err < 0) {
dev_err(panel->dev, "failed to enable dvdd: %d\n", err);
@@ -180,8 +158,6 @@ static int seiko_panel_prepare(struct drm_panel *panel)
 
gpiod_set_value_cansleep(p->enable_gpio, 1);
 
-   p->prepared = true;
-
return 0;
 
 disable_dvdd:
@@ -189,18 +165,6 @@ static int seiko_panel_prepare(struct drm_panel *panel)
return err;
 }
 
-static int seiko_panel_enable(struct drm_panel *panel)
-{
-   struct seiko_panel *p = to_seiko_panel(panel);
-
-   if (p->enabled)
-   return 0;
-
-   p->enabled = true;
-
-   return 0;
-}
-
 static int seiko_panel_get_modes(struct drm_panel *panel,
 struct drm_connector *connector)
 {
@@ -228,10 +192,8 @@ static int seiko_panel_get_timings(struct drm_panel *panel,
 }
 
 static const struct drm_panel_funcs seiko_panel_funcs = {
-   .disable = seiko_panel_disable,
.unprepare = seiko_panel_unprepare,
.prepare = seiko_panel_prepare,
-   .enable = seiko_panel_enable,
.get_modes = seiko_panel_get_modes,
.get_timings = seiko_panel_get_timings,
 };
@@ -246,8 +208,6 @@ static int seiko_panel_probe(struct device *dev,
if (!panel)
return -ENOMEM;
 
-   panel->enabled = false;
-   panel->prepared = false;
panel->desc = desc;
 
panel->dvdd = devm_regulator_get(dev, "dvdd");
-- 
2.45.0.rc1.225.g2a3ae87e7f-goog



[RFT PATCH v2 35/48] drm/panel: panasonic-vvx10f034n00: Don't call disable at shutdown/remove

2024-05-03 Thread Douglas Anderson
It's the responsibility of a correctly written DRM modeset driver to
call drm_atomic_helper_shutdown() at shutdown time and that should be
disabling / unpreparing the panel if needed. Panel drivers shouldn't
be calling these functions themselves.

A recent effort was made to fix as many DRM modeset drivers as
possible [1] [2] [3] and most drivers are fixed now.

Unfortunately, grepping mainline for this panel's compatible string
shows no hits, so we can't be 100% sure if the DRM modeset driver used
with this panel has been fixed. If it is found that the DRM modeset
driver hasn't been fixed then this patch could be temporarily reverted
until it is.

[1] https://lore.kernel.org/r/20230901234015.566018-1-diand...@chromium.org
[2] https://lore.kernel.org/r/20230901234202.566951-1-diand...@chromium.org
[3] https://lore.kernel.org/r/20230921192749.1542462-1-diand...@chromium.org

Cc: Werner Johansson 
Signed-off-by: Douglas Anderson 
---

Changes in v2:
- Only handle 1 panel per patch.
- Split removal of prepared/enabled from handling of remove/shutdown.

 drivers/gpu/drm/panel/panel-panasonic-vvx10f034n00.c | 12 
 1 file changed, 12 deletions(-)

diff --git a/drivers/gpu/drm/panel/panel-panasonic-vvx10f034n00.c 
b/drivers/gpu/drm/panel/panel-panasonic-vvx10f034n00.c
index 822ca2f971eb..d1c5c9bc3c56 100644
--- a/drivers/gpu/drm/panel/panel-panasonic-vvx10f034n00.c
+++ b/drivers/gpu/drm/panel/panel-panasonic-vvx10f034n00.c
@@ -222,10 +222,6 @@ static void wuxga_nt_panel_remove(struct mipi_dsi_device 
*dsi)
struct wuxga_nt_panel *wuxga_nt = mipi_dsi_get_drvdata(dsi);
int ret;
 
-   ret = drm_panel_disable(&wuxga_nt->base);
-   if (ret < 0)
-   dev_err(&dsi->dev, "failed to disable panel: %d\n", ret);
-
ret = mipi_dsi_detach(dsi);
if (ret < 0)
dev_err(&dsi->dev, "failed to detach from DSI host: %d\n", ret);
@@ -233,13 +229,6 @@ static void wuxga_nt_panel_remove(struct mipi_dsi_device 
*dsi)
wuxga_nt_panel_del(wuxga_nt);
 }
 
-static void wuxga_nt_panel_shutdown(struct mipi_dsi_device *dsi)
-{
-   struct wuxga_nt_panel *wuxga_nt = mipi_dsi_get_drvdata(dsi);
-
-   drm_panel_disable(&wuxga_nt->base);
-}
-
 static struct mipi_dsi_driver wuxga_nt_panel_driver = {
.driver = {
.name = "panel-panasonic-vvx10f034n00",
@@ -247,7 +236,6 @@ static struct mipi_dsi_driver wuxga_nt_panel_driver = {
},
.probe = wuxga_nt_panel_probe,
.remove = wuxga_nt_panel_remove,
-   .shutdown = wuxga_nt_panel_shutdown,
 };
 module_mipi_dsi_driver(wuxga_nt_panel_driver);
 
-- 
2.45.0.rc1.225.g2a3ae87e7f-goog



[RFT PATCH v2 34/48] drm/panel: panasonic-vvx10f034n00: Stop tracking prepared/enabled

2024-05-03 Thread Douglas Anderson
As talked about in commit d2aacaf07395 ("drm/panel: Check for already
prepared/enabled in drm_panel"), we want to remove needless code from
panel drivers that was storing and double-checking the
prepared/enabled state. Even if someone was relying on the
double-check before, that double-check is now in the core and not
needed in individual drivers.

Cc: Werner Johansson 
Signed-off-by: Douglas Anderson 
---

Changes in v2:
- Only handle 1 panel per patch.
- Split removal of prepared/enabled from handling of remove/shutdown.

 .../drm/panel/panel-panasonic-vvx10f034n00.c  | 35 +--
 1 file changed, 1 insertion(+), 34 deletions(-)

diff --git a/drivers/gpu/drm/panel/panel-panasonic-vvx10f034n00.c 
b/drivers/gpu/drm/panel/panel-panasonic-vvx10f034n00.c
index 8ba6d8287938..822ca2f971eb 100644
--- a/drivers/gpu/drm/panel/panel-panasonic-vvx10f034n00.c
+++ b/drivers/gpu/drm/panel/panel-panasonic-vvx10f034n00.c
@@ -32,9 +32,6 @@ struct wuxga_nt_panel {
 
struct regulator *supply;
 
-   bool prepared;
-   bool enabled;
-
ktime_t earliest_wake;
 
const struct drm_display_mode *mode;
@@ -53,28 +50,16 @@ static int wuxga_nt_panel_on(struct wuxga_nt_panel 
*wuxga_nt)
 static int wuxga_nt_panel_disable(struct drm_panel *panel)
 {
struct wuxga_nt_panel *wuxga_nt = to_wuxga_nt_panel(panel);
-   int mipi_ret, bl_ret = 0;
-
-   if (!wuxga_nt->enabled)
-   return 0;
-
-   mipi_ret = mipi_dsi_shutdown_peripheral(wuxga_nt->dsi);
-
-   wuxga_nt->enabled = false;
 
-   return mipi_ret ? mipi_ret : bl_ret;
+   return mipi_dsi_shutdown_peripheral(wuxga_nt->dsi);
 }
 
 static int wuxga_nt_panel_unprepare(struct drm_panel *panel)
 {
struct wuxga_nt_panel *wuxga_nt = to_wuxga_nt_panel(panel);
 
-   if (!wuxga_nt->prepared)
-   return 0;
-
regulator_disable(wuxga_nt->supply);
wuxga_nt->earliest_wake = ktime_add_ms(ktime_get_real(), MIN_POFF_MS);
-   wuxga_nt->prepared = false;
 
return 0;
 }
@@ -85,9 +70,6 @@ static int wuxga_nt_panel_prepare(struct drm_panel *panel)
int ret;
s64 enablewait;
 
-   if (wuxga_nt->prepared)
-   return 0;
-
/*
 * If the user re-enabled the panel before the required off-time then
 * we need to wait the remaining period before re-enabling regulator
@@ -117,8 +99,6 @@ static int wuxga_nt_panel_prepare(struct drm_panel *panel)
goto poweroff;
}
 
-   wuxga_nt->prepared = true;
-
return 0;
 
 poweroff:
@@ -127,18 +107,6 @@ static int wuxga_nt_panel_prepare(struct drm_panel *panel)
return ret;
 }
 
-static int wuxga_nt_panel_enable(struct drm_panel *panel)
-{
-   struct wuxga_nt_panel *wuxga_nt = to_wuxga_nt_panel(panel);
-
-   if (wuxga_nt->enabled)
-   return 0;
-
-   wuxga_nt->enabled = true;
-
-   return 0;
-}
-
 static const struct drm_display_mode default_mode = {
.clock = 164402,
.hdisplay = 1920,
@@ -178,7 +146,6 @@ static const struct drm_panel_funcs wuxga_nt_panel_funcs = {
.disable = wuxga_nt_panel_disable,
.unprepare = wuxga_nt_panel_unprepare,
.prepare = wuxga_nt_panel_prepare,
-   .enable = wuxga_nt_panel_enable,
.get_modes = wuxga_nt_panel_get_modes,
 };
 
-- 
2.45.0.rc1.225.g2a3ae87e7f-goog



[RFT PATCH v2 33/48] drm/panel: jdi-lt070me05000: Don't call disable at shutdown/remove

2024-05-03 Thread Douglas Anderson
It's the responsibility of a correctly written DRM modeset driver to
call drm_atomic_helper_shutdown() at shutdown time and that should be
disabling / unpreparing the panel if needed. Panel drivers shouldn't
be calling these functions themselves.

A recent effort was made to fix as many DRM modeset drivers as
possible [1] [2] [3] and most drivers are fixed now.

A grep through mainline for compatible strings used by this driver
indicates that it is used by Qualcomm boards. The Qualcomm driver
appears to be correctly calling drm_atomic_helper_shutdown() so we can
remove the calls.

[1] https://lore.kernel.org/r/20230901234015.566018-1-diand...@chromium.org
[2] https://lore.kernel.org/r/20230901234202.566951-1-diand...@chromium.org
[3] https://lore.kernel.org/r/20230921192749.1542462-1-diand...@chromium.org

Cc: Vinay Simha BN 
Cc: Sumit Semwal 
Signed-off-by: Douglas Anderson 
---

Changes in v2:
- Only handle 1 panel per patch.
- Split removal of prepared/enabled from handling of remove/shutdown.

 drivers/gpu/drm/panel/panel-jdi-lt070me05000.c | 12 
 1 file changed, 12 deletions(-)

diff --git a/drivers/gpu/drm/panel/panel-jdi-lt070me05000.c 
b/drivers/gpu/drm/panel/panel-jdi-lt070me05000.c
index 4ee6fa1e..b1ce186de261 100644
--- a/drivers/gpu/drm/panel/panel-jdi-lt070me05000.c
+++ b/drivers/gpu/drm/panel/panel-jdi-lt070me05000.c
@@ -452,10 +452,6 @@ static void jdi_panel_remove(struct mipi_dsi_device *dsi)
struct jdi_panel *jdi = mipi_dsi_get_drvdata(dsi);
int ret;
 
-   ret = drm_panel_disable(&jdi->base);
-   if (ret < 0)
-   dev_err(&dsi->dev, "failed to disable panel: %d\n", ret);
-
ret = mipi_dsi_detach(dsi);
if (ret < 0)
dev_err(&dsi->dev, "failed to detach from DSI host: %d\n",
@@ -464,13 +460,6 @@ static void jdi_panel_remove(struct mipi_dsi_device *dsi)
jdi_panel_del(jdi);
 }
 
-static void jdi_panel_shutdown(struct mipi_dsi_device *dsi)
-{
-   struct jdi_panel *jdi = mipi_dsi_get_drvdata(dsi);
-
-   drm_panel_disable(&jdi->base);
-}
-
 static struct mipi_dsi_driver jdi_panel_driver = {
.driver = {
.name = "panel-jdi-lt070me05000",
@@ -478,7 +467,6 @@ static struct mipi_dsi_driver jdi_panel_driver = {
},
.probe = jdi_panel_probe,
.remove = jdi_panel_remove,
-   .shutdown = jdi_panel_shutdown,
 };
 module_mipi_dsi_driver(jdi_panel_driver);
 
-- 
2.45.0.rc1.225.g2a3ae87e7f-goog



[RFT PATCH v2 32/48] drm/panel: jdi-lt070me05000: Stop tracking prepared/enabled

2024-05-03 Thread Douglas Anderson
As talked about in commit d2aacaf07395 ("drm/panel: Check for already
prepared/enabled in drm_panel"), we want to remove needless code from
panel drivers that was storing and double-checking the
prepared/enabled state. Even if someone was relying on the
double-check before, that double-check is now in the core and not
needed in individual drivers.

NOTE: as part of this, transition the panel's direct calls to its
disable function in shutdown/remove to call through DRM panel.

Cc: Vinay Simha BN 
Cc: Sumit Semwal 
Signed-off-by: Douglas Anderson 
---
Note: since we are able to identify that this panel only appears to be
used on Qualcomm boards and we have to touch the shutdown/remove path
in this patch anyway, we could possibly squash this with the next
patch that removes the disable call in shutdown/remove. For now I'm
keeping them separate just to keep the concepts separate.

Changes in v2:
- Only handle 1 panel per patch.
- Split removal of prepared/enabled from handling of remove/shutdown.

 .../gpu/drm/panel/panel-jdi-lt070me05000.c| 27 ++-
 1 file changed, 2 insertions(+), 25 deletions(-)

diff --git a/drivers/gpu/drm/panel/panel-jdi-lt070me05000.c 
b/drivers/gpu/drm/panel/panel-jdi-lt070me05000.c
index f9a69f347068..4ee6fa1e 100644
--- a/drivers/gpu/drm/panel/panel-jdi-lt070me05000.c
+++ b/drivers/gpu/drm/panel/panel-jdi-lt070me05000.c
@@ -37,9 +37,6 @@ struct jdi_panel {
struct gpio_desc *dcdc_en_gpio;
struct backlight_device *backlight;
 
-   bool prepared;
-   bool enabled;
-
const struct drm_display_mode *mode;
 };
 
@@ -176,13 +173,8 @@ static int jdi_panel_disable(struct drm_panel *panel)
 {
struct jdi_panel *jdi = to_jdi_panel(panel);
 
-   if (!jdi->enabled)
-   return 0;
-
backlight_disable(jdi->backlight);
 
-   jdi->enabled = false;
-
return 0;
 }
 
@@ -192,9 +184,6 @@ static int jdi_panel_unprepare(struct drm_panel *panel)
struct device *dev = &jdi->dsi->dev;
int ret;
 
-   if (!jdi->prepared)
-   return 0;
-
jdi_panel_off(jdi);
 
ret = regulator_bulk_disable(ARRAY_SIZE(jdi->supplies), jdi->supplies);
@@ -207,8 +196,6 @@ static int jdi_panel_unprepare(struct drm_panel *panel)
 
gpiod_set_value(jdi->dcdc_en_gpio, 0);
 
-   jdi->prepared = false;
-
return 0;
 }
 
@@ -218,9 +205,6 @@ static int jdi_panel_prepare(struct drm_panel *panel)
struct device *dev = &jdi->dsi->dev;
int ret;
 
-   if (jdi->prepared)
-   return 0;
-
ret = regulator_bulk_enable(ARRAY_SIZE(jdi->supplies), jdi->supplies);
if (ret < 0) {
dev_err(dev, "regulator enable failed, %d\n", ret);
@@ -250,8 +234,6 @@ static int jdi_panel_prepare(struct drm_panel *panel)
goto poweroff;
}
 
-   jdi->prepared = true;
-
return 0;
 
 poweroff:
@@ -272,13 +254,8 @@ static int jdi_panel_enable(struct drm_panel *panel)
 {
struct jdi_panel *jdi = to_jdi_panel(panel);
 
-   if (jdi->enabled)
-   return 0;
-
backlight_enable(jdi->backlight);
 
-   jdi->enabled = true;
-
return 0;
 }
 
@@ -475,7 +452,7 @@ static void jdi_panel_remove(struct mipi_dsi_device *dsi)
struct jdi_panel *jdi = mipi_dsi_get_drvdata(dsi);
int ret;
 
-   ret = jdi_panel_disable(&jdi->base);
+   ret = drm_panel_disable(&jdi->base);
if (ret < 0)
dev_err(&dsi->dev, "failed to disable panel: %d\n", ret);
 
@@ -491,7 +468,7 @@ static void jdi_panel_shutdown(struct mipi_dsi_device *dsi)
 {
struct jdi_panel *jdi = mipi_dsi_get_drvdata(dsi);
 
-   jdi_panel_disable(&jdi->base);
+   drm_panel_disable(&jdi->base);
 }
 
 static struct mipi_dsi_driver jdi_panel_driver = {
-- 
2.45.0.rc1.225.g2a3ae87e7f-goog



[RFT PATCH v2 30/48] drm/panel: xinpeng-xpp055c272: Stop tracking prepared

2024-05-03 Thread Douglas Anderson
As talked about in commit d2aacaf07395 ("drm/panel: Check for already
prepared/enabled in drm_panel"), we want to remove needless code from
panel drivers that was storing and double-checking the
prepared/enabled state. Even if someone was relying on the
double-check before, that double-check is now in the core and not
needed in individual drivers.

Cc: "Heiko Stübner" 
Signed-off-by: Douglas Anderson 
---

Changes in v2:
- Only handle 1 panel per patch.
- Split removal of prepared/enabled from handling of remove/shutdown.

 drivers/gpu/drm/panel/panel-xinpeng-xpp055c272.c | 11 ---
 1 file changed, 11 deletions(-)

diff --git a/drivers/gpu/drm/panel/panel-xinpeng-xpp055c272.c 
b/drivers/gpu/drm/panel/panel-xinpeng-xpp055c272.c
index 8670386498a4..8262c00670cf 100644
--- a/drivers/gpu/drm/panel/panel-xinpeng-xpp055c272.c
+++ b/drivers/gpu/drm/panel/panel-xinpeng-xpp055c272.c
@@ -52,7 +52,6 @@ struct xpp055c272 {
struct gpio_desc *reset_gpio;
struct regulator *vci;
struct regulator *iovcc;
-   bool prepared;
 };
 
 static inline struct xpp055c272 *panel_to_xpp055c272(struct drm_panel *panel)
@@ -136,9 +135,6 @@ static int xpp055c272_unprepare(struct drm_panel *panel)
struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev);
int ret;
 
-   if (!ctx->prepared)
-   return 0;
-
ret = mipi_dsi_dcs_set_display_off(dsi);
if (ret < 0)
dev_err(ctx->dev, "failed to set display off: %d\n", ret);
@@ -152,8 +148,6 @@ static int xpp055c272_unprepare(struct drm_panel *panel)
regulator_disable(ctx->iovcc);
regulator_disable(ctx->vci);
 
-   ctx->prepared = false;
-
return 0;
 }
 
@@ -163,9 +157,6 @@ static int xpp055c272_prepare(struct drm_panel *panel)
struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev);
int ret;
 
-   if (ctx->prepared)
-   return 0;
-
dev_dbg(ctx->dev, "Resetting the panel\n");
ret = regulator_enable(ctx->vci);
if (ret < 0) {
@@ -209,8 +200,6 @@ static int xpp055c272_prepare(struct drm_panel *panel)
 
msleep(50);
 
-   ctx->prepared = true;
-
return 0;
 
 disable_iovcc:
-- 
2.45.0.rc1.225.g2a3ae87e7f-goog



[RFT PATCH v2 31/48] drm/panel: xinpeng-xpp055c272: Don't call unprepare+disable at shutdown/remove

2024-05-03 Thread Douglas Anderson
It's the responsibility of a correctly written DRM modeset driver to
call drm_atomic_helper_shutdown() at shutdown time and that should be
disabling / unpreparing the panel if needed. Panel drivers shouldn't
be calling these functions themselves.

A recent effort was made to fix as many DRM modeset drivers as
possible [1] [2] [3] and most drivers are fixed now.

A grep through mainline for compatible strings used by this driver
indicates that it is used by Rockchip boards. The Rockchip driver
appears to be correctly calling drm_atomic_helper_shutdown() so we can
remove the calls.

[1] https://lore.kernel.org/r/20230901234015.566018-1-diand...@chromium.org
[2] https://lore.kernel.org/r/20230901234202.566951-1-diand...@chromium.org
[3] https://lore.kernel.org/r/20230921192749.1542462-1-diand...@chromium.org

Cc: "Heiko Stübner" 
Signed-off-by: Douglas Anderson 
---

Changes in v2:
- Only handle 1 panel per patch.
- Split removal of prepared/enabled from handling of remove/shutdown.

 .../gpu/drm/panel/panel-xinpeng-xpp055c272.c| 17 -
 1 file changed, 17 deletions(-)

diff --git a/drivers/gpu/drm/panel/panel-xinpeng-xpp055c272.c 
b/drivers/gpu/drm/panel/panel-xinpeng-xpp055c272.c
index 8262c00670cf..22a14006765e 100644
--- a/drivers/gpu/drm/panel/panel-xinpeng-xpp055c272.c
+++ b/drivers/gpu/drm/panel/panel-xinpeng-xpp055c272.c
@@ -306,27 +306,11 @@ static int xpp055c272_probe(struct mipi_dsi_device *dsi)
return 0;
 }
 
-static void xpp055c272_shutdown(struct mipi_dsi_device *dsi)
-{
-   struct xpp055c272 *ctx = mipi_dsi_get_drvdata(dsi);
-   int ret;
-
-   ret = drm_panel_unprepare(&ctx->panel);
-   if (ret < 0)
-   dev_err(&dsi->dev, "Failed to unprepare panel: %d\n", ret);
-
-   ret = drm_panel_disable(&ctx->panel);
-   if (ret < 0)
-   dev_err(&dsi->dev, "Failed to disable panel: %d\n", ret);
-}
-
 static void xpp055c272_remove(struct mipi_dsi_device *dsi)
 {
struct xpp055c272 *ctx = mipi_dsi_get_drvdata(dsi);
int ret;
 
-   xpp055c272_shutdown(dsi);
-
ret = mipi_dsi_detach(dsi);
if (ret < 0)
dev_err(&dsi->dev, "Failed to detach from DSI host: %d\n", ret);
@@ -347,7 +331,6 @@ static struct mipi_dsi_driver xpp055c272_driver = {
},
.probe  = xpp055c272_probe,
.remove = xpp055c272_remove,
-   .shutdown = xpp055c272_shutdown,
 };
 module_mipi_dsi_driver(xpp055c272_driver);
 
-- 
2.45.0.rc1.225.g2a3ae87e7f-goog



[RFT PATCH v2 20/48] drm/panel: olimex-lcd-olinuxino: Stop tracking prepared/enabled

2024-05-03 Thread Douglas Anderson
As talked about in commit d2aacaf07395 ("drm/panel: Check for already
prepared/enabled in drm_panel"), we want to remove needless code from
panel drivers that was storing and double-checking the
prepared/enabled state. Even if someone was relying on the
double-check before, that double-check is now in the core and not
needed in individual drivers.

Cc: Stefan Mavrodiev 
Signed-off-by: Douglas Anderson 
---

Changes in v2:
- Only handle 1 panel per patch.
- Split removal of prepared/enabled from handling of remove/shutdown.

 .../drm/panel/panel-olimex-lcd-olinuxino.c| 41 ---
 1 file changed, 41 deletions(-)

diff --git a/drivers/gpu/drm/panel/panel-olimex-lcd-olinuxino.c 
b/drivers/gpu/drm/panel/panel-olimex-lcd-olinuxino.c
index 4819ada69482..8a687d3ba236 100644
--- a/drivers/gpu/drm/panel/panel-olimex-lcd-olinuxino.c
+++ b/drivers/gpu/drm/panel/panel-olimex-lcd-olinuxino.c
@@ -64,9 +64,6 @@ struct lcd_olinuxino {
struct i2c_client *client;
struct mutex mutex;
 
-   bool prepared;
-   bool enabled;
-
struct regulator *supply;
struct gpio_desc *enable_gpio;
 
@@ -78,30 +75,13 @@ static inline struct lcd_olinuxino *to_lcd_olinuxino(struct 
drm_panel *panel)
return container_of(panel, struct lcd_olinuxino, panel);
 }
 
-static int lcd_olinuxino_disable(struct drm_panel *panel)
-{
-   struct lcd_olinuxino *lcd = to_lcd_olinuxino(panel);
-
-   if (!lcd->enabled)
-   return 0;
-
-   lcd->enabled = false;
-
-   return 0;
-}
-
 static int lcd_olinuxino_unprepare(struct drm_panel *panel)
 {
struct lcd_olinuxino *lcd = to_lcd_olinuxino(panel);
 
-   if (!lcd->prepared)
-   return 0;
-
gpiod_set_value_cansleep(lcd->enable_gpio, 0);
regulator_disable(lcd->supply);
 
-   lcd->prepared = false;
-
return 0;
 }
 
@@ -110,27 +90,11 @@ static int lcd_olinuxino_prepare(struct drm_panel *panel)
struct lcd_olinuxino *lcd = to_lcd_olinuxino(panel);
int ret;
 
-   if (lcd->prepared)
-   return 0;
-
ret = regulator_enable(lcd->supply);
if (ret < 0)
return ret;
 
gpiod_set_value_cansleep(lcd->enable_gpio, 1);
-   lcd->prepared = true;
-
-   return 0;
-}
-
-static int lcd_olinuxino_enable(struct drm_panel *panel)
-{
-   struct lcd_olinuxino *lcd = to_lcd_olinuxino(panel);
-
-   if (lcd->enabled)
-   return 0;
-
-   lcd->enabled = true;
 
return 0;
 }
@@ -195,10 +159,8 @@ static int lcd_olinuxino_get_modes(struct drm_panel *panel,
 }
 
 static const struct drm_panel_funcs lcd_olinuxino_funcs = {
-   .disable = lcd_olinuxino_disable,
.unprepare = lcd_olinuxino_unprepare,
.prepare = lcd_olinuxino_prepare,
-   .enable = lcd_olinuxino_enable,
.get_modes = lcd_olinuxino_get_modes,
 };
 
@@ -264,9 +226,6 @@ static int lcd_olinuxino_probe(struct i2c_client *client)
lcd->eeprom.num_modes = 4;
}
 
-   lcd->enabled = false;
-   lcd->prepared = false;
-
lcd->supply = devm_regulator_get(dev, "power");
if (IS_ERR(lcd->supply))
return PTR_ERR(lcd->supply);
-- 
2.45.0.rc1.225.g2a3ae87e7f-goog



[RFT PATCH v2 29/48] drm/panel: tdo-tl070wsh30: Don't call unprepare+disable at shutdown/remove

2024-05-03 Thread Douglas Anderson
It's the responsibility of a correctly written DRM modeset driver to
call drm_atomic_helper_shutdown() at shutdown time and that should be
disabling / unpreparing the panel if needed. Panel drivers shouldn't
be calling these functions themselves.

A recent effort was made to fix as many DRM modeset drivers as
possible [1] [2] [3] and most drivers are fixed now.

Unfortunately, grepping mainline for this panel's compatible string
shows no hits, so we can't be 100% sure if the DRM modeset driver used
with this panel has been fixed. If it is found that the DRM modeset
driver hasn't been fixed then this patch could be temporarily reverted
until it is.

[1] https://lore.kernel.org/r/20230901234015.566018-1-diand...@chromium.org
[2] https://lore.kernel.org/r/20230901234202.566951-1-diand...@chromium.org
[3] https://lore.kernel.org/r/20230921192749.1542462-1-diand...@chromium.org

Cc: Neil Armstrong 
Signed-off-by: Douglas Anderson 
---

Changes in v2:
- Only handle 1 panel per patch.
- Split removal of prepared/enabled from handling of remove/shutdown.

 drivers/gpu/drm/panel/panel-tdo-tl070wsh30.c | 11 ---
 1 file changed, 11 deletions(-)

diff --git a/drivers/gpu/drm/panel/panel-tdo-tl070wsh30.c 
b/drivers/gpu/drm/panel/panel-tdo-tl070wsh30.c
index 36f27c664b69..227f97f9b136 100644
--- a/drivers/gpu/drm/panel/panel-tdo-tl070wsh30.c
+++ b/drivers/gpu/drm/panel/panel-tdo-tl070wsh30.c
@@ -208,16 +208,6 @@ static void tdo_tl070wsh30_panel_remove(struct 
mipi_dsi_device *dsi)
dev_err(&dsi->dev, "failed to detach from DSI host: %d\n", err);
 
drm_panel_remove(&tdo_tl070wsh30->base);
-   drm_panel_disable(&tdo_tl070wsh30->base);
-   drm_panel_unprepare(&tdo_tl070wsh30->base);
-}
-
-static void tdo_tl070wsh30_panel_shutdown(struct mipi_dsi_device *dsi)
-{
-   struct tdo_tl070wsh30_panel *tdo_tl070wsh30 = mipi_dsi_get_drvdata(dsi);
-
-   drm_panel_disable(&tdo_tl070wsh30->base);
-   drm_panel_unprepare(&tdo_tl070wsh30->base);
 }
 
 static struct mipi_dsi_driver tdo_tl070wsh30_panel_driver = {
@@ -227,7 +217,6 @@ static struct mipi_dsi_driver tdo_tl070wsh30_panel_driver = 
{
},
.probe = tdo_tl070wsh30_panel_probe,
.remove = tdo_tl070wsh30_panel_remove,
-   .shutdown = tdo_tl070wsh30_panel_shutdown,
 };
 module_mipi_dsi_driver(tdo_tl070wsh30_panel_driver);
 
-- 
2.45.0.rc1.225.g2a3ae87e7f-goog



[RFT PATCH v2 28/48] drm/panel: tdo-tl070wsh30: Stop tracking prepared

2024-05-03 Thread Douglas Anderson
As talked about in commit d2aacaf07395 ("drm/panel: Check for already
prepared/enabled in drm_panel"), we want to remove needless code from
panel drivers that was storing and double-checking the
prepared/enabled state. Even if someone was relying on the
double-check before, that double-check is now in the core and not
needed in individual drivers.

Cc: Neil Armstrong 
Signed-off-by: Douglas Anderson 
---

Changes in v2:
- Only handle 1 panel per patch.
- Split removal of prepared/enabled from handling of remove/shutdown.

 drivers/gpu/drm/panel/panel-tdo-tl070wsh30.c | 12 
 1 file changed, 12 deletions(-)

diff --git a/drivers/gpu/drm/panel/panel-tdo-tl070wsh30.c 
b/drivers/gpu/drm/panel/panel-tdo-tl070wsh30.c
index d8487bc6d611..36f27c664b69 100644
--- a/drivers/gpu/drm/panel/panel-tdo-tl070wsh30.c
+++ b/drivers/gpu/drm/panel/panel-tdo-tl070wsh30.c
@@ -24,8 +24,6 @@ struct tdo_tl070wsh30_panel {
 
struct regulator *supply;
struct gpio_desc *reset_gpio;
-
-   bool prepared;
 };
 
 static inline
@@ -39,9 +37,6 @@ static int tdo_tl070wsh30_panel_prepare(struct drm_panel 
*panel)
struct tdo_tl070wsh30_panel *tdo_tl070wsh30 = 
to_tdo_tl070wsh30_panel(panel);
int err;
 
-   if (tdo_tl070wsh30->prepared)
-   return 0;
-
err = regulator_enable(tdo_tl070wsh30->supply);
if (err < 0)
return err;
@@ -74,8 +69,6 @@ static int tdo_tl070wsh30_panel_prepare(struct drm_panel 
*panel)
 
msleep(20);
 
-   tdo_tl070wsh30->prepared = true;
-
return 0;
 }
 
@@ -84,9 +77,6 @@ static int tdo_tl070wsh30_panel_unprepare(struct drm_panel 
*panel)
struct tdo_tl070wsh30_panel *tdo_tl070wsh30 = 
to_tdo_tl070wsh30_panel(panel);
int err;
 
-   if (!tdo_tl070wsh30->prepared)
-   return 0;
-
err = mipi_dsi_dcs_set_display_off(tdo_tl070wsh30->link);
if (err < 0)
dev_err(panel->dev, "failed to set display off: %d\n", err);
@@ -103,8 +93,6 @@ static int tdo_tl070wsh30_panel_unprepare(struct drm_panel 
*panel)
 
regulator_disable(tdo_tl070wsh30->supply);
 
-   tdo_tl070wsh30->prepared = false;
-
return 0;
 }
 
-- 
2.45.0.rc1.225.g2a3ae87e7f-goog



[RFT PATCH v2 19/48] drm/panel: novatek-nt36672a: Don't call unprepare+disable at shutdown/remove

2024-05-03 Thread Douglas Anderson
It's the responsibility of a correctly written DRM modeset driver to
call drm_atomic_helper_shutdown() at shutdown time and that should be
disabling / unpreparing the panel if needed. Panel drivers shouldn't
be calling these functions themselves.

A recent effort was made to fix as many DRM modeset drivers as
possible [1] [2] [3] and most drivers are fixed now.

A grep through mainline for compatible strings used by this driver
indicates that it is used by Qualcomm boards. The Qualcomm driver
appears to be correctly calling drm_atomic_helper_shutdown() so we can
remove the calls.

[1] https://lore.kernel.org/r/20230901234015.566018-1-diand...@chromium.org
[2] https://lore.kernel.org/r/20230901234202.566951-1-diand...@chromium.org
[3] https://lore.kernel.org/r/20230921192749.1542462-1-diand...@chromium.org

Cc: Sumit Semwal 
Cc: Benni Steini 
Cc: Joel Selvaraj 
Cc: Marijn Suijten 
Signed-off-by: Douglas Anderson 
---

Changes in v2:
- Only handle 1 panel per patch.
- Split removal of prepared/enabled from handling of remove/shutdown.

 drivers/gpu/drm/panel/panel-novatek-nt36672a.c | 17 -
 1 file changed, 17 deletions(-)

diff --git a/drivers/gpu/drm/panel/panel-novatek-nt36672a.c 
b/drivers/gpu/drm/panel/panel-novatek-nt36672a.c
index 35aace79613a..c2abd20e0734 100644
--- a/drivers/gpu/drm/panel/panel-novatek-nt36672a.c
+++ b/drivers/gpu/drm/panel/panel-novatek-nt36672a.c
@@ -656,14 +656,6 @@ static void nt36672a_panel_remove(struct mipi_dsi_device 
*dsi)
struct nt36672a_panel *pinfo = mipi_dsi_get_drvdata(dsi);
int err;
 
-   err = drm_panel_unprepare(&pinfo->base);
-   if (err < 0)
-   dev_err(&dsi->dev, "failed to unprepare panel: %d\n", err);
-
-   err = drm_panel_disable(&pinfo->base);
-   if (err < 0)
-   dev_err(&dsi->dev, "failed to disable panel: %d\n", err);
-
err = mipi_dsi_detach(dsi);
if (err < 0)
dev_err(&dsi->dev, "failed to detach from DSI host: %d\n", err);
@@ -671,14 +663,6 @@ static void nt36672a_panel_remove(struct mipi_dsi_device 
*dsi)
drm_panel_remove(&pinfo->base);
 }
 
-static void nt36672a_panel_shutdown(struct mipi_dsi_device *dsi)
-{
-   struct nt36672a_panel *pinfo = mipi_dsi_get_drvdata(dsi);
-
-   drm_panel_disable(&pinfo->base);
-   drm_panel_unprepare(&pinfo->base);
-}
-
 static const struct of_device_id tianma_fhd_video_of_match[] = {
{ .compatible = "tianma,fhd-video", .data = 
&tianma_fhd_video_panel_desc },
{ },
@@ -692,7 +676,6 @@ static struct mipi_dsi_driver nt36672a_panel_driver = {
},
.probe = nt36672a_panel_probe,
.remove = nt36672a_panel_remove,
-   .shutdown = nt36672a_panel_shutdown,
 };
 module_mipi_dsi_driver(nt36672a_panel_driver);
 
-- 
2.45.0.rc1.225.g2a3ae87e7f-goog



[RFT PATCH v2 26/48] drm/panel: simple: Stop tracking prepared/enabled

2024-05-03 Thread Douglas Anderson
As talked about in commit d2aacaf07395 ("drm/panel: Check for already
prepared/enabled in drm_panel"), we want to remove needless code from
panel drivers that was storing and double-checking the
prepared/enabled state. Even if someone was relying on the
double-check before, that double-check is now in the core and not
needed in individual drivers.

Signed-off-by: Douglas Anderson 
---

Changes in v2:
- Only handle 1 panel per patch.
- Split removal of prepared/enabled from handling of remove/shutdown.

 drivers/gpu/drm/panel/panel-simple.c | 27 ---
 1 file changed, 27 deletions(-)

diff --git a/drivers/gpu/drm/panel/panel-simple.c 
b/drivers/gpu/drm/panel/panel-simple.c
index dcb6d0b6ced0..42d902d2bbbe 100644
--- a/drivers/gpu/drm/panel/panel-simple.c
+++ b/drivers/gpu/drm/panel/panel-simple.c
@@ -138,9 +138,6 @@ struct panel_desc {
 
 struct panel_simple {
struct drm_panel base;
-   bool enabled;
-
-   bool prepared;
 
ktime_t unprepared_time;
 
@@ -290,14 +287,9 @@ static int panel_simple_disable(struct drm_panel *panel)
 {
struct panel_simple *p = to_panel_simple(panel);
 
-   if (!p->enabled)
-   return 0;
-
if (p->desc->delay.disable)
msleep(p->desc->delay.disable);
 
-   p->enabled = false;
-
return 0;
 }
 
@@ -317,18 +309,12 @@ static int panel_simple_suspend(struct device *dev)
 
 static int panel_simple_unprepare(struct drm_panel *panel)
 {
-   struct panel_simple *p = to_panel_simple(panel);
int ret;
 
-   /* Unpreparing when already unprepared is a no-op */
-   if (!p->prepared)
-   return 0;
-
pm_runtime_mark_last_busy(panel->dev);
ret = pm_runtime_put_autosuspend(panel->dev);
if (ret < 0)
return ret;
-   p->prepared = false;
 
return 0;
 }
@@ -356,21 +342,14 @@ static int panel_simple_resume(struct device *dev)
 
 static int panel_simple_prepare(struct drm_panel *panel)
 {
-   struct panel_simple *p = to_panel_simple(panel);
int ret;
 
-   /* Preparing when already prepared is a no-op */
-   if (p->prepared)
-   return 0;
-
ret = pm_runtime_get_sync(panel->dev);
if (ret < 0) {
pm_runtime_put_autosuspend(panel->dev);
return ret;
}
 
-   p->prepared = true;
-
return 0;
 }
 
@@ -378,14 +357,9 @@ static int panel_simple_enable(struct drm_panel *panel)
 {
struct panel_simple *p = to_panel_simple(panel);
 
-   if (p->enabled)
-   return 0;
-
if (p->desc->delay.enable)
msleep(p->desc->delay.enable);
 
-   p->enabled = true;
-
return 0;
 }
 
@@ -609,7 +583,6 @@ static int panel_simple_probe(struct device *dev, const 
struct panel_desc *desc)
if (!panel)
return -ENOMEM;
 
-   panel->enabled = false;
panel->desc = desc;
 
panel->supply = devm_regulator_get(dev, "power");
-- 
2.45.0.rc1.225.g2a3ae87e7f-goog



[RFT PATCH v2 27/48] drm/panel: simple: Add a comment about unprepare+disable at shutdown/remove

2024-05-03 Thread Douglas Anderson
It's the responsibility of a correctly written DRM modeset driver to
call drm_atomic_helper_shutdown() at shutdown time and that should be
disabling / unpreparing the panel if needed. Panel drivers shouldn't
be calling these functions themselves.

A recent effort was made to fix as many DRM modeset drivers as
possible [1] [2] [3] and most drivers are fixed now.

Unfortunately, it's very difficult to know exactly which DRM modeset
drivers are using panel-simple due to the sheer number of panels it
handles. For now, we'll leave the calls and just add a comment to keep
people from copying this code.

[1] https://lore.kernel.org/r/20230901234015.566018-1-diand...@chromium.org
[2] https://lore.kernel.org/r/20230901234202.566951-1-diand...@chromium.org
[3] https://lore.kernel.org/r/20230921192749.1542462-1-diand...@chromium.org

Signed-off-by: Douglas Anderson 
---

Changes in v2:
- Only handle 1 panel per patch.
- Split removal of prepared/enabled from handling of remove/shutdown.
- panel-edp and panel-simple just get a comment now.

 drivers/gpu/drm/panel/panel-simple.c | 33 +++-
 1 file changed, 23 insertions(+), 10 deletions(-)

diff --git a/drivers/gpu/drm/panel/panel-simple.c 
b/drivers/gpu/drm/panel/panel-simple.c
index 42d902d2bbbe..f39122ffdead 100644
--- a/drivers/gpu/drm/panel/panel-simple.c
+++ b/drivers/gpu/drm/panel/panel-simple.c
@@ -716,26 +716,39 @@ static int panel_simple_probe(struct device *dev, const 
struct panel_desc *desc)
return err;
 }
 
-static void panel_simple_remove(struct device *dev)
+static void panel_simple_shutdown(struct device *dev)
 {
struct panel_simple *panel = dev_get_drvdata(dev);
 
-   drm_panel_remove(&panel->base);
+   /*
+* NOTE: the following two calls don't really belong here. It is the
+* responsibility of a correctly written DRM modeset driver to call
+* drm_atomic_helper_shutdown() at shutdown time and that should
+* cause the panel to be disabled / unprepared if needed. For now,
+* however, we'll keep these calls due to the sheer number of
+* different DRM modeset drivers used with panel-simple. The fact that
+* we're calling these and _also_ the drm_atomic_helper_shutdown()
+* will try to disable/unprepare means that we can get a warning about
+* trying to disable/unprepare an already disabled/unprepared panel,
+* but that's something we'll have to live with until we've confirmed
+* that all DRM modeset drivers are properly calling
+* drm_atomic_helper_shutdown().
+*/
drm_panel_disable(&panel->base);
drm_panel_unprepare(&panel->base);
-
-   pm_runtime_dont_use_autosuspend(dev);
-   pm_runtime_disable(dev);
-   if (panel->ddc)
-   put_device(&panel->ddc->dev);
 }
 
-static void panel_simple_shutdown(struct device *dev)
+static void panel_simple_remove(struct device *dev)
 {
struct panel_simple *panel = dev_get_drvdata(dev);
 
-   drm_panel_disable(&panel->base);
-   drm_panel_unprepare(&panel->base);
+   drm_panel_remove(&panel->base);
+   panel_simple_shutdown(dev);
+
+   pm_runtime_dont_use_autosuspend(dev);
+   pm_runtime_disable(dev);
+   if (panel->ddc)
+   put_device(&panel->ddc->dev);
 }
 
 static const struct drm_display_mode ampire_am_1280800n3tzqw_t00h_mode = {
-- 
2.45.0.rc1.225.g2a3ae87e7f-goog



  1   2   3   4   5   6   7   8   9   >