Commit a5fb26cd authored by Marek Szyprowski's avatar Marek Szyprowski Committed by Inki Dae

drm/exynos: refactor driver and device registration code

This patch refactors driver and device registration by moving all drivers
to the common array. This way additional flags can be added later for
new features. #ifdef-based code has been replaced by IS_ENABLED() macro
usage.
Signed-off-by: default avatarMarek Szyprowski <m.szyprowski@samsung.com>
Signed-off-by: default avatarInki Dae <inki.dae@samsung.com>
parent cbf0acef
...@@ -481,69 +481,64 @@ static const struct dev_pm_ops exynos_drm_pm_ops = { ...@@ -481,69 +481,64 @@ static const struct dev_pm_ops exynos_drm_pm_ops = {
/* forward declaration */ /* forward declaration */
static struct platform_driver exynos_drm_platform_driver; static struct platform_driver exynos_drm_platform_driver;
struct exynos_drm_driver_info {
struct platform_driver *driver;
unsigned int flags;
};
#define DRM_COMPONENT_DRIVER BIT(0) /* supports component framework */
#define DRM_VIRTUAL_DEVICE BIT(1) /* create virtual platform device */
#define DRV_PTR(drv, cond) (IS_ENABLED(cond) ? &drv : NULL)
/* /*
* Connector drivers should not be placed before associated crtc drivers, * Connector drivers should not be placed before associated crtc drivers,
* because connector requires pipe number of its crtc during initialization. * because connector requires pipe number of its crtc during initialization.
*/ */
static struct platform_driver *const exynos_drm_kms_drivers[] = { static struct exynos_drm_driver_info exynos_drm_drivers[] = {
#ifdef CONFIG_DRM_EXYNOS_FIMD {
&fimd_driver, DRV_PTR(fimd_driver, CONFIG_DRM_EXYNOS_FIMD),
#endif DRM_COMPONENT_DRIVER
#ifdef CONFIG_DRM_EXYNOS5433_DECON }, {
&exynos5433_decon_driver, DRV_PTR(exynos5433_decon_driver, CONFIG_DRM_EXYNOS5433_DECON),
#endif DRM_COMPONENT_DRIVER
#ifdef CONFIG_DRM_EXYNOS7_DECON }, {
&decon_driver, DRV_PTR(decon_driver, CONFIG_DRM_EXYNOS7_DECON),
#endif DRM_COMPONENT_DRIVER
#ifdef CONFIG_DRM_EXYNOS_MIC }, {
&mic_driver, DRV_PTR(mixer_driver, CONFIG_DRM_EXYNOS_MIXER),
#endif DRM_COMPONENT_DRIVER
#ifdef CONFIG_DRM_EXYNOS_DP }, {
&dp_driver, DRV_PTR(mic_driver, CONFIG_DRM_EXYNOS_MIC),
#endif DRM_COMPONENT_DRIVER
#ifdef CONFIG_DRM_EXYNOS_DSI }, {
&dsi_driver, DRV_PTR(dp_driver, CONFIG_DRM_EXYNOS_DP),
#endif DRM_COMPONENT_DRIVER
#ifdef CONFIG_DRM_EXYNOS_MIXER }, {
&mixer_driver, DRV_PTR(dsi_driver, CONFIG_DRM_EXYNOS_DSI),
#endif DRM_COMPONENT_DRIVER
#ifdef CONFIG_DRM_EXYNOS_HDMI }, {
&hdmi_driver, DRV_PTR(hdmi_driver, CONFIG_DRM_EXYNOS_HDMI),
#endif DRM_COMPONENT_DRIVER
#ifdef CONFIG_DRM_EXYNOS_VIDI }, {
&vidi_driver, DRV_PTR(vidi_driver, CONFIG_DRM_EXYNOS_VIDI),
#endif DRM_COMPONENT_DRIVER | DRM_VIRTUAL_DEVICE
}; }, {
DRV_PTR(g2d_driver, CONFIG_DRM_EXYNOS_G2D),
static struct platform_driver *const exynos_drm_non_kms_drivers[] = { }, {
#ifdef CONFIG_DRM_EXYNOS_G2D DRV_PTR(fimc_driver, CONFIG_DRM_EXYNOS_FIMC),
&g2d_driver, }, {
#endif DRV_PTR(rotator_driver, CONFIG_DRM_EXYNOS_ROTATOR),
#ifdef CONFIG_DRM_EXYNOS_FIMC }, {
&fimc_driver, DRV_PTR(gsc_driver, CONFIG_DRM_EXYNOS_GSC),
#endif }, {
#ifdef CONFIG_DRM_EXYNOS_ROTATOR DRV_PTR(ipp_driver, CONFIG_DRM_EXYNOS_IPP),
&rotator_driver, DRM_VIRTUAL_DEVICE
#endif }, {
#ifdef CONFIG_DRM_EXYNOS_GSC
&gsc_driver,
#endif
#ifdef CONFIG_DRM_EXYNOS_IPP
&ipp_driver,
#endif
&exynos_drm_platform_driver,
};
static struct platform_driver *const exynos_drm_drv_with_simple_dev[] = {
#ifdef CONFIG_DRM_EXYNOS_VIDI
&vidi_driver,
#endif
#ifdef CONFIG_DRM_EXYNOS_IPP
&ipp_driver,
#endif
&exynos_drm_platform_driver, &exynos_drm_platform_driver,
DRM_VIRTUAL_DEVICE
}
}; };
#define PDEV_COUNT ARRAY_SIZE(exynos_drm_drv_with_simple_dev)
static int compare_dev(struct device *dev, void *data) static int compare_dev(struct device *dev, void *data)
{ {
...@@ -555,11 +550,15 @@ static struct component_match *exynos_drm_match_add(struct device *dev) ...@@ -555,11 +550,15 @@ static struct component_match *exynos_drm_match_add(struct device *dev)
struct component_match *match = NULL; struct component_match *match = NULL;
int i; int i;
for (i = 0; i < ARRAY_SIZE(exynos_drm_kms_drivers); ++i) { for (i = 0; i < ARRAY_SIZE(exynos_drm_drivers); ++i) {
struct device_driver *drv = &exynos_drm_kms_drivers[i]->driver; struct exynos_drm_driver_info *info = &exynos_drm_drivers[i];
struct device *p = NULL, *d; struct device *p = NULL, *d;
while ((d = bus_find_device(&platform_bus_type, p, drv, if (!info->driver || !(info->flags & DRM_COMPONENT_DRIVER))
continue;
while ((d = bus_find_device(&platform_bus_type, p,
&info->driver->driver,
(void *)platform_bus_type.match))) { (void *)platform_bus_type.match))) {
put_device(p); put_device(p);
component_match_add(dev, &match, compare_dev, d); component_match_add(dev, &match, compare_dev, d);
...@@ -616,91 +615,81 @@ static struct platform_driver exynos_drm_platform_driver = { ...@@ -616,91 +615,81 @@ static struct platform_driver exynos_drm_platform_driver = {
}, },
}; };
static struct platform_device *exynos_drm_pdevs[PDEV_COUNT];
static void exynos_drm_unregister_devices(void) static void exynos_drm_unregister_devices(void)
{ {
int i = PDEV_COUNT; int i;
while (--i >= 0) { for (i = ARRAY_SIZE(exynos_drm_drivers) - 1; i >= 0; --i) {
platform_device_unregister(exynos_drm_pdevs[i]); struct exynos_drm_driver_info *info = &exynos_drm_drivers[i];
exynos_drm_pdevs[i] = NULL; struct device *dev;
if (!info->driver || !(info->flags & DRM_VIRTUAL_DEVICE))
continue;
while ((dev = bus_find_device(&platform_bus_type, NULL,
&info->driver->driver,
(void *)platform_bus_type.match))) {
put_device(dev);
platform_device_unregister(to_platform_device(dev));
}
} }
} }
static int exynos_drm_register_devices(void) static int exynos_drm_register_devices(void)
{ {
struct platform_device *pdev;
int i; int i;
for (i = 0; i < PDEV_COUNT; ++i) { for (i = 0; i < ARRAY_SIZE(exynos_drm_drivers); ++i) {
struct platform_driver *d = exynos_drm_drv_with_simple_dev[i]; struct exynos_drm_driver_info *info = &exynos_drm_drivers[i];
struct platform_device *pdev =
platform_device_register_simple(d->driver.name, -1,
NULL, 0);
if (!IS_ERR(pdev)) { if (!info->driver || !(info->flags & DRM_VIRTUAL_DEVICE))
exynos_drm_pdevs[i] = pdev;
continue; continue;
}
while (--i >= 0) {
platform_device_unregister(exynos_drm_pdevs[i]);
exynos_drm_pdevs[i] = NULL;
}
return PTR_ERR(pdev); pdev = platform_device_register_simple(
info->driver->driver.name, -1, NULL, 0);
if (IS_ERR(pdev))
goto fail;
} }
return 0; return 0;
fail:
exynos_drm_unregister_devices();
return PTR_ERR(pdev);
} }
static void exynos_drm_unregister_drivers(struct platform_driver * const *drv, static void exynos_drm_unregister_drivers(void)
int count)
{ {
while (--count >= 0) int i;
platform_driver_unregister(drv[count]);
}
static int exynos_drm_register_drivers(struct platform_driver * const *drv, for (i = ARRAY_SIZE(exynos_drm_drivers) - 1; i >= 0; --i) {
int count) struct exynos_drm_driver_info *info = &exynos_drm_drivers[i];
{
int i, ret;
for (i = 0; i < count; ++i) { if (!info->driver)
ret = platform_driver_register(drv[i]);
if (!ret)
continue; continue;
while (--i >= 0) platform_driver_unregister(info->driver);
platform_driver_unregister(drv[i]);
return ret;
} }
return 0;
} }
static inline int exynos_drm_register_kms_drivers(void) static int exynos_drm_register_drivers(void)
{ {
return exynos_drm_register_drivers(exynos_drm_kms_drivers, int i, ret;
ARRAY_SIZE(exynos_drm_kms_drivers));
}
static inline int exynos_drm_register_non_kms_drivers(void) for (i = 0; i < ARRAY_SIZE(exynos_drm_drivers); ++i) {
{ struct exynos_drm_driver_info *info = &exynos_drm_drivers[i];
return exynos_drm_register_drivers(exynos_drm_non_kms_drivers,
ARRAY_SIZE(exynos_drm_non_kms_drivers));
}
static inline void exynos_drm_unregister_kms_drivers(void) if (!info->driver)
{ continue;
exynos_drm_unregister_drivers(exynos_drm_kms_drivers,
ARRAY_SIZE(exynos_drm_kms_drivers));
}
static inline void exynos_drm_unregister_non_kms_drivers(void) ret = platform_driver_register(info->driver);
{ if (ret)
exynos_drm_unregister_drivers(exynos_drm_non_kms_drivers, goto fail;
ARRAY_SIZE(exynos_drm_non_kms_drivers)); }
return 0;
fail:
exynos_drm_unregister_drivers();
return ret;
} }
static int exynos_drm_init(void) static int exynos_drm_init(void)
...@@ -711,19 +700,12 @@ static int exynos_drm_init(void) ...@@ -711,19 +700,12 @@ static int exynos_drm_init(void)
if (ret) if (ret)
return ret; return ret;
ret = exynos_drm_register_kms_drivers(); ret = exynos_drm_register_drivers();
if (ret) if (ret)
goto err_unregister_pdevs; goto err_unregister_pdevs;
ret = exynos_drm_register_non_kms_drivers();
if (ret)
goto err_unregister_kms_drivers;
return 0; return 0;
err_unregister_kms_drivers:
exynos_drm_unregister_kms_drivers();
err_unregister_pdevs: err_unregister_pdevs:
exynos_drm_unregister_devices(); exynos_drm_unregister_devices();
...@@ -732,8 +714,7 @@ static int exynos_drm_init(void) ...@@ -732,8 +714,7 @@ static int exynos_drm_init(void)
static void exynos_drm_exit(void) static void exynos_drm_exit(void)
{ {
exynos_drm_unregister_non_kms_drivers(); exynos_drm_unregister_drivers();
exynos_drm_unregister_kms_drivers();
exynos_drm_unregister_devices(); exynos_drm_unregister_devices();
} }
......
...@@ -297,7 +297,6 @@ extern struct platform_driver dp_driver; ...@@ -297,7 +297,6 @@ extern struct platform_driver dp_driver;
extern struct platform_driver dsi_driver; extern struct platform_driver dsi_driver;
extern struct platform_driver mixer_driver; extern struct platform_driver mixer_driver;
extern struct platform_driver hdmi_driver; extern struct platform_driver hdmi_driver;
extern struct platform_driver exynos_drm_common_hdmi_driver;
extern struct platform_driver vidi_driver; extern struct platform_driver vidi_driver;
extern struct platform_driver g2d_driver; extern struct platform_driver g2d_driver;
extern struct platform_driver fimc_driver; extern struct platform_driver fimc_driver;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment