drm/vc4: Call drm_atomic_helper_shutdown() at shutdown time
authorDouglas Anderson <dianders@chromium.org>
Fri, 1 Sep 2023 23:39:54 +0000 (16:39 -0700)
committerDouglas Anderson <dianders@chromium.org>
Thu, 21 Sep 2023 17:49:04 +0000 (10:49 -0700)
Based on grepping through the source code these drivers appear 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 <mripard@kernel.org>
Acked-by: Maxime Ripard <mripard@kernel.org>
Signed-off-by: Douglas Anderson <dianders@chromium.org>
Link: https://patchwork.freedesktop.org/patch/msgid/20230901163944.RFT.3.I10dbe099fb1059d304ba847d19fc45054f7ffe9f@changeid
drivers/gpu/drm/vc4/vc4_drv.c

index 1b35313..c133e96 100644 (file)
@@ -324,21 +324,21 @@ static int vc4_drm_bind(struct device *dev)
        if (!is_vc5) {
                ret = drmm_mutex_init(drm, &vc4->bin_bo_lock);
                if (ret)
-                       return ret;
+                       goto err;
 
                ret = vc4_bo_cache_init(drm);
                if (ret)
-                       return ret;
+                       goto err;
        }
 
        ret = drmm_mode_config_init(drm);
        if (ret)
-               return ret;
+               goto err;
 
        if (!is_vc5) {
                ret = vc4_gem_init(drm);
                if (ret)
-                       return ret;
+                       goto err;
        }
 
        node = of_find_compatible_node(NULL, NULL, "raspberrypi,bcm2835-firmware");
@@ -346,13 +346,15 @@ static int vc4_drm_bind(struct device *dev)
                firmware = rpi_firmware_get(node);
                of_node_put(node);
 
-               if (!firmware)
-                       return -EPROBE_DEFER;
+               if (!firmware) {
+                       ret = -EPROBE_DEFER;
+                       goto err;
+               }
        }
 
        ret = drm_aperture_remove_framebuffers(driver);
        if (ret)
-               return ret;
+               goto err;
 
        if (firmware) {
                ret = rpi_firmware_property(firmware,
@@ -366,32 +368,33 @@ static int vc4_drm_bind(struct device *dev)
 
        ret = component_bind_all(dev, drm);
        if (ret)
-               return ret;
+               goto err;
 
        ret = devm_add_action_or_reset(dev, vc4_component_unbind_all, vc4);
        if (ret)
-               return ret;
+               goto err;
 
        ret = vc4_plane_create_additional_planes(drm);
        if (ret)
-               goto unbind_all;
+               goto err;
 
        ret = vc4_kms_load(drm);
        if (ret < 0)
-               goto unbind_all;
+               goto err;
 
        drm_for_each_crtc(crtc, drm)
                vc4_crtc_disable_at_boot(crtc);
 
        ret = drm_dev_register(drm, 0);
        if (ret < 0)
-               goto unbind_all;
+               goto err;
 
        drm_fbdev_dma_setup(drm, 16);
 
        return 0;
 
-unbind_all:
+err:
+       platform_set_drvdata(pdev, NULL);
        return ret;
 }
 
@@ -401,6 +404,7 @@ static void vc4_drm_unbind(struct device *dev)
 
        drm_dev_unplug(drm);
        drm_atomic_helper_shutdown(drm);
+       dev_set_drvdata(dev, NULL);
 }
 
 static const struct component_master_ops vc4_drm_ops = {
@@ -444,6 +448,11 @@ static void vc4_platform_drm_remove(struct platform_device *pdev)
        component_master_del(&pdev->dev, &vc4_drm_ops);
 }
 
+static void vc4_platform_drm_shutdown(struct platform_device *pdev)
+{
+       drm_atomic_helper_shutdown(platform_get_drvdata(pdev));
+}
+
 static const struct of_device_id vc4_of_match[] = {
        { .compatible = "brcm,bcm2711-vc5", },
        { .compatible = "brcm,bcm2835-vc4", },
@@ -455,6 +464,7 @@ MODULE_DEVICE_TABLE(of, vc4_of_match);
 static struct platform_driver vc4_platform_driver = {
        .probe          = vc4_platform_drm_probe,
        .remove_new     = vc4_platform_drm_remove,
+       .shutdown       = vc4_platform_drm_shutdown,
        .driver         = {
                .name   = "vc4-drm",
                .of_match_table = vc4_of_match,