cpu hotplug: msr: fix cpu hotplug error handling
[linux-2.6/kvm.git] / sound / pci / hda / hda_proc.c
blobe94944f34ffdcfffc4c8c9385ba268899ce824c2
1 /*
2 * Universal Interface for Intel High Definition Audio Codec
3 *
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",
43 wid_value &= 0xf;
44 if (names[wid_value])
45 return names[wid_value];
46 else
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)
53 unsigned int caps;
54 caps = snd_hda_param_read(codec, nid,
55 dir == HDA_OUTPUT ?
56 AC_PAR_AMP_OUT_CAP : AC_PAR_AMP_IN_CAP);
57 if (caps == -1 || caps == 0) {
58 snd_iprintf(buffer, "N/A\n");
59 return;
61 snd_iprintf(buffer, "ofs=0x%02x, nsteps=0x%02x, stepsize=0x%02x, "
62 "mute=%x\n",
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)
73 unsigned int val;
74 int i;
76 dir = dir == HDA_OUTPUT ? AC_AMP_GET_OUTPUT : AC_AMP_GET_INPUT;
77 for (i = 0; i < indices; i++) {
78 snd_iprintf(buffer, " [");
79 if (stereo) {
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
99 int i;
101 pcm &= AC_SUPPCM_RATES;
102 snd_iprintf(buffer, " rates [0x%x]:", pcm);
103 for (i = 0; i < ARRAY_SIZE(rates); i++)
104 if (pcm & (1 << 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 };
112 int i;
114 pcm = (pcm >> 16) & 0xff;
115 snd_iprintf(buffer, " bits [0x%x]:", pcm);
116 for (i = 0; i < ARRAY_SIZE(bits); i++)
117 if (pcm & (1 << 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");
142 return;
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[] = {
155 0x07, 0x08,
156 0x17, 0x18, 0x19,
157 0x37, 0x38
159 static char *specials[] = {
160 "Rear Panel", "Drive Bar",
161 "Riser", "HDMI", "ATAPI",
162 "Mobile-In", "Mobile-Out"
164 int i;
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])
170 return specials[i];
172 return "UNKNOWN";
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;
184 if (names[cfg])
185 return names[cfg];
186 else
187 return "UNKNOWN";
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;
199 if (names[cfg])
200 return names[cfg];
201 else
202 return "UNKNOWN";
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;
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));
243 static void print_codec_info(struct snd_info_entry *entry,
244 struct snd_info_buffer *buffer)
246 struct hda_codec *codec = entry->private_data;
247 char buf[32];
248 hda_nid_t nid;
249 int i, nodes;
251 snd_hda_get_codec_name(codec, buf, sizeof(buf));
252 snd_iprintf(buffer, "Codec: %s\n", buf);
253 snd_iprintf(buffer, "Address: %d\n", codec->addr);
254 snd_iprintf(buffer, "Vendor Id: 0x%x\n", codec->vendor_id);
255 snd_iprintf(buffer, "Subsystem Id: 0x%x\n", codec->subsystem_id);
256 snd_iprintf(buffer, "Revision Id: 0x%x\n", codec->revision_id);
258 if (codec->mfg)
259 snd_iprintf(buffer, "Modem Function Group: 0x%x\n", codec->mfg);
260 else
261 snd_iprintf(buffer, "No Modem Function Group found\n");
263 if (! codec->afg)
264 return;
265 snd_hda_power_up(codec);
266 snd_iprintf(buffer, "Default PCM:\n");
267 print_pcm_caps(buffer, codec, codec->afg);
268 snd_iprintf(buffer, "Default Amp-In caps: ");
269 print_amp_caps(buffer, codec, codec->afg, HDA_INPUT);
270 snd_iprintf(buffer, "Default Amp-Out caps: ");
271 print_amp_caps(buffer, codec, codec->afg, HDA_OUTPUT);
273 nodes = snd_hda_get_sub_nodes(codec, codec->afg, &nid);
274 if (! nid || nodes < 0) {
275 snd_iprintf(buffer, "Invalid AFG subtree\n");
276 snd_hda_power_down(codec);
277 return;
279 for (i = 0; i < nodes; i++, nid++) {
280 unsigned int wid_caps =
281 snd_hda_param_read(codec, nid,
282 AC_PAR_AUDIO_WIDGET_CAP);
283 unsigned int wid_type =
284 (wid_caps & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT;
285 int conn_len = 0;
286 hda_nid_t conn[HDA_MAX_CONNECTIONS];
288 snd_iprintf(buffer, "Node 0x%02x [%s] wcaps 0x%x:", nid,
289 get_wid_type_name(wid_type), wid_caps);
290 if (wid_caps & AC_WCAP_STEREO)
291 snd_iprintf(buffer, " Stereo");
292 else
293 snd_iprintf(buffer, " Mono");
294 if (wid_caps & AC_WCAP_DIGITAL)
295 snd_iprintf(buffer, " Digital");
296 if (wid_caps & AC_WCAP_IN_AMP)
297 snd_iprintf(buffer, " Amp-In");
298 if (wid_caps & AC_WCAP_OUT_AMP)
299 snd_iprintf(buffer, " Amp-Out");
300 snd_iprintf(buffer, "\n");
302 if (wid_caps & AC_WCAP_CONN_LIST)
303 conn_len = snd_hda_get_connections(codec, nid, conn,
304 HDA_MAX_CONNECTIONS);
306 if (wid_caps & AC_WCAP_IN_AMP) {
307 snd_iprintf(buffer, " Amp-In caps: ");
308 print_amp_caps(buffer, codec, nid, HDA_INPUT);
309 snd_iprintf(buffer, " Amp-In vals: ");
310 print_amp_vals(buffer, codec, nid, HDA_INPUT,
311 wid_caps & AC_WCAP_STEREO, conn_len);
313 if (wid_caps & AC_WCAP_OUT_AMP) {
314 snd_iprintf(buffer, " Amp-Out caps: ");
315 print_amp_caps(buffer, codec, nid, HDA_OUTPUT);
316 snd_iprintf(buffer, " Amp-Out vals: ");
317 print_amp_vals(buffer, codec, nid, HDA_OUTPUT,
318 wid_caps & AC_WCAP_STEREO, 1);
321 if (wid_type == AC_WID_PIN) {
322 unsigned int pinctls;
323 print_pin_caps(buffer, codec, nid);
324 pinctls = snd_hda_codec_read(codec, nid, 0,
325 AC_VERB_GET_PIN_WIDGET_CONTROL,
327 snd_iprintf(buffer, " Pin-ctls: 0x%02x:", pinctls);
328 if (pinctls & AC_PINCTL_IN_EN)
329 snd_iprintf(buffer, " IN");
330 if (pinctls & AC_PINCTL_OUT_EN)
331 snd_iprintf(buffer, " OUT");
332 if (pinctls & AC_PINCTL_HP_EN)
333 snd_iprintf(buffer, " HP");
334 snd_iprintf(buffer, "\n");
337 if ((wid_type == AC_WID_AUD_OUT || wid_type == AC_WID_AUD_IN) &&
338 (wid_caps & AC_WCAP_FORMAT_OVRD)) {
339 snd_iprintf(buffer, " PCM:\n");
340 print_pcm_caps(buffer, codec, nid);
343 if (wid_caps & AC_WCAP_POWER)
344 snd_iprintf(buffer, " Power: 0x%x\n",
345 snd_hda_codec_read(codec, nid, 0,
346 AC_VERB_GET_POWER_STATE,
347 0));
349 if (wid_caps & AC_WCAP_CONN_LIST) {
350 int c, curr = -1;
351 if (conn_len > 1 && wid_type != AC_WID_AUD_MIX)
352 curr = snd_hda_codec_read(codec, nid, 0,
353 AC_VERB_GET_CONNECT_SEL, 0);
354 snd_iprintf(buffer, " Connection: %d\n", conn_len);
355 snd_iprintf(buffer, " ");
356 for (c = 0; c < conn_len; c++) {
357 snd_iprintf(buffer, " 0x%02x", conn[c]);
358 if (c == curr)
359 snd_iprintf(buffer, "*");
361 snd_iprintf(buffer, "\n");
364 snd_hda_power_down(codec);
368 * create a proc read
370 int snd_hda_codec_proc_new(struct hda_codec *codec)
372 char name[32];
373 struct snd_info_entry *entry;
374 int err;
376 snprintf(name, sizeof(name), "codec#%d", codec->addr);
377 err = snd_card_proc_new(codec->bus->card, name, &entry);
378 if (err < 0)
379 return err;
381 snd_info_set_text_ops(entry, codec, print_codec_info);
382 return 0;