[PATCH v9 4/4] drm/tidss: Add OLDI bridge support
Jayesh Choudhary
j-choudhary at ti.com
Mon Jun 30 10:56:14 UTC 2025
Hello Aradhya, Tomi,
On 28/05/25 17:55, Aradhya Bhatia wrote:
> From: Aradhya Bhatia <a-bhatia1 at ti.com>
>
> The AM62x and AM62Px SoCs feature 2 OLDI TXes each, which makes it
> possible to connect them in dual-link or cloned single-link OLDI display
> modes. The current OLDI support in tidss_dispc.c can only support for
> a single OLDI TX, connected to a VP and doesn't really support
> configuration of OLDIs in the other modes. The current OLDI support in
> tidss_dispc.c also works on the principle that the OLDI output can only
> be served by one, and only one, DSS video-port. This isn't the case in
> the AM62Px SoC, where there are 2 DSS controllers present that share the
> OLDI TXes.
>
[...]
> +}
> +
> +int tidss_oldi_init(struct tidss_device *tidss)
> +{
> + struct tidss_oldi *oldi;
> + struct device_node *child;
> + struct drm_bridge *bridge;
> + u32 parent_vp, oldi_instance;
> + int companion_instance = -1;
> + enum tidss_oldi_link_type link_type = OLDI_MODE_UNSUPPORTED;
> + struct device_node *oldi_parent;
> + int ret = 0;
> +
> + tidss->num_oldis = 0;
> +
> + oldi_parent = of_get_child_by_name(tidss->dev->of_node, "oldi-transmitters");
> + if (!oldi_parent)
> + /* Return gracefully */
> + return 0;
> +
> + for_each_available_child_of_node(oldi_parent, child) {
> + ret = get_parent_dss_vp(child, &parent_vp);
> + if (ret) {
> + if (ret == -ENODEV) {
> + /*
> + * ENODEV means that this particular OLDI node
> + * is not connected with the DSS, which is not
> + * a harmful case. There could be another OLDI
> + * which may still be connected.
> + * Continue to search for that.
> + */
> + ret = 0;
> + continue;
> + }
> + goto err_put_node;
> + }
> +
> + ret = of_property_read_u32(child, "reg", &oldi_instance);
> + if (ret)
> + goto err_put_node;
> +
> + /*
> + * Now that it's confirmed that OLDI is connected with DSS,
> + * let's continue getting the OLDI sinks ahead and other OLDI
> + * properties.
> + */
> + bridge = devm_drm_of_get_bridge(tidss->dev, child,
> + OLDI_OUTPUT_PORT, 0);
> + if (IS_ERR(bridge)) {
> + /*
> + * Either there was no OLDI sink in the devicetree, or
> + * the OLDI sink has not been added yet. In any case,
> + * return.
> + * We don't want to have an OLDI node connected to DSS
> + * but not to any sink.
> + */
> + ret = dev_err_probe(tidss->dev, PTR_ERR(bridge),
> + "no panel/bridge for OLDI%u.\n",
> + oldi_instance);
> + goto err_put_node;
> + }
> +
> + link_type = get_oldi_mode(child, &companion_instance);
> + if (link_type == OLDI_MODE_UNSUPPORTED) {
> + ret = dev_err_probe(tidss->dev, -EINVAL,
> + "OLDI%u: Unsupported OLDI connection.\n",
> + oldi_instance);
> + goto err_put_node;
> + } else if ((link_type == OLDI_MODE_SECONDARY_CLONE_SINGLE_LINK) ||
> + (link_type == OLDI_MODE_CLONE_SINGLE_LINK)) {
> + /*
> + * The OLDI driver cannot support OLDI clone mode
> + * properly at present.
> + * The clone mode requires 2 working encoder-bridge
> + * pipelines, generating from the same crtc. The DRM
> + * framework does not support this at present. If
> + * there were to be, say, 2 OLDI sink bridges each
> + * connected to an OLDI TXes, they couldn't both be
> + * supported simultaneously.
> + * This driver still has some code pertaining to OLDI
> + * clone mode configuration in DSS hardware for future,
> + * when there is a better infrastructure in the DRM
> + * framework to support 2 encoder-bridge pipelines
> + * simultaneously.
> + * Till that time, this driver shall error out if it
> + * detects a clone mode configuration.
> + */
> + ret = dev_err_probe(tidss->dev, -EOPNOTSUPP,
> + "The OLDI driver does not support Clone Mode at present.\n");
> + goto err_put_node;
> + } else if (link_type == OLDI_MODE_SECONDARY_DUAL_LINK) {
> + /*
> + * This is the secondary OLDI node, which serves as a
> + * companion to the primary OLDI, when it is configured
> + * for the dual-link mode. Since the primary OLDI will
> + * be a part of bridge chain, no need to put this one
> + * too. Continue onto the next OLDI node.
> + */
> + continue;
> + }
> +
> + oldi = devm_kzalloc(tidss->dev, sizeof(*oldi), GFP_KERNEL);
I think this needs to be changed to devm_drm_bridge_alloc() to get rid
of the kernel warning. I am seeing WARNING in OLDI like:
[ 10.198109] WARNING: lib/refcount.c:25 at
refcount_warn_saturate+0x120/0x144, CPU#0: kworker/u16:0/12
[ 10.198140] Modules linked in: snd_soc_simple_card mux_gpio
snd_soc_simple_card_utils panel_simple cdns3_ti display_connector
snd_soc_davinci_mcasp phy_can_transceiver k3_j72xx_bandgap tps6594_i2c tps6
[ 10.198310] CPU: 0 UID: 0 PID: 12 Comm: kworker/u16:0 Not tainted
6.16.0-rc3-next-20250627-00046-ga876218600d6 #197 PREEMPT
[ 10.198321] Hardware name: Texas Instruments J722S EVM (DT)
[ 10.198327] Workqueue: events_unbound deferred_probe_work_func
[ 10.198344] pstate: 60000005 (nZCv daif -PAN -UAO -TCO -DIT -SSBS
BTYPE=--)
[ 10.198352] pc : refcount_warn_saturate+0x120/0x144
[ 10.198359] lr : refcount_warn_saturate+0x120/0x144
[ 10.198365] sp : ffff800082fa3a30
[ 10.198368] x29: ffff800082fa3a30 x28: 0000000000000000 x27:
0000000000000000
[ 10.198377] x26: 0000000000000004 x25: 0000000000000001 x24:
ffff80007b1edf48
[ 10.198386] x23: ffff000806fa0000 x22: ffff00080c466800 x21:
ffff00094701ec20
[ 10.198395] x20: ffff00080f9cec80 x19: ffff00080f9cec90 x18:
fffffffffffe99f8
[ 10.198404] x17: ffff8008c4f5e000 x16: ffff800080000000 x15:
0000000000000002
[ 10.198414] x14: ffff0008001dc680 x13: 0000000000000021 x12:
0000000013cbce01
[ 10.198423] x11: 00000005cc209839 x10: ffff000946f68a40 x9 :
ffff0008001dc680
[ 10.198433] x8 : 0000000000000000 x7 : ffff0008001dc680 x6 :
0000000000000002
[ 10.198441] x5 : 0000000000000400 x4 : 0000000000000400 x3 :
0000000013cbce01
[ 10.198450] x2 : 0000000000000000 x1 : 0000000000000000 x0 :
ffff0008001dc600
[ 10.198459] Call trace:
[ 10.198464] refcount_warn_saturate+0x120/0x144 (P)
[ 10.198473] drm_bridge_add+0xec/0xf0 [drm]
[ 10.198733] tidss_oldi_init+0x2e0/0x434 [tidss]
[ 10.198759] tidss_probe+0x1a4/0x2e0 [tidss]
[ 10.198774] platform_probe+0x68/0xc4
[ 10.198786] really_probe+0xbc/0x29c
[ 10.198798] __driver_probe_device+0x78/0x12c
[ 10.198808] driver_probe_device+0xd8/0x15c
[ 10.198817] __device_attach_driver+0xb8/0x134
oldi = devm_drm_bridge_alloc(tidss->dev, struct tidss_oldi, bridge,
&tidss_oldi_bridge_funcs);
I am posting a fix patch for this since now its merged to linux-next.
Thanks,
Jayesh
[...]
More information about the dri-devel
mailing list