drivers/gpu/drm/tidss/tidss_oldi.c

Source file repositories/reference/linux-study-clean/drivers/gpu/drm/tidss/tidss_oldi.c

File Facts

System
Linux kernel
Corpus path
drivers/gpu/drm/tidss/tidss_oldi.c
Extension
.c
Size
17367 bytes
Lines
620
Domain
Driver Families
Bucket
drivers/gpu
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

struct tidss_oldi {
	struct tidss_device	*tidss;
	struct device		*dev;

	struct drm_bridge	bridge;
	struct drm_bridge	*next_bridge;

	enum tidss_oldi_link_type link_type;
	const struct oldi_bus_format *bus_format;
	u32 oldi_instance;
	int companion_instance;	/* -1 when OLDI TX operates in Single-Link */
	u32 parent_vp;

	struct clk *serial;
	struct regmap *io_ctrl;
};

struct oldi_bus_format {
	u32 bus_fmt;
	u32 data_width;
	enum oldi_mode_reg_val oldi_mode_reg_val;
	u32 input_bus_fmt;
};

static const struct oldi_bus_format oldi_bus_formats[] = {
	{ MEDIA_BUS_FMT_RGB666_1X7X3_SPWG,	18, SPWG_18,	MEDIA_BUS_FMT_RGB666_1X18 },
	{ MEDIA_BUS_FMT_RGB888_1X7X4_SPWG,	24, SPWG_24,	MEDIA_BUS_FMT_RGB888_1X24 },
	{ MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA,	24, JEIDA_24,	MEDIA_BUS_FMT_RGB888_1X24 },
};

#define OLDI_IDLE_CLK_HZ	25000000 /*25 MHz */

static inline struct tidss_oldi *
drm_bridge_to_tidss_oldi(struct drm_bridge *bridge)
{
	return container_of(bridge, struct tidss_oldi, bridge);
}

static int tidss_oldi_bridge_attach(struct drm_bridge *bridge,
				    struct drm_encoder *encoder,
				    enum drm_bridge_attach_flags flags)
{
	struct tidss_oldi *oldi = drm_bridge_to_tidss_oldi(bridge);

	if (!oldi->next_bridge) {
		dev_err(oldi->dev,
			"%s: OLDI%u Failure attach next bridge\n",
			__func__, oldi->oldi_instance);
		return -ENODEV;
	}

	if (!(flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR)) {
		dev_err(oldi->dev,
			"%s: OLDI%u DRM_BRIDGE_ATTACH_NO_CONNECTOR is mandatory.\n",
			__func__, oldi->oldi_instance);
		return -EINVAL;
	}

	return drm_bridge_attach(encoder, oldi->next_bridge, bridge, flags);
}

static int
tidss_oldi_set_serial_clk(struct tidss_oldi *oldi, unsigned long rate)
{
	unsigned long new_rate;
	int ret;

	ret = clk_set_rate(oldi->serial, rate);
	if (ret) {
		dev_err(oldi->dev,
			"OLDI%u: failed to set serial clk rate to %lu Hz\n",
			 oldi->oldi_instance, rate);
		return ret;
	}

	new_rate = clk_get_rate(oldi->serial);

	if (dispc_pclk_diff(rate, new_rate) > 5)
		dev_warn(oldi->dev,
			 "OLDI%u Clock rate %lu differs over 5%% from requested %lu\n",
			 oldi->oldi_instance, new_rate, rate);

	dev_dbg(oldi->dev, "OLDI%u: new rate %lu Hz (requested %lu Hz)\n",
		oldi->oldi_instance, clk_get_rate(oldi->serial), rate);

	return 0;
}

static void tidss_oldi_tx_power(struct tidss_oldi *oldi, bool enable)
{

Annotation

Implementation Notes