drivers/gpu/drm/gud/gud_connector.c

Source file repositories/reference/linux-study-clean/drivers/gpu/drm/gud/gud_connector.c

File Facts

System
Linux kernel
Corpus path
drivers/gpu/drm/gud/gud_connector.c
Extension
.c
Size
19802 bytes
Lines
726
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 gud_connector {
	struct drm_connector connector;
	struct drm_encoder encoder;
	struct backlight_device *backlight;
	struct work_struct backlight_work;

	/* Supported properties */
	u16 *properties;
	unsigned int num_properties;

	/* Initial gadget tv state if applicable, applied on state reset */
	struct drm_tv_connector_state initial_tv_state;

	/*
	 * Initial gadget backlight brightness if applicable, applied on state reset.
	 * The value -ENODEV is used to signal no backlight.
	 */
	int initial_brightness;
};

static inline struct gud_connector *to_gud_connector(struct drm_connector *connector)
{
	return container_of(connector, struct gud_connector, connector);
}

static void gud_conn_err(struct drm_connector *connector, const char *msg, int ret)
{
	dev_err(connector->dev->dev, "%s: %s (ret=%d)\n", connector->name, msg, ret);
}

/*
 * Use a worker to avoid taking kms locks inside the backlight lock.
 * Other display drivers use backlight within their kms locks.
 * This avoids inconsistent locking rules, which would upset lockdep.
 */
static void gud_connector_backlight_update_status_work(struct work_struct *work)
{
	struct gud_connector *gconn = container_of(work, struct gud_connector, backlight_work);
	struct drm_connector *connector = &gconn->connector;
	struct drm_connector_state *connector_state;
	struct drm_device *drm = connector->dev;
	struct drm_modeset_acquire_ctx ctx;
	struct drm_atomic_commit *state;
	int idx, ret;

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

	state = drm_atomic_commit_alloc(drm);
	if (!state) {
		ret = -ENOMEM;
		goto exit;
	}

	drm_modeset_acquire_init(&ctx, 0);
	state->acquire_ctx = &ctx;
retry:
	connector_state = drm_atomic_get_connector_state(state, connector);
	if (IS_ERR(connector_state)) {
		ret = PTR_ERR(connector_state);
		goto out;
	}

	/* Reuse tv.brightness to avoid having to subclass */
	connector_state->tv.brightness = gconn->backlight->props.brightness;

	ret = drm_atomic_commit(state);
out:
	if (ret == -EDEADLK) {
		drm_atomic_commit_clear(state);
		drm_modeset_backoff(&ctx);
		goto retry;
	}

	drm_atomic_commit_put(state);

	drm_modeset_drop_locks(&ctx);
	drm_modeset_acquire_fini(&ctx);
exit:
	drm_dev_exit(idx);

	if (ret)
		dev_err(drm->dev, "Failed to update backlight, err=%d\n", ret);
}

static int gud_connector_backlight_update_status(struct backlight_device *bd)
{
	struct drm_connector *connector = bl_get_data(bd);
	struct gud_connector *gconn = to_gud_connector(connector);

Annotation

Implementation Notes