[PATCH] regulator: core: Stub devm_regulator_bulk_get_const() if !CONFIG_REGULATOR
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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()
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
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()
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()
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
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
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
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
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
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
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
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()
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()
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
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()
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()
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()
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
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
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
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
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()
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()
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()
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
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()
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()
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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