Commit 7246e092 authored by Aradhya Bhatia's avatar Aradhya Bhatia Committed by Tomi Valkeinen
Browse files

drm/tidss: Add OLDI bridge support



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.

Having their own devicetree and their own bridge entity will help
support the various display modes and sharing possiblilities of the OLDI
hardware.

For all these reasons, add support for the OLDI TXes as DRM bridges.

Signed-off-by: default avatarAradhya Bhatia <a-bhatia1@ti.com>
Signed-off-by: default avatarAradhya Bhatia <aradhya.bhatia@linux.dev>
Tested-by: Michael Walle <mwalle@kernel.org> # on am67a
Reviewed-by: default avatarTomi Valkeinen <tomi.valkeinen@ideasonboard.com>
Link: https://lore.kernel.org/r/20250528122544.817829-5-aradhya.bhatia@linux.dev


Signed-off-by: default avatarTomi Valkeinen <tomi.valkeinen@ideasonboard.com>
parent d18bf712
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -7,6 +7,7 @@ tidss-y := tidss_crtc.o \
	tidss_irq.o \
	tidss_plane.o \
	tidss_scale_coefs.o \
	tidss_dispc.o
	tidss_dispc.o \
	tidss_oldi.o

obj-$(CONFIG_DRM_TIDSS) += tidss.o
+23 −1
Original line number Diff line number Diff line
@@ -566,6 +566,29 @@ static u32 dispc_vp_read(struct dispc_device *dispc, u32 hw_videoport, u16 reg)
	return ioread32(base + reg);
}

int tidss_configure_oldi(struct tidss_device *tidss, u32 hw_videoport,
			 u32 oldi_cfg)
{
	u32 count = 0;
	u32 oldi_reset_bit = BIT(5 + hw_videoport);

	dispc_vp_write(tidss->dispc, hw_videoport, DISPC_VP_DSS_OLDI_CFG, oldi_cfg);

	while (!(oldi_reset_bit & dispc_read(tidss->dispc, DSS_SYSSTATUS)) &&
	       count < 10000)
		count++;

	if (!(oldi_reset_bit & dispc_read(tidss->dispc, DSS_SYSSTATUS)))
		return -ETIMEDOUT;

	return 0;
}

void tidss_disable_oldi(struct tidss_device *tidss, u32 hw_videoport)
{
	dispc_vp_write(tidss->dispc, hw_videoport, DISPC_VP_DSS_OLDI_CFG, 0);
}

/*
 * TRM gives bitfields as start:end, where start is the higher bit
 * number. For example 7:0
@@ -1418,7 +1441,6 @@ void dispc_vp_disable_clk(struct dispc_device *dispc, u32 hw_videoport)
 * Calculate the percentage difference between the requested pixel clock rate
 * and the effective rate resulting from calculating the clock divider value.
 */
static
unsigned int dispc_pclk_diff(unsigned long rate, unsigned long real_rate)
{
	int r = rate / 100, rr = real_rate / 100;
+5 −0
Original line number Diff line number Diff line
@@ -101,6 +101,11 @@ extern const struct dispc_features dispc_am62l_feats;
extern const struct dispc_features dispc_am65x_feats;
extern const struct dispc_features dispc_j721e_feats;

int tidss_configure_oldi(struct tidss_device *tidss, u32 hw_videoport,
			 u32 oldi_cfg);
void tidss_disable_oldi(struct tidss_device *tidss, u32 hw_videoport);
unsigned int dispc_pclk_diff(unsigned long rate, unsigned long real_rate);

void dispc_set_irqenable(struct dispc_device *dispc, dispc_irq_t mask);
dispc_irq_t dispc_read_and_clear_irqstatus(struct dispc_device *dispc);

+14 −0
Original line number Diff line number Diff line
@@ -226,6 +226,20 @@ enum dispc_common_regs {
#define DISPC_VP_DSS_DMA_THREADSIZE		0x170 /* J721E */
#define DISPC_VP_DSS_DMA_THREADSIZE_STATUS	0x174 /* J721E */

/* OLDI Config Bits (DISPC_VP_DSS_OLDI_CFG) */
#define OLDI_ENABLE		BIT(0)
#define OLDI_MAP		(BIT(1) | BIT(2) | BIT(3))
#define OLDI_SRC		BIT(4)
#define OLDI_CLONE_MODE		BIT(5)
#define OLDI_MASTERSLAVE	BIT(6)
#define OLDI_DEPOL		BIT(7)
#define OLDI_MSB		BIT(8)
#define OLDI_LBEN		BIT(9)
#define OLDI_LBDATA		BIT(10)
#define OLDI_DUALMODESYNC	BIT(11)
#define OLDI_SOFTRST		BIT(12)
#define OLDI_TPATCFG		BIT(13)

/* LVDS Format values for OLDI_MAP field in DISPC_VP_OLDI_CFG register */
enum oldi_mode_reg_val { SPWG_18 = 0, JEIDA_24 = 1, SPWG_24 = 2 };

+9 −0
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@
#include "tidss_drv.h"
#include "tidss_kms.h"
#include "tidss_irq.h"
#include "tidss_oldi.h"

/* Power management */

@@ -147,6 +148,10 @@ static int tidss_probe(struct platform_device *pdev)
		return ret;
	}

	ret = tidss_oldi_init(tidss);
	if (ret)
		return dev_err_probe(dev, ret, "failed to init OLDI\n");

	pm_runtime_enable(dev);

	pm_runtime_set_autosuspend_delay(dev, 1000);
@@ -203,6 +208,8 @@ static int tidss_probe(struct platform_device *pdev)
	pm_runtime_dont_use_autosuspend(dev);
	pm_runtime_disable(dev);

	tidss_oldi_deinit(tidss);

	return ret;
}

@@ -227,6 +234,8 @@ static void tidss_remove(struct platform_device *pdev)
	pm_runtime_dont_use_autosuspend(dev);
	pm_runtime_disable(dev);

	tidss_oldi_deinit(tidss);

	/* devm allocated dispc goes away with the dev so mark it NULL */
	dispc_remove(tidss);

Loading