sound/hda/codecs/hdmi/intelhdmi.c

Source file repositories/reference/linux-study-clean/sound/hda/codecs/hdmi/intelhdmi.c

File Facts

System
Linux kernel
Corpus path
sound/hda/codecs/hdmi/intelhdmi.c
Extension
.c
Size
22796 bytes
Lines
813
Domain
Driver Families
Bucket
sound/hda
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 (power_state == AC_PWRST_D0) {
			intel_haswell_enable_all_pins(codec, false);
			intel_haswell_fixup_enable_dp12(codec);
		}
	}

	snd_hda_codec_write_sync(codec, fg, 0, AC_VERB_SET_POWER_STATE, power_state);
	snd_hda_codec_set_power_to_all(codec, fg, power_state);
}

/* There is a fixed mapping between audio pin node and display port.
 * on SNB, IVY, HSW, BSW, SKL, BXT, KBL:
 * Pin Widget 5 - PORT B (port = 1 in i915 driver)
 * Pin Widget 6 - PORT C (port = 2 in i915 driver)
 * Pin Widget 7 - PORT D (port = 3 in i915 driver)
 *
 * on VLV, ILK:
 * Pin Widget 4 - PORT B (port = 1 in i915 driver)
 * Pin Widget 5 - PORT C (port = 2 in i915 driver)
 * Pin Widget 6 - PORT D (port = 3 in i915 driver)
 */
static int intel_base_nid(struct hda_codec *codec)
{
	switch (codec->core.vendor_id) {
	case 0x80860054: /* ILK */
	case 0x80862804: /* ILK */
	case 0x80862882: /* VLV */
		return 4;
	default:
		return 5;
	}
}

static int intel_pin2port(void *audio_ptr, int pin_nid)
{
	struct hda_codec *codec = audio_ptr;
	struct hdmi_spec *spec = codec->spec;
	int base_nid, i;

	if (!spec->port_num) {
		base_nid = intel_base_nid(codec);
		if (WARN_ON(pin_nid < base_nid || pin_nid >= base_nid + 3))
			return -1;
		return pin_nid - base_nid + 1;
	}

	/*
	 * looking for the pin number in the mapping table and return
	 * the index which indicate the port number
	 */
	for (i = 0; i < spec->port_num; i++) {
		if (pin_nid == spec->port_map[i])
			return i;
	}

	codec_info(codec, "Can't find the HDMI/DP port for pin NID 0x%x\n", pin_nid);
	return -1;
}

static int intel_port2pin(struct hda_codec *codec, int port)
{
	struct hdmi_spec *spec = codec->spec;

	if (!spec->port_num) {
		/* we assume only from port-B to port-D */
		if (port < 1 || port > 3)
			return 0;
		return port + intel_base_nid(codec) - 1;
	}

	if (port < 0 || port >= spec->port_num)
		return 0;
	return spec->port_map[port];
}

static void intel_pin_eld_notify(void *audio_ptr, int port, int pipe)
{
	struct hda_codec *codec = audio_ptr;
	int pin_nid;
	int dev_id = pipe;

	pin_nid = intel_port2pin(codec, port);
	if (!pin_nid)
		return;
	/* skip notification during system suspend (but not in runtime PM);
	 * the state will be updated at resume
	 */
	if (codec->core.dev.power.power_state.event == PM_EVENT_SUSPEND)
		return;

Annotation

Implementation Notes