To support more transmitters, we need to allow non-component framework bridges to be attached to a dummy drm_encoder in our driver. A/B tested for equivalence against tda998x, and also tested ti_tfp410 as an alternate transmitter. Signed-off-by: Mihail Atanassov <mihail.atanassov@xxxxxxx> --- .../gpu/drm/arm/display/komeda/komeda_drv.c | 54 ++++++------- .../gpu/drm/arm/display/komeda/komeda_kms.c | 77 +++++++++++++++++-- .../gpu/drm/arm/display/komeda/komeda_kms.h | 2 + 3 files changed, 100 insertions(+), 33 deletions(-) diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_drv.c b/drivers/gpu/drm/arm/display/komeda/komeda_drv.c index d6c2222c5d33..2870123bef37 100644 --- a/drivers/gpu/drm/arm/display/komeda/komeda_drv.c +++ b/drivers/gpu/drm/arm/display/komeda/komeda_drv.c @@ -6,10 +6,10 @@ */ #include <linux/module.h> #include <linux/kernel.h> +#include <linux/of_graph.h> #include <linux/platform_device.h> -#include <linux/component.h> #include <linux/pm_runtime.h> -#include <drm/drm_of.h> +#include <drm/drm_bridge.h> #include "komeda_dev.h" #include "komeda_kms.h" @@ -72,35 +72,29 @@ static int komeda_bind(struct device *dev) return err; } -static const struct component_master_ops komeda_master_ops = { - .bind = komeda_bind, - .unbind = komeda_unbind, -}; - -static int compare_of(struct device *dev, void *data) -{ - return dev->of_node == data; -} - -static void komeda_add_slave(struct device *master, - struct component_match **match, - struct device_node *np, - u32 port, u32 endpoint) +static int komeda_add_slave(struct device_node *np, u32 port, u32 endpoint) { struct device_node *remote; + struct drm_bridge *bridge; + int ret = 0; remote = of_graph_get_remote_node(np, port, endpoint); - if (remote) { - drm_of_component_match_add(master, match, compare_of, remote); - of_node_put(remote); - } + if (!remote) + return 0; + + bridge = of_drm_find_bridge(remote); + if (!bridge) + ret = -EPROBE_DEFER; + + of_node_put(remote); + return ret; } static int komeda_platform_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; - struct component_match *match = NULL; struct device_node *child; + int ret; if (!dev->of_node) return -ENODEV; @@ -109,17 +103,25 @@ static int komeda_platform_probe(struct platform_device *pdev) if (of_node_cmp(child->name, "pipeline") != 0) continue; - /* add connector */ - komeda_add_slave(dev, &match, child, KOMEDA_OF_PORT_OUTPUT, 0); - komeda_add_slave(dev, &match, child, KOMEDA_OF_PORT_OUTPUT, 1); + /* attach any remote devices if present */ + ret = komeda_add_slave(child, KOMEDA_OF_PORT_OUTPUT, 0); + if (ret) { + of_node_put(child); + return ret; + } + ret = komeda_add_slave(child, KOMEDA_OF_PORT_OUTPUT, 1); + if (ret) { + of_node_put(child); + return ret; + } } - return component_master_add_with_match(dev, &komeda_master_ops, match); + return komeda_bind(dev); } static int komeda_platform_remove(struct platform_device *pdev) { - component_master_del(&pdev->dev, &komeda_master_ops); + komeda_unbind(&pdev->dev); return 0; } diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_kms.c b/drivers/gpu/drm/arm/display/komeda/komeda_kms.c index e30a5b43caa9..2fc6cd9956fd 100644 --- a/drivers/gpu/drm/arm/display/komeda/komeda_kms.c +++ b/drivers/gpu/drm/arm/display/komeda/komeda_kms.c @@ -4,8 +4,8 @@ * Author: James.Qian.Wang <james.qian.wang@xxxxxxx> * */ -#include <linux/component.h> #include <linux/interrupt.h> +#include <linux/of_graph.h> #include <drm/drm_atomic.h> #include <drm/drm_atomic_helper.h> @@ -14,6 +14,9 @@ #include <drm/drm_gem_cma_helper.h> #include <drm/drm_gem_framebuffer_helper.h> #include <drm/drm_irq.h> +#include <drm/drm_of.h> +#include <drm/drm_encoder.h> +#include <drm/drm_bridge.h> #include <drm/drm_probe_helper.h> #include <drm/drm_vblank.h> @@ -257,6 +260,69 @@ static void komeda_kms_mode_config_init(struct komeda_kms_dev *kms, config->helper_private = &komeda_mode_config_helpers; } +static void komeda_encoder_destroy(struct drm_encoder *encoder) +{ + drm_encoder_cleanup(encoder); +} + +static const struct drm_encoder_funcs komeda_dummy_enc_funcs = { + .destroy = komeda_encoder_destroy, +}; + +static int komeda_encoder_attach_bridge(struct komeda_dev *mdev, + struct komeda_kms_dev *kms, + struct drm_encoder *encoder, + struct device_node *np) +{ + struct device_node *remote; + struct drm_bridge *bridge; + u32 crtcs = 0; + int ret = 0; + + remote = of_graph_get_remote_node(np, KOMEDA_OF_PORT_OUTPUT, 0); + if (!remote) + return 0; + + bridge = of_drm_find_bridge_devlink(&kms->base, remote); + if (!bridge) { + ret = -EINVAL; + goto exit; + } + + crtcs = drm_of_find_possible_crtcs(&kms->base, remote); + + encoder->possible_crtcs = crtcs ? crtcs : 1; + + ret = drm_encoder_init(&kms->base, encoder, &komeda_dummy_enc_funcs, + DRM_MODE_ENCODER_TMDS, NULL); + if (ret) + goto exit; + + ret = drm_bridge_attach(encoder, bridge, NULL); + if (ret) + goto exit; + +exit: + of_node_put(remote); + return ret; +} + +static int komeda_encoder_attach_bridges(struct komeda_kms_dev *kms, + struct komeda_dev *mdev) +{ + int i, err; + + for (i = 0; i < kms->n_crtcs; i++) { + err = komeda_encoder_attach_bridge( + mdev, kms, + &kms->encoders[i], mdev->pipelines[i]->of_node); + if (err) + return err; + } + + return 0; +} + struct komeda_kms_dev *komeda_kms_attach(struct komeda_dev *mdev) { struct komeda_kms_dev *kms = kzalloc(sizeof(*kms), GFP_KERNEL); @@ -295,7 +361,7 @@ struct komeda_kms_dev *komeda_kms_attach(struct komeda_dev *mdev) if (err) goto cleanup_mode_config; - err = component_bind_all(mdev->dev, kms); + err = komeda_encoder_attach_bridges(kms, mdev); if (err) goto cleanup_mode_config; @@ -305,11 +371,11 @@ struct komeda_kms_dev *komeda_kms_attach(struct komeda_dev *mdev) komeda_kms_irq_handler, IRQF_SHARED, drm->driver->name, drm); if (err) - goto free_component_binding; + goto cleanup_mode_config; err = mdev->funcs->enable_irq(mdev); if (err) - goto free_component_binding; + goto cleanup_mode_config; drm->irq_enabled = true; @@ -325,8 +391,6 @@ struct komeda_kms_dev *komeda_kms_attach(struct komeda_dev *mdev) drm_kms_helper_poll_fini(drm); drm->irq_enabled = false; mdev->funcs->disable_irq(mdev); -free_component_binding: - component_unbind_all(mdev->dev, drm); cleanup_mode_config: drm_mode_config_cleanup(drm); komeda_kms_cleanup_private_objs(kms); @@ -347,7 +411,6 @@ void komeda_kms_detach(struct komeda_kms_dev *kms) drm_atomic_helper_shutdown(drm); drm->irq_enabled = false; mdev->funcs->disable_irq(mdev); - component_unbind_all(mdev->dev, drm); drm_mode_config_cleanup(drm); komeda_kms_cleanup_private_objs(kms); drm->dev_private = NULL; diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_kms.h b/drivers/gpu/drm/arm/display/komeda/komeda_kms.h index 456f3c435719..b40ba0f476b1 100644 --- a/drivers/gpu/drm/arm/display/komeda/komeda_kms.h +++ b/drivers/gpu/drm/arm/display/komeda/komeda_kms.h @@ -12,6 +12,7 @@ #include <drm/drm_atomic_helper.h> #include <drm/drm_crtc_helper.h> #include <drm/drm_device.h> +#include <drm/drm_encoder.h> #include <drm/drm_writeback.h> #include <drm/drm_print.h> @@ -123,6 +124,7 @@ struct komeda_kms_dev { int n_crtcs; /** @crtcs: crtcs list */ struct komeda_crtc crtcs[KOMEDA_MAX_PIPELINES]; + struct drm_encoder encoders[KOMEDA_MAX_PIPELINES]; }; #define to_kplane(p) container_of(p, struct komeda_plane, base) -- 2.23.0 _______________________________________________ dri-devel mailing list dri-devel@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/dri-devel