drivers/gpu/drm/bridge/waveshare-dsi.c

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

File Facts

System
Linux kernel
Corpus path
drivers/gpu/drm/bridge/waveshare-dsi.c
Extension
.c
Size
5469 bytes
Lines
207
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 ws_bridge {
	struct drm_bridge bridge;
	struct drm_bridge *next_bridge;
	struct backlight_device *backlight;
	struct device *dev;
	struct regmap *reg_map;
};

static const struct regmap_config ws_regmap_config = {
	.reg_bits = 8,
	.val_bits = 8,
	.max_register = 0xff,
};

static struct ws_bridge *bridge_to_ws_bridge(struct drm_bridge *bridge)
{
	return container_of(bridge, struct ws_bridge, bridge);
}

static int ws_bridge_attach_dsi(struct ws_bridge *ws)
{
	const struct mipi_dsi_device_info info = {
		.type = "ws-bridge",
		.channel = 0,
		.node = NULL,
	};
	struct device_node *dsi_host_node;
	struct device *dev = ws->dev;
	struct mipi_dsi_device *dsi;
	struct mipi_dsi_host *host;
	int ret;

	dsi_host_node = of_graph_get_remote_node(dev->of_node, 0, 0);
	if (!dsi_host_node) {
		dev_err(dev, "Failed to get remote port\n");
		return -ENODEV;
	}
	host = of_find_mipi_dsi_host_by_node(dsi_host_node);
	of_node_put(dsi_host_node);
	if (!host)
		return dev_err_probe(dev, -EPROBE_DEFER, "Failed to find dsi_host\n");

	dsi = devm_mipi_dsi_device_register_full(dev, host, &info);
	if (IS_ERR(dsi))
		return dev_err_probe(dev, PTR_ERR(dsi), "Failed to create dsi device\n");

	dsi->mode_flags = MIPI_DSI_MODE_VIDEO_HSE | MIPI_DSI_MODE_VIDEO |
			  MIPI_DSI_CLOCK_NON_CONTINUOUS;
	dsi->format = MIPI_DSI_FMT_RGB888;
	ret = drm_of_get_data_lanes_count_ep(dev->of_node, 0, 0, 1, 4);
	if (ret < 0) {
		dev_warn(dev, "Invalid or missing DSI lane count %d, falling back to 2 lanes\n",
			 ret);
		dsi->lanes = 2;	/* Old DT backward compatibility */
	} else {
		dsi->lanes = ret;
	}

	ret = devm_mipi_dsi_attach(dev, dsi);
	if (ret < 0)
		return dev_err_probe(dev, ret, "Failed to attach dsi to host\n");

	return 0;
}

static int ws_bridge_bridge_attach(struct drm_bridge *bridge,
				   struct drm_encoder *encoder,
				   enum drm_bridge_attach_flags flags)
{
	struct ws_bridge *ws = bridge_to_ws_bridge(bridge);

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

static void ws_bridge_bridge_enable(struct drm_bridge *bridge)
{
	struct ws_bridge *ws = bridge_to_ws_bridge(bridge);

	regmap_write(ws->reg_map, 0xad, 0x01);
	backlight_enable(ws->backlight);
}

static void ws_bridge_bridge_disable(struct drm_bridge *bridge)
{
	struct ws_bridge *ws = bridge_to_ws_bridge(bridge);

	backlight_disable(ws->backlight);
	regmap_write(ws->reg_map, 0xad, 0x00);
}

Annotation

Implementation Notes