Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d8c96083 authored by Russell King's avatar Russell King
Browse files

drm/armada: permit CRTCs to be registered as separate devices

parent ad49579a
Loading
Loading
Loading
Loading
+104 −9
Original line number Diff line number Diff line
@@ -7,6 +7,9 @@
 * published by the Free Software Foundation.
 */
#include <linux/clk.h>
#include <linux/component.h>
#include <linux/of_device.h>
#include <linux/platform_device.h>
#include <drm/drmP.h>
#include <drm/drm_crtc_helper.h>
#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,
};
+4 −2
Original line number Diff line number Diff line
@@ -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
+14 −3
Original line number Diff line number Diff line
@@ -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);