|
@@ -481,69 +481,64 @@ static const struct dev_pm_ops exynos_drm_pm_ops = {
|
|
|
/* forward declaration */
|
|
|
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,
|
|
|
* because connector requires pipe number of its crtc during initialization.
|
|
|
*/
|
|
|
-static struct platform_driver *const exynos_drm_kms_drivers[] = {
|
|
|
-#ifdef CONFIG_DRM_EXYNOS_FIMD
|
|
|
- &fimd_driver,
|
|
|
-#endif
|
|
|
-#ifdef CONFIG_DRM_EXYNOS5433_DECON
|
|
|
- &exynos5433_decon_driver,
|
|
|
-#endif
|
|
|
-#ifdef CONFIG_DRM_EXYNOS7_DECON
|
|
|
- &decon_driver,
|
|
|
-#endif
|
|
|
-#ifdef CONFIG_DRM_EXYNOS_MIC
|
|
|
- &mic_driver,
|
|
|
-#endif
|
|
|
-#ifdef CONFIG_DRM_EXYNOS_DP
|
|
|
- &dp_driver,
|
|
|
-#endif
|
|
|
-#ifdef CONFIG_DRM_EXYNOS_DSI
|
|
|
- &dsi_driver,
|
|
|
-#endif
|
|
|
-#ifdef CONFIG_DRM_EXYNOS_MIXER
|
|
|
- &mixer_driver,
|
|
|
-#endif
|
|
|
-#ifdef CONFIG_DRM_EXYNOS_HDMI
|
|
|
- &hdmi_driver,
|
|
|
-#endif
|
|
|
-#ifdef CONFIG_DRM_EXYNOS_VIDI
|
|
|
- &vidi_driver,
|
|
|
-#endif
|
|
|
-};
|
|
|
-
|
|
|
-static struct platform_driver *const exynos_drm_non_kms_drivers[] = {
|
|
|
-#ifdef CONFIG_DRM_EXYNOS_G2D
|
|
|
- &g2d_driver,
|
|
|
-#endif
|
|
|
-#ifdef CONFIG_DRM_EXYNOS_FIMC
|
|
|
- &fimc_driver,
|
|
|
-#endif
|
|
|
-#ifdef CONFIG_DRM_EXYNOS_ROTATOR
|
|
|
- &rotator_driver,
|
|
|
-#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,
|
|
|
+static struct exynos_drm_driver_info exynos_drm_drivers[] = {
|
|
|
+ {
|
|
|
+ DRV_PTR(fimd_driver, CONFIG_DRM_EXYNOS_FIMD),
|
|
|
+ DRM_COMPONENT_DRIVER
|
|
|
+ }, {
|
|
|
+ DRV_PTR(exynos5433_decon_driver, CONFIG_DRM_EXYNOS5433_DECON),
|
|
|
+ DRM_COMPONENT_DRIVER
|
|
|
+ }, {
|
|
|
+ DRV_PTR(decon_driver, CONFIG_DRM_EXYNOS7_DECON),
|
|
|
+ DRM_COMPONENT_DRIVER
|
|
|
+ }, {
|
|
|
+ DRV_PTR(mixer_driver, CONFIG_DRM_EXYNOS_MIXER),
|
|
|
+ DRM_COMPONENT_DRIVER
|
|
|
+ }, {
|
|
|
+ DRV_PTR(mic_driver, CONFIG_DRM_EXYNOS_MIC),
|
|
|
+ DRM_COMPONENT_DRIVER
|
|
|
+ }, {
|
|
|
+ DRV_PTR(dp_driver, CONFIG_DRM_EXYNOS_DP),
|
|
|
+ DRM_COMPONENT_DRIVER
|
|
|
+ }, {
|
|
|
+ DRV_PTR(dsi_driver, CONFIG_DRM_EXYNOS_DSI),
|
|
|
+ DRM_COMPONENT_DRIVER
|
|
|
+ }, {
|
|
|
+ DRV_PTR(hdmi_driver, CONFIG_DRM_EXYNOS_HDMI),
|
|
|
+ DRM_COMPONENT_DRIVER
|
|
|
+ }, {
|
|
|
+ DRV_PTR(vidi_driver, CONFIG_DRM_EXYNOS_VIDI),
|
|
|
+ DRM_COMPONENT_DRIVER | DRM_VIRTUAL_DEVICE
|
|
|
+ }, {
|
|
|
+ DRV_PTR(g2d_driver, CONFIG_DRM_EXYNOS_G2D),
|
|
|
+ }, {
|
|
|
+ DRV_PTR(fimc_driver, CONFIG_DRM_EXYNOS_FIMC),
|
|
|
+ }, {
|
|
|
+ DRV_PTR(rotator_driver, CONFIG_DRM_EXYNOS_ROTATOR),
|
|
|
+ }, {
|
|
|
+ DRV_PTR(gsc_driver, CONFIG_DRM_EXYNOS_GSC),
|
|
|
+ }, {
|
|
|
+ DRV_PTR(ipp_driver, CONFIG_DRM_EXYNOS_IPP),
|
|
|
+ DRM_VIRTUAL_DEVICE
|
|
|
+ }, {
|
|
|
+ &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)
|
|
|
{
|
|
@@ -555,11 +550,15 @@ 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;
|
|
|
+ for (i = 0; i < ARRAY_SIZE(exynos_drm_drivers); ++i) {
|
|
|
+ struct exynos_drm_driver_info *info = &exynos_drm_drivers[i];
|
|
|
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))) {
|
|
|
put_device(p);
|
|
|
component_match_add(dev, &match, compare_dev, d);
|
|
@@ -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)
|
|
|
{
|
|
|
- int i = PDEV_COUNT;
|
|
|
+ int i;
|
|
|
+
|
|
|
+ for (i = ARRAY_SIZE(exynos_drm_drivers) - 1; i >= 0; --i) {
|
|
|
+ struct exynos_drm_driver_info *info = &exynos_drm_drivers[i];
|
|
|
+ struct device *dev;
|
|
|
|
|
|
- while (--i >= 0) {
|
|
|
- platform_device_unregister(exynos_drm_pdevs[i]);
|
|
|
- exynos_drm_pdevs[i] = NULL;
|
|
|
+ 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)
|
|
|
{
|
|
|
+ struct platform_device *pdev;
|
|
|
int i;
|
|
|
|
|
|
- for (i = 0; i < PDEV_COUNT; ++i) {
|
|
|
- struct platform_driver *d = exynos_drm_drv_with_simple_dev[i];
|
|
|
- struct platform_device *pdev =
|
|
|
- platform_device_register_simple(d->driver.name, -1,
|
|
|
- NULL, 0);
|
|
|
+ for (i = 0; i < ARRAY_SIZE(exynos_drm_drivers); ++i) {
|
|
|
+ struct exynos_drm_driver_info *info = &exynos_drm_drivers[i];
|
|
|
|
|
|
- if (!IS_ERR(pdev)) {
|
|
|
- exynos_drm_pdevs[i] = pdev;
|
|
|
+ if (!info->driver || !(info->flags & DRM_VIRTUAL_DEVICE))
|
|
|
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;
|
|
|
+fail:
|
|
|
+ exynos_drm_unregister_devices();
|
|
|
+ return PTR_ERR(pdev);
|
|
|
}
|
|
|
|
|
|
-static void exynos_drm_unregister_drivers(struct platform_driver * const *drv,
|
|
|
- int count)
|
|
|
+static void exynos_drm_unregister_drivers(void)
|
|
|
{
|
|
|
- while (--count >= 0)
|
|
|
- platform_driver_unregister(drv[count]);
|
|
|
-}
|
|
|
+ int i;
|
|
|
|
|
|
-static int exynos_drm_register_drivers(struct platform_driver * const *drv,
|
|
|
- int count)
|
|
|
-{
|
|
|
- int i, ret;
|
|
|
+ for (i = ARRAY_SIZE(exynos_drm_drivers) - 1; i >= 0; --i) {
|
|
|
+ struct exynos_drm_driver_info *info = &exynos_drm_drivers[i];
|
|
|
|
|
|
- for (i = 0; i < count; ++i) {
|
|
|
- ret = platform_driver_register(drv[i]);
|
|
|
- if (!ret)
|
|
|
+ if (!info->driver)
|
|
|
continue;
|
|
|
|
|
|
- while (--i >= 0)
|
|
|
- platform_driver_unregister(drv[i]);
|
|
|
-
|
|
|
- return ret;
|
|
|
+ platform_driver_unregister(info->driver);
|
|
|
}
|
|
|
-
|
|
|
- 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,
|
|
|
- ARRAY_SIZE(exynos_drm_kms_drivers));
|
|
|
-}
|
|
|
+ int i, ret;
|
|
|
|
|
|
-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));
|
|
|
-}
|
|
|
+ for (i = 0; i < ARRAY_SIZE(exynos_drm_drivers); ++i) {
|
|
|
+ struct exynos_drm_driver_info *info = &exynos_drm_drivers[i];
|
|
|
|
|
|
-static inline void exynos_drm_unregister_kms_drivers(void)
|
|
|
-{
|
|
|
- exynos_drm_unregister_drivers(exynos_drm_kms_drivers,
|
|
|
- ARRAY_SIZE(exynos_drm_kms_drivers));
|
|
|
-}
|
|
|
+ if (!info->driver)
|
|
|
+ continue;
|
|
|
|
|
|
-static inline void exynos_drm_unregister_non_kms_drivers(void)
|
|
|
-{
|
|
|
- exynos_drm_unregister_drivers(exynos_drm_non_kms_drivers,
|
|
|
- ARRAY_SIZE(exynos_drm_non_kms_drivers));
|
|
|
+ ret = platform_driver_register(info->driver);
|
|
|
+ if (ret)
|
|
|
+ goto fail;
|
|
|
+ }
|
|
|
+ return 0;
|
|
|
+fail:
|
|
|
+ exynos_drm_unregister_drivers();
|
|
|
+ return ret;
|
|
|
}
|
|
|
|
|
|
static int exynos_drm_init(void)
|
|
@@ -711,19 +700,12 @@ static int exynos_drm_init(void)
|
|
|
if (ret)
|
|
|
return ret;
|
|
|
|
|
|
- ret = exynos_drm_register_kms_drivers();
|
|
|
+ ret = exynos_drm_register_drivers();
|
|
|
if (ret)
|
|
|
goto err_unregister_pdevs;
|
|
|
|
|
|
- ret = exynos_drm_register_non_kms_drivers();
|
|
|
- if (ret)
|
|
|
- goto err_unregister_kms_drivers;
|
|
|
-
|
|
|
return 0;
|
|
|
|
|
|
-err_unregister_kms_drivers:
|
|
|
- exynos_drm_unregister_kms_drivers();
|
|
|
-
|
|
|
err_unregister_pdevs:
|
|
|
exynos_drm_unregister_devices();
|
|
|
|
|
@@ -732,8 +714,7 @@ err_unregister_pdevs:
|
|
|
|
|
|
static void exynos_drm_exit(void)
|
|
|
{
|
|
|
- exynos_drm_unregister_non_kms_drivers();
|
|
|
- exynos_drm_unregister_kms_drivers();
|
|
|
+ exynos_drm_unregister_drivers();
|
|
|
exynos_drm_unregister_devices();
|
|
|
}
|
|
|
|