2 * Universal Interface for Intel High Definition Audio Codec
4 * Generic proc interface
6 * Copyright (c) 2004 Takashi Iwai <tiwai@suse.de>
9 * This driver is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This driver is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 #include <sound/driver.h>
25 #include <linux/init.h>
26 #include <sound/core.h>
27 #include "hda_codec.h"
28 #include "hda_local.h"
30 static const char *get_wid_type_name(unsigned int wid_value)
32 static char *names[16] = {
33 [AC_WID_AUD_OUT] = "Audio Output",
34 [AC_WID_AUD_IN] = "Audio Input",
35 [AC_WID_AUD_MIX] = "Audio Mixer",
36 [AC_WID_AUD_SEL] = "Audio Selector",
37 [AC_WID_PIN] = "Pin Complex",
38 [AC_WID_POWER] = "Power Widget",
39 [AC_WID_VOL_KNB] = "Volume Knob Widget",
40 [AC_WID_BEEP] = "Beep Generator Widget",
41 [AC_WID_VENDOR] = "Vendor Defined Widget",
45 return names[wid_value];
47 return "UNKNOWN Widget";
50 static void print_amp_caps(struct snd_info_buffer *buffer,
51 struct hda_codec *codec, hda_nid_t nid, int dir)
54 caps = snd_hda_param_read(codec, nid,
56 AC_PAR_AMP_OUT_CAP : AC_PAR_AMP_IN_CAP);
57 if (caps == -1 || caps == 0) {
58 snd_iprintf(buffer, "N/A\n");
61 snd_iprintf(buffer, "ofs=0x%02x, nsteps=0x%02x, stepsize=0x%02x, "
63 caps & AC_AMPCAP_OFFSET,
64 (caps & AC_AMPCAP_NUM_STEPS) >> AC_AMPCAP_NUM_STEPS_SHIFT,
65 (caps & AC_AMPCAP_STEP_SIZE) >> AC_AMPCAP_STEP_SIZE_SHIFT,
66 (caps & AC_AMPCAP_MUTE) >> AC_AMPCAP_MUTE_SHIFT);
69 static void print_amp_vals(struct snd_info_buffer *buffer,
70 struct hda_codec *codec, hda_nid_t nid,
71 int dir, int stereo, int indices)
76 dir = dir == HDA_OUTPUT ? AC_AMP_GET_OUTPUT : AC_AMP_GET_INPUT;
77 for (i = 0; i < indices; i++) {
78 snd_iprintf(buffer, " [");
80 val = snd_hda_codec_read(codec, nid, 0,
81 AC_VERB_GET_AMP_GAIN_MUTE,
82 AC_AMP_GET_LEFT | dir | i);
83 snd_iprintf(buffer, "0x%02x ", val);
85 val = snd_hda_codec_read(codec, nid, 0,
86 AC_VERB_GET_AMP_GAIN_MUTE,
87 AC_AMP_GET_RIGHT | dir | i);
88 snd_iprintf(buffer, "0x%02x]", val);
90 snd_iprintf(buffer, "\n");
93 static void print_pcm_rates(struct snd_info_buffer *buffer, unsigned int pcm)
95 static unsigned int rates[] = {
96 8000, 11025, 16000, 22050, 32000, 44100, 48000, 88200,
97 96000, 176400, 192000, 384000
101 pcm &= AC_SUPPCM_RATES;
102 snd_iprintf(buffer, " rates [0x%x]:", pcm);
103 for (i = 0; i < ARRAY_SIZE(rates); i++)
105 snd_iprintf(buffer, " %d", rates[i]);
106 snd_iprintf(buffer, "\n");
109 static void print_pcm_bits(struct snd_info_buffer *buffer, unsigned int pcm)
111 static unsigned int bits[] = { 8, 16, 20, 24, 32 };
114 pcm = (pcm >> 16) & 0xff;
115 snd_iprintf(buffer, " bits [0x%x]:", pcm);
116 for (i = 0; i < ARRAY_SIZE(bits); i++)
118 snd_iprintf(buffer, " %d", bits[i]);
119 snd_iprintf(buffer, "\n");
122 static void print_pcm_formats(struct snd_info_buffer *buffer,
123 unsigned int streams)
125 snd_iprintf(buffer, " formats [0x%x]:", streams & 0xf);
126 if (streams & AC_SUPFMT_PCM)
127 snd_iprintf(buffer, " PCM");
128 if (streams & AC_SUPFMT_FLOAT32)
129 snd_iprintf(buffer, " FLOAT");
130 if (streams & AC_SUPFMT_AC3)
131 snd_iprintf(buffer, " AC3");
132 snd_iprintf(buffer, "\n");
135 static void print_pcm_caps(struct snd_info_buffer *buffer,
136 struct hda_codec *codec, hda_nid_t nid)
138 unsigned int pcm = snd_hda_param_read(codec, nid, AC_PAR_PCM);
139 unsigned int stream = snd_hda_param_read(codec, nid, AC_PAR_STREAM);
140 if (pcm == -1 || stream == -1) {
141 snd_iprintf(buffer, "N/A\n");
144 print_pcm_rates(buffer, pcm);
145 print_pcm_bits(buffer, pcm);
146 print_pcm_formats(buffer, stream);
149 static const char *get_jack_location(u32 cfg)
151 static char *bases[7] = {
152 "N/A", "Rear", "Front", "Left", "Right", "Top", "Bottom",
154 static unsigned char specials_idx[] = {
159 static char *specials[] = {
160 "Rear Panel", "Drive Bar",
161 "Riser", "HDMI", "ATAPI",
162 "Mobile-In", "Mobile-Out"
165 cfg = (cfg & AC_DEFCFG_LOCATION) >> AC_DEFCFG_LOCATION_SHIFT;
166 if ((cfg & 0x0f) < 7)
167 return bases[cfg & 0x0f];
168 for (i = 0; i < ARRAY_SIZE(specials_idx); i++) {
169 if (cfg == specials_idx[i])
175 static const char *get_jack_connection(u32 cfg)
177 static char *names[16] = {
178 "Unknown", "1/8", "1/4", "ATAPI",
179 "RCA", "Optical","Digital", "Analog",
180 "DIN", "XLR", "RJ11", "Comb",
181 NULL, NULL, NULL, "Other"
183 cfg = (cfg & AC_DEFCFG_CONN_TYPE) >> AC_DEFCFG_CONN_TYPE_SHIFT;
190 static const char *get_jack_color(u32 cfg)
192 static char *names[16] = {
193 "Unknown", "Black", "Grey", "Blue",
194 "Green", "Red", "Orange", "Yellow",
195 "Purple", "Pink", NULL, NULL,
196 NULL, NULL, "White", "Other",
198 cfg = (cfg & AC_DEFCFG_COLOR) >> AC_DEFCFG_COLOR_SHIFT;
205 static void print_pin_caps(struct snd_info_buffer *buffer,
206 struct hda_codec *codec, hda_nid_t nid)
208 static char *jack_conns[4] = { "Jack", "N/A", "Fixed", "Both" };
209 static char *jack_types[16] = {
210 "Line Out", "Speaker", "HP Out", "CD",
211 "SPDIF Out", "Digital Out", "Modem Line", "Modem Hand",
212 "Line In", "Aux", "Mic", "Telephony",
213 "SPDIF In", "Digitial In", "Reserved", "Other"
215 static char *jack_locations[4] = { "Ext", "Int", "Sep", "Oth" };
216 unsigned int caps, val;
218 caps = snd_hda_param_read(codec, nid, AC_PAR_PIN_CAP);
219 snd_iprintf(buffer, " Pincap 0x08%x:", caps);
220 if (caps & AC_PINCAP_IN)
221 snd_iprintf(buffer, " IN");
222 if (caps & AC_PINCAP_OUT)
223 snd_iprintf(buffer, " OUT");
224 if (caps & AC_PINCAP_HP_DRV)
225 snd_iprintf(buffer, " HP");
226 if (caps & AC_PINCAP_EAPD)
227 snd_iprintf(buffer, " EAPD");
228 if (caps & AC_PINCAP_PRES_DETECT)
229 snd_iprintf(buffer, " Detect");
230 snd_iprintf(buffer, "\n");
231 caps = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONFIG_DEFAULT, 0);
232 snd_iprintf(buffer, " Pin Default 0x%08x: [%s] %s at %s %s\n", caps,
233 jack_conns[(caps & AC_DEFCFG_PORT_CONN) >> AC_DEFCFG_PORT_CONN_SHIFT],
234 jack_types[(caps & AC_DEFCFG_DEVICE) >> AC_DEFCFG_DEVICE_SHIFT],
235 jack_locations[(caps >> (AC_DEFCFG_LOCATION_SHIFT + 4)) & 3],
236 get_jack_location(caps));
237 snd_iprintf(buffer, " Conn = %s, Color = %s\n",
238 get_jack_connection(caps),
239 get_jack_color(caps));
240 if (caps & AC_PINCAP_EAPD) {
241 val = snd_hda_codec_read(codec, nid, 0,
242 AC_VERB_GET_EAPD_BTLENABLE, 0);
243 snd_iprintf(buffer, " EAPD: 0x%x\n", val);
248 static void print_codec_info(struct snd_info_entry *entry,
249 struct snd_info_buffer *buffer)
251 struct hda_codec *codec = entry->private_data;
256 snd_hda_get_codec_name(codec, buf, sizeof(buf));
257 snd_iprintf(buffer, "Codec: %s\n", buf);
258 snd_iprintf(buffer, "Address: %d\n", codec->addr);
259 snd_iprintf(buffer, "Vendor Id: 0x%x\n", codec->vendor_id);
260 snd_iprintf(buffer, "Subsystem Id: 0x%x\n", codec->subsystem_id);
261 snd_iprintf(buffer, "Revision Id: 0x%x\n", codec->revision_id);
264 snd_iprintf(buffer, "Modem Function Group: 0x%x\n", codec->mfg);
266 snd_iprintf(buffer, "No Modem Function Group found\n");
270 snd_hda_power_up(codec);
271 snd_iprintf(buffer, "Default PCM:\n");
272 print_pcm_caps(buffer, codec, codec->afg);
273 snd_iprintf(buffer, "Default Amp-In caps: ");
274 print_amp_caps(buffer, codec, codec->afg, HDA_INPUT);
275 snd_iprintf(buffer, "Default Amp-Out caps: ");
276 print_amp_caps(buffer, codec, codec->afg, HDA_OUTPUT);
278 nodes = snd_hda_get_sub_nodes(codec, codec->afg, &nid);
279 if (! nid || nodes < 0) {
280 snd_iprintf(buffer, "Invalid AFG subtree\n");
281 snd_hda_power_down(codec);
284 for (i = 0; i < nodes; i++, nid++) {
285 unsigned int wid_caps =
286 snd_hda_param_read(codec, nid,
287 AC_PAR_AUDIO_WIDGET_CAP);
288 unsigned int wid_type =
289 (wid_caps & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT;
291 hda_nid_t conn[HDA_MAX_CONNECTIONS];
292 unsigned int pinctls;
294 snd_iprintf(buffer, "Node 0x%02x [%s] wcaps 0x%x:", nid,
295 get_wid_type_name(wid_type), wid_caps);
296 if (wid_caps & AC_WCAP_STEREO)
297 snd_iprintf(buffer, " Stereo");
299 snd_iprintf(buffer, " Mono");
300 if (wid_caps & AC_WCAP_DIGITAL)
301 snd_iprintf(buffer, " Digital");
302 if (wid_caps & AC_WCAP_IN_AMP)
303 snd_iprintf(buffer, " Amp-In");
304 if (wid_caps & AC_WCAP_OUT_AMP)
305 snd_iprintf(buffer, " Amp-Out");
306 snd_iprintf(buffer, "\n");
308 if (wid_caps & AC_WCAP_CONN_LIST)
309 conn_len = snd_hda_get_connections(codec, nid, conn,
310 HDA_MAX_CONNECTIONS);
312 if (wid_caps & AC_WCAP_IN_AMP) {
313 snd_iprintf(buffer, " Amp-In caps: ");
314 print_amp_caps(buffer, codec, nid, HDA_INPUT);
315 snd_iprintf(buffer, " Amp-In vals: ");
316 print_amp_vals(buffer, codec, nid, HDA_INPUT,
317 wid_caps & AC_WCAP_STEREO, conn_len);
319 if (wid_caps & AC_WCAP_OUT_AMP) {
320 snd_iprintf(buffer, " Amp-Out caps: ");
321 print_amp_caps(buffer, codec, nid, HDA_OUTPUT);
322 snd_iprintf(buffer, " Amp-Out vals: ");
323 print_amp_vals(buffer, codec, nid, HDA_OUTPUT,
324 wid_caps & AC_WCAP_STEREO, 1);
329 print_pin_caps(buffer, codec, nid);
330 pinctls = snd_hda_codec_read(codec, nid, 0,
331 AC_VERB_GET_PIN_WIDGET_CONTROL,
333 snd_iprintf(buffer, " Pin-ctls: 0x%02x:", pinctls);
334 if (pinctls & AC_PINCTL_IN_EN)
335 snd_iprintf(buffer, " IN");
336 if (pinctls & AC_PINCTL_OUT_EN)
337 snd_iprintf(buffer, " OUT");
338 if (pinctls & AC_PINCTL_HP_EN)
339 snd_iprintf(buffer, " HP");
340 snd_iprintf(buffer, "\n");
343 snd_iprintf(buffer, " Volume-Knob: 0x%x\n",
344 snd_hda_codec_read(codec, nid, 0,
345 AC_VERB_GET_VOLUME_KNOB_CONTROL, 0));
349 if (wid_caps & AC_WCAP_FORMAT_OVRD) {
350 snd_iprintf(buffer, " PCM:\n");
351 print_pcm_caps(buffer, codec, nid);
356 if (wid_caps & AC_WCAP_POWER)
357 snd_iprintf(buffer, " Power: 0x%x\n",
358 snd_hda_codec_read(codec, nid, 0,
359 AC_VERB_GET_POWER_STATE,
362 if (wid_caps & AC_WCAP_CONN_LIST) {
364 if (conn_len > 1 && wid_type != AC_WID_AUD_MIX)
365 curr = snd_hda_codec_read(codec, nid, 0,
366 AC_VERB_GET_CONNECT_SEL, 0);
367 snd_iprintf(buffer, " Connection: %d\n", conn_len);
368 snd_iprintf(buffer, " ");
369 for (c = 0; c < conn_len; c++) {
370 snd_iprintf(buffer, " 0x%02x", conn[c]);
372 snd_iprintf(buffer, "*");
374 snd_iprintf(buffer, "\n");
377 snd_hda_power_down(codec);
383 int snd_hda_codec_proc_new(struct hda_codec *codec)
386 struct snd_info_entry *entry;
389 snprintf(name, sizeof(name), "codec#%d", codec->addr);
390 err = snd_card_proc_new(codec->bus->card, name, &entry);
394 snd_info_set_text_ops(entry, codec, print_codec_info);