drivers/gpu/drm/panel/panel-samsung-s6d7aa0.c

Source file repositories/reference/linux-study-clean/drivers/gpu/drm/panel/panel-samsung-s6d7aa0.c

File Facts

System
Linux kernel
Corpus path
drivers/gpu/drm/panel/panel-samsung-s6d7aa0.c
Extension
.c
Size
13262 bytes
Lines
493
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 s6d7aa0 {
	struct drm_panel panel;
	struct mipi_dsi_device *dsi;
	struct gpio_desc *reset_gpio;
	struct regulator_bulk_data supplies[2];
	const struct s6d7aa0_panel_desc *desc;
};

struct s6d7aa0_panel_desc {
	unsigned int panel_type;
	void (*init_func)(struct s6d7aa0 *ctx, struct mipi_dsi_multi_context *dsi_ctx);
	void (*off_func)(struct mipi_dsi_multi_context *dsi_ctx);
	const struct drm_display_mode *drm_mode;
	unsigned long mode_flags;
	u32 bus_flags;
	bool has_backlight;
	bool use_passwd3;
};

enum s6d7aa0_panels {
	S6D7AA0_PANEL_LSL080AL02,
	S6D7AA0_PANEL_LSL080AL03,
	S6D7AA0_PANEL_LTL101AT01,
};

static inline struct s6d7aa0 *panel_to_s6d7aa0(struct drm_panel *panel)
{
	return container_of(panel, struct s6d7aa0, panel);
}

static void s6d7aa0_reset(struct s6d7aa0 *ctx)
{
	gpiod_set_value_cansleep(ctx->reset_gpio, 1);
	msleep(50);
	gpiod_set_value_cansleep(ctx->reset_gpio, 0);
	msleep(50);
}

static void s6d7aa0_lock(struct s6d7aa0 *ctx, struct mipi_dsi_multi_context *dsi_ctx, bool lock)
{
	if (lock) {
		mipi_dsi_dcs_write_seq_multi(dsi_ctx, MCS_PASSWD1, 0xa5, 0xa5);
		mipi_dsi_dcs_write_seq_multi(dsi_ctx, MCS_PASSWD2, 0xa5, 0xa5);
		if (ctx->desc->use_passwd3)
			mipi_dsi_dcs_write_seq_multi(dsi_ctx, MCS_PASSWD3, 0x5a, 0x5a);
	} else {
		mipi_dsi_dcs_write_seq_multi(dsi_ctx, MCS_PASSWD1, 0x5a, 0x5a);
		mipi_dsi_dcs_write_seq_multi(dsi_ctx, MCS_PASSWD2, 0x5a, 0x5a);
		if (ctx->desc->use_passwd3)
			mipi_dsi_dcs_write_seq_multi(dsi_ctx, MCS_PASSWD3, 0xa5, 0xa5);
	}
}

static int s6d7aa0_on(struct s6d7aa0 *ctx)
{
	struct mipi_dsi_device *dsi = ctx->dsi;
	struct mipi_dsi_multi_context dsi_ctx = { .dsi = dsi };

	ctx->desc->init_func(ctx, &dsi_ctx);

	mipi_dsi_dcs_set_display_on_multi(&dsi_ctx);

	return dsi_ctx.accum_err;
}

static void s6d7aa0_off(struct s6d7aa0 *ctx)
{
	struct mipi_dsi_device *dsi = ctx->dsi;
	struct mipi_dsi_multi_context dsi_ctx = { .dsi = dsi };

	ctx->desc->off_func(&dsi_ctx);

	mipi_dsi_dcs_set_display_off_multi(&dsi_ctx);
	mipi_dsi_msleep(&dsi_ctx, 64);

	mipi_dsi_dcs_enter_sleep_mode_multi(&dsi_ctx);

	mipi_dsi_msleep(&dsi_ctx, 120);
}

static int s6d7aa0_prepare(struct drm_panel *panel)
{
	struct s6d7aa0 *ctx = panel_to_s6d7aa0(panel);
	int ret;

	ret = regulator_bulk_enable(ARRAY_SIZE(ctx->supplies), ctx->supplies);
	if (ret < 0)
		return ret;

	s6d7aa0_reset(ctx);

Annotation

Implementation Notes