sound/hda/codecs/hdmi/atihdmi.c
Source file repositories/reference/linux-study-clean/sound/hda/codecs/hdmi/atihdmi.c
File Facts
- System
- Linux kernel
- Corpus path
sound/hda/codecs/hdmi/atihdmi.c- Extension
.c- Size
- 18134 bytes
- Lines
- 616
- 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.
- 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.
- Defines or uses C structs; map object ownership, embedded links, reference counts, and lock ownership.
Dependency Surface
linux/init.hlinux/slab.hlinux/module.hlinux/unaligned.hsound/core.hsound/tlv.hsound/hdaudio.hsound/hda_codec.hhda_local.hhdmi_local.h
Detected Declarations
enum ati_sink_info_idxfunction get_eld_atifunction atihdmi_pin_get_eldfunction atihdmi_pin_setup_infoframefunction atihdmi_paired_swap_fc_lfefunction atihdmi_paired_chmap_validatefunction atihdmi_pin_set_slot_channelfunction atihdmi_pin_get_slot_channelfunction atihdmi_paired_chmap_cea_alloc_validate_get_typefunction atihdmi_paired_cea_alloc_to_tlv_chmapfunction atihdmi_pin_hbr_setupfunction atihdmi_setup_streamfunction atihdmi_initfunction atihdmi_pin2portfunction atihdmi_port2pinfunction atihdmi_probe
Annotated Snippet
if (sink_desc_len > ELD_MAX_MNL) {
codec_info(codec, "HDMI ATI/AMD: Truncating HDMI sink description with length %d\n",
sink_desc_len);
sink_desc_len = ELD_MAX_MNL;
}
buf[4] |= sink_desc_len;
for (i = 0; i < sink_desc_len; i++) {
snd_hda_codec_write(codec, nid, 0, ATI_VERB_SET_SINK_INFO_INDEX, ATI_INFO_IDX_SINK_DESC_FIRST + i);
buf[pos++] = snd_hda_codec_read(codec, nid, 0, ATI_VERB_GET_SINK_INFO_DATA, 0);
}
}
for (i = AUDIO_CODING_TYPE_LPCM; i <= AUDIO_CODING_TYPE_WMAPRO; i++) {
if (i == AUDIO_CODING_TYPE_SACD || i == AUDIO_CODING_TYPE_DST)
continue; /* not handled by ATI/AMD */
snd_hda_codec_write(codec, nid, 0, ATI_VERB_SET_AUDIO_DESCRIPTOR, i << 3);
ati_sad = snd_hda_codec_read(codec, nid, 0, ATI_VERB_GET_AUDIO_DESCRIPTOR, 0);
if (ati_sad <= 0)
continue;
if (ati_sad & ATI_AUDIODESC_RATES) {
/* format is supported, copy SAD as-is */
buf[pos++] = (ati_sad & 0x0000ff) >> 0;
buf[pos++] = (ati_sad & 0x00ff00) >> 8;
buf[pos++] = (ati_sad & 0xff0000) >> 16;
}
if (i == AUDIO_CODING_TYPE_LPCM
&& (ati_sad & ATI_AUDIODESC_LPCM_STEREO_RATES)
&& (ati_sad & ATI_AUDIODESC_LPCM_STEREO_RATES) >> 16 != (ati_sad & ATI_AUDIODESC_RATES)) {
/* for PCM there is a separate stereo rate mask */
buf[pos++] = ((ati_sad & 0x000000ff) & ~ATI_AUDIODESC_CHANNELS) | 0x1;
/* rates from the extra byte */
buf[pos++] = (ati_sad & 0xff000000) >> 24;
buf[pos++] = (ati_sad & 0x00ff0000) >> 16;
}
}
if (pos == ELD_FIXED_BYTES + sink_desc_len) {
codec_info(codec, "HDMI ATI/AMD: no audio descriptors for ELD\n");
return -EINVAL;
}
/*
* HDMI VSDB latency format:
* separately for both audio and video:
* 0 field not valid or unknown latency
* [1..251] msecs = (x-1)*2 (max 500ms with x = 251 = 0xfb)
* 255 audio/video not supported
*
* HDA latency format:
* single value indicating video latency relative to audio:
* 0 unknown or 0ms
* [1..250] msecs = x*2 (max 500ms with x = 250 = 0xfa)
* [251..255] reserved
*/
aud_synch = snd_hda_codec_read(codec, nid, 0, ATI_VERB_GET_AUDIO_VIDEO_DELAY, 0);
if ((aud_synch & ATI_DELAY_VIDEO_LATENCY) && (aud_synch & ATI_DELAY_AUDIO_LATENCY)) {
int video_latency_hdmi = (aud_synch & ATI_DELAY_VIDEO_LATENCY);
int audio_latency_hdmi = (aud_synch & ATI_DELAY_AUDIO_LATENCY) >> 8;
if (video_latency_hdmi <= 0xfb && audio_latency_hdmi <= 0xfb &&
video_latency_hdmi > audio_latency_hdmi)
buf[6] = video_latency_hdmi - audio_latency_hdmi;
/* else unknown/invalid or 0ms or video ahead of audio, so use zero */
}
/* SAD count */
buf[5] |= ((pos - ELD_FIXED_BYTES - sink_desc_len) / 3) << 4;
/* Baseline ELD block length is 4-byte aligned */
pos = round_up(pos, 4);
/* Baseline ELD length (4-byte header is not counted in) */
buf[2] = (pos - 4) / 4;
*eld_size = pos;
return 0;
}
static int atihdmi_pin_get_eld(struct hda_codec *codec, hda_nid_t nid,
int dev_id, unsigned char *buf, int *eld_size)
{
WARN_ON(dev_id != 0);
/* call hda_eld.c ATI/AMD-specific function */
Annotation
- Immediate include surface: `linux/init.h`, `linux/slab.h`, `linux/module.h`, `linux/unaligned.h`, `sound/core.h`, `sound/tlv.h`, `sound/hdaudio.h`, `sound/hda_codec.h`.
- Detected declarations: `enum ati_sink_info_idx`, `function get_eld_ati`, `function atihdmi_pin_get_eld`, `function atihdmi_pin_setup_infoframe`, `function atihdmi_paired_swap_fc_lfe`, `function atihdmi_paired_chmap_validate`, `function atihdmi_pin_set_slot_channel`, `function atihdmi_pin_get_slot_channel`, `function atihdmi_paired_chmap_cea_alloc_validate_get_type`, `function atihdmi_paired_cea_alloc_to_tlv_chmap`.
- Atlas domain: Driver Families / sound/hda.
- Implementation status: source implementation candidate.
Implementation Notes
- This generated page is the file-by-file coverage layer; curated subsystem chapters should link here when they synthesize a multi-file control flow.
- Core OS pages should be promoted from atlas-only to deep-reviewed when they explain data structures, invariants, locking, lifecycle, and C implementation snippets.
- Driver-family pages are intentionally pattern-oriented unless they are part of the selected PCIe/NVMe representative device path.