Commit 86650408 authored by Andrzej Hajda's avatar Andrzej Hajda Committed by Inki Dae

drm/exynos: fix broken component binding in case of multiple pipelines

In case there are multiple pipelines and deferred probe occurs, only components
of the first pipeline were bound. As a result only one pipeline was available.
The main cause of this issue was dynamic generation of component match table -
every component driver during probe registered itself on helper list, if there
was at least one pipeline present on this list component match table were
created without deferred components.
This patch removes this helper list, instead it creates match table from
existing devices requiring exynos_drm KMS drivers. This way match table do not
depend on probe/deferral order and contains all KMS components.
As a side effect patch makes the code cleaner and significantly smaller.
Signed-off-by: default avatarAndrzej Hajda <a.hajda@samsung.com>
Signed-off-by: default avatarInki Dae <inki.dae@samsung.com>
parent 417133e4
...@@ -789,11 +789,6 @@ static int decon_probe(struct platform_device *pdev) ...@@ -789,11 +789,6 @@ static int decon_probe(struct platform_device *pdev)
if (!ctx) if (!ctx)
return -ENOMEM; return -ENOMEM;
ret = exynos_drm_component_add(dev, EXYNOS_DEVICE_TYPE_CRTC,
EXYNOS_DISPLAY_TYPE_LCD);
if (ret)
return ret;
ctx->dev = dev; ctx->dev = dev;
ctx->suspended = true; ctx->suspended = true;
...@@ -803,10 +798,8 @@ static int decon_probe(struct platform_device *pdev) ...@@ -803,10 +798,8 @@ static int decon_probe(struct platform_device *pdev)
of_node_put(i80_if_timings); of_node_put(i80_if_timings);
ctx->regs = of_iomap(dev->of_node, 0); ctx->regs = of_iomap(dev->of_node, 0);
if (!ctx->regs) { if (!ctx->regs)
ret = -ENOMEM; return -ENOMEM;
goto err_del_component;
}
ctx->pclk = devm_clk_get(dev, "pclk_decon0"); ctx->pclk = devm_clk_get(dev, "pclk_decon0");
if (IS_ERR(ctx->pclk)) { if (IS_ERR(ctx->pclk)) {
...@@ -876,8 +869,6 @@ static int decon_probe(struct platform_device *pdev) ...@@ -876,8 +869,6 @@ static int decon_probe(struct platform_device *pdev)
err_iounmap: err_iounmap:
iounmap(ctx->regs); iounmap(ctx->regs);
err_del_component:
exynos_drm_component_del(dev, EXYNOS_DEVICE_TYPE_CRTC);
return ret; return ret;
} }
...@@ -890,7 +881,6 @@ static int decon_remove(struct platform_device *pdev) ...@@ -890,7 +881,6 @@ static int decon_remove(struct platform_device *pdev)
iounmap(ctx->regs); iounmap(ctx->regs);
component_del(&pdev->dev, &decon_component_ops); component_del(&pdev->dev, &decon_component_ops);
exynos_drm_component_del(&pdev->dev, EXYNOS_DEVICE_TYPE_CRTC);
return 0; return 0;
} }
......
...@@ -1332,7 +1332,6 @@ static int exynos_dp_probe(struct platform_device *pdev) ...@@ -1332,7 +1332,6 @@ static int exynos_dp_probe(struct platform_device *pdev)
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
struct device_node *panel_node, *bridge_node, *endpoint; struct device_node *panel_node, *bridge_node, *endpoint;
struct exynos_dp_device *dp; struct exynos_dp_device *dp;
int ret;
dp = devm_kzalloc(&pdev->dev, sizeof(struct exynos_dp_device), dp = devm_kzalloc(&pdev->dev, sizeof(struct exynos_dp_device),
GFP_KERNEL); GFP_KERNEL);
...@@ -1343,11 +1342,6 @@ static int exynos_dp_probe(struct platform_device *pdev) ...@@ -1343,11 +1342,6 @@ static int exynos_dp_probe(struct platform_device *pdev)
dp->display.ops = &exynos_dp_display_ops; dp->display.ops = &exynos_dp_display_ops;
platform_set_drvdata(pdev, dp); platform_set_drvdata(pdev, dp);
ret = exynos_drm_component_add(&pdev->dev, EXYNOS_DEVICE_TYPE_CONNECTOR,
dp->display.type);
if (ret)
return ret;
panel_node = of_parse_phandle(dev->of_node, "panel", 0); panel_node = of_parse_phandle(dev->of_node, "panel", 0);
if (panel_node) { if (panel_node) {
dp->panel = of_drm_find_panel(panel_node); dp->panel = of_drm_find_panel(panel_node);
...@@ -1368,18 +1362,12 @@ static int exynos_dp_probe(struct platform_device *pdev) ...@@ -1368,18 +1362,12 @@ static int exynos_dp_probe(struct platform_device *pdev)
return -EPROBE_DEFER; return -EPROBE_DEFER;
} }
ret = component_add(&pdev->dev, &exynos_dp_ops); return component_add(&pdev->dev, &exynos_dp_ops);
if (ret)
exynos_drm_component_del(&pdev->dev,
EXYNOS_DEVICE_TYPE_CONNECTOR);
return ret;
} }
static int exynos_dp_remove(struct platform_device *pdev) static int exynos_dp_remove(struct platform_device *pdev)
{ {
component_del(&pdev->dev, &exynos_dp_ops); component_del(&pdev->dev, &exynos_dp_ops);
exynos_drm_component_del(&pdev->dev, EXYNOS_DEVICE_TYPE_CONNECTOR);
return 0; return 0;
} }
......
...@@ -313,33 +313,19 @@ struct exynos_drm_display *exynos_dpi_probe(struct device *dev) ...@@ -313,33 +313,19 @@ struct exynos_drm_display *exynos_dpi_probe(struct device *dev)
ctx->dev = dev; ctx->dev = dev;
ctx->dpms_mode = DRM_MODE_DPMS_OFF; ctx->dpms_mode = DRM_MODE_DPMS_OFF;
ret = exynos_drm_component_add(dev,
EXYNOS_DEVICE_TYPE_CONNECTOR,
ctx->display.type);
if (ret)
return ERR_PTR(ret);
ret = exynos_dpi_parse_dt(ctx); ret = exynos_dpi_parse_dt(ctx);
if (ret < 0) { if (ret < 0) {
devm_kfree(dev, ctx); devm_kfree(dev, ctx);
goto err_del_component; return NULL;
} }
if (ctx->panel_node) { if (ctx->panel_node) {
ctx->panel = of_drm_find_panel(ctx->panel_node); ctx->panel = of_drm_find_panel(ctx->panel_node);
if (!ctx->panel) { if (!ctx->panel)
exynos_drm_component_del(dev,
EXYNOS_DEVICE_TYPE_CONNECTOR);
return ERR_PTR(-EPROBE_DEFER); return ERR_PTR(-EPROBE_DEFER);
}
} }
return &ctx->display; return &ctx->display;
err_del_component:
exynos_drm_component_del(dev, EXYNOS_DEVICE_TYPE_CONNECTOR);
return NULL;
} }
int exynos_dpi_remove(struct exynos_drm_display *display) int exynos_dpi_remove(struct exynos_drm_display *display)
...@@ -351,7 +337,5 @@ int exynos_dpi_remove(struct exynos_drm_display *display) ...@@ -351,7 +337,5 @@ int exynos_dpi_remove(struct exynos_drm_display *display)
if (ctx->panel) if (ctx->panel)
drm_panel_detach(ctx->panel); drm_panel_detach(ctx->panel);
exynos_drm_component_del(ctx->dev, EXYNOS_DEVICE_TYPE_CONNECTOR);
return 0; return 0;
} }
...@@ -38,17 +38,6 @@ ...@@ -38,17 +38,6 @@
#define DRIVER_MAJOR 1 #define DRIVER_MAJOR 1
#define DRIVER_MINOR 0 #define DRIVER_MINOR 0
static DEFINE_MUTEX(drm_component_lock);
static LIST_HEAD(drm_component_list);
struct component_dev {
struct list_head list;
struct device *crtc_dev;
struct device *conn_dev;
enum exynos_drm_output_type out_type;
unsigned int dev_type_flag;
};
static int exynos_drm_load(struct drm_device *dev, unsigned long flags) static int exynos_drm_load(struct drm_device *dev, unsigned long flags)
{ {
struct exynos_drm_private *private; struct exynos_drm_private *private;
...@@ -348,108 +337,70 @@ static const struct dev_pm_ops exynos_drm_pm_ops = { ...@@ -348,108 +337,70 @@ static const struct dev_pm_ops exynos_drm_pm_ops = {
SET_SYSTEM_SLEEP_PM_OPS(exynos_drm_sys_suspend, exynos_drm_sys_resume) SET_SYSTEM_SLEEP_PM_OPS(exynos_drm_sys_suspend, exynos_drm_sys_resume)
}; };
int exynos_drm_component_add(struct device *dev, /* forward declaration */
enum exynos_drm_device_type dev_type, static struct platform_driver exynos_drm_platform_driver;
enum exynos_drm_output_type out_type)
{
struct component_dev *cdev;
if (dev_type != EXYNOS_DEVICE_TYPE_CRTC &&
dev_type != EXYNOS_DEVICE_TYPE_CONNECTOR) {
DRM_ERROR("invalid device type.\n");
return -EINVAL;
}
mutex_lock(&drm_component_lock);
/* /*
* Make sure to check if there is a component which has two device * Connector drivers should not be placed before associated crtc drivers,
* objects, for connector and for encoder/connector. * because connector requires pipe number of its crtc during initialization.
* It should make sure that crtc and encoder/connector drivers are */
* ready before exynos drm core binds them. static struct platform_driver *const exynos_drm_kms_drivers[] = {
*/ #ifdef CONFIG_DRM_EXYNOS_VIDI
list_for_each_entry(cdev, &drm_component_list, list) { &vidi_driver,
if (cdev->out_type == out_type) { #endif
/* #ifdef CONFIG_DRM_EXYNOS_FIMD
* If crtc and encoder/connector device objects are &fimd_driver,
* added already just return. #endif
*/ #ifdef CONFIG_DRM_EXYNOS5433_DECON
if (cdev->dev_type_flag == (EXYNOS_DEVICE_TYPE_CRTC | &exynos5433_decon_driver,
EXYNOS_DEVICE_TYPE_CONNECTOR)) { #endif
mutex_unlock(&drm_component_lock); #ifdef CONFIG_DRM_EXYNOS7_DECON
return 0; &decon_driver,
} #endif
#ifdef CONFIG_DRM_EXYNOS_DP
if (dev_type == EXYNOS_DEVICE_TYPE_CRTC) { &dp_driver,
cdev->crtc_dev = dev; #endif
cdev->dev_type_flag |= dev_type; #ifdef CONFIG_DRM_EXYNOS_DSI
} &dsi_driver,
#endif
if (dev_type == EXYNOS_DEVICE_TYPE_CONNECTOR) { #ifdef CONFIG_DRM_EXYNOS_HDMI
cdev->conn_dev = dev; &mixer_driver,
cdev->dev_type_flag |= dev_type; &hdmi_driver,
} #endif
};
mutex_unlock(&drm_component_lock);
return 0;
}
}
mutex_unlock(&drm_component_lock);
cdev = kzalloc(sizeof(*cdev), GFP_KERNEL);
if (!cdev)
return -ENOMEM;
if (dev_type == EXYNOS_DEVICE_TYPE_CRTC)
cdev->crtc_dev = dev;
if (dev_type == EXYNOS_DEVICE_TYPE_CONNECTOR)
cdev->conn_dev = dev;
cdev->out_type = out_type;
cdev->dev_type_flag = dev_type;
mutex_lock(&drm_component_lock);
list_add_tail(&cdev->list, &drm_component_list);
mutex_unlock(&drm_component_lock);
return 0;
}
void exynos_drm_component_del(struct device *dev,
enum exynos_drm_device_type dev_type)
{
struct component_dev *cdev, *next;
mutex_lock(&drm_component_lock);
list_for_each_entry_safe(cdev, next, &drm_component_list, list) {
if (dev_type == EXYNOS_DEVICE_TYPE_CRTC) {
if (cdev->crtc_dev == dev) {
cdev->crtc_dev = NULL;
cdev->dev_type_flag &= ~dev_type;
}
}
if (dev_type == EXYNOS_DEVICE_TYPE_CONNECTOR) {
if (cdev->conn_dev == dev) {
cdev->conn_dev = NULL;
cdev->dev_type_flag &= ~dev_type;
}
}
/* static struct platform_driver *const exynos_drm_non_kms_drivers[] = {
* Release cdev object only in case that both of crtc and #ifdef CONFIG_DRM_EXYNOS_MIC
* encoder/connector device objects are NULL. &mic_driver,
*/ #endif
if (!cdev->crtc_dev && !cdev->conn_dev) { #ifdef CONFIG_DRM_EXYNOS_G2D
list_del(&cdev->list); &g2d_driver,
kfree(cdev); #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,
};
mutex_unlock(&drm_component_lock); 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,
};
#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)
{ {
...@@ -459,55 +410,22 @@ static int compare_dev(struct device *dev, void *data) ...@@ -459,55 +410,22 @@ static int compare_dev(struct device *dev, void *data)
static struct component_match *exynos_drm_match_add(struct device *dev) static struct component_match *exynos_drm_match_add(struct device *dev)
{ {
struct component_match *match = NULL; struct component_match *match = NULL;
struct component_dev *cdev; int i;
unsigned int attach_cnt = 0;
mutex_lock(&drm_component_lock);
/* Do not retry to probe if there is no any kms driver regitered. */
if (list_empty(&drm_component_list)) {
mutex_unlock(&drm_component_lock);
return ERR_PTR(-ENODEV);
}
list_for_each_entry(cdev, &drm_component_list, list) {
/*
* Add components to master only in case that crtc and
* encoder/connector device objects exist.
*/
if (!cdev->crtc_dev || !cdev->conn_dev)
continue;
attach_cnt++;
mutex_unlock(&drm_component_lock); 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,
* fimd and dpi modules have same device object so add (void *)platform_bus_type.match))) {
* only crtc device object in this case. put_device(p);
*/ component_match_add(dev, &match, compare_dev, d);
if (cdev->crtc_dev == cdev->conn_dev) { p = d;
component_match_add(dev, &match, compare_dev,
cdev->crtc_dev);
goto out_lock;
} }
put_device(p);
/*
* Do not chage below call order.
* crtc device first should be added to master because
* connector/encoder need pipe number of crtc when they
* are created.
*/
component_match_add(dev, &match, compare_dev, cdev->crtc_dev);
component_match_add(dev, &match, compare_dev, cdev->conn_dev);
out_lock:
mutex_lock(&drm_component_lock);
} }
mutex_unlock(&drm_component_lock); return match ?: ERR_PTR(-ENODEV);
return attach_cnt ? match : ERR_PTR(-EPROBE_DEFER);
} }
static int exynos_drm_bind(struct device *dev) static int exynos_drm_bind(struct device *dev)
...@@ -555,60 +473,6 @@ static struct platform_driver exynos_drm_platform_driver = { ...@@ -555,60 +473,6 @@ static struct platform_driver exynos_drm_platform_driver = {
}, },
}; };
static struct platform_driver *const exynos_drm_kms_drivers[] = {
#ifdef CONFIG_DRM_EXYNOS_VIDI
&vidi_driver,
#endif
#ifdef CONFIG_DRM_EXYNOS_FIMD
&fimd_driver,
#endif
#ifdef CONFIG_DRM_EXYNOS7_DECON
&decon_driver,
#endif
#ifdef CONFIG_DRM_EXYNOS_DP
&dp_driver,
#endif
#ifdef CONFIG_DRM_EXYNOS_DSI
&dsi_driver,
#endif
#ifdef CONFIG_DRM_EXYNOS_HDMI
&mixer_driver,
&hdmi_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,
};
#define PDEV_COUNT ARRAY_SIZE(exynos_drm_drv_with_simple_dev)
static struct platform_device *exynos_drm_pdevs[PDEV_COUNT]; static struct platform_device *exynos_drm_pdevs[PDEV_COUNT];
static void exynos_drm_unregister_devices(void) static void exynos_drm_unregister_devices(void)
......
...@@ -25,13 +25,6 @@ ...@@ -25,13 +25,6 @@
#define to_exynos_crtc(x) container_of(x, struct exynos_drm_crtc, base) #define to_exynos_crtc(x) container_of(x, struct exynos_drm_crtc, base)
#define to_exynos_plane(x) container_of(x, struct exynos_drm_plane, base) #define to_exynos_plane(x) container_of(x, struct exynos_drm_plane, base)
/* This enumerates device type. */
enum exynos_drm_device_type {
EXYNOS_DEVICE_TYPE_NONE,
EXYNOS_DEVICE_TYPE_CRTC,
EXYNOS_DEVICE_TYPE_CONNECTOR,
};
/* this enumerates display type. */ /* this enumerates display type. */
enum exynos_drm_output_type { enum exynos_drm_output_type {
EXYNOS_DISPLAY_TYPE_NONE, EXYNOS_DISPLAY_TYPE_NONE,
...@@ -311,13 +304,6 @@ static inline int exynos_dpi_remove(struct exynos_drm_display *display) ...@@ -311,13 +304,6 @@ static inline int exynos_dpi_remove(struct exynos_drm_display *display)
int exynos_drm_create_enc_conn(struct drm_device *dev, int exynos_drm_create_enc_conn(struct drm_device *dev,
struct exynos_drm_display *display); struct exynos_drm_display *display);
int exynos_drm_component_add(struct device *dev,
enum exynos_drm_device_type dev_type,
enum exynos_drm_output_type out_type);
void exynos_drm_component_del(struct device *dev,
enum exynos_drm_device_type dev_type);
extern struct platform_driver fimd_driver; extern struct platform_driver fimd_driver;
extern struct platform_driver decon_driver; extern struct platform_driver decon_driver;
extern struct platform_driver dp_driver; extern struct platform_driver dp_driver;
......
...@@ -1686,11 +1686,6 @@ static int exynos_dsi_probe(struct platform_device *pdev) ...@@ -1686,11 +1686,6 @@ static int exynos_dsi_probe(struct platform_device *pdev)
dsi->display.type = EXYNOS_DISPLAY_TYPE_LCD; dsi->display.type = EXYNOS_DISPLAY_TYPE_LCD;
dsi->display.ops = &exynos_dsi_display_ops; dsi->display.ops = &exynos_dsi_display_ops;
ret = exynos_drm_component_add(dev, EXYNOS_DEVICE_TYPE_CONNECTOR,
dsi->display.type);
if (ret)
return ret;
/* To be checked as invalid one */ /* To be checked as invalid one */
dsi->te_gpio = -ENOENT; dsi->te_gpio = -ENOENT;
...@@ -1706,7 +1701,7 @@ static int exynos_dsi_probe(struct platform_device *pdev) ...@@ -1706,7 +1701,7 @@ static int exynos_dsi_probe(struct platform_device *pdev)
ret = exynos_dsi_parse_dt(dsi); ret = exynos_dsi_parse_dt(dsi);
if (ret) if (ret)
goto err_del_component; return ret;
dsi->supplies[0].supply = "vddcore"; dsi->supplies[0].supply = "vddcore";
dsi->supplies[1].supply = "vddio"; dsi->supplies[1].supply = "vddio";
...@@ -1720,37 +1715,32 @@ static int exynos_dsi_probe(struct platform_device *pdev) ...@@ -1720,37 +1715,32 @@ static int exynos_dsi_probe(struct platform_device *pdev)
dsi->pll_clk = devm_clk_get(dev, "pll_clk"); dsi->pll_clk = devm_clk_get(dev, "pll_clk");
if (IS_ERR(dsi->pll_clk)) { if (IS_ERR(dsi->pll_clk)) {
dev_info(dev, "failed to get dsi pll input clock\n"); dev_info(dev, "failed to get dsi pll input clock\n");
ret = PTR_ERR(dsi->pll_clk); return PTR_ERR(dsi->pll_clk);
goto err_del_component;
} }
dsi->bus_clk = devm_clk_get(dev, "bus_clk"); dsi->bus_clk = devm_clk_get(dev, "bus_clk");
if (IS_ERR(dsi->bus_clk)) { if (IS_ERR(dsi->bus_clk)) {
dev_info(dev, "failed to get dsi bus clock\n"); dev_info(dev, "failed to get dsi bus clock\n");
ret = PTR_ERR(dsi->bus_clk); return PTR_ERR(dsi->bus_clk);
goto err_del_component;
} }
res = platform_get_resource(pdev, IORESOURCE_MEM, 0); res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
dsi->reg_base = devm_ioremap_resource(dev, res); dsi->reg_base = devm_ioremap_resource(dev, res);
if (IS_ERR(dsi->reg_base)) { if (IS_ERR(dsi->reg_base)) {
dev_err(dev, "failed to remap io region\n"); dev_err(dev, "failed to remap io region\n");
ret = PTR_ERR(dsi->reg_base); return PTR_ERR(dsi->reg_base);
goto err_del_component;
} }
dsi->phy = devm_phy_get(dev, "dsim"); dsi->phy = devm_phy_get(dev, "dsim");
if (IS_ERR(dsi->phy)) { if (IS_ERR(dsi->phy)) {
dev_info(dev, "failed to get dsim phy\n"); dev_info(dev, "failed to get dsim phy\n");
ret = PTR_ERR(dsi->phy); return PTR_ERR(dsi->phy);
goto err_del_component;
} }
dsi->irq = platform_get_irq(pdev, 0); dsi->irq = platform_get_irq(pdev, 0);
if (dsi->irq < 0) { if (dsi->irq < 0) {
dev_err(dev, "failed to request dsi irq resource\n"); dev_err(dev, "failed to request dsi irq resource\n");
ret = dsi->irq; return dsi->irq;
goto err_del_component;
} }
irq_set_status_flags(dsi->irq, IRQ_NOAUTOEN); irq_set_status_flags(dsi->irq, IRQ_NOAUTOEN);
...@@ -1759,26 +1749,17 @@ static int exynos_dsi_probe(struct platform_device *pdev) ...@@ -1759,26 +1749,17 @@ static int exynos_dsi_probe(struct platform_device *pdev)
dev_name(dev), dsi); dev_name(dev), dsi);
if (ret) { if (ret) {
dev_err(dev, "failed to request dsi irq\n"); dev_err(dev, "failed to request dsi irq\n");
goto err_del_component; return ret;
} }
platform_set_drvdata(pdev, &dsi->display); platform_set_drvdata(pdev, &dsi->display);
ret = component_add(dev, &exynos_dsi_component_ops); return component_add(dev, &exynos_dsi_component_ops);
if (ret)
goto err_del_component;
return ret;
err_del_component:
exynos_drm_component_del(dev, EXYNOS_DEVICE_TYPE_CONNECTOR);
return ret;
} }
static int exynos_dsi_remove(struct platform_device *pdev) static int exynos_dsi_remove(struct platform_device *pdev)
{ {
component_del(&pdev->dev, &exynos_dsi_component_ops); component_del(&pdev->dev, &exynos_dsi_component_ops);
exynos_drm_component_del(&pdev->dev, EXYNOS_DEVICE_TYPE_CONNECTOR);
return 0; return 0;
} }
......
...@@ -1048,11 +1048,6 @@ static int fimd_probe(struct platform_device *pdev) ...@@ -1048,11 +1048,6 @@ static int fimd_probe(struct platform_device *pdev)
if (!ctx) if (!ctx)
return -ENOMEM; return -ENOMEM;
ret = exynos_drm_component_add(dev, EXYNOS_DEVICE_TYPE_CRTC,
EXYNOS_DISPLAY_TYPE_LCD);
if (ret)
return ret;
ctx->dev = dev; ctx->dev = dev;
ctx->suspended = true; ctx->suspended = true;
ctx->driver_data = drm_fimd_get_driver_data(pdev); ctx->driver_data = drm_fimd_get_driver_data(pdev);
...@@ -1103,38 +1098,33 @@ static int fimd_probe(struct platform_device *pdev) ...@@ -1103,38 +1098,33 @@ static int fimd_probe(struct platform_device *pdev)
ctx->bus_clk = devm_clk_get(dev, "fimd"); ctx->bus_clk = devm_clk_get(dev, "fimd");
if (IS_ERR(ctx->bus_clk)) { if (IS_ERR(ctx->bus_clk)) {
dev_err(dev, "failed to get bus clock\n"); dev_err(dev, "failed to get bus clock\n");
ret = PTR_ERR(ctx->bus_clk); return PTR_ERR(ctx->bus_clk);
goto err_del_component;
} }
ctx->lcd_clk = devm_clk_get(dev, "sclk_fimd"); ctx->lcd_clk = devm_clk_get(dev, "sclk_fimd");
if (IS_ERR(ctx->lcd_clk)) { if (IS_ERR(ctx->lcd_clk)) {
dev_err(dev, "failed to get lcd clock\n"); dev_err(dev, "failed to get lcd clock\n");
ret = PTR_ERR(ctx->lcd_clk); return PTR_ERR(ctx->lcd_clk);
goto err_del_component;
} }
res = platform_get_resource(pdev, IORESOURCE_MEM, 0); res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
ctx->regs = devm_ioremap_resource(dev, res); ctx->regs = devm_ioremap_resource(dev, res);
if (IS_ERR(ctx->regs)) { if (IS_ERR(ctx->regs))
ret = PTR_ERR(ctx->regs); return PTR_ERR(ctx->regs);
goto err_del_component;
}
res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, res = platform_get_resource_byname(pdev, IORESOURCE_IRQ,
ctx->i80_if ? "lcd_sys" : "vsync"); ctx->i80_if ? "lcd_sys" : "vsync");
if (!res) { if (!res) {
dev_err(dev, "irq request failed.\n"); dev_err(dev, "irq request failed.\n");
ret = -ENXIO; return -ENXIO;
goto err_del_component;
} }
ret = devm_request_irq(dev, res->start, fimd_irq_handler, ret = devm_request_irq(dev, res->start, fimd_irq_handler,
0, "drm_fimd", ctx); 0, "drm_fimd", ctx);
if (ret) { if (ret) {
dev_err(dev, "irq request failed.\n"); dev_err(dev, "irq request failed.\n");
goto err_del_component; return ret;
} }
init_waitqueue_head(&ctx->wait_vsync_queue); init_waitqueue_head(&ctx->wait_vsync_queue);
...@@ -1144,8 +1134,7 @@ static int fimd_probe(struct platform_device *pdev) ...@@ -1144,8 +1134,7 @@ static int fimd_probe(struct platform_device *pdev)
ctx->display = exynos_dpi_probe(dev); ctx->display = exynos_dpi_probe(dev);
if (IS_ERR(ctx->display)) { if (IS_ERR(ctx->display)) {
ret = PTR_ERR(ctx->display); return PTR_ERR(ctx->display);
goto err_del_component;
} }
pm_runtime_enable(dev); pm_runtime_enable(dev);
...@@ -1159,8 +1148,6 @@ static int fimd_probe(struct platform_device *pdev) ...@@ -1159,8 +1148,6 @@ static int fimd_probe(struct platform_device *pdev)
err_disable_pm_runtime: err_disable_pm_runtime:
pm_runtime_disable(dev); pm_runtime_disable(dev);
err_del_component:
exynos_drm_component_del(dev, EXYNOS_DEVICE_TYPE_CRTC);
return ret; return ret;
} }
...@@ -1169,7 +1156,6 @@ static int fimd_remove(struct platform_device *pdev) ...@@ -1169,7 +1156,6 @@ static int fimd_remove(struct platform_device *pdev)
pm_runtime_disable(&pdev->dev); pm_runtime_disable(&pdev->dev);
component_del(&pdev->dev, &fimd_component_ops); component_del(&pdev->dev, &fimd_component_ops);
exynos_drm_component_del(&pdev->dev, EXYNOS_DEVICE_TYPE_CRTC);
return 0; return 0;
} }
......
...@@ -505,16 +505,6 @@ static int vidi_probe(struct platform_device *pdev) ...@@ -505,16 +505,6 @@ static int vidi_probe(struct platform_device *pdev)
ctx->default_win = 0; ctx->default_win = 0;
ctx->pdev = pdev; ctx->pdev = pdev;
ret = exynos_drm_component_add(&pdev->dev, EXYNOS_DEVICE_TYPE_CRTC,
EXYNOS_DISPLAY_TYPE_VIDI);
if (ret)
return ret;
ret = exynos_drm_component_add(&pdev->dev, EXYNOS_DEVICE_TYPE_CONNECTOR,
ctx->display.type);
if (ret)
goto err_del_crtc_component;
INIT_WORK(&ctx->work, vidi_fake_vblank_handler); INIT_WORK(&ctx->work, vidi_fake_vblank_handler);
mutex_init(&ctx->lock); mutex_init(&ctx->lock);
...@@ -524,7 +514,7 @@ static int vidi_probe(struct platform_device *pdev) ...@@ -524,7 +514,7 @@ static int vidi_probe(struct platform_device *pdev)
ret = device_create_file(&pdev->dev, &dev_attr_connection); ret = device_create_file(&pdev->dev, &dev_attr_connection);
if (ret < 0) { if (ret < 0) {
DRM_ERROR("failed to create connection sysfs.\n"); DRM_ERROR("failed to create connection sysfs.\n");
goto err_del_conn_component; return ret;
} }
ret = component_add(&pdev->dev, &vidi_component_ops); ret = component_add(&pdev->dev, &vidi_component_ops);
...@@ -535,10 +525,6 @@ static int vidi_probe(struct platform_device *pdev) ...@@ -535,10 +525,6 @@ static int vidi_probe(struct platform_device *pdev)
err_remove_file: err_remove_file:
device_remove_file(&pdev->dev, &dev_attr_connection); device_remove_file(&pdev->dev, &dev_attr_connection);
err_del_conn_component:
exynos_drm_component_del(&pdev->dev, EXYNOS_DEVICE_TYPE_CONNECTOR);
err_del_crtc_component:
exynos_drm_component_del(&pdev->dev, EXYNOS_DEVICE_TYPE_CRTC);
return ret; return ret;
} }
...@@ -555,8 +541,6 @@ static int vidi_remove(struct platform_device *pdev) ...@@ -555,8 +541,6 @@ static int vidi_remove(struct platform_device *pdev)
} }
component_del(&pdev->dev, &vidi_component_ops); component_del(&pdev->dev, &vidi_component_ops);
exynos_drm_component_del(&pdev->dev, EXYNOS_DEVICE_TYPE_CONNECTOR);
exynos_drm_component_del(&pdev->dev, EXYNOS_DEVICE_TYPE_CRTC);
return 0; return 0;
} }
......
...@@ -2360,20 +2360,13 @@ static int hdmi_probe(struct platform_device *pdev) ...@@ -2360,20 +2360,13 @@ static int hdmi_probe(struct platform_device *pdev)
hdata->display.type = EXYNOS_DISPLAY_TYPE_HDMI; hdata->display.type = EXYNOS_DISPLAY_TYPE_HDMI;
hdata->display.ops = &hdmi_display_ops; hdata->display.ops = &hdmi_display_ops;
ret = exynos_drm_component_add(&pdev->dev, EXYNOS_DEVICE_TYPE_CONNECTOR,
hdata->display.type);
if (ret)
return ret;
mutex_init(&hdata->hdmi_mutex); mutex_init(&hdata->hdmi_mutex);
platform_set_drvdata(pdev, hdata); platform_set_drvdata(pdev, hdata);
match = of_match_node(hdmi_match_types, dev->of_node); match = of_match_node(hdmi_match_types, dev->of_node);
if (!match) { if (!match)
ret = -ENODEV; return -ENODEV;
goto err_del_component;
}
drv_data = (struct hdmi_driver_data *)match->data; drv_data = (struct hdmi_driver_data *)match->data;
hdata->type = drv_data->type; hdata->type = drv_data->type;
...@@ -2393,13 +2386,13 @@ static int hdmi_probe(struct platform_device *pdev) ...@@ -2393,13 +2386,13 @@ static int hdmi_probe(struct platform_device *pdev)
hdata->regs = devm_ioremap_resource(dev, res); hdata->regs = devm_ioremap_resource(dev, res);
if (IS_ERR(hdata->regs)) { if (IS_ERR(hdata->regs)) {
ret = PTR_ERR(hdata->regs); ret = PTR_ERR(hdata->regs);
goto err_del_component; return ret;
} }
ret = devm_gpio_request(dev, hdata->hpd_gpio, "HPD"); ret = devm_gpio_request(dev, hdata->hpd_gpio, "HPD");
if (ret) { if (ret) {
DRM_ERROR("failed to request HPD gpio\n"); DRM_ERROR("failed to request HPD gpio\n");
goto err_del_component; return ret;
} }
ddc_node = hdmi_legacy_ddc_dt_binding(dev); ddc_node = hdmi_legacy_ddc_dt_binding(dev);
...@@ -2410,8 +2403,7 @@ static int hdmi_probe(struct platform_device *pdev) ...@@ -2410,8 +2403,7 @@ static int hdmi_probe(struct platform_device *pdev)
ddc_node = of_parse_phandle(dev->of_node, "ddc", 0); ddc_node = of_parse_phandle(dev->of_node, "ddc", 0);
if (!ddc_node) { if (!ddc_node) {
DRM_ERROR("Failed to find ddc node in device tree\n"); DRM_ERROR("Failed to find ddc node in device tree\n");
ret = -ENODEV; return -ENODEV;
goto err_del_component;
} }
out_get_ddc_adpt: out_get_ddc_adpt:
...@@ -2495,9 +2487,6 @@ static int hdmi_probe(struct platform_device *pdev) ...@@ -2495,9 +2487,6 @@ static int hdmi_probe(struct platform_device *pdev)
err_ddc: err_ddc:
put_device(&hdata->ddc_adpt->dev); put_device(&hdata->ddc_adpt->dev);
err_del_component:
exynos_drm_component_del(&pdev->dev, EXYNOS_DEVICE_TYPE_CONNECTOR);
return ret; return ret;
} }
...@@ -2517,7 +2506,6 @@ static int hdmi_remove(struct platform_device *pdev) ...@@ -2517,7 +2506,6 @@ static int hdmi_remove(struct platform_device *pdev)
pm_runtime_disable(&pdev->dev); pm_runtime_disable(&pdev->dev);
component_del(&pdev->dev, &hdmi_component_ops); component_del(&pdev->dev, &hdmi_component_ops);
exynos_drm_component_del(&pdev->dev, EXYNOS_DEVICE_TYPE_CONNECTOR);
return 0; return 0;
} }
......
...@@ -1287,18 +1287,9 @@ static int mixer_probe(struct platform_device *pdev) ...@@ -1287,18 +1287,9 @@ static int mixer_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, ctx); platform_set_drvdata(pdev, ctx);
ret = exynos_drm_component_add(&pdev->dev, EXYNOS_DEVICE_TYPE_CRTC,
EXYNOS_DISPLAY_TYPE_HDMI);
if (ret)
return ret;
ret = component_add(&pdev->dev, &mixer_component_ops); ret = component_add(&pdev->dev, &mixer_component_ops);
if (ret) { if (!ret)
exynos_drm_component_del(&pdev->dev, EXYNOS_DEVICE_TYPE_CRTC); pm_runtime_enable(dev);
return ret;
}
pm_runtime_enable(dev);
return ret; return ret;
} }
...@@ -1308,7 +1299,6 @@ static int mixer_remove(struct platform_device *pdev) ...@@ -1308,7 +1299,6 @@ static int mixer_remove(struct platform_device *pdev)
pm_runtime_disable(&pdev->dev); pm_runtime_disable(&pdev->dev);
component_del(&pdev->dev, &mixer_component_ops); component_del(&pdev->dev, &mixer_component_ops);
exynos_drm_component_del(&pdev->dev, EXYNOS_DEVICE_TYPE_CRTC);
return 0; return 0;
} }
......
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