drivers/gpu/drm/vc4/vc4_dpi.c

Source file repositories/reference/linux-study-clean/drivers/gpu/drm/vc4/vc4_dpi.c

File Facts

System
Linux kernel
Corpus path
drivers/gpu/drm/vc4/vc4_dpi.c
Extension
.c
Size
10652 bytes
Lines
405
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 vc4_dpi {
	struct vc4_encoder encoder;

	struct platform_device *pdev;

	void __iomem *regs;

	struct clk *pixel_clock;
	struct clk *core_clock;

	struct debugfs_regset32 regset;
};

#define to_vc4_dpi(_encoder)						\
	container_of_const(_encoder, struct vc4_dpi, encoder.base)

#define DPI_READ(offset)								\
	({										\
		kunit_fail_current_test("Accessing a register in a unit test!\n");	\
		readl(dpi->regs + (offset));						\
	})

#define DPI_WRITE(offset, val)								\
	do {										\
		kunit_fail_current_test("Accessing a register in a unit test!\n");	\
		writel(val, dpi->regs + (offset));					\
	} while (0)

static const struct debugfs_reg32 dpi_regs[] = {
	VC4_REG32(DPI_C),
	VC4_REG32(DPI_ID),
};

static void vc4_dpi_encoder_disable(struct drm_encoder *encoder)
{
	struct drm_device *dev = encoder->dev;
	struct vc4_dpi *dpi = to_vc4_dpi(encoder);
	int idx;

	if (!drm_dev_enter(dev, &idx))
		return;

	clk_disable_unprepare(dpi->pixel_clock);

	drm_dev_exit(idx);
}

static void vc4_dpi_encoder_enable(struct drm_encoder *encoder)
{
	struct drm_device *dev = encoder->dev;
	struct drm_display_mode *mode = &encoder->crtc->mode;
	struct vc4_dpi *dpi = to_vc4_dpi(encoder);
	struct drm_connector_list_iter conn_iter;
	struct drm_connector *connector = NULL, *connector_scan;
	u32 dpi_c = DPI_ENABLE;
	int idx;
	int ret;

	/* Look up the connector attached to DPI so we can get the
	 * bus_format.  Ideally the bridge would tell us the
	 * bus_format we want, but it doesn't yet, so assume that it's
	 * uniform throughout the bridge chain.
	 */
	drm_connector_list_iter_begin(dev, &conn_iter);
	drm_for_each_connector_iter(connector_scan, &conn_iter) {
		if (connector_scan->encoder == encoder) {
			connector = connector_scan;
			break;
		}
	}
	drm_connector_list_iter_end(&conn_iter);

	/* Default to 18bit if no connector or format found. */
	dpi_c |= VC4_SET_FIELD(DPI_FORMAT_18BIT_666_RGB_1, DPI_FORMAT);

	if (connector) {
		if (connector->display_info.num_bus_formats) {
			u32 bus_format = connector->display_info.bus_formats[0];

			dpi_c &= ~DPI_FORMAT_MASK;

			switch (bus_format) {
			case MEDIA_BUS_FMT_RGB888_1X24:
				dpi_c |= VC4_SET_FIELD(DPI_FORMAT_24BIT_888_RGB,
						       DPI_FORMAT);
				break;
			case MEDIA_BUS_FMT_BGR888_1X24:
				dpi_c |= VC4_SET_FIELD(DPI_FORMAT_24BIT_888_RGB,
						       DPI_FORMAT);
				dpi_c |= VC4_SET_FIELD(DPI_ORDER_BGR,

Annotation

Implementation Notes