drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c

Source file repositories/reference/linux-study-clean/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c

File Facts

System
Linux kernel
Corpus path
drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c
Extension
.c
Size
40440 bytes
Lines
1412
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 cdns_dsi_bridge_state {
	struct drm_bridge_state base;
	struct cdns_dsi_cfg dsi_cfg;
};

static inline struct cdns_dsi_bridge_state *
to_cdns_dsi_bridge_state(struct drm_bridge_state *bridge_state)
{
	return container_of(bridge_state, struct cdns_dsi_bridge_state, base);
}

static inline struct cdns_dsi *input_to_dsi(struct cdns_dsi_input *input)
{
	return container_of(input, struct cdns_dsi, input);
}

static inline struct cdns_dsi *to_cdns_dsi(struct mipi_dsi_host *host)
{
	return container_of(host, struct cdns_dsi, base);
}

static inline struct cdns_dsi_input *
bridge_to_cdns_dsi_input(struct drm_bridge *bridge)
{
	return container_of(bridge, struct cdns_dsi_input, bridge);
}

static unsigned int dpi_to_dsi_timing(unsigned int dpi_timing,
				      unsigned int dpi_bpp,
				      unsigned int dsi_pkt_overhead)
{
	unsigned int dsi_timing = DIV_ROUND_UP(dpi_timing * dpi_bpp, 8);

	if (dsi_timing < dsi_pkt_overhead)
		dsi_timing = 0;
	else
		dsi_timing -= dsi_pkt_overhead;

	return dsi_timing;
}

static int cdns_dsi_mode2cfg(struct cdns_dsi *dsi,
			     const struct videomode *vm,
			     struct cdns_dsi_cfg *dsi_cfg)
{
	struct cdns_dsi_output *output = &dsi->output;
	u32 dpi_hsa, dpi_hbp, dpi_hfp, dpi_hact;
	bool sync_pulse;
	int bpp;

	dpi_hsa = vm->hsync_len;
	dpi_hbp = vm->hback_porch;
	dpi_hfp = vm->hfront_porch;
	dpi_hact = vm->hactive;

	memset(dsi_cfg, 0, sizeof(*dsi_cfg));

	sync_pulse = output->dev->mode_flags & MIPI_DSI_MODE_VIDEO_SYNC_PULSE;

	bpp = mipi_dsi_pixel_format_to_bpp(output->dev->format);

	if (sync_pulse) {
		dsi_cfg->hbp = dpi_to_dsi_timing(dpi_hbp, bpp,
						 DSI_HBP_FRAME_PULSE_OVERHEAD);

		dsi_cfg->hsa = dpi_to_dsi_timing(dpi_hsa, bpp,
						 DSI_HSA_FRAME_OVERHEAD);
	} else {
		dsi_cfg->hbp = dpi_to_dsi_timing(dpi_hbp + dpi_hsa, bpp,
						 DSI_HBP_FRAME_EVENT_OVERHEAD);

		dsi_cfg->hsa = 0;
	}

	dsi_cfg->hact = dpi_to_dsi_timing(dpi_hact, bpp, 0);

	dsi_cfg->hfp = dpi_to_dsi_timing(dpi_hfp, bpp, DSI_HFP_FRAME_OVERHEAD);

	dsi_cfg->htotal = dsi_cfg->hact + dsi_cfg->hfp + DSI_HFP_FRAME_OVERHEAD;

	if (sync_pulse) {
		dsi_cfg->htotal += dsi_cfg->hbp + DSI_HBP_FRAME_PULSE_OVERHEAD;
		dsi_cfg->htotal += dsi_cfg->hsa + DSI_HSA_FRAME_OVERHEAD;
	} else {
		dsi_cfg->htotal += dsi_cfg->hbp + DSI_HBP_FRAME_EVENT_OVERHEAD;
	}

	return 0;
}

Annotation

Implementation Notes