Re: [PATCH 1/2] of: Create platform devices for OF framebuffers

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi

Am 13.04.22 um 14:51 schrieb Rob Herring:
On Wed, Apr 13, 2022 at 4:24 AM Thomas Zimmermann <tzimmermann@xxxxxxx> wrote:

Create a platform device for each OF-declared framebuffer and have
offb bind to these devices. Allows for real hot-unplugging and other
drivers besides offb.

Originally, offb created framebuffer devices while initializing its
module by parsing the OF device tree. No actual Linux device was set
up. This tied OF framebuffers to offb and makes writing other drivers
for the OF framebuffers complicated. The absence of a Linux device
prevented real hot-unplugging. Adding a distinct platform device for
each OF framebuffer solves both problems. Specifically, a DRM drivers
can now provide graphics output with modern userspace.

Some of the offb init code is now located in the OF initialization.
There's now also an implementation of of_platform_default_populate_init(),
which was missing before. The OF side creates different devices for
either OF display nodes or bootx displays as they require different
handling by the driver. The offb drivers picks up each type of device
and runs the appropriate fbdev initialization.

Tested with OF display nodes on qemu's ppc64le target.

Signed-off-by: Thomas Zimmermann <tzimmermann@xxxxxxx>
---
  drivers/of/platform.c      | 73 ++++++++++++++++++++++++++--
  drivers/video/fbdev/offb.c | 98 +++++++++++++++++++++++++-------------
  2 files changed, 134 insertions(+), 37 deletions(-)

diff --git a/drivers/of/platform.c b/drivers/of/platform.c
index a16b74f32aa9..4c63b9a73587 100644
--- a/drivers/of/platform.c
+++ b/drivers/of/platform.c
@@ -447,6 +447,60 @@ int of_platform_bus_probe(struct device_node *root,
  }
  EXPORT_SYMBOL(of_platform_bus_probe);

+static int __init of_platform_populate_framebuffers(void)
+{
+       struct device_node *boot_display = NULL;
+       struct device_node *node;
+       struct platform_device *dev;
+       int ret;
+
+       node = of_get_compatible_child(of_chosen, "simple-framebuffer");
+       of_platform_device_create(node, NULL, NULL);
+       of_node_put(node);
+

The rest is PPC only, so bail out here if !PPC.

+       /* Check if we have a MacOS display without a node spec */
+       if (of_get_property(of_chosen, "linux,bootx-noscreen", NULL)) {
+               /*
+                * The old code tried to work out which node was the MacOS
+                * display based on the address. I'm dropping that since the
+                * lack of a node spec only happens with old BootX versions
+                * (users can update) and with this code, they'll still get
+                * a display (just not the palette hacks).
+                */
+               dev = platform_device_alloc("bootx-noscreen", 0);
+               if (WARN_ON(!dev))
+                       return -ENOMEM;
+               ret = platform_device_add(dev);
+               if (WARN_ON(ret)) {
+                       platform_device_put(dev);
+                       return ret;
+               }
+       }
+
+       /*
+        * For OF framebuffers, first create the device for the boot display,
+        * then for the other framebuffers. Only fail for the boot display;
+        * ignore errors for the rest.
+        */
+       for_each_node_by_type(node, "display") {
+               if (!of_get_property(node, "linux,opened", NULL) ||
+                   !of_get_property(node, "linux,boot-display", NULL))
+                       continue;
+               dev = of_platform_device_create(node, "of-display", NULL);
+               if (WARN_ON(!dev))
+                       return -ENOMEM;
+               boot_display = node;
+               break;
+       }
+       for_each_node_by_type(node, "display") {
+               if (!of_get_property(node, "linux,opened", NULL) || node == boot_display)
+                       continue;
+               of_platform_device_create(node, "of-display", NULL);
+       }
+
+       return 0;
+}
+
  /**
   * of_platform_populate() - Populate platform_devices from device tree data
   * @root: parent of the first level to probe or NULL for the root of the tree
@@ -541,9 +595,7 @@ static int __init of_platform_default_populate_init(void)
                 of_node_put(node);
         }

-       node = of_get_compatible_child(of_chosen, "simple-framebuffer");
-       of_platform_device_create(node, NULL, NULL);
-       of_node_put(node);
+       of_platform_populate_framebuffers();

         /* Populate everything else. */
         of_platform_default_populate(NULL, NULL, NULL);

I'm pretty sure it's just this call that's the problem for PPC though
none of the above existed when adding this caused a regression. Can we
remove the ifdef and just make this call conditional on
!IS_ENABLED(CONFIG_PPC).

Together with the changes in of_platform_populate_framebuffers(), the code is more or less an "if-else" depending on PPC. I'll drop of_platform_populate_framebuffers() from the patch and make a separate implementation of of_platform_default_populate_init for PPC. Seems like the easiest solution to me.

Best regards
Thomas



@@ -551,6 +603,20 @@ static int __init of_platform_default_populate_init(void)
         return 0;
  }
  arch_initcall_sync(of_platform_default_populate_init);
+#else
+static int __init of_platform_default_populate_init(void)
+{
+       device_links_supplier_sync_state_pause();
+
+       if (!of_have_populated_dt())
+               return -ENODEV;
+
+       of_platform_populate_framebuffers();
+
+       return 0;
+}
+arch_initcall_sync(of_platform_default_populate_init);
+#endif

  static int __init of_platform_sync_state_init(void)
  {
@@ -558,7 +624,6 @@ static int __init of_platform_sync_state_init(void)
         return 0;
  }
  late_initcall_sync(of_platform_sync_state_init);
-#endif

  int of_platform_device_destroy(struct device *dev, void *data)
  {

--
Thomas Zimmermann
Graphics Driver Developer
SUSE Software Solutions Germany GmbH
Maxfeldstr. 5, 90409 Nürnberg, Germany
(HRB 36809, AG Nürnberg)
Geschäftsführer: Ivo Totev

Attachment: OpenPGP_signature
Description: OpenPGP digital signature


[Index of Archives]     [Device Tree Compilter]     [Device Tree Spec]     [Linux Driver Backports]     [Video for Linux]     [Linux USB Devel]     [Linux PCI Devel]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [XFree86]     [Yosemite Backpacking]


  Powered by Linux