drivers/gpu/drm/vc4/vc4_hdmi.c

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

File Facts

System
Linux kernel
Corpus path
drivers/gpu/drm/vc4/vc4_hdmi.c
Extension
.c
Size
100095 bytes
Lines
3518
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

static void vc4_hdmi_cec_update_clk_div(struct vc4_hdmi *vc4_hdmi) {}
#endif

static int vc4_hdmi_reset_link(struct drm_connector *connector,
			       struct drm_modeset_acquire_ctx *ctx)
{
	struct drm_device *drm;
	struct vc4_hdmi *vc4_hdmi;
	struct drm_connector_state *conn_state;
	struct drm_crtc_state *crtc_state;
	struct drm_crtc *crtc;
	bool scrambling_needed;
	u8 config;
	int ret;

	if (!connector)
		return 0;

	drm = connector->dev;
	ret = drm_modeset_lock(&drm->mode_config.connection_mutex, ctx);
	if (ret)
		return ret;

	conn_state = connector->state;
	crtc = conn_state->crtc;
	if (!crtc)
		return 0;

	ret = drm_modeset_lock(&crtc->mutex, ctx);
	if (ret)
		return ret;

	crtc_state = crtc->state;
	if (!crtc_state->active)
		return 0;

	vc4_hdmi = connector_to_vc4_hdmi(connector);
	mutex_lock(&vc4_hdmi->mutex);

	if (!vc4_hdmi_supports_scrambling(vc4_hdmi)) {
		mutex_unlock(&vc4_hdmi->mutex);
		return 0;
	}

	scrambling_needed = vc4_hdmi_mode_needs_scrambling(&vc4_hdmi->saved_adjusted_mode,
							   vc4_hdmi->output_bpc,
							   vc4_hdmi->output_format);
	if (!scrambling_needed) {
		mutex_unlock(&vc4_hdmi->mutex);
		return 0;
	}

	if (conn_state->commit &&
	    !try_wait_for_completion(&conn_state->commit->hw_done)) {
		mutex_unlock(&vc4_hdmi->mutex);
		return 0;
	}

	ret = drm_scdc_readb(connector->ddc, SCDC_TMDS_CONFIG, &config);
	if (ret < 0) {
		drm_err(drm, "Failed to read TMDS config: %d\n", ret);
		mutex_unlock(&vc4_hdmi->mutex);
		return 0;
	}

	if (!!(config & SCDC_SCRAMBLING_ENABLE) == scrambling_needed) {
		mutex_unlock(&vc4_hdmi->mutex);
		return 0;
	}

	mutex_unlock(&vc4_hdmi->mutex);

	/*
	 * HDMI 2.0 says that one should not send scrambled data
	 * prior to configuring the sink scrambling, and that
	 * TMDS clock/data transmission should be suspended when
	 * changing the TMDS clock rate in the sink. So let's
	 * just do a full modeset here, even though some sinks
	 * would be perfectly happy if were to just reconfigure
	 * the SCDC settings on the fly.
	 */
	return drm_atomic_helper_reset_crtc(crtc, ctx);
}

static void vc4_hdmi_handle_hotplug(struct vc4_hdmi *vc4_hdmi,
				    struct drm_modeset_acquire_ctx *ctx,
				    enum drm_connector_status status)
{
	struct drm_connector *connector = &vc4_hdmi->connector;
	int ret;

Annotation

Implementation Notes