I had previously modeled vc4 off of msm's component driver registration, but on further investigation exynos has an even cleaner way of doing it. Here's a series to turn exynos's style into core helpers, and use it from msm.
The patches are build tested, but I don't have either of the platforms to test on.
This is mostly just a move of the code from exynos, with a slight reformat. I wanted to do a similar thing for vc4, and msm looks like a good candidate as well.
Signed-off-by: Eric Anholt eric@anholt.net --- drivers/gpu/drm/Makefile | 3 ++- drivers/gpu/drm/drm_platform_helpers.c | 45 +++++++++++++++++++++++++++++++++ drivers/gpu/drm/exynos/exynos_drm_drv.c | 38 +++++----------------------- include/drm/drmP.h | 4 +++ 4 files changed, 57 insertions(+), 33 deletions(-) create mode 100644 drivers/gpu/drm/drm_platform_helpers.c
diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile index 45e7719..266d199 100644 --- a/drivers/gpu/drm/Makefile +++ b/drivers/gpu/drm/Makefile @@ -7,7 +7,8 @@ drm-y := drm_auth.o drm_bufs.o drm_cache.o \ drm_fops.o drm_gem.o drm_ioctl.o drm_irq.o \ drm_lock.o drm_memory.o drm_drv.o drm_vm.o \ drm_agpsupport.o drm_scatter.o drm_pci.o \ - drm_platform.o drm_sysfs.o drm_hashtab.o drm_mm.o \ + drm_platform.o drm_platform_helpers.o \ + drm_sysfs.o drm_hashtab.o drm_mm.o \ drm_crtc.o drm_modes.o drm_edid.o \ drm_info.o drm_debugfs.o drm_encoder_slave.o \ drm_trace_points.o drm_global.o drm_prime.o \ diff --git a/drivers/gpu/drm/drm_platform_helpers.c b/drivers/gpu/drm/drm_platform_helpers.c new file mode 100644 index 0000000..a54c3e3 --- /dev/null +++ b/drivers/gpu/drm/drm_platform_helpers.c @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#include <drm/drmP.h> + +/** + * drm_platform_register_drivers - Helper to register an array of + * struct platform_drivers. + */ +int drm_platform_register_drivers(struct platform_driver *const *drv, + int count) +{ + int i, ret; + + for (i = 0; i < count; ++i) { + ret = platform_driver_register(drv[i]); + if (ret) { + while (--i >= 0) + platform_driver_unregister(drv[i]); + return ret; + } + } + + return 0; +} +EXPORT_SYMBOL_GPL(drm_platform_register_drivers); + +/** + * drm_platform_unregister_drivers - Helper to unregister an array of + * struct platform_drivers (in the opposite order they would have been + * registered by drm_platform_register_drivers()). + */ +void drm_platform_unregister_drivers(struct platform_driver *const *drv, + int count) +{ + while (--count >= 0) + platform_driver_unregister(drv[count]); +} +EXPORT_SYMBOL_GPL(drm_platform_unregister_drivers); diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.c b/drivers/gpu/drm/exynos/exynos_drm_drv.c index fa5194c..83f829b 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_drv.c +++ b/drivers/gpu/drm/exynos/exynos_drm_drv.c @@ -520,53 +520,27 @@ static int exynos_drm_register_devices(void) return 0; }
-static void exynos_drm_unregister_drivers(struct platform_driver * const *drv, - int count) -{ - while (--count >= 0) - platform_driver_unregister(drv[count]); -} - -static int exynos_drm_register_drivers(struct platform_driver * const *drv, - int count) -{ - int i, ret; - - for (i = 0; i < count; ++i) { - ret = platform_driver_register(drv[i]); - if (!ret) - continue; - - while (--i >= 0) - platform_driver_unregister(drv[i]); - - return ret; - } - - return 0; -} - static inline int exynos_drm_register_kms_drivers(void) { - return exynos_drm_register_drivers(exynos_drm_kms_drivers, - ARRAY_SIZE(exynos_drm_kms_drivers)); + return drm_platform_register_drivers(exynos_drm_kms_drivers, + ARRAY_SIZE(exynos_drm_kms_drivers)); }
static inline int exynos_drm_register_non_kms_drivers(void) { - return exynos_drm_register_drivers(exynos_drm_non_kms_drivers, - ARRAY_SIZE(exynos_drm_non_kms_drivers)); + return drm_platform_register_drivers(exynos_drm_non_kms_drivers, + ARRAY_SIZE(exynos_drm_non_kms_drivers)); }
static inline void exynos_drm_unregister_kms_drivers(void) { - exynos_drm_unregister_drivers(exynos_drm_kms_drivers, + drm_platform_unregister_drivers(exynos_drm_kms_drivers, ARRAY_SIZE(exynos_drm_kms_drivers)); }
static inline void exynos_drm_unregister_non_kms_drivers(void) { - exynos_drm_unregister_drivers(exynos_drm_non_kms_drivers, + drm_platform_unregister_drivers(exynos_drm_non_kms_drivers, ARRAY_SIZE(exynos_drm_non_kms_drivers)); }
diff --git a/include/drm/drmP.h b/include/drm/drmP.h index 8b5ce7c..a774574 100644 --- a/include/drm/drmP.h +++ b/include/drm/drmP.h @@ -1087,6 +1087,10 @@ extern int drm_pcie_get_speed_cap_mask(struct drm_device *dev, u32 *speed_mask); /* platform section */ extern int drm_platform_init(struct drm_driver *driver, struct platform_device *platform_device); extern int drm_platform_set_busid(struct drm_device *d, struct drm_master *m); +int drm_platform_register_drivers(struct platform_driver *const *drv, + int count); +void drm_platform_unregister_drivers(struct platform_driver *const *drv, + int count);
/* returns true if currently okay to sleep */ static __inline__ bool drm_can_sleep(void)
On Wed, Sep 16, 2015 at 11:14 AM, Eric Anholt eric@anholt.net wrote:
This is mostly just a move of the code from exynos, with a slight reformat. I wanted to do a similar thing for vc4, and msm looks like a good candidate as well.
Signed-off-by: Eric Anholt eric@anholt.net
drivers/gpu/drm/Makefile | 3 ++- drivers/gpu/drm/drm_platform_helpers.c | 45 +++++++++++++++++++++++++++++++++ drivers/gpu/drm/exynos/exynos_drm_drv.c | 38 +++++----------------------- include/drm/drmP.h | 4 +++ 4 files changed, 57 insertions(+), 33 deletions(-) create mode 100644 drivers/gpu/drm/drm_platform_helpers.c
diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile index 45e7719..266d199 100644 --- a/drivers/gpu/drm/Makefile +++ b/drivers/gpu/drm/Makefile @@ -7,7 +7,8 @@ drm-y := drm_auth.o drm_bufs.o drm_cache.o \ drm_fops.o drm_gem.o drm_ioctl.o drm_irq.o \ drm_lock.o drm_memory.o drm_drv.o drm_vm.o \ drm_agpsupport.o drm_scatter.o drm_pci.o \
drm_platform.o drm_sysfs.o drm_hashtab.o drm_mm.o \
drm_platform.o drm_platform_helpers.o \
drm_sysfs.o drm_hashtab.o drm_mm.o \
Imo it'd would be good to have a separate module for helpers like these (maybe even put them into the kms helpers). At least that explicit split on the modeset side seems to help with a clean split between mandatory core bits and helper code.
drm_crtc.o drm_modes.o drm_edid.o \ drm_info.o drm_debugfs.o drm_encoder_slave.o \ drm_trace_points.o drm_global.o drm_prime.o \
diff --git a/drivers/gpu/drm/drm_platform_helpers.c b/drivers/gpu/drm/drm_platform_helpers.c new file mode 100644 index 0000000..a54c3e3 --- /dev/null +++ b/drivers/gpu/drm/drm_platform_helpers.c @@ -0,0 +1,45 @@ +/*
- Copyright (c) 2011 Samsung Electronics Co., Ltd.
- This program is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published by the
- Free Software Foundation; either version 2 of the License, or (at your
- option) any later version.
- */
+#include <drm/drmP.h>
+/**
- drm_platform_register_drivers - Helper to register an array of
- struct platform_drivers.
- */
Please add a new section to Documentation/DocBook/drm.tmpl so that these kerneldoc comments are included. Without that 0day won't catch mismatches in kerneldoc and hopefully including it will also make it a bit more discoverable. And with the new markdown stuff in drm-intel-nightly you could even include an example snippet for how to use it, but that's kinda overkilla ;-) If you do that kerneldoc will complain about the missing parameter helpers. Also I recommend to point at other functions which should be used together with this one (like _unregister), in 4.3 the htmldocs will actually insert hyperlinks for that.
Thanks, Daniel
+int drm_platform_register_drivers(struct platform_driver *const *drv,
int count)
+{
int i, ret;
for (i = 0; i < count; ++i) {
ret = platform_driver_register(drv[i]);
if (ret) {
while (--i >= 0)
platform_driver_unregister(drv[i]);
return ret;
}
}
return 0;
+} +EXPORT_SYMBOL_GPL(drm_platform_register_drivers);
+/**
- drm_platform_unregister_drivers - Helper to unregister an array of
- struct platform_drivers (in the opposite order they would have been
- registered by drm_platform_register_drivers()).
- */
+void drm_platform_unregister_drivers(struct platform_driver *const *drv,
int count)
+{
while (--count >= 0)
platform_driver_unregister(drv[count]);
+} +EXPORT_SYMBOL_GPL(drm_platform_unregister_drivers); diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.c b/drivers/gpu/drm/exynos/exynos_drm_drv.c index fa5194c..83f829b 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_drv.c +++ b/drivers/gpu/drm/exynos/exynos_drm_drv.c @@ -520,53 +520,27 @@ static int exynos_drm_register_devices(void) return 0; }
-static void exynos_drm_unregister_drivers(struct platform_driver * const *drv,
int count)
-{
while (--count >= 0)
platform_driver_unregister(drv[count]);
-}
-static int exynos_drm_register_drivers(struct platform_driver * const *drv,
int count)
-{
int i, ret;
for (i = 0; i < count; ++i) {
ret = platform_driver_register(drv[i]);
if (!ret)
continue;
while (--i >= 0)
platform_driver_unregister(drv[i]);
return ret;
}
return 0;
-}
static inline int exynos_drm_register_kms_drivers(void) {
return exynos_drm_register_drivers(exynos_drm_kms_drivers,
ARRAY_SIZE(exynos_drm_kms_drivers));
return drm_platform_register_drivers(exynos_drm_kms_drivers,
ARRAY_SIZE(exynos_drm_kms_drivers));
}
static inline int exynos_drm_register_non_kms_drivers(void) {
return exynos_drm_register_drivers(exynos_drm_non_kms_drivers,
ARRAY_SIZE(exynos_drm_non_kms_drivers));
return drm_platform_register_drivers(exynos_drm_non_kms_drivers,
ARRAY_SIZE(exynos_drm_non_kms_drivers));
}
static inline void exynos_drm_unregister_kms_drivers(void) {
exynos_drm_unregister_drivers(exynos_drm_kms_drivers,
drm_platform_unregister_drivers(exynos_drm_kms_drivers, ARRAY_SIZE(exynos_drm_kms_drivers));
}
static inline void exynos_drm_unregister_non_kms_drivers(void) {
exynos_drm_unregister_drivers(exynos_drm_non_kms_drivers,
drm_platform_unregister_drivers(exynos_drm_non_kms_drivers, ARRAY_SIZE(exynos_drm_non_kms_drivers));
}
diff --git a/include/drm/drmP.h b/include/drm/drmP.h index 8b5ce7c..a774574 100644 --- a/include/drm/drmP.h +++ b/include/drm/drmP.h @@ -1087,6 +1087,10 @@ extern int drm_pcie_get_speed_cap_mask(struct drm_device *dev, u32 *speed_mask); /* platform section */ extern int drm_platform_init(struct drm_driver *driver, struct platform_device *platform_device); extern int drm_platform_set_busid(struct drm_device *d, struct drm_master *m); +int drm_platform_register_drivers(struct platform_driver *const *drv,
int count);
+void drm_platform_unregister_drivers(struct platform_driver *const *drv,
int count);
/* returns true if currently okay to sleep */ static __inline__ bool drm_can_sleep(void) -- 2.1.4
dri-devel mailing list dri-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/dri-devel
This matches how exynos handles the registration of its component drivers.
Signed-off-by: Eric Anholt eric@anholt.net --- drivers/gpu/drm/msm/adreno/adreno_device.c | 12 +----------- drivers/gpu/drm/msm/dsi/dsi.c | 16 +--------------- drivers/gpu/drm/msm/dsi/dsi.h | 2 -- drivers/gpu/drm/msm/dsi/phy/dsi_phy.c | 12 +----------- drivers/gpu/drm/msm/edp/edp.c | 14 +------------- drivers/gpu/drm/msm/hdmi/hdmi.c | 12 +----------- drivers/gpu/drm/msm/msm_drv.c | 26 ++++++++++++++++++-------- drivers/gpu/drm/msm/msm_drv.h | 16 ++++------------ drivers/gpu/drm/msm/msm_gpu.h | 3 +-- 9 files changed, 28 insertions(+), 85 deletions(-)
diff --git a/drivers/gpu/drm/msm/adreno/adreno_device.c b/drivers/gpu/drm/msm/adreno/adreno_device.c index 1ea2df5..8b0eb95 100644 --- a/drivers/gpu/drm/msm/adreno/adreno_device.c +++ b/drivers/gpu/drm/msm/adreno/adreno_device.c @@ -286,7 +286,7 @@ static const struct of_device_id dt_match[] = { {} };
-static struct platform_driver adreno_driver = { +struct platform_driver adreno_driver = { .probe = adreno_probe, .remove = adreno_remove, .driver = { @@ -294,13 +294,3 @@ static struct platform_driver adreno_driver = { .of_match_table = dt_match, }, }; - -void __init adreno_register(void) -{ - platform_driver_register(&adreno_driver); -} - -void __exit adreno_unregister(void) -{ - platform_driver_unregister(&adreno_driver); -} diff --git a/drivers/gpu/drm/msm/dsi/dsi.c b/drivers/gpu/drm/msm/dsi/dsi.c index 6edcd6f..41cfbd5 100644 --- a/drivers/gpu/drm/msm/dsi/dsi.c +++ b/drivers/gpu/drm/msm/dsi/dsi.c @@ -163,7 +163,7 @@ static const struct of_device_id dt_match[] = { {} };
-static struct platform_driver dsi_driver = { +struct platform_driver msm_dsi_driver = { .probe = dsi_dev_probe, .remove = dsi_dev_remove, .driver = { @@ -172,20 +172,6 @@ static struct platform_driver dsi_driver = { }, };
-void __init msm_dsi_register(void) -{ - DBG(""); - msm_dsi_phy_driver_register(); - platform_driver_register(&dsi_driver); -} - -void __exit msm_dsi_unregister(void) -{ - DBG(""); - msm_dsi_phy_driver_unregister(); - platform_driver_unregister(&dsi_driver); -} - int msm_dsi_modeset_init(struct msm_dsi *msm_dsi, struct drm_device *dev, struct drm_encoder *encoders[MSM_DSI_ENCODER_NUM]) { diff --git a/drivers/gpu/drm/msm/dsi/dsi.h b/drivers/gpu/drm/msm/dsi/dsi.h index 5f5a373..08fff5c 100644 --- a/drivers/gpu/drm/msm/dsi/dsi.h +++ b/drivers/gpu/drm/msm/dsi/dsi.h @@ -164,8 +164,6 @@ int msm_dsi_host_init(struct msm_dsi *msm_dsi);
/* dsi phy */ struct msm_dsi_phy; -void msm_dsi_phy_driver_register(void); -void msm_dsi_phy_driver_unregister(void); int msm_dsi_phy_enable(struct msm_dsi_phy *phy, int src_pll_id, const unsigned long bit_rate, const unsigned long esc_rate); void msm_dsi_phy_disable(struct msm_dsi_phy *phy); diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c b/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c index 401ff58..f918b56 100644 --- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c +++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c @@ -375,7 +375,7 @@ static int dsi_phy_driver_remove(struct platform_device *pdev) return 0; }
-static struct platform_driver dsi_phy_platform_driver = { +struct platform_driver msm_dsi_phy_driver = { .probe = dsi_phy_driver_probe, .remove = dsi_phy_driver_remove, .driver = { @@ -384,16 +384,6 @@ static struct platform_driver dsi_phy_platform_driver = { }, };
-void __init msm_dsi_phy_driver_register(void) -{ - platform_driver_register(&dsi_phy_platform_driver); -} - -void __exit msm_dsi_phy_driver_unregister(void) -{ - platform_driver_unregister(&dsi_phy_platform_driver); -} - int msm_dsi_phy_enable(struct msm_dsi_phy *phy, int src_pll_id, const unsigned long bit_rate, const unsigned long esc_rate) { diff --git a/drivers/gpu/drm/msm/edp/edp.c b/drivers/gpu/drm/msm/edp/edp.c index 0940e84..0bf75b0 100644 --- a/drivers/gpu/drm/msm/edp/edp.c +++ b/drivers/gpu/drm/msm/edp/edp.c @@ -122,7 +122,7 @@ static const struct of_device_id dt_match[] = { {} };
-static struct platform_driver edp_driver = { +struct platform_driver msm_edp_driver = { .probe = edp_dev_probe, .remove = edp_dev_remove, .driver = { @@ -131,18 +131,6 @@ static struct platform_driver edp_driver = { }, };
-void __init msm_edp_register(void) -{ - DBG(""); - platform_driver_register(&edp_driver); -} - -void __exit msm_edp_unregister(void) -{ - DBG(""); - platform_driver_unregister(&edp_driver); -} - /* Second part of initialization, the drm/kms level modeset_init */ int msm_edp_modeset_init(struct msm_edp *edp, struct drm_device *dev, struct drm_encoder *encoder) diff --git a/drivers/gpu/drm/msm/hdmi/hdmi.c b/drivers/gpu/drm/msm/hdmi/hdmi.c index 101b324..b44b3f1 100644 --- a/drivers/gpu/drm/msm/hdmi/hdmi.c +++ b/drivers/gpu/drm/msm/hdmi/hdmi.c @@ -518,7 +518,7 @@ static int hdmi_dev_remove(struct platform_device *pdev) return 0; }
-static struct platform_driver hdmi_driver = { +struct platform_driver msm_hdmi_driver = { .probe = hdmi_dev_probe, .remove = hdmi_dev_remove, .driver = { @@ -526,13 +526,3 @@ static struct platform_driver hdmi_driver = { .of_match_table = dt_match, }, }; - -void __init hdmi_register(void) -{ - platform_driver_register(&hdmi_driver); -} - -void __exit hdmi_unregister(void) -{ - platform_driver_unregister(&hdmi_driver); -} diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c index 0339c5d..a9b0573 100644 --- a/drivers/gpu/drm/msm/msm_drv.c +++ b/drivers/gpu/drm/msm/msm_drv.c @@ -1159,13 +1159,25 @@ static struct platform_driver msm_platform_driver = { .id_table = msm_id, };
+static struct platform_driver *const component_drivers[] = { +#if IS_ENABLED(CONFIG_DRM_MSM_DSI) + &msm_dsi_phy_driver, + &msm_dsi_driver, +#endif + &msm_hdmi_driver, + &adreno_driver, +}; + static int __init msm_drm_register(void) { + int ret; + DBG("init"); - msm_dsi_register(); - msm_edp_register(); - hdmi_register(); - adreno_register(); + ret = drm_platform_register_drivers(component_drivers, + ARRAY_SIZE(component_drivers)); + if (ret) + return ret; + return platform_driver_register(&msm_platform_driver); }
@@ -1173,10 +1185,8 @@ static void __exit msm_drm_unregister(void) { DBG("fini"); platform_driver_unregister(&msm_platform_driver); - hdmi_unregister(); - adreno_unregister(); - msm_edp_unregister(); - msm_dsi_unregister(); + drm_platform_unregister_drivers(component_drivers, + ARRAY_SIZE(component_drivers)); }
module_init(msm_drm_register); diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h index 3be7a56..88e542b 100644 --- a/drivers/gpu/drm/msm/msm_drv.h +++ b/drivers/gpu/drm/msm/msm_drv.h @@ -249,12 +249,10 @@ struct drm_fb_helper *msm_fbdev_init(struct drm_device *dev); struct hdmi; int hdmi_modeset_init(struct hdmi *hdmi, struct drm_device *dev, struct drm_encoder *encoder); -void __init hdmi_register(void); -void __exit hdmi_unregister(void); +extern struct platform_driver msm_hdmi_driver;
struct msm_edp; -void __init msm_edp_register(void); -void __exit msm_edp_unregister(void); +extern struct platform_driver msm_edp_driver; int msm_edp_modeset_init(struct msm_edp *edp, struct drm_device *dev, struct drm_encoder *encoder);
@@ -265,17 +263,11 @@ enum msm_dsi_encoder_id { MSM_DSI_ENCODER_NUM = 2 }; #ifdef CONFIG_DRM_MSM_DSI -void __init msm_dsi_register(void); -void __exit msm_dsi_unregister(void); +extern struct platform_driver msm_dsi_driver; +extern struct platform_driver msm_dsi_phy_driver; int msm_dsi_modeset_init(struct msm_dsi *msm_dsi, struct drm_device *dev, struct drm_encoder *encoders[MSM_DSI_ENCODER_NUM]); #else -static inline void __init msm_dsi_register(void) -{ -} -static inline void __exit msm_dsi_unregister(void) -{ -} static inline int msm_dsi_modeset_init(struct msm_dsi *msm_dsi, struct drm_device *dev, struct drm_encoder *encoders[MSM_DSI_ENCODER_NUM]) diff --git a/drivers/gpu/drm/msm/msm_gpu.h b/drivers/gpu/drm/msm/msm_gpu.h index 2bbe85a..2cd6a68 100644 --- a/drivers/gpu/drm/msm/msm_gpu.h +++ b/drivers/gpu/drm/msm/msm_gpu.h @@ -169,7 +169,6 @@ int msm_gpu_init(struct drm_device *drm, struct platform_device *pdev, void msm_gpu_cleanup(struct msm_gpu *gpu);
struct msm_gpu *adreno_load_gpu(struct drm_device *dev); -void __init adreno_register(void); -void __exit adreno_unregister(void); +extern struct platform_driver adreno_driver;
#endif /* __MSM_GPU_H__ */
This is a really nice way to handle the component setup. The subsystem driver knows that it's got a bunch of component drivers, and for any devices that matched its component drivers, it wants all of those to bind to it as master.
Signed-off-by: Eric Anholt eric@anholt.net --- drivers/gpu/drm/drm_platform_helpers.c | 33 +++++++++++++++++++++++++++++ drivers/gpu/drm/exynos/exynos_drm_drv.c | 37 +++++++-------------------------- include/drm/drmP.h | 5 +++++ 3 files changed, 45 insertions(+), 30 deletions(-)
diff --git a/drivers/gpu/drm/drm_platform_helpers.c b/drivers/gpu/drm/drm_platform_helpers.c index a54c3e3..0819c49 100644 --- a/drivers/gpu/drm/drm_platform_helpers.c +++ b/drivers/gpu/drm/drm_platform_helpers.c @@ -7,6 +7,7 @@ * option) any later version. */
+#include <linux/component.h> #include <drm/drmP.h>
/** @@ -43,3 +44,35 @@ void drm_platform_unregister_drivers(struct platform_driver *const *drv, platform_driver_unregister(drv[count]); } EXPORT_SYMBOL_GPL(drm_platform_unregister_drivers); + +static int compare_dev(struct device *dev, void *data) +{ + return dev == (struct device *)data; +} + +/** + * drm_platform_component_match_add_drivers - For each driver passed + * in, finds each device that matched to it and adds it as a component + * driver to the match list. + */ +void drm_platform_component_match_add_drivers(struct device *dev, + struct component_match **match, + struct platform_driver *const *drivers, + int count) +{ + int i; + + for (i = 0; i < count; i++) { + struct device_driver *drv = &drivers[i]->driver; + struct device *p = NULL, *d; + + while ((d = bus_find_device(&platform_bus_type, p, drv, + (void *)platform_bus_type.match))) { + put_device(p); + component_match_add(dev, match, compare_dev, d); + p = d; + } + put_device(p); + } +} +EXPORT_SYMBOL_GPL(drm_platform_component_match_add_drivers); diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.c b/drivers/gpu/drm/exynos/exynos_drm_drv.c index 83f829b..9151304 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_drv.c +++ b/drivers/gpu/drm/exynos/exynos_drm_drv.c @@ -412,32 +412,6 @@ static struct platform_driver *const exynos_drm_drv_with_simple_dev[] = { }; #define PDEV_COUNT ARRAY_SIZE(exynos_drm_drv_with_simple_dev)
-static int compare_dev(struct device *dev, void *data) -{ - return dev == (struct device *)data; -} - -static struct component_match *exynos_drm_match_add(struct device *dev) -{ - struct component_match *match = NULL; - int i; - - for (i = 0; i < ARRAY_SIZE(exynos_drm_kms_drivers); ++i) { - struct device_driver *drv = &exynos_drm_kms_drivers[i]->driver; - struct device *p = NULL, *d; - - while ((d = bus_find_device(&platform_bus_type, p, drv, - (void *)platform_bus_type.match))) { - put_device(p); - component_match_add(dev, &match, compare_dev, d); - p = d; - } - put_device(p); - } - - return match ?: ERR_PTR(-ENODEV); -} - static int exynos_drm_bind(struct device *dev) { return drm_platform_init(&exynos_drm_driver, to_platform_device(dev)); @@ -455,14 +429,17 @@ static const struct component_master_ops exynos_drm_ops = {
static int exynos_drm_platform_probe(struct platform_device *pdev) { - struct component_match *match; + struct component_match *match = NULL;
pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32); exynos_drm_driver.num_ioctls = ARRAY_SIZE(exynos_ioctls);
- match = exynos_drm_match_add(&pdev->dev); - if (IS_ERR(match)) - return PTR_ERR(match); + drm_platform_component_match_add_drivers(&pdev->dev, &match, + exynos_drm_kms_drivers, + ARRAY_SIZE(exynos_drm_kms_drivers)); + + if (!match) + return -ENODEV;
return component_master_add_with_match(&pdev->dev, &exynos_drm_ops, match); diff --git a/include/drm/drmP.h b/include/drm/drmP.h index a774574..b65d886 100644 --- a/include/drm/drmP.h +++ b/include/drm/drmP.h @@ -88,6 +88,7 @@ struct device_node; struct videomode; struct reservation_object; struct dma_buf_attachment; +struct component_match;
/* * 4 debug categories are defined: @@ -1091,6 +1092,10 @@ int drm_platform_register_drivers(struct platform_driver *const *drv, int count); void drm_platform_unregister_drivers(struct platform_driver *const *drv, int count); +void drm_platform_component_match_add_drivers(struct device *dev, + struct component_match **match, + struct platform_driver **drivers, + int count);
/* returns true if currently okay to sleep */ static __inline__ bool drm_can_sleep(void)
This eliminates the need for the "connectors" and "gpus" nodes in the devicetree, which we were doing nothing connector- or gpu-specific with.
Signed-off-by: Eric Anholt eric@anholt.net --- drivers/gpu/drm/msm/msm_drv.c | 65 +++++++++++++++++-------------------------- include/drm/drmP.h | 2 +- 2 files changed, 27 insertions(+), 40 deletions(-)
diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c index a9b0573..4e1263b 100644 --- a/drivers/gpu/drm/msm/msm_drv.c +++ b/drivers/gpu/drm/msm/msm_drv.c @@ -1039,34 +1039,7 @@ static const struct dev_pm_ops msm_pm_ops = { * Componentized driver support: */
-#ifdef CONFIG_OF -/* NOTE: the CONFIG_OF case duplicates the same code as exynos or imx - * (or probably any other).. so probably some room for some helpers - */ -static int compare_of(struct device *dev, void *data) -{ - return dev->of_node == data; -} - -static int add_components(struct device *dev, struct component_match **matchptr, - const char *name) -{ - struct device_node *np = dev->of_node; - unsigned i; - - for (i = 0; ; i++) { - struct device_node *node; - - node = of_parse_phandle(np, name, i); - if (!node) - break; - - component_match_add(dev, matchptr, compare_of, node); - } - - return 0; -} -#else +#ifndef CONFIG_OF static int compare_dev(struct device *dev, void *data) { return dev == data; @@ -1088,6 +1061,20 @@ static const struct component_master_ops msm_drm_ops = { .unbind = msm_drm_unbind, };
+static struct platform_driver *const noncomponent_drivers[] = { +#if IS_ENABLED(CONFIG_DRM_MSM_DSI) + &msm_dsi_phy_driver, +#endif +}; + +static struct platform_driver *const component_drivers[] = { +#if IS_ENABLED(CONFIG_DRM_MSM_DSI) + &msm_dsi_driver, +#endif + &msm_hdmi_driver, + &adreno_driver, +}; + /* * Platform driver: */ @@ -1096,8 +1083,9 @@ static int msm_pdev_probe(struct platform_device *pdev) { struct component_match *match = NULL; #ifdef CONFIG_OF - add_components(&pdev->dev, &match, "connectors"); - add_components(&pdev->dev, &match, "gpus"); + drm_platform_component_match_add_drivers(&pdev->dev, &match, + component_drivers, + ARRAY_SIZE(component_drivers)); #else /* For non-DT case, it kinda sucks. We don't actually have a way * to know whether or not we are waiting for certain devices (or if @@ -1159,20 +1147,17 @@ static struct platform_driver msm_platform_driver = { .id_table = msm_id, };
-static struct platform_driver *const component_drivers[] = { -#if IS_ENABLED(CONFIG_DRM_MSM_DSI) - &msm_dsi_phy_driver, - &msm_dsi_driver, -#endif - &msm_hdmi_driver, - &adreno_driver, -}; - static int __init msm_drm_register(void) { int ret;
DBG("init"); + + ret = drm_platform_register_drivers(noncomponent_drivers, + ARRAY_SIZE(noncomponent_drivers)); + if (ret) + return ret; + ret = drm_platform_register_drivers(component_drivers, ARRAY_SIZE(component_drivers)); if (ret) @@ -1187,6 +1172,8 @@ static void __exit msm_drm_unregister(void) platform_driver_unregister(&msm_platform_driver); drm_platform_unregister_drivers(component_drivers, ARRAY_SIZE(component_drivers)); + drm_platform_unregister_drivers(noncomponent_drivers, + ARRAY_SIZE(noncomponent_drivers)); }
module_init(msm_drm_register); diff --git a/include/drm/drmP.h b/include/drm/drmP.h index b65d886..0da8599 100644 --- a/include/drm/drmP.h +++ b/include/drm/drmP.h @@ -1094,7 +1094,7 @@ void drm_platform_unregister_drivers(struct platform_driver *const *drv, int count); void drm_platform_component_match_add_drivers(struct device *dev, struct component_match **match, - struct platform_driver **drivers, + struct platform_driver *const *drivers, int count);
/* returns true if currently okay to sleep */
dri-devel@lists.freedesktop.org