drivers/gpu/drm/bridge/simple-bridge.c

Source file repositories/reference/linux-study-clean/drivers/gpu/drm/bridge/simple-bridge.c

File Facts

System
Linux kernel
Corpus path
drivers/gpu/drm/bridge/simple-bridge.c
Extension
.c
Size
9208 bytes
Lines
327
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 simple_bridge_info {
	const struct drm_bridge_timings *timings;
	unsigned int connector_type;
};

struct simple_bridge {
	struct drm_bridge	bridge;
	struct drm_connector	connector;

	const struct simple_bridge_info *info;

	struct regulator	*vdd;
	struct gpio_desc	*enable;
};

static inline struct simple_bridge *
drm_bridge_to_simple_bridge(struct drm_bridge *bridge)
{
	return container_of(bridge, struct simple_bridge, bridge);
}

static inline struct simple_bridge *
drm_connector_to_simple_bridge(struct drm_connector *connector)
{
	return container_of(connector, struct simple_bridge, connector);
}

static int simple_bridge_get_modes(struct drm_connector *connector)
{
	struct simple_bridge *sbridge = drm_connector_to_simple_bridge(connector);
	const struct drm_edid *drm_edid;
	int ret;

	if (sbridge->bridge.next_bridge->ops & DRM_BRIDGE_OP_EDID) {
		drm_edid = drm_bridge_edid_read(sbridge->bridge.next_bridge, connector);
		if (!drm_edid)
			DRM_INFO("EDID read failed. Fallback to standard modes\n");
	} else {
		drm_edid = NULL;
	}

	drm_edid_connector_update(connector, drm_edid);

	if (!drm_edid) {
		/*
		 * In case we cannot retrieve the EDIDs (missing or broken DDC
		 * bus from the next bridge), fallback on the XGA standards and
		 * prefer a mode pretty much anyone can handle.
		 */
		ret = drm_add_modes_noedid(connector, 1920, 1200);
		drm_set_preferred_mode(connector, 1024, 768);
		return ret;
	}

	ret = drm_edid_connector_add_modes(connector);
	drm_edid_free(drm_edid);

	return ret;
}

static const struct drm_connector_helper_funcs simple_bridge_con_helper_funcs = {
	.get_modes	= simple_bridge_get_modes,
};

static enum drm_connector_status
simple_bridge_connector_detect(struct drm_connector *connector, bool force)
{
	struct simple_bridge *sbridge = drm_connector_to_simple_bridge(connector);

	return drm_bridge_detect(sbridge->bridge.next_bridge, connector);
}

static const struct drm_connector_funcs simple_bridge_con_funcs = {
	.detect			= simple_bridge_connector_detect,
	.fill_modes		= drm_helper_probe_single_connector_modes,
	.destroy		= drm_connector_cleanup,
	.reset			= drm_atomic_helper_connector_reset,
	.atomic_duplicate_state	= drm_atomic_helper_connector_duplicate_state,
	.atomic_destroy_state	= drm_atomic_helper_connector_destroy_state,
};

static int simple_bridge_attach(struct drm_bridge *bridge,
				struct drm_encoder *encoder,
				enum drm_bridge_attach_flags flags)
{
	struct simple_bridge *sbridge = drm_bridge_to_simple_bridge(bridge);
	int ret;

	ret = drm_bridge_attach(encoder, sbridge->bridge.next_bridge, bridge,
				DRM_BRIDGE_ATTACH_NO_CONNECTOR);

Annotation

Implementation Notes