Introduce the component framework to bind childs and siblings, for better
modularity and paper over the deferral probe problems if it need to attach
exterinal module someday. Hardware units come with PCI(e) are actually all
ready to drive, but there has some board specific modules will return
-EPROBE_DEFER. We need all other submodules ready to attach before we can
register the drm device to userspace.
The idea is to devide the exterinal module dependent part and exterinal
module independent part clearly, for example, the display controller and
the builtin GPIO-I2C just belong to exterinal module independent part.
While the output is belong to exterinal module dependent part.
Also for better reflecting the hardware, we intend to abstract the output
ports as child devices. The output ports may consists of encoder phy and
level shift, while the GPU and VPU are standalone siblings. As those units
are relative separate hardware units from display controller itself.
By design, the display controller PCI(e) is selected as the component
master, gpio-i2c go with master. The manually created virtual child device
are functional as agents for the master, it could return the -EPROBE_DEFER
back to the component core. This allows the master don't have to tear down
everything, the majority setups work can be preserved. The potential cyclic
dependency problem can be solved with such framework.
Signed-off-by: Sui Jingfeng
---
drivers/gpu/drm/loongson/Makefile | 1 +
drivers/gpu/drm/loongson/loongson_module.c | 17 ++-
drivers/gpu/drm/loongson/loongson_module.h | 1 +
drivers/gpu/drm/loongson/lsdc_drv.c| 59 +
drivers/gpu/drm/loongson/lsdc_drv.h| 6 +-
drivers/gpu/drm/loongson/lsdc_output.c | 142 +
drivers/gpu/drm/loongson/lsdc_output.h | 22 +++-
7 files changed, 241 insertions(+), 7 deletions(-)
create mode 100644 drivers/gpu/drm/loongson/lsdc_output.c
diff --git a/drivers/gpu/drm/loongson/Makefile
b/drivers/gpu/drm/loongson/Makefile
index 91e72bd900c1..e15cb9bff378 100644
--- a/drivers/gpu/drm/loongson/Makefile
+++ b/drivers/gpu/drm/loongson/Makefile
@@ -9,6 +9,7 @@ loongson-y := \
lsdc_gfxpll.o \
lsdc_i2c.o \
lsdc_irq.o \
+ lsdc_output.o \
lsdc_output_7a1000.o \
lsdc_output_7a2000.o \
lsdc_plane.o \
diff --git a/drivers/gpu/drm/loongson/loongson_module.c
b/drivers/gpu/drm/loongson/loongson_module.c
index d2a51bd395f6..037fa7ffe9c9 100644
--- a/drivers/gpu/drm/loongson/loongson_module.c
+++ b/drivers/gpu/drm/loongson/loongson_module.c
@@ -4,6 +4,7 @@
*/
#include
+#include
#include
@@ -19,15 +20,29 @@ module_param_named(vblank, loongson_vblank, int, 0400);
static int __init loongson_module_init(void)
{
+ int ret;
+
if (!loongson_modeset || video_firmware_drivers_only())
return -ENODEV;
- return pci_register_driver(_pci_driver);
+ ret = platform_driver_register(_output_port_platform_driver);
+ if (ret)
+ return ret;
+
+ ret = pci_register_driver(_pci_driver);
+ if (ret) {
+ platform_driver_unregister(_output_port_platform_driver);
+ return ret;
+ }
+
+ return 0;
}
module_init(loongson_module_init);
static void __exit loongson_module_exit(void)
{
pci_unregister_driver(_pci_driver);
+
+ platform_driver_unregister(_output_port_platform_driver);
}
module_exit(loongson_module_exit);
diff --git a/drivers/gpu/drm/loongson/loongson_module.h
b/drivers/gpu/drm/loongson/loongson_module.h
index 931c17521bf0..8dc71b98f5cc 100644
--- a/drivers/gpu/drm/loongson/loongson_module.h
+++ b/drivers/gpu/drm/loongson/loongson_module.h
@@ -8,5 +8,6 @@
extern int loongson_vblank;
extern struct pci_driver lsdc_pci_driver;
+extern struct platform_driver lsdc_output_port_platform_driver;
#endif
diff --git a/drivers/gpu/drm/loongson/lsdc_drv.c
b/drivers/gpu/drm/loongson/lsdc_drv.c
index adc7344d2f80..45c30e3d178f 100644
--- a/drivers/gpu/drm/loongson/lsdc_drv.c
+++ b/drivers/gpu/drm/loongson/lsdc_drv.c
@@ -3,7 +3,9 @@
* Copyright (C) 2023 Loongson Technology Corporation Limited
*/
+#include
#include
+#include
#include
#include
@@ -257,12 +259,39 @@ static unsigned int lsdc_vga_set_decode(struct pci_dev
*pdev, bool state)
return VGA_RSRC_NORMAL_IO | VGA_RSRC_NORMAL_MEM;
}
+static int loongson_drm_master_bind(struct device *dev)
+{
+ int ret;
+
+ ret = component_bind_all(dev, NULL);
+ if (ret) {
+ dev_err(dev, "master bind all failed: %d\n", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+static void loongson_drm_master_unbind(struct device *dev)
+{
+ component_unbind_all(dev, NULL);
+
+ return;
+}
+
+const struct component_master_ops loongson_drm_master_ops = {
+ .bind = loongson_drm_master_bind,
+ .unbind = loongson_drm_master_unbind,
+};
+
static int