sound/hda/common/proc.c

Source file repositories/reference/linux-study-clean/sound/hda/common/proc.c

File Facts

System
Linux kernel
Corpus path
sound/hda/common/proc.c
Extension
.c
Size
28775 bytes
Lines
980
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 (item->nid == nid) {
			kctl = item->kctl;
			snd_iprintf(buffer,
			  "  Control: name=\"%s\", index=%i, device=%i\n",
			  kctl->id.name, kctl->id.index + item->index,
			  kctl->id.device);
			if (item->flags & HDA_NID_ITEM_AMP)
				snd_iprintf(buffer,
				  "    ControlAmp: chs=%lu, dir=%s, "
				  "idx=%lu, ofs=%lu\n",
				  get_amp_channels(kctl),
				  get_amp_direction(kctl) ? "Out" : "In",
				  get_amp_index(kctl),
				  get_amp_offset(kctl));
		}
	}
}

static void print_nid_pcms(struct snd_info_buffer *buffer,
			   struct hda_codec *codec, hda_nid_t nid)
{
	int type;
	struct hda_pcm *cpcm;

	list_for_each_entry(cpcm, &codec->pcm_list_head, list) {
		for (type = 0; type < 2; type++) {
			if (cpcm->stream[type].nid != nid || cpcm->pcm == NULL)
				continue;
			snd_iprintf(buffer, "  Device: name=\"%s\", "
				    "type=\"%s\", device=%i\n",
				    cpcm->name,
				    snd_hda_pcm_type_name[cpcm->pcm_type],
				    cpcm->pcm->device);
		}
	}
}

static void print_amp_caps(struct snd_info_buffer *buffer,
			   struct hda_codec *codec, hda_nid_t nid, int dir)
{
	unsigned int caps;
	caps = param_read(codec, nid, dir == HDA_OUTPUT ?
			  AC_PAR_AMP_OUT_CAP : AC_PAR_AMP_IN_CAP);
	if (caps == -1 || caps == 0) {
		snd_iprintf(buffer, "N/A\n");
		return;
	}
	snd_iprintf(buffer, "ofs=0x%02x, nsteps=0x%02x, stepsize=0x%02x, "
		    "mute=%x\n",
		    caps & AC_AMPCAP_OFFSET,
		    (caps & AC_AMPCAP_NUM_STEPS) >> AC_AMPCAP_NUM_STEPS_SHIFT,
		    (caps & AC_AMPCAP_STEP_SIZE) >> AC_AMPCAP_STEP_SIZE_SHIFT,
		    (caps & AC_AMPCAP_MUTE) >> AC_AMPCAP_MUTE_SHIFT);
}

/* is this a stereo widget or a stereo-to-mono mix? */
static bool is_stereo_amps(struct hda_codec *codec, hda_nid_t nid,
			   int dir, unsigned int wcaps, int indices)
{
	hda_nid_t conn;

	if (wcaps & AC_WCAP_STEREO)
		return true;
	/* check for a stereo-to-mono mix; it must be:
	 * only a single connection, only for input, and only a mixer widget
	 */
	if (indices != 1 || dir != HDA_INPUT ||
	    get_wcaps_type(wcaps) != AC_WID_AUD_MIX)
		return false;

	if (snd_hda_get_raw_connections(codec, nid, &conn, 1) < 0)
		return false;
	/* the connection source is a stereo? */
	wcaps = snd_hda_param_read(codec, conn, AC_PAR_AUDIO_WIDGET_CAP);
	return !!(wcaps & AC_WCAP_STEREO);
}

static void print_amp_vals(struct snd_info_buffer *buffer,
			   struct hda_codec *codec, hda_nid_t nid,
			   int dir, unsigned int wcaps, int indices)
{
	unsigned int val;
	bool stereo;
	int i;

	stereo = is_stereo_amps(codec, nid, dir, wcaps, indices);

	dir = dir == HDA_OUTPUT ? AC_AMP_GET_OUTPUT : AC_AMP_GET_INPUT;
	for (i = 0; i < indices; i++) {
		snd_iprintf(buffer, " [");

Annotation

Implementation Notes