Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   1) // SPDX-License-Identifier: GPL-2.0-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   3)  * Universal Interface for Intel High Definition Audio Codec
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4)  * 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5)  * Generic proc interface
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7)  * Copyright (c) 2004 Takashi Iwai <tiwai@suse.de>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12) #include <sound/core.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14) #include <sound/hda_codec.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15) #include "hda_local.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17) static int dump_coef = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18) module_param(dump_coef, int, 0644);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19) MODULE_PARM_DESC(dump_coef, "Dump processing coefficients in codec proc file (-1=auto, 0=disable, 1=enable)");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21) /* always use noncached version */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22) #define param_read(codec, nid, parm) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23) 	snd_hdac_read_parm_uncached(&(codec)->core, nid, parm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25) static const char *get_wid_type_name(unsigned int wid_value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27) 	static const char * const names[16] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28) 		[AC_WID_AUD_OUT] = "Audio Output",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29) 		[AC_WID_AUD_IN] = "Audio Input",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30) 		[AC_WID_AUD_MIX] = "Audio Mixer",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31) 		[AC_WID_AUD_SEL] = "Audio Selector",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32) 		[AC_WID_PIN] = "Pin Complex",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33) 		[AC_WID_POWER] = "Power Widget",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34) 		[AC_WID_VOL_KNB] = "Volume Knob Widget",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35) 		[AC_WID_BEEP] = "Beep Generator Widget",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36) 		[AC_WID_VENDOR] = "Vendor Defined Widget",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37) 	};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38) 	if (wid_value == -1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39) 		return "UNKNOWN Widget";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40) 	wid_value &= 0xf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41) 	if (names[wid_value])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42) 		return names[wid_value];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44) 		return "UNKNOWN Widget";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47) static void print_nid_array(struct snd_info_buffer *buffer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48) 			    struct hda_codec *codec, hda_nid_t nid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49) 			    struct snd_array *array)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52) 	struct hda_nid_item *items = array->list, *item;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53) 	struct snd_kcontrol *kctl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54) 	for (i = 0; i < array->used; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55) 		item = &items[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56) 		if (item->nid == nid) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57) 			kctl = item->kctl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58) 			snd_iprintf(buffer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59) 			  "  Control: name=\"%s\", index=%i, device=%i\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60) 			  kctl->id.name, kctl->id.index + item->index,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61) 			  kctl->id.device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62) 			if (item->flags & HDA_NID_ITEM_AMP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63) 				snd_iprintf(buffer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64) 				  "    ControlAmp: chs=%lu, dir=%s, "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65) 				  "idx=%lu, ofs=%lu\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66) 				  get_amp_channels(kctl),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67) 				  get_amp_direction(kctl) ? "Out" : "In",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68) 				  get_amp_index(kctl),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69) 				  get_amp_offset(kctl));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74) static void print_nid_pcms(struct snd_info_buffer *buffer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75) 			   struct hda_codec *codec, hda_nid_t nid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77) 	int type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78) 	struct hda_pcm *cpcm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80) 	list_for_each_entry(cpcm, &codec->pcm_list_head, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81) 		for (type = 0; type < 2; type++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82) 			if (cpcm->stream[type].nid != nid || cpcm->pcm == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83) 				continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84) 			snd_iprintf(buffer, "  Device: name=\"%s\", "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85) 				    "type=\"%s\", device=%i\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86) 				    cpcm->name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87) 				    snd_hda_pcm_type_name[cpcm->pcm_type],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88) 				    cpcm->pcm->device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) static void print_amp_caps(struct snd_info_buffer *buffer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94) 			   struct hda_codec *codec, hda_nid_t nid, int dir)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) 	unsigned int caps;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) 	caps = param_read(codec, nid, dir == HDA_OUTPUT ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) 			  AC_PAR_AMP_OUT_CAP : AC_PAR_AMP_IN_CAP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) 	if (caps == -1 || caps == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) 		snd_iprintf(buffer, "N/A\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) 	snd_iprintf(buffer, "ofs=0x%02x, nsteps=0x%02x, stepsize=0x%02x, "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) 		    "mute=%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) 		    caps & AC_AMPCAP_OFFSET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) 		    (caps & AC_AMPCAP_NUM_STEPS) >> AC_AMPCAP_NUM_STEPS_SHIFT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) 		    (caps & AC_AMPCAP_STEP_SIZE) >> AC_AMPCAP_STEP_SIZE_SHIFT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) 		    (caps & AC_AMPCAP_MUTE) >> AC_AMPCAP_MUTE_SHIFT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) /* is this a stereo widget or a stereo-to-mono mix? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) static bool is_stereo_amps(struct hda_codec *codec, hda_nid_t nid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) 			   int dir, unsigned int wcaps, int indices)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) 	hda_nid_t conn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) 	if (wcaps & AC_WCAP_STEREO)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) 		return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) 	/* check for a stereo-to-mono mix; it must be:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) 	 * only a single connection, only for input, and only a mixer widget
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) 	if (indices != 1 || dir != HDA_INPUT ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) 	    get_wcaps_type(wcaps) != AC_WID_AUD_MIX)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) 		return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) 	if (snd_hda_get_raw_connections(codec, nid, &conn, 1) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) 		return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) 	/* the connection source is a stereo? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) 	wcaps = snd_hda_param_read(codec, conn, AC_PAR_AUDIO_WIDGET_CAP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) 	return !!(wcaps & AC_WCAP_STEREO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) static void print_amp_vals(struct snd_info_buffer *buffer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) 			   struct hda_codec *codec, hda_nid_t nid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) 			   int dir, unsigned int wcaps, int indices)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) 	unsigned int val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) 	bool stereo;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) 	stereo = is_stereo_amps(codec, nid, dir, wcaps, indices);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) 	dir = dir == HDA_OUTPUT ? AC_AMP_GET_OUTPUT : AC_AMP_GET_INPUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) 	for (i = 0; i < indices; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) 		snd_iprintf(buffer, " [");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) 		val = snd_hda_codec_read(codec, nid, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) 					 AC_VERB_GET_AMP_GAIN_MUTE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) 					 AC_AMP_GET_LEFT | dir | i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) 		snd_iprintf(buffer, "0x%02x", val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) 		if (stereo) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) 			val = snd_hda_codec_read(codec, nid, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) 						 AC_VERB_GET_AMP_GAIN_MUTE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) 						 AC_AMP_GET_RIGHT | dir | i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) 			snd_iprintf(buffer, " 0x%02x", val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) 		snd_iprintf(buffer, "]");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) 	snd_iprintf(buffer, "\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) static void print_pcm_rates(struct snd_info_buffer *buffer, unsigned int pcm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) 	static const unsigned int rates[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) 		8000, 11025, 16000, 22050, 32000, 44100, 48000, 88200,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) 		96000, 176400, 192000, 384000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) 	};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) 	pcm &= AC_SUPPCM_RATES;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) 	snd_iprintf(buffer, "    rates [0x%x]:", pcm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) 	for (i = 0; i < ARRAY_SIZE(rates); i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) 		if (pcm & (1 << i))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) 			snd_iprintf(buffer,  " %d", rates[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) 	snd_iprintf(buffer, "\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) static void print_pcm_bits(struct snd_info_buffer *buffer, unsigned int pcm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) 	char buf[SND_PRINT_BITS_ADVISED_BUFSIZE];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) 	snd_iprintf(buffer, "    bits [0x%x]:", (pcm >> 16) & 0xff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) 	snd_print_pcm_bits(pcm, buf, sizeof(buf));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) 	snd_iprintf(buffer, "%s\n", buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) static void print_pcm_formats(struct snd_info_buffer *buffer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) 			      unsigned int streams)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) 	snd_iprintf(buffer, "    formats [0x%x]:", streams & 0xf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) 	if (streams & AC_SUPFMT_PCM)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) 		snd_iprintf(buffer, " PCM");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) 	if (streams & AC_SUPFMT_FLOAT32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) 		snd_iprintf(buffer, " FLOAT");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) 	if (streams & AC_SUPFMT_AC3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) 		snd_iprintf(buffer, " AC3");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) 	snd_iprintf(buffer, "\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) static void print_pcm_caps(struct snd_info_buffer *buffer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) 			   struct hda_codec *codec, hda_nid_t nid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) 	unsigned int pcm = param_read(codec, nid, AC_PAR_PCM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) 	unsigned int stream = param_read(codec, nid, AC_PAR_STREAM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) 	if (pcm == -1 || stream == -1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) 		snd_iprintf(buffer, "N/A\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) 	print_pcm_rates(buffer, pcm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) 	print_pcm_bits(buffer, pcm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) 	print_pcm_formats(buffer, stream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) static const char *get_jack_connection(u32 cfg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) 	static const char * const names[16] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) 		"Unknown", "1/8", "1/4", "ATAPI",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) 		"RCA", "Optical","Digital", "Analog",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) 		"DIN", "XLR", "RJ11", "Comb",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) 		NULL, NULL, NULL, "Other"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) 	};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) 	cfg = (cfg & AC_DEFCFG_CONN_TYPE) >> AC_DEFCFG_CONN_TYPE_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) 	if (names[cfg])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) 		return names[cfg];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) 		return "UNKNOWN";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) static const char *get_jack_color(u32 cfg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) 	static const char * const names[16] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) 		"Unknown", "Black", "Grey", "Blue",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) 		"Green", "Red", "Orange", "Yellow",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) 		"Purple", "Pink", NULL, NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) 		NULL, NULL, "White", "Other",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) 	};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) 	cfg = (cfg & AC_DEFCFG_COLOR) >> AC_DEFCFG_COLOR_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) 	if (names[cfg])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) 		return names[cfg];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) 		return "UNKNOWN";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244)  * Parse the pin default config value and returns the string of the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245)  * jack location, e.g. "Rear", "Front", etc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) static const char *get_jack_location(u32 cfg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) 	static const char * const bases[7] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) 		"N/A", "Rear", "Front", "Left", "Right", "Top", "Bottom",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) 	};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) 	static const unsigned char specials_idx[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) 		0x07, 0x08,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) 		0x17, 0x18, 0x19,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) 		0x37, 0x38
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) 	};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) 	static const char * const specials[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) 		"Rear Panel", "Drive Bar",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) 		"Riser", "HDMI", "ATAPI",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) 		"Mobile-In", "Mobile-Out"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) 	};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) 	cfg = (cfg & AC_DEFCFG_LOCATION) >> AC_DEFCFG_LOCATION_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) 	if ((cfg & 0x0f) < 7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) 		return bases[cfg & 0x0f];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) 	for (i = 0; i < ARRAY_SIZE(specials_idx); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) 		if (cfg == specials_idx[i])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) 			return specials[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) 	return "UNKNOWN";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275)  * Parse the pin default config value and returns the string of the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276)  * jack connectivity, i.e. external or internal connection.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) static const char *get_jack_connectivity(u32 cfg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) 	static const char * const jack_locations[4] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) 		"Ext", "Int", "Sep", "Oth"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) 	};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) 	return jack_locations[(cfg >> (AC_DEFCFG_LOCATION_SHIFT + 4)) & 3];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288)  * Parse the pin default config value and returns the string of the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289)  * jack type, i.e. the purpose of the jack, such as Line-Out or CD.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) static const char *get_jack_type(u32 cfg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) 	static const char * const jack_types[16] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) 		"Line Out", "Speaker", "HP Out", "CD",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) 		"SPDIF Out", "Digital Out", "Modem Line", "Modem Hand",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) 		"Line In", "Aux", "Mic", "Telephony",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) 		"SPDIF In", "Digital In", "Reserved", "Other"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) 	};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) 	return jack_types[(cfg & AC_DEFCFG_DEVICE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) 				>> AC_DEFCFG_DEVICE_SHIFT];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) static void print_pin_caps(struct snd_info_buffer *buffer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) 			   struct hda_codec *codec, hda_nid_t nid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) 			   int *supports_vref)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) 	static const char * const jack_conns[4] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) 		"Jack", "N/A", "Fixed", "Both"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) 	};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) 	unsigned int caps, val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) 	caps = param_read(codec, nid, AC_PAR_PIN_CAP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) 	snd_iprintf(buffer, "  Pincap 0x%08x:", caps);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) 	if (caps & AC_PINCAP_IN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) 		snd_iprintf(buffer, " IN");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) 	if (caps & AC_PINCAP_OUT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) 		snd_iprintf(buffer, " OUT");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) 	if (caps & AC_PINCAP_HP_DRV)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) 		snd_iprintf(buffer, " HP");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) 	if (caps & AC_PINCAP_EAPD)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) 		snd_iprintf(buffer, " EAPD");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) 	if (caps & AC_PINCAP_PRES_DETECT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) 		snd_iprintf(buffer, " Detect");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) 	if (caps & AC_PINCAP_BALANCE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) 		snd_iprintf(buffer, " Balanced");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) 	if (caps & AC_PINCAP_HDMI) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) 		/* Realtek uses this bit as a different meaning */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) 		if ((codec->core.vendor_id >> 16) == 0x10ec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) 			snd_iprintf(buffer, " R/L");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) 		else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) 			if (caps & AC_PINCAP_HBR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) 				snd_iprintf(buffer, " HBR");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) 			snd_iprintf(buffer, " HDMI");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) 	if (caps & AC_PINCAP_DP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) 		snd_iprintf(buffer, " DP");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) 	if (caps & AC_PINCAP_TRIG_REQ)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) 		snd_iprintf(buffer, " Trigger");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) 	if (caps & AC_PINCAP_IMP_SENSE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) 		snd_iprintf(buffer, " ImpSense");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) 	snd_iprintf(buffer, "\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) 	if (caps & AC_PINCAP_VREF) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) 		unsigned int vref =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) 			(caps & AC_PINCAP_VREF) >> AC_PINCAP_VREF_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) 		snd_iprintf(buffer, "    Vref caps:");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) 		if (vref & AC_PINCAP_VREF_HIZ)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) 			snd_iprintf(buffer, " HIZ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) 		if (vref & AC_PINCAP_VREF_50)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) 			snd_iprintf(buffer, " 50");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) 		if (vref & AC_PINCAP_VREF_GRD)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) 			snd_iprintf(buffer, " GRD");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) 		if (vref & AC_PINCAP_VREF_80)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) 			snd_iprintf(buffer, " 80");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) 		if (vref & AC_PINCAP_VREF_100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) 			snd_iprintf(buffer, " 100");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) 		snd_iprintf(buffer, "\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) 		*supports_vref = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) 	} else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) 		*supports_vref = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) 	if (caps & AC_PINCAP_EAPD) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) 		val = snd_hda_codec_read(codec, nid, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) 					 AC_VERB_GET_EAPD_BTLENABLE, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) 		snd_iprintf(buffer, "  EAPD 0x%x:", val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) 		if (val & AC_EAPDBTL_BALANCED)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) 			snd_iprintf(buffer, " BALANCED");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) 		if (val & AC_EAPDBTL_EAPD)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) 			snd_iprintf(buffer, " EAPD");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) 		if (val & AC_EAPDBTL_LR_SWAP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) 			snd_iprintf(buffer, " R/L");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) 		snd_iprintf(buffer, "\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) 	caps = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONFIG_DEFAULT, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) 	snd_iprintf(buffer, "  Pin Default 0x%08x: [%s] %s at %s %s\n", caps,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) 		    jack_conns[(caps & AC_DEFCFG_PORT_CONN) >> AC_DEFCFG_PORT_CONN_SHIFT],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) 		    get_jack_type(caps),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) 		    get_jack_connectivity(caps),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) 		    get_jack_location(caps));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) 	snd_iprintf(buffer, "    Conn = %s, Color = %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) 		    get_jack_connection(caps),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) 		    get_jack_color(caps));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) 	/* Default association and sequence values refer to default grouping
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) 	 * of pin complexes and their sequence within the group. This is used
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) 	 * for priority and resource allocation.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) 	snd_iprintf(buffer, "    DefAssociation = 0x%x, Sequence = 0x%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) 		    (caps & AC_DEFCFG_DEF_ASSOC) >> AC_DEFCFG_ASSOC_SHIFT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) 		    caps & AC_DEFCFG_SEQUENCE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) 	if (((caps & AC_DEFCFG_MISC) >> AC_DEFCFG_MISC_SHIFT) &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) 	    AC_DEFCFG_MISC_NO_PRESENCE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) 		/* Miscellaneous bit indicates external hardware does not
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) 		 * support presence detection even if the pin complex
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) 		 * indicates it is supported.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) 		snd_iprintf(buffer, "    Misc = NO_PRESENCE\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) static void print_pin_ctls(struct snd_info_buffer *buffer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) 			   struct hda_codec *codec, hda_nid_t nid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) 			   int supports_vref)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) 	unsigned int pinctls;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) 	pinctls = snd_hda_codec_read(codec, nid, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) 				     AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) 	snd_iprintf(buffer, "  Pin-ctls: 0x%02x:", pinctls);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) 	if (pinctls & AC_PINCTL_IN_EN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) 		snd_iprintf(buffer, " IN");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) 	if (pinctls & AC_PINCTL_OUT_EN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) 		snd_iprintf(buffer, " OUT");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) 	if (pinctls & AC_PINCTL_HP_EN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) 		snd_iprintf(buffer, " HP");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) 	if (supports_vref) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) 		int vref = pinctls & AC_PINCTL_VREFEN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) 		switch (vref) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) 		case AC_PINCTL_VREF_HIZ:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) 			snd_iprintf(buffer, " VREF_HIZ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) 		case AC_PINCTL_VREF_50:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) 			snd_iprintf(buffer, " VREF_50");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) 		case AC_PINCTL_VREF_GRD:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) 			snd_iprintf(buffer, " VREF_GRD");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) 		case AC_PINCTL_VREF_80:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) 			snd_iprintf(buffer, " VREF_80");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) 		case AC_PINCTL_VREF_100:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) 			snd_iprintf(buffer, " VREF_100");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) 	snd_iprintf(buffer, "\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) static void print_vol_knob(struct snd_info_buffer *buffer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) 			   struct hda_codec *codec, hda_nid_t nid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) 	unsigned int cap = param_read(codec, nid, AC_PAR_VOL_KNB_CAP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) 	snd_iprintf(buffer, "  Volume-Knob: delta=%d, steps=%d, ",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) 		    (cap >> 7) & 1, cap & 0x7f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) 	cap = snd_hda_codec_read(codec, nid, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) 				 AC_VERB_GET_VOLUME_KNOB_CONTROL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) 	snd_iprintf(buffer, "direct=%d, val=%d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) 		    (cap >> 7) & 1, cap & 0x7f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) static void print_audio_io(struct snd_info_buffer *buffer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) 			   struct hda_codec *codec, hda_nid_t nid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) 			   unsigned int wid_type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) 	int conv = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONV, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) 	snd_iprintf(buffer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) 		    "  Converter: stream=%d, channel=%d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) 		    (conv & AC_CONV_STREAM) >> AC_CONV_STREAM_SHIFT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) 		    conv & AC_CONV_CHANNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) 	if (wid_type == AC_WID_AUD_IN && (conv & AC_CONV_CHANNEL) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) 		int sdi = snd_hda_codec_read(codec, nid, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) 					     AC_VERB_GET_SDI_SELECT, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) 		snd_iprintf(buffer, "  SDI-Select: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) 			    sdi & AC_SDI_SELECT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) static void print_digital_conv(struct snd_info_buffer *buffer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) 			       struct hda_codec *codec, hda_nid_t nid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) 	unsigned int digi1 = snd_hda_codec_read(codec, nid, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) 						AC_VERB_GET_DIGI_CONVERT_1, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) 	unsigned char digi2 = digi1 >> 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) 	unsigned char digi3 = digi1 >> 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) 	snd_iprintf(buffer, "  Digital:");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) 	if (digi1 & AC_DIG1_ENABLE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) 		snd_iprintf(buffer, " Enabled");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) 	if (digi1 & AC_DIG1_V)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) 		snd_iprintf(buffer, " Validity");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) 	if (digi1 & AC_DIG1_VCFG)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) 		snd_iprintf(buffer, " ValidityCfg");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) 	if (digi1 & AC_DIG1_EMPHASIS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) 		snd_iprintf(buffer, " Preemphasis");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) 	if (digi1 & AC_DIG1_COPYRIGHT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) 		snd_iprintf(buffer, " Non-Copyright");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) 	if (digi1 & AC_DIG1_NONAUDIO)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) 		snd_iprintf(buffer, " Non-Audio");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) 	if (digi1 & AC_DIG1_PROFESSIONAL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) 		snd_iprintf(buffer, " Pro");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) 	if (digi1 & AC_DIG1_LEVEL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) 		snd_iprintf(buffer, " GenLevel");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) 	if (digi3 & AC_DIG3_KAE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) 		snd_iprintf(buffer, " KAE");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) 	snd_iprintf(buffer, "\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) 	snd_iprintf(buffer, "  Digital category: 0x%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) 		    digi2 & AC_DIG2_CC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) 	snd_iprintf(buffer, "  IEC Coding Type: 0x%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) 			digi3 & AC_DIG3_ICT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) static const char *get_pwr_state(u32 state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) 	static const char * const buf[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) 		"D0", "D1", "D2", "D3", "D3cold"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) 	};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) 	if (state < ARRAY_SIZE(buf))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) 		return buf[state];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) 	return "UNKNOWN";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) static void print_power_state(struct snd_info_buffer *buffer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) 			      struct hda_codec *codec, hda_nid_t nid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) 	static const char * const names[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) 		[ilog2(AC_PWRST_D0SUP)]		= "D0",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) 		[ilog2(AC_PWRST_D1SUP)]		= "D1",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) 		[ilog2(AC_PWRST_D2SUP)]		= "D2",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) 		[ilog2(AC_PWRST_D3SUP)]		= "D3",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) 		[ilog2(AC_PWRST_D3COLDSUP)]	= "D3cold",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) 		[ilog2(AC_PWRST_S3D3COLDSUP)]	= "S3D3cold",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) 		[ilog2(AC_PWRST_CLKSTOP)]	= "CLKSTOP",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) 		[ilog2(AC_PWRST_EPSS)]		= "EPSS",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) 	};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) 	int sup = param_read(codec, nid, AC_PAR_POWER_STATE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) 	int pwr = snd_hda_codec_read(codec, nid, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) 				     AC_VERB_GET_POWER_STATE, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) 	if (sup != -1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) 		int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) 		snd_iprintf(buffer, "  Power states: ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) 		for (i = 0; i < ARRAY_SIZE(names); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) 			if (sup & (1U << i))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) 				snd_iprintf(buffer, " %s", names[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) 		snd_iprintf(buffer, "\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) 	snd_iprintf(buffer, "  Power: setting=%s, actual=%s",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) 		    get_pwr_state(pwr & AC_PWRST_SETTING),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) 		    get_pwr_state((pwr & AC_PWRST_ACTUAL) >>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) 				  AC_PWRST_ACTUAL_SHIFT));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) 	if (pwr & AC_PWRST_ERROR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) 		snd_iprintf(buffer, ", Error");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) 	if (pwr & AC_PWRST_CLK_STOP_OK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) 		snd_iprintf(buffer, ", Clock-stop-OK");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) 	if (pwr & AC_PWRST_SETTING_RESET)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) 		snd_iprintf(buffer, ", Setting-reset");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) 	snd_iprintf(buffer, "\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) static void print_unsol_cap(struct snd_info_buffer *buffer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) 			      struct hda_codec *codec, hda_nid_t nid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) 	int unsol = snd_hda_codec_read(codec, nid, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) 				       AC_VERB_GET_UNSOLICITED_RESPONSE, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) 	snd_iprintf(buffer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) 		    "  Unsolicited: tag=%02x, enabled=%d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) 		    unsol & AC_UNSOL_TAG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) 		    (unsol & AC_UNSOL_ENABLED) ? 1 : 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) static inline bool can_dump_coef(struct hda_codec *codec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) 	switch (dump_coef) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) 	case 0: return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) 	case 1: return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) 	default: return codec->dump_coef;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) static void print_proc_caps(struct snd_info_buffer *buffer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) 			    struct hda_codec *codec, hda_nid_t nid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) 	unsigned int i, ncoeff, oldindex;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) 	unsigned int proc_caps = param_read(codec, nid, AC_PAR_PROC_CAP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) 	ncoeff = (proc_caps & AC_PCAP_NUM_COEF) >> AC_PCAP_NUM_COEF_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) 	snd_iprintf(buffer, "  Processing caps: benign=%d, ncoeff=%d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) 		    proc_caps & AC_PCAP_BENIGN, ncoeff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) 	if (!can_dump_coef(codec))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) 	/* Note: This is racy - another process could run in parallel and change
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) 	   the coef index too. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) 	oldindex = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_COEF_INDEX, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) 	for (i = 0; i < ncoeff; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) 		unsigned int val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) 		snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_COEF_INDEX, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) 		val = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_PROC_COEF,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) 					 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) 		snd_iprintf(buffer, "    Coeff 0x%02x: 0x%04x\n", i, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) 	snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_COEF_INDEX, oldindex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) static void print_conn_list(struct snd_info_buffer *buffer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) 			    struct hda_codec *codec, hda_nid_t nid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) 			    unsigned int wid_type, hda_nid_t *conn,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) 			    int conn_len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) 	int c, curr = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) 	const hda_nid_t *list;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) 	int cache_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) 	if (conn_len > 1 &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) 	    wid_type != AC_WID_AUD_MIX &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) 	    wid_type != AC_WID_VOL_KNB &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) 	    wid_type != AC_WID_POWER)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) 		curr = snd_hda_codec_read(codec, nid, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) 					  AC_VERB_GET_CONNECT_SEL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) 	snd_iprintf(buffer, "  Connection: %d\n", conn_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) 	if (conn_len > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) 		snd_iprintf(buffer, "    ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) 		for (c = 0; c < conn_len; c++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) 			snd_iprintf(buffer, " 0x%02x", conn[c]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) 			if (c == curr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) 				snd_iprintf(buffer, "*");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) 		snd_iprintf(buffer, "\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) 	/* Get Cache connections info */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) 	cache_len = snd_hda_get_conn_list(codec, nid, &list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) 	if (cache_len >= 0 && (cache_len != conn_len ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) 			      memcmp(list, conn, conn_len) != 0)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) 		snd_iprintf(buffer, "  In-driver Connection: %d\n", cache_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) 		if (cache_len > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) 			snd_iprintf(buffer, "    ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) 			for (c = 0; c < cache_len; c++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) 				snd_iprintf(buffer, " 0x%02x", list[c]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) 			snd_iprintf(buffer, "\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) static void print_gpio(struct snd_info_buffer *buffer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) 		       struct hda_codec *codec, hda_nid_t nid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) 	unsigned int gpio =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) 		param_read(codec, codec->core.afg, AC_PAR_GPIO_CAP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) 	unsigned int enable, direction, wake, unsol, sticky, data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) 	int i, max;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) 	snd_iprintf(buffer, "GPIO: io=%d, o=%d, i=%d, "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) 		    "unsolicited=%d, wake=%d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) 		    gpio & AC_GPIO_IO_COUNT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) 		    (gpio & AC_GPIO_O_COUNT) >> AC_GPIO_O_COUNT_SHIFT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) 		    (gpio & AC_GPIO_I_COUNT) >> AC_GPIO_I_COUNT_SHIFT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) 		    (gpio & AC_GPIO_UNSOLICITED) ? 1 : 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) 		    (gpio & AC_GPIO_WAKE) ? 1 : 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) 	max = gpio & AC_GPIO_IO_COUNT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) 	if (!max || max > 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) 	enable = snd_hda_codec_read(codec, nid, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) 				    AC_VERB_GET_GPIO_MASK, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) 	direction = snd_hda_codec_read(codec, nid, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) 				       AC_VERB_GET_GPIO_DIRECTION, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) 	wake = snd_hda_codec_read(codec, nid, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) 				  AC_VERB_GET_GPIO_WAKE_MASK, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) 	unsol  = snd_hda_codec_read(codec, nid, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) 				    AC_VERB_GET_GPIO_UNSOLICITED_RSP_MASK, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) 	sticky = snd_hda_codec_read(codec, nid, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) 				    AC_VERB_GET_GPIO_STICKY_MASK, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) 	data = snd_hda_codec_read(codec, nid, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) 				  AC_VERB_GET_GPIO_DATA, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) 	for (i = 0; i < max; ++i)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) 		snd_iprintf(buffer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) 			    "  IO[%d]: enable=%d, dir=%d, wake=%d, "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) 			    "sticky=%d, data=%d, unsol=%d\n", i,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) 			    (enable & (1<<i)) ? 1 : 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) 			    (direction & (1<<i)) ? 1 : 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) 			    (wake & (1<<i)) ? 1 : 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) 			    (sticky & (1<<i)) ? 1 : 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) 			    (data & (1<<i)) ? 1 : 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) 			    (unsol & (1<<i)) ? 1 : 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) 	/* FIXME: add GPO and GPI pin information */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) 	print_nid_array(buffer, codec, nid, &codec->mixers);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) 	print_nid_array(buffer, codec, nid, &codec->nids);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) static void print_device_list(struct snd_info_buffer *buffer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) 			    struct hda_codec *codec, hda_nid_t nid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) 	int i, curr = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) 	u8 dev_list[AC_MAX_DEV_LIST_LEN];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) 	int devlist_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) 	devlist_len = snd_hda_get_devices(codec, nid, dev_list,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) 					AC_MAX_DEV_LIST_LEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) 	snd_iprintf(buffer, "  Devices: %d\n", devlist_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) 	if (devlist_len <= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) 	curr = snd_hda_codec_read(codec, nid, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) 				AC_VERB_GET_DEVICE_SEL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) 	for (i = 0; i < devlist_len; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) 		if (i == curr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) 			snd_iprintf(buffer, "    *");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) 		else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) 			snd_iprintf(buffer, "     ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) 		snd_iprintf(buffer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) 			"Dev %02d: PD = %d, ELDV = %d, IA = %d\n", i,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) 			!!(dev_list[i] & AC_DE_PD),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) 			!!(dev_list[i] & AC_DE_ELDV),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) 			!!(dev_list[i] & AC_DE_IA));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) static void print_codec_core_info(struct hdac_device *codec,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) 				  struct snd_info_buffer *buffer)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) 	snd_iprintf(buffer, "Codec: ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) 	if (codec->vendor_name && codec->chip_name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) 		snd_iprintf(buffer, "%s %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) 			    codec->vendor_name, codec->chip_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) 		snd_iprintf(buffer, "Not Set\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) 	snd_iprintf(buffer, "Address: %d\n", codec->addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) 	if (codec->afg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) 		snd_iprintf(buffer, "AFG Function Id: 0x%x (unsol %u)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) 			codec->afg_function_id, codec->afg_unsol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) 	if (codec->mfg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) 		snd_iprintf(buffer, "MFG Function Id: 0x%x (unsol %u)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) 			codec->mfg_function_id, codec->mfg_unsol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) 	snd_iprintf(buffer, "Vendor Id: 0x%08x\n", codec->vendor_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) 	snd_iprintf(buffer, "Subsystem Id: 0x%08x\n", codec->subsystem_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) 	snd_iprintf(buffer, "Revision Id: 0x%x\n", codec->revision_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) 	if (codec->mfg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) 		snd_iprintf(buffer, "Modem Function Group: 0x%x\n", codec->mfg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) 		snd_iprintf(buffer, "No Modem Function Group found\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) static void print_codec_info(struct snd_info_entry *entry,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) 			     struct snd_info_buffer *buffer)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) 	struct hda_codec *codec = entry->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) 	hda_nid_t nid, fg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) 	int i, nodes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) 	print_codec_core_info(&codec->core, buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) 	fg = codec->core.afg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) 	if (!fg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) 	snd_hda_power_up(codec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) 	snd_iprintf(buffer, "Default PCM:\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) 	print_pcm_caps(buffer, codec, fg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) 	snd_iprintf(buffer, "Default Amp-In caps: ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) 	print_amp_caps(buffer, codec, fg, HDA_INPUT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) 	snd_iprintf(buffer, "Default Amp-Out caps: ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) 	print_amp_caps(buffer, codec, fg, HDA_OUTPUT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) 	snd_iprintf(buffer, "State of AFG node 0x%02x:\n", fg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) 	print_power_state(buffer, codec, fg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) 	nodes = snd_hda_get_sub_nodes(codec, fg, &nid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) 	if (! nid || nodes < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) 		snd_iprintf(buffer, "Invalid AFG subtree\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) 		snd_hda_power_down(codec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) 	print_gpio(buffer, codec, fg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) 	if (codec->proc_widget_hook)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) 		codec->proc_widget_hook(buffer, codec, fg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) 	for (i = 0; i < nodes; i++, nid++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) 		unsigned int wid_caps =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) 			param_read(codec, nid, AC_PAR_AUDIO_WIDGET_CAP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) 		unsigned int wid_type = get_wcaps_type(wid_caps);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) 		hda_nid_t *conn = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) 		int conn_len = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) 		snd_iprintf(buffer, "Node 0x%02x [%s] wcaps 0x%x:", nid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) 			    get_wid_type_name(wid_type), wid_caps);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) 		if (wid_caps & AC_WCAP_STEREO) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) 			unsigned int chans = get_wcaps_channels(wid_caps);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) 			if (chans == 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) 				snd_iprintf(buffer, " Stereo");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) 			else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) 				snd_iprintf(buffer, " %d-Channels", chans);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) 		} else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) 			snd_iprintf(buffer, " Mono");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) 		if (wid_caps & AC_WCAP_DIGITAL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) 			snd_iprintf(buffer, " Digital");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) 		if (wid_caps & AC_WCAP_IN_AMP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) 			snd_iprintf(buffer, " Amp-In");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) 		if (wid_caps & AC_WCAP_OUT_AMP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) 			snd_iprintf(buffer, " Amp-Out");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) 		if (wid_caps & AC_WCAP_STRIPE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) 			snd_iprintf(buffer, " Stripe");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) 		if (wid_caps & AC_WCAP_LR_SWAP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) 			snd_iprintf(buffer, " R/L");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) 		if (wid_caps & AC_WCAP_CP_CAPS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) 			snd_iprintf(buffer, " CP");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) 		snd_iprintf(buffer, "\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) 		print_nid_array(buffer, codec, nid, &codec->mixers);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) 		print_nid_array(buffer, codec, nid, &codec->nids);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) 		print_nid_pcms(buffer, codec, nid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) 		/* volume knob is a special widget that always have connection
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) 		 * list
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) 		if (wid_type == AC_WID_VOL_KNB)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) 			wid_caps |= AC_WCAP_CONN_LIST;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) 		if (wid_caps & AC_WCAP_CONN_LIST) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) 			conn_len = snd_hda_get_num_raw_conns(codec, nid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) 			if (conn_len > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) 				conn = kmalloc_array(conn_len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) 						     sizeof(hda_nid_t),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) 						     GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) 				if (!conn)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) 					return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) 				if (snd_hda_get_raw_connections(codec, nid, conn,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) 								conn_len) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) 					conn_len = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) 		if (wid_caps & AC_WCAP_IN_AMP) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) 			snd_iprintf(buffer, "  Amp-In caps: ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) 			print_amp_caps(buffer, codec, nid, HDA_INPUT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) 			snd_iprintf(buffer, "  Amp-In vals: ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) 			if (wid_type == AC_WID_PIN ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) 			    (codec->single_adc_amp &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) 			     wid_type == AC_WID_AUD_IN))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) 				print_amp_vals(buffer, codec, nid, HDA_INPUT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) 					       wid_caps, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) 			else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) 				print_amp_vals(buffer, codec, nid, HDA_INPUT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) 					       wid_caps, conn_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) 		if (wid_caps & AC_WCAP_OUT_AMP) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) 			snd_iprintf(buffer, "  Amp-Out caps: ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) 			print_amp_caps(buffer, codec, nid, HDA_OUTPUT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) 			snd_iprintf(buffer, "  Amp-Out vals: ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) 			if (wid_type == AC_WID_PIN &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) 			    codec->pin_amp_workaround)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) 				print_amp_vals(buffer, codec, nid, HDA_OUTPUT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) 					       wid_caps, conn_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) 			else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) 				print_amp_vals(buffer, codec, nid, HDA_OUTPUT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) 					       wid_caps, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) 		switch (wid_type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) 		case AC_WID_PIN: {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) 			int supports_vref;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) 			print_pin_caps(buffer, codec, nid, &supports_vref);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) 			print_pin_ctls(buffer, codec, nid, supports_vref);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) 		case AC_WID_VOL_KNB:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) 			print_vol_knob(buffer, codec, nid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) 		case AC_WID_AUD_OUT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) 		case AC_WID_AUD_IN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) 			print_audio_io(buffer, codec, nid, wid_type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) 			if (wid_caps & AC_WCAP_DIGITAL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) 				print_digital_conv(buffer, codec, nid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) 			if (wid_caps & AC_WCAP_FORMAT_OVRD) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) 				snd_iprintf(buffer, "  PCM:\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) 				print_pcm_caps(buffer, codec, nid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) 		if (wid_caps & AC_WCAP_UNSOL_CAP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) 			print_unsol_cap(buffer, codec, nid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) 		if (wid_caps & AC_WCAP_POWER)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) 			print_power_state(buffer, codec, nid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) 		if (wid_caps & AC_WCAP_DELAY)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) 			snd_iprintf(buffer, "  Delay: %d samples\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) 				    (wid_caps & AC_WCAP_DELAY) >>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) 				    AC_WCAP_DELAY_SHIFT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) 		if (wid_type == AC_WID_PIN && codec->dp_mst)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) 			print_device_list(buffer, codec, nid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) 		if (wid_caps & AC_WCAP_CONN_LIST)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) 			print_conn_list(buffer, codec, nid, wid_type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) 					conn, conn_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) 		if (wid_caps & AC_WCAP_PROC_WID)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) 			print_proc_caps(buffer, codec, nid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) 		if (codec->proc_widget_hook)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) 			codec->proc_widget_hook(buffer, codec, nid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) 		kfree(conn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) 	snd_hda_power_down(codec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903)  * create a proc read
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) int snd_hda_codec_proc_new(struct hda_codec *codec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) 	char name[32];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) 	snprintf(name, sizeof(name), "codec#%d", codec->core.addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) 	return snd_card_ro_proc_new(codec->card, name, codec, print_codec_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912)