From d8c96083cf5e4a910c20836414e8a06ebcf07317 Mon Sep 17 00:00:00 2001 From: Russell King Date: Tue, 22 Apr 2014 11:10:15 +0100 Subject: drm/armada: permit CRTCs to be registered as separate devices Signed-off-by: Russell King --- drivers/gpu/drm/armada/armada_crtc.c | 113 ++++++++++++++++++++++++++++++++--- drivers/gpu/drm/armada/armada_crtc.h | 6 +- drivers/gpu/drm/armada/armada_drv.c | 17 +++++- 3 files changed, 122 insertions(+), 14 deletions(-) (limited to 'drivers/gpu/drm/armada') diff --git a/drivers/gpu/drm/armada/armada_crtc.c b/drivers/gpu/drm/armada/armada_crtc.c index afa497489000..0642b5cfa563 100644 --- a/drivers/gpu/drm/armada/armada_crtc.c +++ b/drivers/gpu/drm/armada/armada_crtc.c @@ -7,6 +7,9 @@ * published by the Free Software Foundation. */ #include +#include +#include +#include #include #include #include "armada_crtc.h" @@ -1046,19 +1049,19 @@ static int armada_drm_crtc_create_properties(struct drm_device *dev) return 0; } -int armada_drm_crtc_create(struct drm_device *dev, struct resource *res, - int irq, const struct armada_variant *variant) +int armada_drm_crtc_create(struct drm_device *drm, struct device *dev, + struct resource *res, int irq, const struct armada_variant *variant) { - struct armada_private *priv = dev->dev_private; + struct armada_private *priv = drm->dev_private; struct armada_crtc *dcrtc; void __iomem *base; int ret; - ret = armada_drm_crtc_create_properties(dev); + ret = armada_drm_crtc_create_properties(drm); if (ret) return ret; - base = devm_request_and_ioremap(dev->dev, res); + base = devm_request_and_ioremap(dev, res); if (!base) { DRM_ERROR("failed to ioremap register\n"); return -ENOMEM; @@ -1070,9 +1073,12 @@ int armada_drm_crtc_create(struct drm_device *dev, struct resource *res, return -ENOMEM; } + if (dev != drm->dev) + dev_set_drvdata(dev, dcrtc); + dcrtc->variant = variant; dcrtc->base = base; - dcrtc->num = dev->mode_config.num_crtc; + dcrtc->num = drm->mode_config.num_crtc; dcrtc->clk = ERR_PTR(-EINVAL); dcrtc->csc_yuv_mode = CSC_AUTO; dcrtc->csc_rgb_mode = CSC_AUTO; @@ -1105,7 +1111,7 @@ int armada_drm_crtc_create(struct drm_device *dev, struct resource *res, } if (dcrtc->variant->init) { - ret = dcrtc->variant->init(dcrtc, dev->dev); + ret = dcrtc->variant->init(dcrtc, dev); if (ret) { kfree(dcrtc); return ret; @@ -1117,7 +1123,7 @@ int armada_drm_crtc_create(struct drm_device *dev, struct resource *res, priv->dcrtc[dcrtc->num] = dcrtc; - drm_crtc_init(dev, &dcrtc->crtc, &armada_crtc_funcs); + drm_crtc_init(drm, &dcrtc->crtc, &armada_crtc_funcs); drm_crtc_helper_add(&dcrtc->crtc, &armada_crtc_helper_funcs); drm_object_attach_property(&dcrtc->crtc.base, priv->csc_yuv_prop, @@ -1125,5 +1131,94 @@ int armada_drm_crtc_create(struct drm_device *dev, struct resource *res, drm_object_attach_property(&dcrtc->crtc.base, priv->csc_rgb_prop, dcrtc->csc_rgb_mode); - return armada_overlay_plane_create(dev, 1 << dcrtc->num); + return armada_overlay_plane_create(drm, 1 << dcrtc->num); +} + +static int +armada_lcd_bind(struct device *dev, struct device *master, void *data) +{ + struct platform_device *pdev = to_platform_device(dev); + struct drm_device *drm = data; + struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + int irq = platform_get_irq(pdev, 0); + const struct armada_variant *variant; + + if (irq < 0) + return irq; + + if (!dev->of_node) { + const struct platform_device_id *id; + + id = platform_get_device_id(pdev); + if (!id) + return -ENXIO; + + variant = (const struct armada_variant *)id->driver_data; + } else { + const struct of_device_id *match; + + match = of_match_device(dev->driver->of_match_table, dev); + if (!match) + return -ENXIO; + + variant = match->data; + } + + return armada_drm_crtc_create(drm, dev, res, irq, variant); +} + +static void +armada_lcd_unbind(struct device *dev, struct device *master, void *data) +{ + struct armada_crtc *dcrtc = dev_get_drvdata(dev); + + armada_drm_crtc_destroy(&dcrtc->crtc); +} + +static const struct component_ops armada_lcd_ops = { + .bind = armada_lcd_bind, + .unbind = armada_lcd_unbind, +}; + +static int armada_lcd_probe(struct platform_device *pdev) +{ + return component_add(&pdev->dev, &armada_lcd_ops); +} + +static int armada_lcd_remove(struct platform_device *pdev) +{ + component_del(&pdev->dev, &armada_lcd_ops); + return 0; } + +static struct of_device_id armada_lcd_of_match[] = { + { + .compatible = "marvell,dove-lcd", + .data = &armada510_ops, + }, + {} +}; +MODULE_DEVICE_TABLE(of, armada_lcd_of_match); + +static const struct platform_device_id armada_lcd_platform_ids[] = { + { + .name = "armada-lcd", + .driver_data = (unsigned long)&armada510_ops, + }, { + .name = "armada-510-lcd", + .driver_data = (unsigned long)&armada510_ops, + }, + { }, +}; +MODULE_DEVICE_TABLE(platform, armada_lcd_platform_ids); + +struct platform_driver armada_lcd_platform_driver = { + .probe = armada_lcd_probe, + .remove = armada_lcd_remove, + .driver = { + .name = "armada-lcd", + .owner = THIS_MODULE, + .of_match_table = armada_lcd_of_match, + }, + .id_table = armada_lcd_platform_ids, +}; diff --git a/drivers/gpu/drm/armada/armada_crtc.h b/drivers/gpu/drm/armada/armada_crtc.h index 73efcfcdf814..0d9a80392b1e 100644 --- a/drivers/gpu/drm/armada/armada_crtc.h +++ b/drivers/gpu/drm/armada/armada_crtc.h @@ -75,12 +75,14 @@ struct armada_crtc { }; #define drm_to_armada_crtc(c) container_of(c, struct armada_crtc, crtc) -int armada_drm_crtc_create(struct drm_device *, struct resource *, int, - const struct armada_variant *); +int armada_drm_crtc_create(struct drm_device *, struct device *, + struct resource *, int, const struct armada_variant *); void armada_drm_crtc_gamma_set(struct drm_crtc *, u16, u16, u16, int); void armada_drm_crtc_gamma_get(struct drm_crtc *, u16 *, u16 *, u16 *, int); void armada_drm_crtc_disable_irq(struct armada_crtc *, u32); void armada_drm_crtc_enable_irq(struct armada_crtc *, u32); void armada_drm_crtc_update_regs(struct armada_crtc *, struct armada_regs *); +extern struct platform_driver armada_lcd_platform_driver; + #endif diff --git a/drivers/gpu/drm/armada/armada_drv.c b/drivers/gpu/drm/armada/armada_drv.c index 2b6fc6cf62f2..f237f44d8b6d 100644 --- a/drivers/gpu/drm/armada/armada_drv.c +++ b/drivers/gpu/drm/armada/armada_drv.c @@ -115,7 +115,7 @@ static int armada_drm_load(struct drm_device *dev, unsigned long flags) return -EINVAL; } - if (!res[0] || !mem) + if (!mem) return -ENXIO; if (!devm_request_mem_region(dev->dev, mem->start, @@ -168,7 +168,8 @@ static int armada_drm_load(struct drm_device *dev, unsigned long flags) if (irq < 0) goto err_kms; - ret = armada_drm_crtc_create(dev, res[n], irq, variant); + ret = armada_drm_crtc_create(dev, dev->dev, res[n], irq, + variant); if (ret) goto err_kms; } @@ -490,14 +491,24 @@ static struct platform_driver armada_drm_platform_driver = { static int __init armada_drm_init(void) { + int ret; + armada_drm_driver.num_ioctls = ARRAY_SIZE(armada_ioctls); - return platform_driver_register(&armada_drm_platform_driver); + + ret = platform_driver_register(&armada_lcd_platform_driver); + if (ret) + return ret; + ret = platform_driver_register(&armada_drm_platform_driver); + if (ret) + platform_driver_unregister(&armada_lcd_platform_driver); + return ret; } module_init(armada_drm_init); static void __exit armada_drm_exit(void) { platform_driver_unregister(&armada_drm_platform_driver); + platform_driver_unregister(&armada_lcd_platform_driver); } module_exit(armada_drm_exit); -- cgit