^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)