* GNU General Public License for more details.
*
*/
-
+#include <linux/component.h>
#include <linux/device.h>
#include <linux/platform_device.h>
#include <drm/drmP.h>
{
struct imx_drm_device *imxdrm = drm->dev_private;
+ component_unbind_all(drm->dev, drm);
+
imx_drm_device_put();
drm_vblank_cleanup(drm);
return NULL;
}
-int imx_drm_crtc_panel_format_pins(struct drm_crtc *crtc, u32 encoder_type,
+int imx_drm_panel_format_pins(struct drm_encoder *encoder,
u32 interface_pix_fmt, int hsync_pin, int vsync_pin)
{
struct imx_drm_crtc_helper_funcs *helper;
struct imx_drm_crtc *imx_crtc;
- imx_crtc = imx_drm_find_crtc(crtc);
+ imx_crtc = imx_drm_find_crtc(encoder->crtc);
if (!imx_crtc)
return -EINVAL;
helper = &imx_crtc->imx_drm_helper_funcs;
if (helper->set_interface_pix_fmt)
- return helper->set_interface_pix_fmt(crtc,
- encoder_type, interface_pix_fmt,
+ return helper->set_interface_pix_fmt(encoder->crtc,
+ encoder->encoder_type, interface_pix_fmt,
hsync_pin, vsync_pin);
return 0;
}
-EXPORT_SYMBOL_GPL(imx_drm_crtc_panel_format_pins);
+EXPORT_SYMBOL_GPL(imx_drm_panel_format_pins);
-int imx_drm_crtc_panel_format(struct drm_crtc *crtc, u32 encoder_type,
- u32 interface_pix_fmt)
+int imx_drm_panel_format(struct drm_encoder *encoder, u32 interface_pix_fmt)
{
- return imx_drm_crtc_panel_format_pins(crtc, encoder_type,
- interface_pix_fmt, 2, 3);
+ return imx_drm_panel_format_pins(encoder, interface_pix_fmt, 2, 3);
}
-EXPORT_SYMBOL_GPL(imx_drm_crtc_panel_format);
+EXPORT_SYMBOL_GPL(imx_drm_panel_format);
int imx_drm_crtc_vblank_get(struct imx_drm_crtc *imx_drm_crtc)
{
}
/*
- * Called by the CRTC driver when all CRTCs are registered. This
- * puts all the pieces together and initializes the driver.
- * Once this is called no more CRTCs can be registered since
- * the drm core has hardcoded the number of crtcs in several
- * places.
+ * Main DRM initialisation. This binds, initialises and registers
+ * with DRM the subcomponents of the driver.
*/
static int imx_drm_driver_load(struct drm_device *drm, unsigned long flags)
{
platform_set_drvdata(drm->platformdev, drm);
mutex_unlock(&imxdrm->mutex);
+
+ /* Now try and bind all our sub-components */
+ ret = component_bind_all(drm->dev, drm);
+ if (ret)
+ goto err_relock;
return 0;
+err_relock:
+ mutex_lock(&imxdrm->mutex);
err_vblank:
drm_vblank_cleanup(drm);
err_kms:
.patchlevel = 0,
};
+static int compare_parent_of(struct device *dev, void *data)
+{
+ struct of_phandle_args *args = data;
+ return dev->parent && dev->parent->of_node == args->np;
+}
+
+static int compare_of(struct device *dev, void *data)
+{
+ return dev->of_node == data;
+}
+
+static int imx_drm_add_components(struct device *master, struct master *m)
+{
+ struct device_node *np = master->of_node;
+ unsigned i;
+ int ret;
+
+ for (i = 0; ; i++) {
+ struct of_phandle_args args;
+
+ ret = of_parse_phandle_with_fixed_args(np, "crtcs", 1,
+ i, &args);
+ if (ret)
+ break;
+
+ ret = component_master_add_child(m, compare_parent_of, &args);
+ of_node_put(args.np);
+
+ if (ret)
+ return ret;
+ }
+
+ for (i = 0; ; i++) {
+ struct device_node *node;
+
+ node = of_parse_phandle(np, "connectors", i);
+ if (!node)
+ break;
+
+ ret = component_master_add_child(m, compare_of, node);
+ of_node_put(node);
+
+ if (ret)
+ return ret;
+ }
+ return 0;
+}
+
+static int imx_drm_bind(struct device *dev)
+{
+ return drm_platform_init(&imx_drm_driver, to_platform_device(dev));
+}
+
+static void imx_drm_unbind(struct device *dev)
+{
+ drm_put_dev(dev_get_drvdata(dev));
+}
+
+static const struct component_master_ops imx_drm_ops = {
+ .add_components = imx_drm_add_components,
+ .bind = imx_drm_bind,
+ .unbind = imx_drm_unbind,
+};
+
static int imx_drm_platform_probe(struct platform_device *pdev)
{
int ret;
imx_drm_device->dev = &pdev->dev;
- return drm_platform_init(&imx_drm_driver, pdev);
+ return component_master_add(&pdev->dev, &imx_drm_ops);
}
static int imx_drm_platform_remove(struct platform_device *pdev)
{
- drm_put_dev(platform_get_drvdata(pdev));
-
+ component_master_del(&pdev->dev, &imx_drm_ops);
return 0;
}
+static const struct of_device_id imx_drm_dt_ids[] = {
+ { .compatible = "fsl,imx-drm", },
+ { /* sentinel */ },
+};
+MODULE_DEVICE_TABLE(of, imx_drm_dt_ids);
+
static struct platform_driver imx_drm_pdrv = {
.probe = imx_drm_platform_probe,
.remove = imx_drm_platform_remove,
.driver = {
.owner = THIS_MODULE,
.name = "imx-drm",
+ .of_match_table = imx_drm_dt_ids,
},
};
-static struct platform_device *imx_drm_pdev;
-
static int __init imx_drm_init(void)
{
int ret;
INIT_LIST_HEAD(&imx_drm_device->connector_list);
INIT_LIST_HEAD(&imx_drm_device->encoder_list);
- imx_drm_pdev = platform_device_register_simple("imx-drm", -1, NULL, 0);
- if (IS_ERR(imx_drm_pdev)) {
- ret = PTR_ERR(imx_drm_pdev);
- goto err_pdev;
- }
-
ret = platform_driver_register(&imx_drm_pdrv);
if (ret)
goto err_pdrv;
return 0;
err_pdrv:
- platform_device_unregister(imx_drm_pdev);
-err_pdev:
kfree(imx_drm_device);
return ret;
static void __exit imx_drm_exit(void)
{
- platform_device_unregister(imx_drm_pdev);
platform_driver_unregister(&imx_drm_pdrv);
kfree(imx_drm_device);