1
0
mirror of https://github.com/libretro/Lakka-LibreELEC.git synced 2024-11-25 04:56:18 +00:00
Lakka-LibreELEC/projects/NXP/devices/iMX8/patches/linux/0041-drm-imx-dcss-add-component-framework-functionality.patch

248 lines
7.0 KiB
Diff

From ec59d2988d1ac50acea0fdaa63513f216ddf016d Mon Sep 17 00:00:00 2001
From: Laurentiu Palcu <laurentiu.palcu@nxp.com>
Date: Thu, 9 Jul 2020 19:47:31 +0300
Subject: [PATCH 41/49] drm/imx/dcss: add component framework functionality
Component framework is needed by HDP driver.
Signed-off-by: Laurentiu Palcu <laurentiu.palcu@nxp.com>
---
drivers/gpu/drm/imx/dcss/dcss-drv.c | 89 ++++++++++++++++++++++-------
drivers/gpu/drm/imx/dcss/dcss-kms.c | 23 +++++---
drivers/gpu/drm/imx/dcss/dcss-kms.h | 4 +-
3 files changed, 85 insertions(+), 31 deletions(-)
diff --git a/drivers/gpu/drm/imx/dcss/dcss-drv.c b/drivers/gpu/drm/imx/dcss/dcss-drv.c
index 8dc2f85c514b..09d0ac28e28a 100644
--- a/drivers/gpu/drm/imx/dcss/dcss-drv.c
+++ b/drivers/gpu/drm/imx/dcss/dcss-drv.c
@@ -6,6 +6,7 @@
#include <linux/kernel.h>
#include <linux/platform_device.h>
#include <drm/drm_module.h>
+#include <linux/component.h>
#include <drm/drm_of.h>
#include "dcss-dev.h"
@@ -14,6 +15,8 @@
struct dcss_drv {
struct dcss_dev *dcss;
struct dcss_kms_dev *kms;
+
+ bool is_componentized;
};
struct dcss_dev *dcss_drv_dev_to_dcss(struct device *dev)
@@ -30,30 +33,18 @@ struct drm_device *dcss_drv_dev_to_drm(struct device *dev)
return mdrv ? &mdrv->kms->base : NULL;
}
-static int dcss_drv_platform_probe(struct platform_device *pdev)
+static int dcss_drv_init(struct device *dev, bool componentized)
{
- struct device *dev = &pdev->dev;
- struct device_node *remote;
struct dcss_drv *mdrv;
int err = 0;
- bool hdmi_output = true;
-
- if (!dev->of_node)
- return -ENODEV;
-
- remote = of_graph_get_remote_node(dev->of_node, 0, 0);
- if (!remote)
- return -ENODEV;
-
- hdmi_output = !of_device_is_compatible(remote, "fsl,imx8mq-nwl-dsi");
-
- of_node_put(remote);
mdrv = kzalloc(sizeof(*mdrv), GFP_KERNEL);
if (!mdrv)
return -ENOMEM;
- mdrv->dcss = dcss_dev_create(dev, hdmi_output);
+ mdrv->is_componentized = componentized;
+
+ mdrv->dcss = dcss_dev_create(dev, componentized);
if (IS_ERR(mdrv->dcss)) {
err = PTR_ERR(mdrv->dcss);
goto err;
@@ -61,7 +52,7 @@ static int dcss_drv_platform_probe(struct platform_device *pdev)
dev_set_drvdata(dev, mdrv);
- mdrv->kms = dcss_kms_attach(mdrv->dcss);
+ mdrv->kms = dcss_kms_attach(mdrv->dcss, componentized);
if (IS_ERR(mdrv->kms)) {
err = PTR_ERR(mdrv->kms);
goto dcss_shutoff;
@@ -79,19 +70,73 @@ static int dcss_drv_platform_probe(struct platform_device *pdev)
return err;
}
-static int dcss_drv_platform_remove(struct platform_device *pdev)
+static void dcss_drv_deinit(struct device *dev, bool componentized)
{
- struct dcss_drv *mdrv = dev_get_drvdata(&pdev->dev);
+ struct dcss_drv *mdrv = dev_get_drvdata(dev);
if (!mdrv)
- return 0;
+ return;
- dcss_kms_detach(mdrv->kms);
+ dcss_kms_detach(mdrv->kms, componentized);
dcss_dev_destroy(mdrv->dcss);
- dev_set_drvdata(&pdev->dev, NULL);
+ dev_set_drvdata(dev, NULL);
kfree(mdrv);
+}
+
+static int dcss_drv_bind(struct device *dev)
+{
+ return dcss_drv_init(dev, true);
+}
+
+static void dcss_drv_unbind(struct device *dev)
+{
+ return dcss_drv_deinit(dev, true);
+}
+
+static const struct component_master_ops dcss_master_ops = {
+ .bind = dcss_drv_bind,
+ .unbind = dcss_drv_unbind,
+};
+
+static int compare_of(struct device *dev, void *data)
+{
+ return dev->of_node == data;
+}
+
+static int dcss_drv_platform_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct component_match *match = NULL;
+ struct device_node *remote;
+
+ if (!dev->of_node)
+ return -ENODEV;
+
+ remote = of_graph_get_remote_node(dev->of_node, 0, 0);
+ if (!remote)
+ return -ENODEV;
+
+ if (of_device_is_compatible(remote, "fsl,imx8mq-nwl-dsi")) {
+ of_node_put(remote);
+ return dcss_drv_init(dev, false);
+ }
+
+ drm_of_component_match_add(dev, &match, compare_of, remote);
+ of_node_put(remote);
+
+ return component_master_add_with_match(dev, &dcss_master_ops, match);
+}
+
+static int dcss_drv_platform_remove(struct platform_device *pdev)
+{
+ struct dcss_drv *mdrv = dev_get_drvdata(&pdev->dev);
+
+ if (mdrv->is_componentized)
+ component_master_del(&pdev->dev, &dcss_master_ops);
+ else
+ dcss_drv_deinit(&pdev->dev, false);
return 0;
}
diff --git a/drivers/gpu/drm/imx/dcss/dcss-kms.c b/drivers/gpu/drm/imx/dcss/dcss-kms.c
index 135a62366ab8..cafb09df6c75 100644
--- a/drivers/gpu/drm/imx/dcss/dcss-kms.c
+++ b/drivers/gpu/drm/imx/dcss/dcss-kms.c
@@ -13,6 +13,7 @@
#include <drm/drm_of.h>
#include <drm/drm_probe_helper.h>
#include <drm/drm_vblank.h>
+#include <linux/component.h>
#include "dcss-dev.h"
#include "dcss-kms.h"
@@ -123,7 +124,7 @@ static int dcss_kms_bridge_connector_init(struct dcss_kms_dev *kms)
return 0;
}
-struct dcss_kms_dev *dcss_kms_attach(struct dcss_dev *dcss)
+struct dcss_kms_dev *dcss_kms_attach(struct dcss_dev *dcss, bool componentized)
{
struct dcss_kms_dev *kms;
struct drm_device *drm;
@@ -148,13 +149,16 @@ struct dcss_kms_dev *dcss_kms_attach(struct dcss_dev *dcss)
goto cleanup_mode_config;
- ret = dcss_kms_bridge_connector_init(kms);
+ ret = dcss_crtc_init(crtc, drm);
if (ret)
goto cleanup_mode_config;
- ret = dcss_crtc_init(crtc, drm);
+ if (componentized)
+ ret = component_bind_all(dcss->dev, kms);
+ else
+ ret = dcss_kms_bridge_connector_init(kms);
if (ret)
- goto cleanup_mode_config;
+ goto cleanup_crtc;
drm_mode_config_reset(drm);
@@ -171,7 +176,8 @@ struct dcss_kms_dev *dcss_kms_attach(struct dcss_dev *dcss)
return kms;
cleanup_crtc:
- drm_bridge_connector_disable_hpd(kms->connector);
+ if (!componentized)
+ drm_bridge_connector_disable_hpd(kms->connector);
drm_kms_helper_poll_fini(drm);
dcss_crtc_deinit(crtc, drm);
@@ -182,9 +188,10 @@ struct dcss_kms_dev *dcss_kms_attach(struct dcss_dev *dcss)
return ERR_PTR(ret);
}
-void dcss_kms_detach(struct dcss_kms_dev *kms)
+void dcss_kms_detach(struct dcss_kms_dev *kms, bool componentized)
{
struct drm_device *drm = &kms->base;
+ struct dcss_dev *dcss = drm->dev_private;
drm_dev_unregister(drm);
drm_bridge_connector_disable_hpd(kms->connector);
@@ -194,5 +201,7 @@ void dcss_kms_detach(struct dcss_kms_dev *kms)
drm->irq_enabled = false;
drm_mode_config_cleanup(drm);
dcss_crtc_deinit(&kms->crtc, drm);
+ if (componentized)
+ component_unbind_all(dcss->dev, drm);
drm->dev_private = NULL;
}
diff --git a/drivers/gpu/drm/imx/dcss/dcss-kms.h b/drivers/gpu/drm/imx/dcss/dcss-kms.h
index dfe5dd99eea3..e98d9c587a43 100644
--- a/drivers/gpu/drm/imx/dcss/dcss-kms.h
+++ b/drivers/gpu/drm/imx/dcss/dcss-kms.h
@@ -32,8 +32,8 @@ struct dcss_kms_dev {
struct drm_connector *connector;
};
-struct dcss_kms_dev *dcss_kms_attach(struct dcss_dev *dcss);
-void dcss_kms_detach(struct dcss_kms_dev *kms);
+struct dcss_kms_dev *dcss_kms_attach(struct dcss_dev *dcss, bool componentized);
+void dcss_kms_detach(struct dcss_kms_dev *kms, bool componentized);
int dcss_crtc_init(struct dcss_crtc *crtc, struct drm_device *drm);
void dcss_crtc_deinit(struct dcss_crtc *crtc, struct drm_device *drm);
struct dcss_plane *dcss_plane_init(struct drm_device *drm,
--
2.29.2