drivers/gpu/drm/omapdrm/dss/hdmi4.c

Source file repositories/reference/linux-study-clean/drivers/gpu/drm/omapdrm/dss/hdmi4.c

File Facts

System
Linux kernel
Corpus path
drivers/gpu/drm/omapdrm/dss/hdmi4.c
Extension
.c
Size
19171 bytes
Lines
857
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

if (ret) {
			DSSERR("Error restoring audio configuration: %d", ret);
			hdmi->audio_abort_cb(&hdmi->pdev->dev);
			hdmi->audio_configured = false;
		}
	}

	spin_lock_irqsave(&hdmi->audio_playing_lock, flags);
	if (hdmi->audio_configured && hdmi->audio_playing)
		hdmi_start_audio_stream(hdmi);
	hdmi->display_enabled = true;
	spin_unlock_irqrestore(&hdmi->audio_playing_lock, flags);

done:
	mutex_unlock(&hdmi->lock);
}

static void hdmi4_bridge_disable(struct drm_bridge *bridge,
				 struct drm_atomic_commit *state)
{
	struct omap_hdmi *hdmi = drm_bridge_to_hdmi(bridge);
	unsigned long flags;

	mutex_lock(&hdmi->lock);

	spin_lock_irqsave(&hdmi->audio_playing_lock, flags);
	hdmi_stop_audio_stream(hdmi);
	hdmi->display_enabled = false;
	spin_unlock_irqrestore(&hdmi->audio_playing_lock, flags);

	hdmi_power_off_full(hdmi);

	mutex_unlock(&hdmi->lock);
}

static void hdmi4_bridge_hpd_notify(struct drm_bridge *bridge,
				    struct drm_connector *connector,
				    enum drm_connector_status status)
{
	struct omap_hdmi *hdmi = drm_bridge_to_hdmi(bridge);

	if (status == connector_status_disconnected)
		hdmi4_cec_set_phys_addr(&hdmi->core, CEC_PHYS_ADDR_INVALID);
}

static const struct drm_edid *hdmi4_bridge_edid_read(struct drm_bridge *bridge,
						     struct drm_connector *connector)
{
	struct omap_hdmi *hdmi = drm_bridge_to_hdmi(bridge);
	const struct drm_edid *drm_edid = NULL;
	unsigned int cec_addr;
	bool need_enable;
	int r;

	need_enable = hdmi->core_enabled == false;

	if (need_enable) {
		r = hdmi4_core_enable(&hdmi->core);
		if (r)
			return NULL;
	}

	mutex_lock(&hdmi->lock);
	r = hdmi_runtime_get(hdmi);
	BUG_ON(r);

	r = hdmi4_core_ddc_init(&hdmi->core);
	if (r)
		goto done;

	drm_edid = drm_edid_read_custom(connector, hdmi4_core_ddc_read, &hdmi->core);

done:
	hdmi_runtime_put(hdmi);
	mutex_unlock(&hdmi->lock);

	if (drm_edid) {
		/*
		 * FIXME: The CEC physical address should be set using
		 * hdmi4_cec_set_phys_addr(&hdmi->core,
		 * connector->display_info.source_physical_address) from a path
		 * that has read the EDID and called
		 * drm_edid_connector_update().
		 */
		const struct edid *edid = drm_edid_raw(drm_edid);
		unsigned int len = (edid->extensions + 1) * EDID_LENGTH;

		cec_addr = cec_get_edid_phys_addr((u8 *)edid, len, NULL);
	} else {
		cec_addr = CEC_PHYS_ADDR_INVALID;

Annotation

Implementation Notes