blob: c848ec0f085edd72681a02a14d54386d17ac3fa0 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * Universal Interface for Intel High Definition Audio Codec
3 *
4 * Copyright (c) 2004 Takashi Iwai <tiwai@suse.de>
5 *
6 *
7 * This driver is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This driver is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21
Linus Torvalds1da177e2005-04-16 15:20:36 -070022#include <linux/init.h>
23#include <linux/delay.h>
24#include <linux/slab.h>
25#include <linux/pci.h>
Ingo Molnar62932df2006-01-16 16:34:20 +010026#include <linux/mutex.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070027#include <sound/core.h>
28#include "hda_codec.h"
29#include <sound/asoundef.h>
Jaroslav Kysela302e9c52006-07-05 17:39:49 +020030#include <sound/tlv.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070031#include <sound/initval.h>
32#include "hda_local.h"
Jaroslav Kysela123c07a2009-10-21 14:48:23 +020033#include "hda_beep.h"
Takashi Iwai28073142007-07-27 18:58:06 +020034#include <sound/hda_hwdep.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070035
Linus Torvalds1da177e2005-04-16 15:20:36 -070036/*
37 * vendor / preset table
38 */
39
40struct hda_vendor_id {
41 unsigned int id;
42 const char *name;
43};
44
45/* codec vendor labels */
46static struct hda_vendor_id hda_vendor_ids[] = {
Takashi Iwaic8cd1282008-02-13 16:59:29 +010047 { 0x1002, "ATI" },
Takashi Iwaie5f14242009-07-01 18:11:44 +020048 { 0x1013, "Cirrus Logic" },
Takashi Iwaia9226252006-09-17 22:05:54 +020049 { 0x1057, "Motorola" },
Takashi Iwaic8cd1282008-02-13 16:59:29 +010050 { 0x1095, "Silicon Image" },
Takashi Iwai31117b72008-12-16 14:43:21 +010051 { 0x10de, "Nvidia" },
Takashi Iwaic8cd1282008-02-13 16:59:29 +010052 { 0x10ec, "Realtek" },
Takashi Iwai4e01f542009-04-16 08:53:34 +020053 { 0x1102, "Creative" },
Joseph Chanc577b8a2006-11-29 15:29:40 +010054 { 0x1106, "VIA" },
Matthew Ranostay7f168592007-10-18 17:38:17 +020055 { 0x111d, "IDT" },
Takashi Iwaic8cd1282008-02-13 16:59:29 +010056 { 0x11c1, "LSI" },
Takashi Iwai54b903e2005-05-15 14:30:10 +020057 { 0x11d4, "Analog Devices" },
Linus Torvalds1da177e2005-04-16 15:20:36 -070058 { 0x13f6, "C-Media" },
Takashi Iwaia9226252006-09-17 22:05:54 +020059 { 0x14f1, "Conexant" },
Takashi Iwaic8cd1282008-02-13 16:59:29 +010060 { 0x17e8, "Chrontel" },
61 { 0x1854, "LG" },
Mark Brown8199de32008-10-28 14:50:13 +000062 { 0x1aec, "Wolfson Microelectronics" },
Linus Torvalds1da177e2005-04-16 15:20:36 -070063 { 0x434d, "C-Media" },
Takashi Iwai74c61132008-12-18 09:11:33 +010064 { 0x8086, "Intel" },
Matt2f2f4252005-04-13 14:45:30 +020065 { 0x8384, "SigmaTel" },
Linus Torvalds1da177e2005-04-16 15:20:36 -070066 {} /* terminator */
67};
68
Takashi Iwai1289e9e2008-11-27 15:47:11 +010069static DEFINE_MUTEX(preset_mutex);
70static LIST_HEAD(hda_preset_tables);
71
72int snd_hda_add_codec_preset(struct hda_codec_preset_list *preset)
73{
74 mutex_lock(&preset_mutex);
75 list_add_tail(&preset->list, &hda_preset_tables);
76 mutex_unlock(&preset_mutex);
77 return 0;
78}
Takashi Iwaiff7a3262008-11-28 15:17:06 +010079EXPORT_SYMBOL_HDA(snd_hda_add_codec_preset);
Takashi Iwai1289e9e2008-11-27 15:47:11 +010080
81int snd_hda_delete_codec_preset(struct hda_codec_preset_list *preset)
82{
83 mutex_lock(&preset_mutex);
84 list_del(&preset->list);
85 mutex_unlock(&preset_mutex);
86 return 0;
87}
Takashi Iwaiff7a3262008-11-28 15:17:06 +010088EXPORT_SYMBOL_HDA(snd_hda_delete_codec_preset);
Linus Torvalds1da177e2005-04-16 15:20:36 -070089
Takashi Iwaicb53c622007-08-10 17:21:45 +020090#ifdef CONFIG_SND_HDA_POWER_SAVE
91static void hda_power_work(struct work_struct *work);
92static void hda_keep_power_on(struct hda_codec *codec);
93#else
94static inline void hda_keep_power_on(struct hda_codec *codec) {}
95#endif
96
Takashi Iwaid5191e52009-11-16 14:58:17 +010097/**
98 * snd_hda_get_jack_location - Give a location string of the jack
99 * @cfg: pin default config value
100 *
101 * Parse the pin default config value and returns the string of the
102 * jack location, e.g. "Rear", "Front", etc.
103 */
Matthew Ranostay50a9f792008-10-25 01:05:45 -0400104const char *snd_hda_get_jack_location(u32 cfg)
105{
106 static char *bases[7] = {
107 "N/A", "Rear", "Front", "Left", "Right", "Top", "Bottom",
108 };
109 static unsigned char specials_idx[] = {
110 0x07, 0x08,
111 0x17, 0x18, 0x19,
112 0x37, 0x38
113 };
114 static char *specials[] = {
115 "Rear Panel", "Drive Bar",
116 "Riser", "HDMI", "ATAPI",
117 "Mobile-In", "Mobile-Out"
118 };
119 int i;
120 cfg = (cfg & AC_DEFCFG_LOCATION) >> AC_DEFCFG_LOCATION_SHIFT;
121 if ((cfg & 0x0f) < 7)
122 return bases[cfg & 0x0f];
123 for (i = 0; i < ARRAY_SIZE(specials_idx); i++) {
124 if (cfg == specials_idx[i])
125 return specials[i];
126 }
127 return "UNKNOWN";
128}
Takashi Iwaiff7a3262008-11-28 15:17:06 +0100129EXPORT_SYMBOL_HDA(snd_hda_get_jack_location);
Matthew Ranostay50a9f792008-10-25 01:05:45 -0400130
Takashi Iwaid5191e52009-11-16 14:58:17 +0100131/**
132 * snd_hda_get_jack_connectivity - Give a connectivity string of the jack
133 * @cfg: pin default config value
134 *
135 * Parse the pin default config value and returns the string of the
136 * jack connectivity, i.e. external or internal connection.
137 */
Matthew Ranostay50a9f792008-10-25 01:05:45 -0400138const char *snd_hda_get_jack_connectivity(u32 cfg)
139{
140 static char *jack_locations[4] = { "Ext", "Int", "Sep", "Oth" };
141
142 return jack_locations[(cfg >> (AC_DEFCFG_LOCATION_SHIFT + 4)) & 3];
143}
Takashi Iwaiff7a3262008-11-28 15:17:06 +0100144EXPORT_SYMBOL_HDA(snd_hda_get_jack_connectivity);
Matthew Ranostay50a9f792008-10-25 01:05:45 -0400145
Takashi Iwaid5191e52009-11-16 14:58:17 +0100146/**
147 * snd_hda_get_jack_type - Give a type string of the jack
148 * @cfg: pin default config value
149 *
150 * Parse the pin default config value and returns the string of the
151 * jack type, i.e. the purpose of the jack, such as Line-Out or CD.
152 */
Matthew Ranostay50a9f792008-10-25 01:05:45 -0400153const char *snd_hda_get_jack_type(u32 cfg)
154{
155 static char *jack_types[16] = {
156 "Line Out", "Speaker", "HP Out", "CD",
157 "SPDIF Out", "Digital Out", "Modem Line", "Modem Hand",
158 "Line In", "Aux", "Mic", "Telephony",
159 "SPDIF In", "Digitial In", "Reserved", "Other"
160 };
161
162 return jack_types[(cfg & AC_DEFCFG_DEVICE)
163 >> AC_DEFCFG_DEVICE_SHIFT];
164}
Takashi Iwaiff7a3262008-11-28 15:17:06 +0100165EXPORT_SYMBOL_HDA(snd_hda_get_jack_type);
Matthew Ranostay50a9f792008-10-25 01:05:45 -0400166
Takashi Iwai33fa35e2008-11-06 16:50:40 +0100167/*
168 * Compose a 32bit command word to be sent to the HD-audio controller
169 */
170static inline unsigned int
171make_codec_cmd(struct hda_codec *codec, hda_nid_t nid, int direct,
172 unsigned int verb, unsigned int parm)
173{
174 u32 val;
175
Takashi Iwai82e1b802009-07-17 12:47:34 +0200176 if ((codec->addr & ~0xf) || (direct & ~1) || (nid & ~0x7f) ||
177 (verb & ~0xfff) || (parm & ~0xffff)) {
Wu Fengguang6430aee2009-07-17 16:49:19 +0800178 printk(KERN_ERR "hda-codec: out of range cmd %x:%x:%x:%x:%x\n",
179 codec->addr, direct, nid, verb, parm);
180 return ~0;
181 }
182
183 val = (u32)codec->addr << 28;
Takashi Iwai33fa35e2008-11-06 16:50:40 +0100184 val |= (u32)direct << 27;
185 val |= (u32)nid << 20;
186 val |= verb << 8;
187 val |= parm;
188 return val;
189}
190
Takashi Iwaiaa2936f2009-05-26 16:07:57 +0200191/*
192 * Send and receive a verb
193 */
194static int codec_exec_verb(struct hda_codec *codec, unsigned int cmd,
195 unsigned int *res)
196{
197 struct hda_bus *bus = codec->bus;
Takashi Iwai8dd78332009-06-02 01:16:07 +0200198 int err;
Takashi Iwaiaa2936f2009-05-26 16:07:57 +0200199
Wu Fengguang6430aee2009-07-17 16:49:19 +0800200 if (cmd == ~0)
201 return -1;
202
Takashi Iwaiaa2936f2009-05-26 16:07:57 +0200203 if (res)
204 *res = -1;
Takashi Iwai8dd78332009-06-02 01:16:07 +0200205 again:
Takashi Iwaiaa2936f2009-05-26 16:07:57 +0200206 snd_hda_power_up(codec);
207 mutex_lock(&bus->cmd_mutex);
Takashi Iwaiaa2936f2009-05-26 16:07:57 +0200208 err = bus->ops.command(bus, cmd);
Takashi Iwai8dd78332009-06-02 01:16:07 +0200209 if (!err && res)
Wu Fengguangdeadff12009-08-01 18:45:16 +0800210 *res = bus->ops.get_response(bus, codec->addr);
Takashi Iwaiaa2936f2009-05-26 16:07:57 +0200211 mutex_unlock(&bus->cmd_mutex);
212 snd_hda_power_down(codec);
Takashi Iwai8dd78332009-06-02 01:16:07 +0200213 if (res && *res == -1 && bus->rirb_error) {
214 if (bus->response_reset) {
215 snd_printd("hda_codec: resetting BUS due to "
216 "fatal communication error\n");
217 bus->ops.bus_reset(bus);
218 }
219 goto again;
220 }
221 /* clear reset-flag when the communication gets recovered */
222 if (!err)
223 bus->response_reset = 0;
Takashi Iwaiaa2936f2009-05-26 16:07:57 +0200224 return err;
225}
226
Linus Torvalds1da177e2005-04-16 15:20:36 -0700227/**
228 * snd_hda_codec_read - send a command and get the response
229 * @codec: the HDA codec
230 * @nid: NID to send the command
231 * @direct: direct flag
232 * @verb: the verb to send
233 * @parm: the parameter for the verb
234 *
235 * Send a single command and read the corresponding response.
236 *
237 * Returns the obtained response value, or -1 for an error.
238 */
Takashi Iwai0ba21762007-04-16 11:29:14 +0200239unsigned int snd_hda_codec_read(struct hda_codec *codec, hda_nid_t nid,
240 int direct,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700241 unsigned int verb, unsigned int parm)
242{
Takashi Iwaiaa2936f2009-05-26 16:07:57 +0200243 unsigned cmd = make_codec_cmd(codec, nid, direct, verb, parm);
244 unsigned int res;
245 codec_exec_verb(codec, cmd, &res);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700246 return res;
247}
Takashi Iwaiff7a3262008-11-28 15:17:06 +0100248EXPORT_SYMBOL_HDA(snd_hda_codec_read);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700249
250/**
251 * snd_hda_codec_write - send a single command without waiting for response
252 * @codec: the HDA codec
253 * @nid: NID to send the command
254 * @direct: direct flag
255 * @verb: the verb to send
256 * @parm: the parameter for the verb
257 *
258 * Send a single command without waiting for response.
259 *
260 * Returns 0 if successful, or a negative error code.
261 */
262int snd_hda_codec_write(struct hda_codec *codec, hda_nid_t nid, int direct,
263 unsigned int verb, unsigned int parm)
264{
Takashi Iwaiaa2936f2009-05-26 16:07:57 +0200265 unsigned int cmd = make_codec_cmd(codec, nid, direct, verb, parm);
Takashi Iwai33fa35e2008-11-06 16:50:40 +0100266 unsigned int res;
Takashi Iwaib20f3b82009-06-02 01:20:22 +0200267 return codec_exec_verb(codec, cmd,
268 codec->bus->sync_write ? &res : NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700269}
Takashi Iwaiff7a3262008-11-28 15:17:06 +0100270EXPORT_SYMBOL_HDA(snd_hda_codec_write);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700271
272/**
273 * snd_hda_sequence_write - sequence writes
274 * @codec: the HDA codec
275 * @seq: VERB array to send
276 *
277 * Send the commands sequentially from the given array.
278 * The array must be terminated with NID=0.
279 */
280void snd_hda_sequence_write(struct hda_codec *codec, const struct hda_verb *seq)
281{
282 for (; seq->nid; seq++)
283 snd_hda_codec_write(codec, seq->nid, 0, seq->verb, seq->param);
284}
Takashi Iwaiff7a3262008-11-28 15:17:06 +0100285EXPORT_SYMBOL_HDA(snd_hda_sequence_write);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700286
287/**
288 * snd_hda_get_sub_nodes - get the range of sub nodes
289 * @codec: the HDA codec
290 * @nid: NID to parse
291 * @start_id: the pointer to store the start NID
292 *
293 * Parse the NID and store the start NID of its sub-nodes.
294 * Returns the number of sub-nodes.
295 */
Takashi Iwai0ba21762007-04-16 11:29:14 +0200296int snd_hda_get_sub_nodes(struct hda_codec *codec, hda_nid_t nid,
297 hda_nid_t *start_id)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700298{
299 unsigned int parm;
300
301 parm = snd_hda_param_read(codec, nid, AC_PAR_NODE_COUNT);
Danny Tholene8a7f132007-09-11 21:41:56 +0200302 if (parm == -1)
303 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700304 *start_id = (parm >> 16) & 0x7fff;
305 return (int)(parm & 0x7fff);
306}
Takashi Iwaiff7a3262008-11-28 15:17:06 +0100307EXPORT_SYMBOL_HDA(snd_hda_get_sub_nodes);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700308
309/**
310 * snd_hda_get_connections - get connection list
311 * @codec: the HDA codec
312 * @nid: NID to parse
313 * @conn_list: connection list array
314 * @max_conns: max. number of connections to store
315 *
316 * Parses the connection list of the given widget and stores the list
317 * of NIDs.
318 *
319 * Returns the number of connections, or a negative error code.
320 */
321int snd_hda_get_connections(struct hda_codec *codec, hda_nid_t nid,
322 hda_nid_t *conn_list, int max_conns)
323{
324 unsigned int parm;
Takashi Iwai54d17402005-11-21 16:33:22 +0100325 int i, conn_len, conns;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700326 unsigned int shift, num_elems, mask;
Takashi Iwai1ba7a7c2009-07-27 12:56:26 +0200327 unsigned int wcaps;
Takashi Iwai54d17402005-11-21 16:33:22 +0100328 hda_nid_t prev_nid;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700329
Takashi Iwaida3cec32008-08-08 17:12:14 +0200330 if (snd_BUG_ON(!conn_list || max_conns <= 0))
331 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700332
Takashi Iwai1ba7a7c2009-07-27 12:56:26 +0200333 wcaps = get_wcaps(codec, nid);
334 if (!(wcaps & AC_WCAP_CONN_LIST) &&
335 get_wcaps_type(wcaps) != AC_WID_VOL_KNB) {
Jaroslav Kysela16a433d2009-07-22 16:20:40 +0200336 snd_printk(KERN_WARNING "hda_codec: "
337 "connection list not available for 0x%x\n", nid);
338 return -EINVAL;
339 }
340
Linus Torvalds1da177e2005-04-16 15:20:36 -0700341 parm = snd_hda_param_read(codec, nid, AC_PAR_CONNLIST_LEN);
342 if (parm & AC_CLIST_LONG) {
343 /* long form */
344 shift = 16;
345 num_elems = 2;
346 } else {
347 /* short form */
348 shift = 8;
349 num_elems = 4;
350 }
351 conn_len = parm & AC_CLIST_LENGTH;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700352 mask = (1 << (shift-1)) - 1;
353
Takashi Iwai0ba21762007-04-16 11:29:14 +0200354 if (!conn_len)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700355 return 0; /* no connection */
356
357 if (conn_len == 1) {
358 /* single connection */
Takashi Iwai0ba21762007-04-16 11:29:14 +0200359 parm = snd_hda_codec_read(codec, nid, 0,
360 AC_VERB_GET_CONNECT_LIST, 0);
Takashi Iwai3c6aae42009-07-10 12:52:27 +0200361 if (parm == -1 && codec->bus->rirb_error)
362 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700363 conn_list[0] = parm & mask;
364 return 1;
365 }
366
367 /* multi connection */
368 conns = 0;
Takashi Iwai54d17402005-11-21 16:33:22 +0100369 prev_nid = 0;
370 for (i = 0; i < conn_len; i++) {
371 int range_val;
372 hda_nid_t val, n;
373
Takashi Iwai3c6aae42009-07-10 12:52:27 +0200374 if (i % num_elems == 0) {
Takashi Iwai54d17402005-11-21 16:33:22 +0100375 parm = snd_hda_codec_read(codec, nid, 0,
376 AC_VERB_GET_CONNECT_LIST, i);
Takashi Iwai3c6aae42009-07-10 12:52:27 +0200377 if (parm == -1 && codec->bus->rirb_error)
378 return -EIO;
379 }
Takashi Iwai0ba21762007-04-16 11:29:14 +0200380 range_val = !!(parm & (1 << (shift-1))); /* ranges */
Takashi Iwai54d17402005-11-21 16:33:22 +0100381 val = parm & mask;
Jaroslav Kysela2e9bf242009-07-18 11:48:19 +0200382 if (val == 0) {
383 snd_printk(KERN_WARNING "hda_codec: "
384 "invalid CONNECT_LIST verb %x[%i]:%x\n",
385 nid, i, parm);
386 return 0;
387 }
Takashi Iwai54d17402005-11-21 16:33:22 +0100388 parm >>= shift;
389 if (range_val) {
390 /* ranges between the previous and this one */
Takashi Iwai0ba21762007-04-16 11:29:14 +0200391 if (!prev_nid || prev_nid >= val) {
392 snd_printk(KERN_WARNING "hda_codec: "
393 "invalid dep_range_val %x:%x\n",
394 prev_nid, val);
Takashi Iwai54d17402005-11-21 16:33:22 +0100395 continue;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700396 }
Takashi Iwai54d17402005-11-21 16:33:22 +0100397 for (n = prev_nid + 1; n <= val; n++) {
398 if (conns >= max_conns) {
Takashi Iwai0ba21762007-04-16 11:29:14 +0200399 snd_printk(KERN_ERR
400 "Too many connections\n");
Takashi Iwai54d17402005-11-21 16:33:22 +0100401 return -EINVAL;
402 }
403 conn_list[conns++] = n;
404 }
405 } else {
406 if (conns >= max_conns) {
407 snd_printk(KERN_ERR "Too many connections\n");
408 return -EINVAL;
409 }
410 conn_list[conns++] = val;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700411 }
Takashi Iwai54d17402005-11-21 16:33:22 +0100412 prev_nid = val;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700413 }
414 return conns;
415}
Takashi Iwaiff7a3262008-11-28 15:17:06 +0100416EXPORT_SYMBOL_HDA(snd_hda_get_connections);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700417
418
419/**
420 * snd_hda_queue_unsol_event - add an unsolicited event to queue
421 * @bus: the BUS
422 * @res: unsolicited event (lower 32bit of RIRB entry)
423 * @res_ex: codec addr and flags (upper 32bit or RIRB entry)
424 *
425 * Adds the given event to the queue. The events are processed in
426 * the workqueue asynchronously. Call this function in the interrupt
427 * hanlder when RIRB receives an unsolicited event.
428 *
429 * Returns 0 if successful, or a negative error code.
430 */
431int snd_hda_queue_unsol_event(struct hda_bus *bus, u32 res, u32 res_ex)
432{
433 struct hda_bus_unsolicited *unsol;
434 unsigned int wp;
435
Takashi Iwai0ba21762007-04-16 11:29:14 +0200436 unsol = bus->unsol;
437 if (!unsol)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700438 return 0;
439
440 wp = (unsol->wp + 1) % HDA_UNSOL_QUEUE_SIZE;
441 unsol->wp = wp;
442
443 wp <<= 1;
444 unsol->queue[wp] = res;
445 unsol->queue[wp + 1] = res_ex;
446
Takashi Iwai6acaed32009-01-12 10:09:24 +0100447 queue_work(bus->workq, &unsol->work);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700448
449 return 0;
450}
Takashi Iwaiff7a3262008-11-28 15:17:06 +0100451EXPORT_SYMBOL_HDA(snd_hda_queue_unsol_event);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700452
453/*
Wu Fengguang5c1d1a92008-10-07 14:17:53 +0800454 * process queued unsolicited events
Linus Torvalds1da177e2005-04-16 15:20:36 -0700455 */
David Howellsc4028952006-11-22 14:57:56 +0000456static void process_unsol_events(struct work_struct *work)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700457{
David Howellsc4028952006-11-22 14:57:56 +0000458 struct hda_bus_unsolicited *unsol =
459 container_of(work, struct hda_bus_unsolicited, work);
460 struct hda_bus *bus = unsol->bus;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700461 struct hda_codec *codec;
462 unsigned int rp, caddr, res;
463
464 while (unsol->rp != unsol->wp) {
465 rp = (unsol->rp + 1) % HDA_UNSOL_QUEUE_SIZE;
466 unsol->rp = rp;
467 rp <<= 1;
468 res = unsol->queue[rp];
469 caddr = unsol->queue[rp + 1];
Takashi Iwai0ba21762007-04-16 11:29:14 +0200470 if (!(caddr & (1 << 4))) /* no unsolicited event? */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700471 continue;
472 codec = bus->caddr_tbl[caddr & 0x0f];
473 if (codec && codec->patch_ops.unsol_event)
474 codec->patch_ops.unsol_event(codec, res);
475 }
476}
477
478/*
479 * initialize unsolicited queue
480 */
Takashi Iwai6c1f45e2008-07-30 15:01:45 +0200481static int init_unsol_queue(struct hda_bus *bus)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700482{
483 struct hda_bus_unsolicited *unsol;
484
Takashi Iwai9f146bb2005-11-17 11:07:49 +0100485 if (bus->unsol) /* already initialized */
486 return 0;
487
Takashi Iwaie560d8d2005-09-09 14:21:46 +0200488 unsol = kzalloc(sizeof(*unsol), GFP_KERNEL);
Takashi Iwai0ba21762007-04-16 11:29:14 +0200489 if (!unsol) {
490 snd_printk(KERN_ERR "hda_codec: "
491 "can't allocate unsolicited queue\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700492 return -ENOMEM;
493 }
David Howellsc4028952006-11-22 14:57:56 +0000494 INIT_WORK(&unsol->work, process_unsol_events);
495 unsol->bus = bus;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700496 bus->unsol = unsol;
497 return 0;
498}
499
500/*
501 * destructor
502 */
503static void snd_hda_codec_free(struct hda_codec *codec);
504
505static int snd_hda_bus_free(struct hda_bus *bus)
506{
Takashi Iwai0ba21762007-04-16 11:29:14 +0200507 struct hda_codec *codec, *n;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700508
Takashi Iwai0ba21762007-04-16 11:29:14 +0200509 if (!bus)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700510 return 0;
Takashi Iwai6acaed32009-01-12 10:09:24 +0100511 if (bus->workq)
512 flush_workqueue(bus->workq);
513 if (bus->unsol)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700514 kfree(bus->unsol);
Takashi Iwai0ba21762007-04-16 11:29:14 +0200515 list_for_each_entry_safe(codec, n, &bus->codec_list, list) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700516 snd_hda_codec_free(codec);
517 }
518 if (bus->ops.private_free)
519 bus->ops.private_free(bus);
Takashi Iwai6acaed32009-01-12 10:09:24 +0100520 if (bus->workq)
521 destroy_workqueue(bus->workq);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700522 kfree(bus);
523 return 0;
524}
525
Takashi Iwaic8b6bf92005-11-17 14:57:47 +0100526static int snd_hda_bus_dev_free(struct snd_device *device)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700527{
528 struct hda_bus *bus = device->device_data;
Takashi Iwaib94d35392008-11-21 09:08:06 +0100529 bus->shutdown = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700530 return snd_hda_bus_free(bus);
531}
532
Takashi Iwaid7ffba12008-07-30 15:01:46 +0200533#ifdef CONFIG_SND_HDA_HWDEP
534static int snd_hda_bus_dev_register(struct snd_device *device)
535{
536 struct hda_bus *bus = device->device_data;
537 struct hda_codec *codec;
538 list_for_each_entry(codec, &bus->codec_list, list) {
539 snd_hda_hwdep_add_sysfs(codec);
Takashi Iwaia2f63092009-11-11 09:34:25 +0100540 snd_hda_hwdep_add_power_sysfs(codec);
Takashi Iwaid7ffba12008-07-30 15:01:46 +0200541 }
542 return 0;
543}
544#else
545#define snd_hda_bus_dev_register NULL
546#endif
547
Linus Torvalds1da177e2005-04-16 15:20:36 -0700548/**
549 * snd_hda_bus_new - create a HDA bus
550 * @card: the card entry
551 * @temp: the template for hda_bus information
552 * @busp: the pointer to store the created bus instance
553 *
554 * Returns 0 if successful, or a negative error code.
555 */
Takashi Iwai1289e9e2008-11-27 15:47:11 +0100556int /*__devinit*/ snd_hda_bus_new(struct snd_card *card,
Takashi Iwai756e2b02007-04-16 11:27:07 +0200557 const struct hda_bus_template *temp,
558 struct hda_bus **busp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700559{
560 struct hda_bus *bus;
561 int err;
Takashi Iwaic8b6bf92005-11-17 14:57:47 +0100562 static struct snd_device_ops dev_ops = {
Takashi Iwaid7ffba12008-07-30 15:01:46 +0200563 .dev_register = snd_hda_bus_dev_register,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700564 .dev_free = snd_hda_bus_dev_free,
565 };
566
Takashi Iwaida3cec32008-08-08 17:12:14 +0200567 if (snd_BUG_ON(!temp))
568 return -EINVAL;
569 if (snd_BUG_ON(!temp->ops.command || !temp->ops.get_response))
570 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700571
572 if (busp)
573 *busp = NULL;
574
Takashi Iwaie560d8d2005-09-09 14:21:46 +0200575 bus = kzalloc(sizeof(*bus), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700576 if (bus == NULL) {
577 snd_printk(KERN_ERR "can't allocate struct hda_bus\n");
578 return -ENOMEM;
579 }
580
581 bus->card = card;
582 bus->private_data = temp->private_data;
583 bus->pci = temp->pci;
584 bus->modelname = temp->modelname;
Takashi Iwaifee2fba2008-11-27 12:43:28 +0100585 bus->power_save = temp->power_save;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700586 bus->ops = temp->ops;
587
Ingo Molnar62932df2006-01-16 16:34:20 +0100588 mutex_init(&bus->cmd_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700589 INIT_LIST_HEAD(&bus->codec_list);
590
Takashi Iwaie8c0ee52009-02-05 07:34:28 +0100591 snprintf(bus->workq_name, sizeof(bus->workq_name),
592 "hd-audio%d", card->number);
593 bus->workq = create_singlethread_workqueue(bus->workq_name);
Takashi Iwai6acaed32009-01-12 10:09:24 +0100594 if (!bus->workq) {
Takashi Iwaie8c0ee52009-02-05 07:34:28 +0100595 snd_printk(KERN_ERR "cannot create workqueue %s\n",
596 bus->workq_name);
Takashi Iwai6acaed32009-01-12 10:09:24 +0100597 kfree(bus);
598 return -ENOMEM;
599 }
600
Takashi Iwai0ba21762007-04-16 11:29:14 +0200601 err = snd_device_new(card, SNDRV_DEV_BUS, bus, &dev_ops);
602 if (err < 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700603 snd_hda_bus_free(bus);
604 return err;
605 }
606 if (busp)
607 *busp = bus;
608 return 0;
609}
Takashi Iwaiff7a3262008-11-28 15:17:06 +0100610EXPORT_SYMBOL_HDA(snd_hda_bus_new);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700611
Takashi Iwai82467612007-07-27 19:15:54 +0200612#ifdef CONFIG_SND_HDA_GENERIC
613#define is_generic_config(codec) \
Takashi Iwaif44ac832008-07-30 15:01:45 +0200614 (codec->modelname && !strcmp(codec->modelname, "generic"))
Takashi Iwai82467612007-07-27 19:15:54 +0200615#else
616#define is_generic_config(codec) 0
617#endif
618
Takashi Iwai645f10c2008-11-28 15:07:37 +0100619#ifdef MODULE
Takashi Iwai1289e9e2008-11-27 15:47:11 +0100620#define HDA_MODREQ_MAX_COUNT 2 /* two request_modules()'s */
621#else
Takashi Iwai645f10c2008-11-28 15:07:37 +0100622#define HDA_MODREQ_MAX_COUNT 0 /* all presets are statically linked */
Takashi Iwai1289e9e2008-11-27 15:47:11 +0100623#endif
624
Linus Torvalds1da177e2005-04-16 15:20:36 -0700625/*
626 * find a matching codec preset
627 */
Takashi Iwai6c1f45e2008-07-30 15:01:45 +0200628static const struct hda_codec_preset *
Takashi Iwai756e2b02007-04-16 11:27:07 +0200629find_codec_preset(struct hda_codec *codec)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700630{
Takashi Iwai1289e9e2008-11-27 15:47:11 +0100631 struct hda_codec_preset_list *tbl;
632 const struct hda_codec_preset *preset;
633 int mod_requested = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700634
Takashi Iwai82467612007-07-27 19:15:54 +0200635 if (is_generic_config(codec))
Takashi Iwaid5ad6302007-03-07 15:55:59 +0100636 return NULL; /* use the generic parser */
637
Takashi Iwai1289e9e2008-11-27 15:47:11 +0100638 again:
639 mutex_lock(&preset_mutex);
640 list_for_each_entry(tbl, &hda_preset_tables, list) {
641 if (!try_module_get(tbl->owner)) {
642 snd_printk(KERN_ERR "hda_codec: cannot module_get\n");
643 continue;
644 }
645 for (preset = tbl->preset; preset->id; preset++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700646 u32 mask = preset->mask;
Marc Boucherca7cfae2008-01-22 15:32:25 +0100647 if (preset->afg && preset->afg != codec->afg)
648 continue;
649 if (preset->mfg && preset->mfg != codec->mfg)
650 continue;
Takashi Iwai0ba21762007-04-16 11:29:14 +0200651 if (!mask)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700652 mask = ~0;
Takashi Iwai9c7f8522006-06-28 15:08:22 +0200653 if (preset->id == (codec->vendor_id & mask) &&
Takashi Iwai0ba21762007-04-16 11:29:14 +0200654 (!preset->rev ||
Takashi Iwai1289e9e2008-11-27 15:47:11 +0100655 preset->rev == codec->revision_id)) {
656 mutex_unlock(&preset_mutex);
657 codec->owner = tbl->owner;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700658 return preset;
Takashi Iwai1289e9e2008-11-27 15:47:11 +0100659 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700660 }
Takashi Iwai1289e9e2008-11-27 15:47:11 +0100661 module_put(tbl->owner);
662 }
663 mutex_unlock(&preset_mutex);
664
665 if (mod_requested < HDA_MODREQ_MAX_COUNT) {
666 char name[32];
667 if (!mod_requested)
668 snprintf(name, sizeof(name), "snd-hda-codec-id:%08x",
669 codec->vendor_id);
670 else
671 snprintf(name, sizeof(name), "snd-hda-codec-id:%04x*",
672 (codec->vendor_id >> 16) & 0xffff);
673 request_module(name);
674 mod_requested++;
675 goto again;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700676 }
677 return NULL;
678}
679
680/*
Takashi Iwaif44ac832008-07-30 15:01:45 +0200681 * get_codec_name - store the codec name
Linus Torvalds1da177e2005-04-16 15:20:36 -0700682 */
Takashi Iwaif44ac832008-07-30 15:01:45 +0200683static int get_codec_name(struct hda_codec *codec)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700684{
685 const struct hda_vendor_id *c;
686 const char *vendor = NULL;
687 u16 vendor_id = codec->vendor_id >> 16;
Takashi Iwai812a2cc2009-05-16 10:00:49 +0200688 char tmp[16];
689
690 if (codec->vendor_name)
691 goto get_chip_name;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700692
693 for (c = hda_vendor_ids; c->id; c++) {
694 if (c->id == vendor_id) {
695 vendor = c->name;
696 break;
697 }
698 }
Takashi Iwai0ba21762007-04-16 11:29:14 +0200699 if (!vendor) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700700 sprintf(tmp, "Generic %04x", vendor_id);
701 vendor = tmp;
702 }
Takashi Iwai812a2cc2009-05-16 10:00:49 +0200703 codec->vendor_name = kstrdup(vendor, GFP_KERNEL);
704 if (!codec->vendor_name)
705 return -ENOMEM;
706
707 get_chip_name:
708 if (codec->chip_name)
709 return 0;
710
Linus Torvalds1da177e2005-04-16 15:20:36 -0700711 if (codec->preset && codec->preset->name)
Takashi Iwai812a2cc2009-05-16 10:00:49 +0200712 codec->chip_name = kstrdup(codec->preset->name, GFP_KERNEL);
713 else {
714 sprintf(tmp, "ID %x", codec->vendor_id & 0xffff);
715 codec->chip_name = kstrdup(tmp, GFP_KERNEL);
716 }
717 if (!codec->chip_name)
Takashi Iwaif44ac832008-07-30 15:01:45 +0200718 return -ENOMEM;
719 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700720}
721
722/*
Sasha Khapyorsky673b6832005-08-11 11:00:16 +0200723 * look for an AFG and MFG nodes
Linus Torvalds1da177e2005-04-16 15:20:36 -0700724 */
Takashi Iwai1289e9e2008-11-27 15:47:11 +0100725static void /*__devinit*/ setup_fg_nodes(struct hda_codec *codec)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700726{
Takashi Iwai93e82ae2009-04-17 18:04:41 +0200727 int i, total_nodes, function_id;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700728 hda_nid_t nid;
729
730 total_nodes = snd_hda_get_sub_nodes(codec, AC_NODE_ROOT, &nid);
731 for (i = 0; i < total_nodes; i++, nid++) {
Takashi Iwai93e82ae2009-04-17 18:04:41 +0200732 function_id = snd_hda_param_read(codec, nid,
Pascal de Bruijn234b4342009-03-23 11:15:59 +0100733 AC_PAR_FUNCTION_TYPE) & 0xff;
Takashi Iwai93e82ae2009-04-17 18:04:41 +0200734 switch (function_id) {
Sasha Khapyorsky673b6832005-08-11 11:00:16 +0200735 case AC_GRP_AUDIO_FUNCTION:
736 codec->afg = nid;
Takashi Iwai93e82ae2009-04-17 18:04:41 +0200737 codec->function_id = function_id;
Sasha Khapyorsky673b6832005-08-11 11:00:16 +0200738 break;
739 case AC_GRP_MODEM_FUNCTION:
740 codec->mfg = nid;
Takashi Iwai93e82ae2009-04-17 18:04:41 +0200741 codec->function_id = function_id;
Sasha Khapyorsky673b6832005-08-11 11:00:16 +0200742 break;
743 default:
744 break;
745 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700746 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700747}
748
749/*
Takashi Iwai54d17402005-11-21 16:33:22 +0100750 * read widget caps for each widget and store in cache
751 */
752static int read_widget_caps(struct hda_codec *codec, hda_nid_t fg_node)
753{
754 int i;
755 hda_nid_t nid;
756
757 codec->num_nodes = snd_hda_get_sub_nodes(codec, fg_node,
758 &codec->start_nid);
759 codec->wcaps = kmalloc(codec->num_nodes * 4, GFP_KERNEL);
Takashi Iwai0ba21762007-04-16 11:29:14 +0200760 if (!codec->wcaps)
Takashi Iwai54d17402005-11-21 16:33:22 +0100761 return -ENOMEM;
762 nid = codec->start_nid;
763 for (i = 0; i < codec->num_nodes; i++, nid++)
764 codec->wcaps[i] = snd_hda_param_read(codec, nid,
765 AC_PAR_AUDIO_WIDGET_CAP);
766 return 0;
767}
768
Takashi Iwai3be14142009-02-20 14:11:16 +0100769/* read all pin default configurations and save codec->init_pins */
770static int read_pin_defaults(struct hda_codec *codec)
771{
772 int i;
773 hda_nid_t nid = codec->start_nid;
774
775 for (i = 0; i < codec->num_nodes; i++, nid++) {
776 struct hda_pincfg *pin;
777 unsigned int wcaps = get_wcaps(codec, nid);
Takashi Iwaia22d5432009-07-27 12:54:26 +0200778 unsigned int wid_type = get_wcaps_type(wcaps);
Takashi Iwai3be14142009-02-20 14:11:16 +0100779 if (wid_type != AC_WID_PIN)
780 continue;
781 pin = snd_array_new(&codec->init_pins);
782 if (!pin)
783 return -ENOMEM;
784 pin->nid = nid;
785 pin->cfg = snd_hda_codec_read(codec, nid, 0,
786 AC_VERB_GET_CONFIG_DEFAULT, 0);
787 }
788 return 0;
789}
790
791/* look up the given pin config list and return the item matching with NID */
792static struct hda_pincfg *look_up_pincfg(struct hda_codec *codec,
793 struct snd_array *array,
794 hda_nid_t nid)
795{
796 int i;
797 for (i = 0; i < array->used; i++) {
798 struct hda_pincfg *pin = snd_array_elem(array, i);
799 if (pin->nid == nid)
800 return pin;
801 }
802 return NULL;
803}
804
805/* write a config value for the given NID */
806static void set_pincfg(struct hda_codec *codec, hda_nid_t nid,
807 unsigned int cfg)
808{
809 int i;
810 for (i = 0; i < 4; i++) {
811 snd_hda_codec_write(codec, nid, 0,
812 AC_VERB_SET_CONFIG_DEFAULT_BYTES_0 + i,
813 cfg & 0xff);
814 cfg >>= 8;
815 }
816}
817
818/* set the current pin config value for the given NID.
819 * the value is cached, and read via snd_hda_codec_get_pincfg()
820 */
821int snd_hda_add_pincfg(struct hda_codec *codec, struct snd_array *list,
822 hda_nid_t nid, unsigned int cfg)
823{
824 struct hda_pincfg *pin;
Takashi Iwai5e7b8e02009-02-23 09:45:59 +0100825 unsigned int oldcfg;
Takashi Iwai3be14142009-02-20 14:11:16 +0100826
Takashi Iwai5e7b8e02009-02-23 09:45:59 +0100827 oldcfg = snd_hda_codec_get_pincfg(codec, nid);
Takashi Iwai3be14142009-02-20 14:11:16 +0100828 pin = look_up_pincfg(codec, list, nid);
829 if (!pin) {
830 pin = snd_array_new(list);
831 if (!pin)
832 return -ENOMEM;
833 pin->nid = nid;
834 }
835 pin->cfg = cfg;
Takashi Iwai5e7b8e02009-02-23 09:45:59 +0100836
837 /* change only when needed; e.g. if the pincfg is already present
838 * in user_pins[], don't write it
839 */
840 cfg = snd_hda_codec_get_pincfg(codec, nid);
841 if (oldcfg != cfg)
842 set_pincfg(codec, nid, cfg);
Takashi Iwai3be14142009-02-20 14:11:16 +0100843 return 0;
844}
845
Takashi Iwaid5191e52009-11-16 14:58:17 +0100846/**
847 * snd_hda_codec_set_pincfg - Override a pin default configuration
848 * @codec: the HDA codec
849 * @nid: NID to set the pin config
850 * @cfg: the pin default config value
851 *
852 * Override a pin default configuration value in the cache.
853 * This value can be read by snd_hda_codec_get_pincfg() in a higher
854 * priority than the real hardware value.
855 */
Takashi Iwai3be14142009-02-20 14:11:16 +0100856int snd_hda_codec_set_pincfg(struct hda_codec *codec,
857 hda_nid_t nid, unsigned int cfg)
858{
Takashi Iwai346ff702009-02-23 09:42:57 +0100859 return snd_hda_add_pincfg(codec, &codec->driver_pins, nid, cfg);
Takashi Iwai3be14142009-02-20 14:11:16 +0100860}
861EXPORT_SYMBOL_HDA(snd_hda_codec_set_pincfg);
862
Takashi Iwaid5191e52009-11-16 14:58:17 +0100863/**
864 * snd_hda_codec_get_pincfg - Obtain a pin-default configuration
865 * @codec: the HDA codec
866 * @nid: NID to get the pin config
867 *
868 * Get the current pin config value of the given pin NID.
869 * If the pincfg value is cached or overridden via sysfs or driver,
870 * returns the cached value.
871 */
Takashi Iwai3be14142009-02-20 14:11:16 +0100872unsigned int snd_hda_codec_get_pincfg(struct hda_codec *codec, hda_nid_t nid)
873{
874 struct hda_pincfg *pin;
875
Takashi Iwai3be14142009-02-20 14:11:16 +0100876#ifdef CONFIG_SND_HDA_HWDEP
Takashi Iwai346ff702009-02-23 09:42:57 +0100877 pin = look_up_pincfg(codec, &codec->user_pins, nid);
Takashi Iwai3be14142009-02-20 14:11:16 +0100878 if (pin)
879 return pin->cfg;
880#endif
Takashi Iwai5e7b8e02009-02-23 09:45:59 +0100881 pin = look_up_pincfg(codec, &codec->driver_pins, nid);
882 if (pin)
883 return pin->cfg;
Takashi Iwai3be14142009-02-20 14:11:16 +0100884 pin = look_up_pincfg(codec, &codec->init_pins, nid);
885 if (pin)
886 return pin->cfg;
887 return 0;
888}
889EXPORT_SYMBOL_HDA(snd_hda_codec_get_pincfg);
890
891/* restore all current pin configs */
892static void restore_pincfgs(struct hda_codec *codec)
893{
894 int i;
895 for (i = 0; i < codec->init_pins.used; i++) {
896 struct hda_pincfg *pin = snd_array_elem(&codec->init_pins, i);
897 set_pincfg(codec, pin->nid,
898 snd_hda_codec_get_pincfg(codec, pin->nid));
899 }
900}
Takashi Iwai54d17402005-11-21 16:33:22 +0100901
Takashi Iwai01751f52007-08-10 16:59:39 +0200902static void init_hda_cache(struct hda_cache_rec *cache,
903 unsigned int record_size);
Takashi Iwai1fcaee62007-08-23 00:01:09 +0200904static void free_hda_cache(struct hda_cache_rec *cache);
Takashi Iwai01751f52007-08-10 16:59:39 +0200905
Takashi Iwai3be14142009-02-20 14:11:16 +0100906/* restore the initial pin cfgs and release all pincfg lists */
907static void restore_init_pincfgs(struct hda_codec *codec)
908{
Takashi Iwai346ff702009-02-23 09:42:57 +0100909 /* first free driver_pins and user_pins, then call restore_pincfg
Takashi Iwai3be14142009-02-20 14:11:16 +0100910 * so that only the values in init_pins are restored
911 */
Takashi Iwai346ff702009-02-23 09:42:57 +0100912 snd_array_free(&codec->driver_pins);
Takashi Iwai3be14142009-02-20 14:11:16 +0100913#ifdef CONFIG_SND_HDA_HWDEP
Takashi Iwai346ff702009-02-23 09:42:57 +0100914 snd_array_free(&codec->user_pins);
Takashi Iwai3be14142009-02-20 14:11:16 +0100915#endif
916 restore_pincfgs(codec);
917 snd_array_free(&codec->init_pins);
918}
919
Takashi Iwai54d17402005-11-21 16:33:22 +0100920/*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700921 * codec destructor
922 */
923static void snd_hda_codec_free(struct hda_codec *codec)
924{
Takashi Iwai0ba21762007-04-16 11:29:14 +0200925 if (!codec)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700926 return;
Takashi Iwai3be14142009-02-20 14:11:16 +0100927 restore_init_pincfgs(codec);
Takashi Iwaicb53c622007-08-10 17:21:45 +0200928#ifdef CONFIG_SND_HDA_POWER_SAVE
929 cancel_delayed_work(&codec->power_work);
Takashi Iwai6acaed32009-01-12 10:09:24 +0100930 flush_workqueue(codec->bus->workq);
Takashi Iwaicb53c622007-08-10 17:21:45 +0200931#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700932 list_del(&codec->list);
Takashi Iwaid13bd412008-07-30 15:01:45 +0200933 snd_array_free(&codec->mixers);
Jaroslav Kysela5b0cb1d2009-12-08 16:13:32 +0100934 snd_array_free(&codec->nids);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700935 codec->bus->caddr_tbl[codec->addr] = NULL;
936 if (codec->patch_ops.free)
937 codec->patch_ops.free(codec);
Takashi Iwai1289e9e2008-11-27 15:47:11 +0100938 module_put(codec->owner);
Takashi Iwai01751f52007-08-10 16:59:39 +0200939 free_hda_cache(&codec->amp_cache);
Takashi Iwaib3ac5632007-08-10 17:03:40 +0200940 free_hda_cache(&codec->cmd_cache);
Takashi Iwai812a2cc2009-05-16 10:00:49 +0200941 kfree(codec->vendor_name);
942 kfree(codec->chip_name);
Takashi Iwaif44ac832008-07-30 15:01:45 +0200943 kfree(codec->modelname);
Takashi Iwai54d17402005-11-21 16:33:22 +0100944 kfree(codec->wcaps);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700945 kfree(codec);
946}
947
Takashi Iwaibb6ac722009-03-13 09:02:42 +0100948static void hda_set_power_state(struct hda_codec *codec, hda_nid_t fg,
949 unsigned int power_state);
950
Linus Torvalds1da177e2005-04-16 15:20:36 -0700951/**
952 * snd_hda_codec_new - create a HDA codec
953 * @bus: the bus to assign
954 * @codec_addr: the codec address
955 * @codecp: the pointer to store the generated codec
956 *
957 * Returns 0 if successful, or a negative error code.
958 */
Takashi Iwai1289e9e2008-11-27 15:47:11 +0100959int /*__devinit*/ snd_hda_codec_new(struct hda_bus *bus, unsigned int codec_addr,
Takashi Iwaia1e21c92009-06-17 09:33:52 +0200960 struct hda_codec **codecp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700961{
962 struct hda_codec *codec;
Jaroslav Kyselaba443682008-08-13 20:55:32 +0200963 char component[31];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700964 int err;
965
Takashi Iwaida3cec32008-08-08 17:12:14 +0200966 if (snd_BUG_ON(!bus))
967 return -EINVAL;
968 if (snd_BUG_ON(codec_addr > HDA_MAX_CODEC_ADDRESS))
969 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700970
971 if (bus->caddr_tbl[codec_addr]) {
Takashi Iwai0ba21762007-04-16 11:29:14 +0200972 snd_printk(KERN_ERR "hda_codec: "
973 "address 0x%x is already occupied\n", codec_addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700974 return -EBUSY;
975 }
976
Takashi Iwaie560d8d2005-09-09 14:21:46 +0200977 codec = kzalloc(sizeof(*codec), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700978 if (codec == NULL) {
979 snd_printk(KERN_ERR "can't allocate struct hda_codec\n");
980 return -ENOMEM;
981 }
982
983 codec->bus = bus;
984 codec->addr = codec_addr;
Ingo Molnar62932df2006-01-16 16:34:20 +0100985 mutex_init(&codec->spdif_mutex);
Wu Fengguang5a9e02e2009-01-09 16:45:24 +0800986 mutex_init(&codec->control_mutex);
Takashi Iwai01751f52007-08-10 16:59:39 +0200987 init_hda_cache(&codec->amp_cache, sizeof(struct hda_amp_info));
Takashi Iwaib3ac5632007-08-10 17:03:40 +0200988 init_hda_cache(&codec->cmd_cache, sizeof(struct hda_cache_head));
Jaroslav Kysela5b0cb1d2009-12-08 16:13:32 +0100989 snd_array_init(&codec->mixers, sizeof(struct hda_nid_item), 32);
990 snd_array_init(&codec->nids, sizeof(struct hda_nid_item), 32);
Takashi Iwai3be14142009-02-20 14:11:16 +0100991 snd_array_init(&codec->init_pins, sizeof(struct hda_pincfg), 16);
Takashi Iwai346ff702009-02-23 09:42:57 +0100992 snd_array_init(&codec->driver_pins, sizeof(struct hda_pincfg), 16);
Takashi Iwai6c1f45e2008-07-30 15:01:45 +0200993 if (codec->bus->modelname) {
994 codec->modelname = kstrdup(codec->bus->modelname, GFP_KERNEL);
995 if (!codec->modelname) {
996 snd_hda_codec_free(codec);
997 return -ENODEV;
998 }
999 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001000
Takashi Iwaicb53c622007-08-10 17:21:45 +02001001#ifdef CONFIG_SND_HDA_POWER_SAVE
1002 INIT_DELAYED_WORK(&codec->power_work, hda_power_work);
1003 /* snd_hda_codec_new() marks the codec as power-up, and leave it as is.
1004 * the caller has to power down appropriatley after initialization
1005 * phase.
1006 */
1007 hda_keep_power_on(codec);
1008#endif
1009
Linus Torvalds1da177e2005-04-16 15:20:36 -07001010 list_add_tail(&codec->list, &bus->codec_list);
1011 bus->caddr_tbl[codec_addr] = codec;
1012
Takashi Iwai0ba21762007-04-16 11:29:14 +02001013 codec->vendor_id = snd_hda_param_read(codec, AC_NODE_ROOT,
1014 AC_PAR_VENDOR_ID);
Takashi Iwai111d3af2006-02-16 18:17:58 +01001015 if (codec->vendor_id == -1)
1016 /* read again, hopefully the access method was corrected
1017 * in the last read...
1018 */
1019 codec->vendor_id = snd_hda_param_read(codec, AC_NODE_ROOT,
1020 AC_PAR_VENDOR_ID);
Takashi Iwai0ba21762007-04-16 11:29:14 +02001021 codec->subsystem_id = snd_hda_param_read(codec, AC_NODE_ROOT,
1022 AC_PAR_SUBSYSTEM_ID);
1023 codec->revision_id = snd_hda_param_read(codec, AC_NODE_ROOT,
1024 AC_PAR_REV_ID);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001025
Sasha Khapyorsky673b6832005-08-11 11:00:16 +02001026 setup_fg_nodes(codec);
Takashi Iwai0ba21762007-04-16 11:29:14 +02001027 if (!codec->afg && !codec->mfg) {
Sasha Khapyorsky673b6832005-08-11 11:00:16 +02001028 snd_printdd("hda_codec: no AFG or MFG node found\n");
Takashi Iwai3be14142009-02-20 14:11:16 +01001029 err = -ENODEV;
1030 goto error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001031 }
1032
Takashi Iwai3be14142009-02-20 14:11:16 +01001033 err = read_widget_caps(codec, codec->afg ? codec->afg : codec->mfg);
1034 if (err < 0) {
Takashi Iwai54d17402005-11-21 16:33:22 +01001035 snd_printk(KERN_ERR "hda_codec: cannot malloc\n");
Takashi Iwai3be14142009-02-20 14:11:16 +01001036 goto error;
Takashi Iwai54d17402005-11-21 16:33:22 +01001037 }
Takashi Iwai3be14142009-02-20 14:11:16 +01001038 err = read_pin_defaults(codec);
1039 if (err < 0)
1040 goto error;
Takashi Iwai54d17402005-11-21 16:33:22 +01001041
Takashi Iwai0ba21762007-04-16 11:29:14 +02001042 if (!codec->subsystem_id) {
Takashi Iwai86284e42005-10-11 15:05:54 +02001043 hda_nid_t nid = codec->afg ? codec->afg : codec->mfg;
Takashi Iwai0ba21762007-04-16 11:29:14 +02001044 codec->subsystem_id =
1045 snd_hda_codec_read(codec, nid, 0,
1046 AC_VERB_GET_SUBSYSTEM_ID, 0);
Takashi Iwai86284e42005-10-11 15:05:54 +02001047 }
1048
Takashi Iwaibb6ac722009-03-13 09:02:42 +01001049 /* power-up all before initialization */
1050 hda_set_power_state(codec,
1051 codec->afg ? codec->afg : codec->mfg,
1052 AC_PWRST_D0);
1053
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001054 snd_hda_codec_proc_new(codec);
1055
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001056 snd_hda_create_hwdep(codec);
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001057
1058 sprintf(component, "HDA:%08x,%08x,%08x", codec->vendor_id,
1059 codec->subsystem_id, codec->revision_id);
1060 snd_component_add(codec->bus->card, component);
1061
1062 if (codecp)
1063 *codecp = codec;
1064 return 0;
Takashi Iwai3be14142009-02-20 14:11:16 +01001065
1066 error:
1067 snd_hda_codec_free(codec);
1068 return err;
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001069}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001070EXPORT_SYMBOL_HDA(snd_hda_codec_new);
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001071
Takashi Iwaid5191e52009-11-16 14:58:17 +01001072/**
1073 * snd_hda_codec_configure - (Re-)configure the HD-audio codec
1074 * @codec: the HDA codec
1075 *
1076 * Start parsing of the given codec tree and (re-)initialize the whole
1077 * patch instance.
1078 *
1079 * Returns 0 if successful or a negative error code.
1080 */
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001081int snd_hda_codec_configure(struct hda_codec *codec)
1082{
1083 int err;
1084
Takashi Iwaid5ad6302007-03-07 15:55:59 +01001085 codec->preset = find_codec_preset(codec);
Takashi Iwai812a2cc2009-05-16 10:00:49 +02001086 if (!codec->vendor_name || !codec->chip_name) {
Takashi Iwaif44ac832008-07-30 15:01:45 +02001087 err = get_codec_name(codec);
1088 if (err < 0)
1089 return err;
1090 }
Takashi Iwai43ea1d42007-04-26 19:12:08 +02001091 /* audio codec should override the mixer name */
Takashi Iwaif44ac832008-07-30 15:01:45 +02001092 if (codec->afg || !*codec->bus->card->mixername)
Takashi Iwai812a2cc2009-05-16 10:00:49 +02001093 snprintf(codec->bus->card->mixername,
1094 sizeof(codec->bus->card->mixername),
1095 "%s %s", codec->vendor_name, codec->chip_name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001096
Takashi Iwai82467612007-07-27 19:15:54 +02001097 if (is_generic_config(codec)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001098 err = snd_hda_parse_generic_codec(codec);
Takashi Iwai82467612007-07-27 19:15:54 +02001099 goto patched;
1100 }
Takashi Iwai82467612007-07-27 19:15:54 +02001101 if (codec->preset && codec->preset->patch) {
1102 err = codec->preset->patch(codec);
1103 goto patched;
1104 }
1105
1106 /* call the default parser */
Takashi Iwai82467612007-07-27 19:15:54 +02001107 err = snd_hda_parse_generic_codec(codec);
Takashi Iwai35a1e0c2007-10-19 08:13:40 +02001108 if (err < 0)
1109 printk(KERN_ERR "hda-codec: No codec parser is available\n");
Takashi Iwai82467612007-07-27 19:15:54 +02001110
1111 patched:
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001112 if (!err && codec->patch_ops.unsol_event)
1113 err = init_unsol_queue(codec->bus);
1114 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001115}
Takashi Iwaia1e21c92009-06-17 09:33:52 +02001116EXPORT_SYMBOL_HDA(snd_hda_codec_configure);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001117
1118/**
1119 * snd_hda_codec_setup_stream - set up the codec for streaming
1120 * @codec: the CODEC to set up
1121 * @nid: the NID to set up
1122 * @stream_tag: stream tag to pass, it's between 0x1 and 0xf.
1123 * @channel_id: channel id to pass, zero based.
1124 * @format: stream format.
1125 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02001126void snd_hda_codec_setup_stream(struct hda_codec *codec, hda_nid_t nid,
1127 u32 stream_tag,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001128 int channel_id, int format)
1129{
Takashi Iwai0ba21762007-04-16 11:29:14 +02001130 if (!nid)
Takashi Iwaid21b37e2005-04-20 13:45:55 +02001131 return;
1132
Takashi Iwai0ba21762007-04-16 11:29:14 +02001133 snd_printdd("hda_codec_setup_stream: "
1134 "NID=0x%x, stream=0x%x, channel=%d, format=0x%x\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07001135 nid, stream_tag, channel_id, format);
1136 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CHANNEL_STREAMID,
1137 (stream_tag << 4) | channel_id);
1138 msleep(1);
1139 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_STREAM_FORMAT, format);
1140}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001141EXPORT_SYMBOL_HDA(snd_hda_codec_setup_stream);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001142
Takashi Iwaid5191e52009-11-16 14:58:17 +01001143/**
1144 * snd_hda_codec_cleanup_stream - clean up the codec for closing
1145 * @codec: the CODEC to clean up
1146 * @nid: the NID to clean up
1147 */
Takashi Iwai888afa12008-03-18 09:57:50 +01001148void snd_hda_codec_cleanup_stream(struct hda_codec *codec, hda_nid_t nid)
1149{
1150 if (!nid)
1151 return;
1152
1153 snd_printdd("hda_codec_cleanup_stream: NID=0x%x\n", nid);
1154 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CHANNEL_STREAMID, 0);
1155#if 0 /* keep the format */
1156 msleep(1);
1157 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_STREAM_FORMAT, 0);
1158#endif
1159}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001160EXPORT_SYMBOL_HDA(snd_hda_codec_cleanup_stream);
Takashi Iwai888afa12008-03-18 09:57:50 +01001161
Linus Torvalds1da177e2005-04-16 15:20:36 -07001162/*
1163 * amp access functions
1164 */
1165
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001166/* FIXME: more better hash key? */
1167#define HDA_HASH_KEY(nid,dir,idx) (u32)((nid) + ((idx) << 16) + ((dir) << 24))
Takashi Iwai1327a322009-03-23 13:07:47 +01001168#define HDA_HASH_PINCAP_KEY(nid) (u32)((nid) + (0x02 << 24))
Takashi Iwai92c7c8a2009-03-24 07:32:14 +01001169#define HDA_HASH_PARPCM_KEY(nid) (u32)((nid) + (0x03 << 24))
1170#define HDA_HASH_PARSTR_KEY(nid) (u32)((nid) + (0x04 << 24))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001171#define INFO_AMP_CAPS (1<<0)
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001172#define INFO_AMP_VOL(ch) (1 << (1 + (ch)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001173
1174/* initialize the hash table */
Takashi Iwai1289e9e2008-11-27 15:47:11 +01001175static void /*__devinit*/ init_hda_cache(struct hda_cache_rec *cache,
Takashi Iwai01751f52007-08-10 16:59:39 +02001176 unsigned int record_size)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001177{
Takashi Iwai01751f52007-08-10 16:59:39 +02001178 memset(cache, 0, sizeof(*cache));
1179 memset(cache->hash, 0xff, sizeof(cache->hash));
Takashi Iwai603c4012008-07-30 15:01:44 +02001180 snd_array_init(&cache->buf, record_size, 64);
Takashi Iwai01751f52007-08-10 16:59:39 +02001181}
1182
Takashi Iwai1fcaee62007-08-23 00:01:09 +02001183static void free_hda_cache(struct hda_cache_rec *cache)
Takashi Iwai01751f52007-08-10 16:59:39 +02001184{
Takashi Iwai603c4012008-07-30 15:01:44 +02001185 snd_array_free(&cache->buf);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001186}
1187
1188/* query the hash. allocate an entry if not found. */
Takashi Iwai01751f52007-08-10 16:59:39 +02001189static struct hda_cache_head *get_alloc_hash(struct hda_cache_rec *cache,
1190 u32 key)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001191{
Takashi Iwai01751f52007-08-10 16:59:39 +02001192 u16 idx = key % (u16)ARRAY_SIZE(cache->hash);
1193 u16 cur = cache->hash[idx];
1194 struct hda_cache_head *info;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001195
1196 while (cur != 0xffff) {
Takashi Iwaif43aa022008-11-10 16:24:26 +01001197 info = snd_array_elem(&cache->buf, cur);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001198 if (info->key == key)
1199 return info;
1200 cur = info->next;
1201 }
1202
1203 /* add a new hash entry */
Takashi Iwai603c4012008-07-30 15:01:44 +02001204 info = snd_array_new(&cache->buf);
Takashi Iwaic2174292008-11-07 00:23:30 +01001205 if (!info)
1206 return NULL;
Takashi Iwaif43aa022008-11-10 16:24:26 +01001207 cur = snd_array_index(&cache->buf, info);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001208 info->key = key;
Takashi Iwai01751f52007-08-10 16:59:39 +02001209 info->val = 0;
1210 info->next = cache->hash[idx];
1211 cache->hash[idx] = cur;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001212
1213 return info;
1214}
1215
Takashi Iwai01751f52007-08-10 16:59:39 +02001216/* query and allocate an amp hash entry */
1217static inline struct hda_amp_info *
1218get_alloc_amp_hash(struct hda_codec *codec, u32 key)
1219{
1220 return (struct hda_amp_info *)get_alloc_hash(&codec->amp_cache, key);
1221}
1222
Takashi Iwaid5191e52009-11-16 14:58:17 +01001223/**
1224 * query_amp_caps - query AMP capabilities
1225 * @codec: the HD-auio codec
1226 * @nid: the NID to query
1227 * @direction: either #HDA_INPUT or #HDA_OUTPUT
1228 *
1229 * Query AMP capabilities for the given widget and direction.
1230 * Returns the obtained capability bits.
1231 *
1232 * When cap bits have been already read, this doesn't read again but
1233 * returns the cached value.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001234 */
Matthew Ranostay09a99952008-01-24 11:49:21 +01001235u32 query_amp_caps(struct hda_codec *codec, hda_nid_t nid, int direction)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001236{
Takashi Iwai0ba21762007-04-16 11:29:14 +02001237 struct hda_amp_info *info;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001238
Takashi Iwai0ba21762007-04-16 11:29:14 +02001239 info = get_alloc_amp_hash(codec, HDA_HASH_KEY(nid, direction, 0));
1240 if (!info)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001241 return 0;
Takashi Iwai01751f52007-08-10 16:59:39 +02001242 if (!(info->head.val & INFO_AMP_CAPS)) {
Takashi Iwai0ba21762007-04-16 11:29:14 +02001243 if (!(get_wcaps(codec, nid) & AC_WCAP_AMP_OVRD))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001244 nid = codec->afg;
Takashi Iwai0ba21762007-04-16 11:29:14 +02001245 info->amp_caps = snd_hda_param_read(codec, nid,
1246 direction == HDA_OUTPUT ?
1247 AC_PAR_AMP_OUT_CAP :
1248 AC_PAR_AMP_IN_CAP);
Takashi Iwaib75e53f2007-05-10 16:56:09 +02001249 if (info->amp_caps)
Takashi Iwai01751f52007-08-10 16:59:39 +02001250 info->head.val |= INFO_AMP_CAPS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001251 }
1252 return info->amp_caps;
1253}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001254EXPORT_SYMBOL_HDA(query_amp_caps);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001255
Takashi Iwaid5191e52009-11-16 14:58:17 +01001256/**
1257 * snd_hda_override_amp_caps - Override the AMP capabilities
1258 * @codec: the CODEC to clean up
1259 * @nid: the NID to clean up
1260 * @direction: either #HDA_INPUT or #HDA_OUTPUT
1261 * @caps: the capability bits to set
1262 *
1263 * Override the cached AMP caps bits value by the given one.
1264 * This function is useful if the driver needs to adjust the AMP ranges,
1265 * e.g. limit to 0dB, etc.
1266 *
1267 * Returns zero if successful or a negative error code.
1268 */
Takashi Iwai897cc182007-05-29 19:01:37 +02001269int snd_hda_override_amp_caps(struct hda_codec *codec, hda_nid_t nid, int dir,
1270 unsigned int caps)
1271{
1272 struct hda_amp_info *info;
1273
1274 info = get_alloc_amp_hash(codec, HDA_HASH_KEY(nid, dir, 0));
1275 if (!info)
1276 return -EINVAL;
1277 info->amp_caps = caps;
Takashi Iwai01751f52007-08-10 16:59:39 +02001278 info->head.val |= INFO_AMP_CAPS;
Takashi Iwai897cc182007-05-29 19:01:37 +02001279 return 0;
1280}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001281EXPORT_SYMBOL_HDA(snd_hda_override_amp_caps);
Takashi Iwai897cc182007-05-29 19:01:37 +02001282
Takashi Iwai92c7c8a2009-03-24 07:32:14 +01001283static unsigned int
1284query_caps_hash(struct hda_codec *codec, hda_nid_t nid, u32 key,
1285 unsigned int (*func)(struct hda_codec *, hda_nid_t))
Takashi Iwai1327a322009-03-23 13:07:47 +01001286{
1287 struct hda_amp_info *info;
1288
Takashi Iwai92c7c8a2009-03-24 07:32:14 +01001289 info = get_alloc_amp_hash(codec, key);
Takashi Iwai1327a322009-03-23 13:07:47 +01001290 if (!info)
1291 return 0;
1292 if (!info->head.val) {
Takashi Iwai1327a322009-03-23 13:07:47 +01001293 info->head.val |= INFO_AMP_CAPS;
Takashi Iwai92c7c8a2009-03-24 07:32:14 +01001294 info->amp_caps = func(codec, nid);
Takashi Iwai1327a322009-03-23 13:07:47 +01001295 }
1296 return info->amp_caps;
1297}
Takashi Iwai92c7c8a2009-03-24 07:32:14 +01001298
1299static unsigned int read_pin_cap(struct hda_codec *codec, hda_nid_t nid)
1300{
1301 return snd_hda_param_read(codec, nid, AC_PAR_PIN_CAP);
1302}
1303
Takashi Iwaid5191e52009-11-16 14:58:17 +01001304/**
1305 * snd_hda_query_pin_caps - Query PIN capabilities
1306 * @codec: the HD-auio codec
1307 * @nid: the NID to query
1308 *
1309 * Query PIN capabilities for the given widget.
1310 * Returns the obtained capability bits.
1311 *
1312 * When cap bits have been already read, this doesn't read again but
1313 * returns the cached value.
1314 */
Takashi Iwai92c7c8a2009-03-24 07:32:14 +01001315u32 snd_hda_query_pin_caps(struct hda_codec *codec, hda_nid_t nid)
1316{
1317 return query_caps_hash(codec, nid, HDA_HASH_PINCAP_KEY(nid),
1318 read_pin_cap);
1319}
Takashi Iwai1327a322009-03-23 13:07:47 +01001320EXPORT_SYMBOL_HDA(snd_hda_query_pin_caps);
1321
Wu Fengguang864f92b2009-11-18 12:38:02 +08001322/**
1323 * snd_hda_pin_sense - execute pin sense measurement
1324 * @codec: the CODEC to sense
1325 * @nid: the pin NID to sense
1326 *
1327 * Execute necessary pin sense measurement and return its Presence Detect,
1328 * Impedance, ELD Valid etc. status bits.
1329 */
1330u32 snd_hda_pin_sense(struct hda_codec *codec, hda_nid_t nid)
1331{
1332 u32 pincap = snd_hda_query_pin_caps(codec, nid);
1333
1334 if (pincap & AC_PINCAP_TRIG_REQ) /* need trigger? */
1335 snd_hda_codec_read(codec, nid, 0, AC_VERB_SET_PIN_SENSE, 0);
1336
1337 return snd_hda_codec_read(codec, nid, 0,
1338 AC_VERB_GET_PIN_SENSE, 0);
1339}
1340EXPORT_SYMBOL_HDA(snd_hda_pin_sense);
1341
1342/**
1343 * snd_hda_jack_detect - query pin Presence Detect status
1344 * @codec: the CODEC to sense
1345 * @nid: the pin NID to sense
1346 *
1347 * Query and return the pin's Presence Detect status.
1348 */
1349int snd_hda_jack_detect(struct hda_codec *codec, hda_nid_t nid)
1350{
1351 u32 sense = snd_hda_pin_sense(codec, nid);
1352 return !!(sense & AC_PINSENSE_PRESENCE);
1353}
1354EXPORT_SYMBOL_HDA(snd_hda_jack_detect);
1355
Linus Torvalds1da177e2005-04-16 15:20:36 -07001356/*
1357 * read the current volume to info
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001358 * if the cache exists, read the cache value.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001359 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02001360static unsigned int get_vol_mute(struct hda_codec *codec,
1361 struct hda_amp_info *info, hda_nid_t nid,
1362 int ch, int direction, int index)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001363{
1364 u32 val, parm;
1365
Takashi Iwai01751f52007-08-10 16:59:39 +02001366 if (info->head.val & INFO_AMP_VOL(ch))
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001367 return info->vol[ch];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001368
1369 parm = ch ? AC_AMP_GET_RIGHT : AC_AMP_GET_LEFT;
1370 parm |= direction == HDA_OUTPUT ? AC_AMP_GET_OUTPUT : AC_AMP_GET_INPUT;
1371 parm |= index;
Takashi Iwai0ba21762007-04-16 11:29:14 +02001372 val = snd_hda_codec_read(codec, nid, 0,
1373 AC_VERB_GET_AMP_GAIN_MUTE, parm);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001374 info->vol[ch] = val & 0xff;
Takashi Iwai01751f52007-08-10 16:59:39 +02001375 info->head.val |= INFO_AMP_VOL(ch);
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001376 return info->vol[ch];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001377}
1378
1379/*
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001380 * write the current volume in info to the h/w and update the cache
Linus Torvalds1da177e2005-04-16 15:20:36 -07001381 */
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001382static void put_vol_mute(struct hda_codec *codec, struct hda_amp_info *info,
Takashi Iwai0ba21762007-04-16 11:29:14 +02001383 hda_nid_t nid, int ch, int direction, int index,
1384 int val)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001385{
1386 u32 parm;
1387
1388 parm = ch ? AC_AMP_SET_RIGHT : AC_AMP_SET_LEFT;
1389 parm |= direction == HDA_OUTPUT ? AC_AMP_SET_OUTPUT : AC_AMP_SET_INPUT;
1390 parm |= index << AC_AMP_SET_INDEX_SHIFT;
1391 parm |= val;
1392 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, parm);
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001393 info->vol[ch] = val;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001394}
1395
Takashi Iwaid5191e52009-11-16 14:58:17 +01001396/**
1397 * snd_hda_codec_amp_read - Read AMP value
1398 * @codec: HD-audio codec
1399 * @nid: NID to read the AMP value
1400 * @ch: channel (left=0 or right=1)
1401 * @direction: #HDA_INPUT or #HDA_OUTPUT
1402 * @index: the index value (only for input direction)
1403 *
1404 * Read AMP value. The volume is between 0 to 0x7f, 0x80 = mute bit.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001405 */
Takashi Iwai834be882006-03-01 14:16:17 +01001406int snd_hda_codec_amp_read(struct hda_codec *codec, hda_nid_t nid, int ch,
1407 int direction, int index)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001408{
Takashi Iwai0ba21762007-04-16 11:29:14 +02001409 struct hda_amp_info *info;
1410 info = get_alloc_amp_hash(codec, HDA_HASH_KEY(nid, direction, index));
1411 if (!info)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001412 return 0;
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001413 return get_vol_mute(codec, info, nid, ch, direction, index);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001414}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001415EXPORT_SYMBOL_HDA(snd_hda_codec_amp_read);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001416
Takashi Iwaid5191e52009-11-16 14:58:17 +01001417/**
1418 * snd_hda_codec_amp_update - update the AMP value
1419 * @codec: HD-audio codec
1420 * @nid: NID to read the AMP value
1421 * @ch: channel (left=0 or right=1)
1422 * @direction: #HDA_INPUT or #HDA_OUTPUT
1423 * @idx: the index value (only for input direction)
1424 * @mask: bit mask to set
1425 * @val: the bits value to set
1426 *
1427 * Update the AMP value with a bit mask.
1428 * Returns 0 if the value is unchanged, 1 if changed.
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001429 */
Takashi Iwai834be882006-03-01 14:16:17 +01001430int snd_hda_codec_amp_update(struct hda_codec *codec, hda_nid_t nid, int ch,
1431 int direction, int idx, int mask, int val)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001432{
Takashi Iwai0ba21762007-04-16 11:29:14 +02001433 struct hda_amp_info *info;
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001434
Takashi Iwai0ba21762007-04-16 11:29:14 +02001435 info = get_alloc_amp_hash(codec, HDA_HASH_KEY(nid, direction, idx));
1436 if (!info)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001437 return 0;
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001438 val &= mask;
1439 val |= get_vol_mute(codec, info, nid, ch, direction, idx) & ~mask;
Takashi Iwai82beb8f2007-08-10 17:09:26 +02001440 if (info->vol[ch] == val)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001441 return 0;
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001442 put_vol_mute(codec, info, nid, ch, direction, idx, val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001443 return 1;
1444}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001445EXPORT_SYMBOL_HDA(snd_hda_codec_amp_update);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001446
Takashi Iwaid5191e52009-11-16 14:58:17 +01001447/**
1448 * snd_hda_codec_amp_stereo - update the AMP stereo values
1449 * @codec: HD-audio codec
1450 * @nid: NID to read the AMP value
1451 * @direction: #HDA_INPUT or #HDA_OUTPUT
1452 * @idx: the index value (only for input direction)
1453 * @mask: bit mask to set
1454 * @val: the bits value to set
1455 *
1456 * Update the AMP values like snd_hda_codec_amp_update(), but for a
1457 * stereo widget with the same mask and value.
Takashi Iwai47fd8302007-08-10 17:11:07 +02001458 */
1459int snd_hda_codec_amp_stereo(struct hda_codec *codec, hda_nid_t nid,
1460 int direction, int idx, int mask, int val)
1461{
1462 int ch, ret = 0;
1463 for (ch = 0; ch < 2; ch++)
1464 ret |= snd_hda_codec_amp_update(codec, nid, ch, direction,
1465 idx, mask, val);
1466 return ret;
1467}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001468EXPORT_SYMBOL_HDA(snd_hda_codec_amp_stereo);
Takashi Iwai47fd8302007-08-10 17:11:07 +02001469
Takashi Iwaicb53c622007-08-10 17:21:45 +02001470#ifdef SND_HDA_NEEDS_RESUME
Takashi Iwaid5191e52009-11-16 14:58:17 +01001471/**
1472 * snd_hda_codec_resume_amp - Resume all AMP commands from the cache
1473 * @codec: HD-audio codec
1474 *
1475 * Resume the all amp commands from the cache.
1476 */
Takashi Iwaib3ac5632007-08-10 17:03:40 +02001477void snd_hda_codec_resume_amp(struct hda_codec *codec)
1478{
Takashi Iwai603c4012008-07-30 15:01:44 +02001479 struct hda_amp_info *buffer = codec->amp_cache.buf.list;
Takashi Iwaib3ac5632007-08-10 17:03:40 +02001480 int i;
1481
Takashi Iwai603c4012008-07-30 15:01:44 +02001482 for (i = 0; i < codec->amp_cache.buf.used; i++, buffer++) {
Takashi Iwaib3ac5632007-08-10 17:03:40 +02001483 u32 key = buffer->head.key;
1484 hda_nid_t nid;
1485 unsigned int idx, dir, ch;
1486 if (!key)
1487 continue;
1488 nid = key & 0xff;
1489 idx = (key >> 16) & 0xff;
1490 dir = (key >> 24) & 0xff;
1491 for (ch = 0; ch < 2; ch++) {
1492 if (!(buffer->head.val & INFO_AMP_VOL(ch)))
1493 continue;
1494 put_vol_mute(codec, buffer, nid, ch, dir, idx,
1495 buffer->vol[ch]);
1496 }
1497 }
1498}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001499EXPORT_SYMBOL_HDA(snd_hda_codec_resume_amp);
Takashi Iwaicb53c622007-08-10 17:21:45 +02001500#endif /* SND_HDA_NEEDS_RESUME */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001501
Takashi Iwaid5191e52009-11-16 14:58:17 +01001502/**
1503 * snd_hda_mixer_amp_volume_info - Info callback for a standard AMP mixer
1504 *
1505 * The control element is supposed to have the private_value field
1506 * set up via HDA_COMPOSE_AMP_VAL*() or related macros.
1507 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02001508int snd_hda_mixer_amp_volume_info(struct snd_kcontrol *kcontrol,
1509 struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001510{
1511 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1512 u16 nid = get_amp_nid(kcontrol);
1513 u8 chs = get_amp_channels(kcontrol);
1514 int dir = get_amp_direction(kcontrol);
Takashi Iwai29fdbec2009-01-20 13:07:55 +01001515 unsigned int ofs = get_amp_offset(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001516 u32 caps;
1517
1518 caps = query_amp_caps(codec, nid, dir);
Takashi Iwai0ba21762007-04-16 11:29:14 +02001519 /* num steps */
1520 caps = (caps & AC_AMPCAP_NUM_STEPS) >> AC_AMPCAP_NUM_STEPS_SHIFT;
1521 if (!caps) {
1522 printk(KERN_WARNING "hda_codec: "
Takashi Iwai9c8f2ab2008-01-11 16:12:23 +01001523 "num_steps = 0 for NID=0x%x (ctl = %s)\n", nid,
1524 kcontrol->id.name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001525 return -EINVAL;
1526 }
Takashi Iwai29fdbec2009-01-20 13:07:55 +01001527 if (ofs < caps)
1528 caps -= ofs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001529 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
1530 uinfo->count = chs == 3 ? 2 : 1;
1531 uinfo->value.integer.min = 0;
1532 uinfo->value.integer.max = caps;
1533 return 0;
1534}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001535EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_volume_info);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001536
Takashi Iwai29fdbec2009-01-20 13:07:55 +01001537
1538static inline unsigned int
1539read_amp_value(struct hda_codec *codec, hda_nid_t nid,
1540 int ch, int dir, int idx, unsigned int ofs)
1541{
1542 unsigned int val;
1543 val = snd_hda_codec_amp_read(codec, nid, ch, dir, idx);
1544 val &= HDA_AMP_VOLMASK;
1545 if (val >= ofs)
1546 val -= ofs;
1547 else
1548 val = 0;
1549 return val;
1550}
1551
1552static inline int
1553update_amp_value(struct hda_codec *codec, hda_nid_t nid,
1554 int ch, int dir, int idx, unsigned int ofs,
1555 unsigned int val)
1556{
1557 if (val > 0)
1558 val += ofs;
1559 return snd_hda_codec_amp_update(codec, nid, ch, dir, idx,
1560 HDA_AMP_VOLMASK, val);
1561}
1562
Takashi Iwaid5191e52009-11-16 14:58:17 +01001563/**
1564 * snd_hda_mixer_amp_volume_get - Get callback for a standard AMP mixer volume
1565 *
1566 * The control element is supposed to have the private_value field
1567 * set up via HDA_COMPOSE_AMP_VAL*() or related macros.
1568 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02001569int snd_hda_mixer_amp_volume_get(struct snd_kcontrol *kcontrol,
1570 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001571{
1572 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1573 hda_nid_t nid = get_amp_nid(kcontrol);
1574 int chs = get_amp_channels(kcontrol);
1575 int dir = get_amp_direction(kcontrol);
1576 int idx = get_amp_index(kcontrol);
Takashi Iwai29fdbec2009-01-20 13:07:55 +01001577 unsigned int ofs = get_amp_offset(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001578 long *valp = ucontrol->value.integer.value;
1579
1580 if (chs & 1)
Takashi Iwai29fdbec2009-01-20 13:07:55 +01001581 *valp++ = read_amp_value(codec, nid, 0, dir, idx, ofs);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001582 if (chs & 2)
Takashi Iwai29fdbec2009-01-20 13:07:55 +01001583 *valp = read_amp_value(codec, nid, 1, dir, idx, ofs);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001584 return 0;
1585}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001586EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_volume_get);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001587
Takashi Iwaid5191e52009-11-16 14:58:17 +01001588/**
1589 * snd_hda_mixer_amp_volume_put - Put callback for a standard AMP mixer volume
1590 *
1591 * The control element is supposed to have the private_value field
1592 * set up via HDA_COMPOSE_AMP_VAL*() or related macros.
1593 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02001594int snd_hda_mixer_amp_volume_put(struct snd_kcontrol *kcontrol,
1595 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001596{
1597 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1598 hda_nid_t nid = get_amp_nid(kcontrol);
1599 int chs = get_amp_channels(kcontrol);
1600 int dir = get_amp_direction(kcontrol);
1601 int idx = get_amp_index(kcontrol);
Takashi Iwai29fdbec2009-01-20 13:07:55 +01001602 unsigned int ofs = get_amp_offset(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001603 long *valp = ucontrol->value.integer.value;
1604 int change = 0;
1605
Takashi Iwaicb53c622007-08-10 17:21:45 +02001606 snd_hda_power_up(codec);
Nicolas Grazianob9f5a892005-07-29 12:17:20 +02001607 if (chs & 1) {
Takashi Iwai29fdbec2009-01-20 13:07:55 +01001608 change = update_amp_value(codec, nid, 0, dir, idx, ofs, *valp);
Nicolas Grazianob9f5a892005-07-29 12:17:20 +02001609 valp++;
1610 }
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001611 if (chs & 2)
Takashi Iwai29fdbec2009-01-20 13:07:55 +01001612 change |= update_amp_value(codec, nid, 1, dir, idx, ofs, *valp);
Takashi Iwaicb53c622007-08-10 17:21:45 +02001613 snd_hda_power_down(codec);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001614 return change;
1615}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001616EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_volume_put);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001617
Takashi Iwaid5191e52009-11-16 14:58:17 +01001618/**
1619 * snd_hda_mixer_amp_volume_put - TLV callback for a standard AMP mixer volume
1620 *
1621 * The control element is supposed to have the private_value field
1622 * set up via HDA_COMPOSE_AMP_VAL*() or related macros.
1623 */
Jaroslav Kysela302e9c52006-07-05 17:39:49 +02001624int snd_hda_mixer_amp_tlv(struct snd_kcontrol *kcontrol, int op_flag,
1625 unsigned int size, unsigned int __user *_tlv)
1626{
1627 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1628 hda_nid_t nid = get_amp_nid(kcontrol);
1629 int dir = get_amp_direction(kcontrol);
Takashi Iwai29fdbec2009-01-20 13:07:55 +01001630 unsigned int ofs = get_amp_offset(kcontrol);
Jaroslav Kysela302e9c52006-07-05 17:39:49 +02001631 u32 caps, val1, val2;
1632
1633 if (size < 4 * sizeof(unsigned int))
1634 return -ENOMEM;
1635 caps = query_amp_caps(codec, nid, dir);
Takashi Iwai0ba21762007-04-16 11:29:14 +02001636 val2 = (caps & AC_AMPCAP_STEP_SIZE) >> AC_AMPCAP_STEP_SIZE_SHIFT;
1637 val2 = (val2 + 1) * 25;
Jaroslav Kysela302e9c52006-07-05 17:39:49 +02001638 val1 = -((caps & AC_AMPCAP_OFFSET) >> AC_AMPCAP_OFFSET_SHIFT);
Takashi Iwai29fdbec2009-01-20 13:07:55 +01001639 val1 += ofs;
Jaroslav Kysela302e9c52006-07-05 17:39:49 +02001640 val1 = ((int)val1) * ((int)val2);
Jaroslav Kysela302e9c52006-07-05 17:39:49 +02001641 if (put_user(SNDRV_CTL_TLVT_DB_SCALE, _tlv))
1642 return -EFAULT;
1643 if (put_user(2 * sizeof(unsigned int), _tlv + 1))
1644 return -EFAULT;
1645 if (put_user(val1, _tlv + 2))
1646 return -EFAULT;
1647 if (put_user(val2, _tlv + 3))
1648 return -EFAULT;
1649 return 0;
1650}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001651EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_tlv);
Jaroslav Kysela302e9c52006-07-05 17:39:49 +02001652
Takashi Iwaid5191e52009-11-16 14:58:17 +01001653/**
1654 * snd_hda_set_vmaster_tlv - Set TLV for a virtual master control
1655 * @codec: HD-audio codec
1656 * @nid: NID of a reference widget
1657 * @dir: #HDA_INPUT or #HDA_OUTPUT
1658 * @tlv: TLV data to be stored, at least 4 elements
1659 *
1660 * Set (static) TLV data for a virtual master volume using the AMP caps
1661 * obtained from the reference NID.
1662 * The volume range is recalculated as if the max volume is 0dB.
Takashi Iwai2134ea42008-01-10 16:53:55 +01001663 */
1664void snd_hda_set_vmaster_tlv(struct hda_codec *codec, hda_nid_t nid, int dir,
1665 unsigned int *tlv)
1666{
1667 u32 caps;
1668 int nums, step;
1669
1670 caps = query_amp_caps(codec, nid, dir);
1671 nums = (caps & AC_AMPCAP_NUM_STEPS) >> AC_AMPCAP_NUM_STEPS_SHIFT;
1672 step = (caps & AC_AMPCAP_STEP_SIZE) >> AC_AMPCAP_STEP_SIZE_SHIFT;
1673 step = (step + 1) * 25;
1674 tlv[0] = SNDRV_CTL_TLVT_DB_SCALE;
1675 tlv[1] = 2 * sizeof(unsigned int);
1676 tlv[2] = -nums * step;
1677 tlv[3] = step;
1678}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001679EXPORT_SYMBOL_HDA(snd_hda_set_vmaster_tlv);
Takashi Iwai2134ea42008-01-10 16:53:55 +01001680
1681/* find a mixer control element with the given name */
Takashi Iwai09f99702008-02-04 12:31:13 +01001682static struct snd_kcontrol *
1683_snd_hda_find_mixer_ctl(struct hda_codec *codec,
1684 const char *name, int idx)
Takashi Iwai2134ea42008-01-10 16:53:55 +01001685{
1686 struct snd_ctl_elem_id id;
1687 memset(&id, 0, sizeof(id));
1688 id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
Takashi Iwai09f99702008-02-04 12:31:13 +01001689 id.index = idx;
Takashi Iwai18cb7102009-04-16 10:22:24 +02001690 if (snd_BUG_ON(strlen(name) >= sizeof(id.name)))
1691 return NULL;
Takashi Iwai2134ea42008-01-10 16:53:55 +01001692 strcpy(id.name, name);
1693 return snd_ctl_find_id(codec->bus->card, &id);
1694}
1695
Takashi Iwaid5191e52009-11-16 14:58:17 +01001696/**
1697 * snd_hda_find_mixer_ctl - Find a mixer control element with the given name
1698 * @codec: HD-audio codec
1699 * @name: ctl id name string
1700 *
1701 * Get the control element with the given id string and IFACE_MIXER.
1702 */
Takashi Iwai09f99702008-02-04 12:31:13 +01001703struct snd_kcontrol *snd_hda_find_mixer_ctl(struct hda_codec *codec,
1704 const char *name)
1705{
1706 return _snd_hda_find_mixer_ctl(codec, name, 0);
1707}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001708EXPORT_SYMBOL_HDA(snd_hda_find_mixer_ctl);
Takashi Iwai09f99702008-02-04 12:31:13 +01001709
Takashi Iwaid5191e52009-11-16 14:58:17 +01001710/**
Jaroslav Kysela5b0cb1d2009-12-08 16:13:32 +01001711 * snd_hda_ctl_add - Add a control element and assign to the codec
Takashi Iwaid5191e52009-11-16 14:58:17 +01001712 * @codec: HD-audio codec
1713 * @nid: corresponding NID (optional)
1714 * @kctl: the control element to assign
1715 *
1716 * Add the given control element to an array inside the codec instance.
1717 * All control elements belonging to a codec are supposed to be added
1718 * by this function so that a proper clean-up works at the free or
1719 * reconfiguration time.
1720 *
1721 * If non-zero @nid is passed, the NID is assigned to the control element.
1722 * The assignment is shown in the codec proc file.
1723 *
1724 * snd_hda_ctl_add() checks the control subdev id field whether
1725 * #HDA_SUBDEV_NID_FLAG bit is set. If set (and @nid is zero), the lower
Jaroslav Kysela9e3fd872009-12-08 17:45:25 +01001726 * bits value is taken as the NID to assign. The #HDA_NID_ITEM_AMP bit
1727 * specifies if kctl->private_value is a HDA amplifier value.
Takashi Iwaid5191e52009-11-16 14:58:17 +01001728 */
Jaroslav Kysela3911a4c2009-11-11 13:43:01 +01001729int snd_hda_ctl_add(struct hda_codec *codec, hda_nid_t nid,
1730 struct snd_kcontrol *kctl)
Takashi Iwaid13bd412008-07-30 15:01:45 +02001731{
1732 int err;
Jaroslav Kysela9e3fd872009-12-08 17:45:25 +01001733 unsigned short flags = 0;
Jaroslav Kysela3911a4c2009-11-11 13:43:01 +01001734 struct hda_nid_item *item;
Takashi Iwaid13bd412008-07-30 15:01:45 +02001735
Jaroslav Kysela5e26dfd2009-12-10 13:57:01 +01001736 if (kctl->id.subdevice & HDA_SUBDEV_AMP_FLAG) {
Jaroslav Kysela9e3fd872009-12-08 17:45:25 +01001737 flags |= HDA_NID_ITEM_AMP;
Jaroslav Kysela5e26dfd2009-12-10 13:57:01 +01001738 if (nid == 0)
1739 nid = get_amp_nid_(kctl->private_value);
1740 }
Jaroslav Kysela9e3fd872009-12-08 17:45:25 +01001741 if ((kctl->id.subdevice & HDA_SUBDEV_NID_FLAG) != 0 && nid == 0)
1742 nid = kctl->id.subdevice & 0xffff;
Jaroslav Kysela5e26dfd2009-12-10 13:57:01 +01001743 if (kctl->id.subdevice & (HDA_SUBDEV_NID_FLAG|HDA_SUBDEV_AMP_FLAG))
Jaroslav Kysela4d02d1b2009-11-12 10:15:48 +01001744 kctl->id.subdevice = 0;
Takashi Iwaid13bd412008-07-30 15:01:45 +02001745 err = snd_ctl_add(codec->bus->card, kctl);
1746 if (err < 0)
1747 return err;
Jaroslav Kysela3911a4c2009-11-11 13:43:01 +01001748 item = snd_array_new(&codec->mixers);
1749 if (!item)
Takashi Iwaid13bd412008-07-30 15:01:45 +02001750 return -ENOMEM;
Jaroslav Kysela3911a4c2009-11-11 13:43:01 +01001751 item->kctl = kctl;
1752 item->nid = nid;
Jaroslav Kysela9e3fd872009-12-08 17:45:25 +01001753 item->flags = flags;
Takashi Iwaid13bd412008-07-30 15:01:45 +02001754 return 0;
1755}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001756EXPORT_SYMBOL_HDA(snd_hda_ctl_add);
Takashi Iwaid13bd412008-07-30 15:01:45 +02001757
Takashi Iwaid5191e52009-11-16 14:58:17 +01001758/**
Jaroslav Kysela5b0cb1d2009-12-08 16:13:32 +01001759 * snd_hda_add_nid - Assign a NID to a control element
1760 * @codec: HD-audio codec
1761 * @nid: corresponding NID (optional)
1762 * @kctl: the control element to assign
1763 * @index: index to kctl
1764 *
1765 * Add the given control element to an array inside the codec instance.
1766 * This function is used when #snd_hda_ctl_add cannot be used for 1:1
1767 * NID:KCTL mapping - for example "Capture Source" selector.
1768 */
1769int snd_hda_add_nid(struct hda_codec *codec, struct snd_kcontrol *kctl,
1770 unsigned int index, hda_nid_t nid)
1771{
1772 struct hda_nid_item *item;
1773
1774 if (nid > 0) {
1775 item = snd_array_new(&codec->nids);
1776 if (!item)
1777 return -ENOMEM;
1778 item->kctl = kctl;
1779 item->index = index;
1780 item->nid = nid;
1781 return 0;
1782 }
1783 return -EINVAL;
1784}
1785EXPORT_SYMBOL_HDA(snd_hda_add_nid);
1786
1787/**
Takashi Iwaid5191e52009-11-16 14:58:17 +01001788 * snd_hda_ctls_clear - Clear all controls assigned to the given codec
1789 * @codec: HD-audio codec
1790 */
Takashi Iwaid13bd412008-07-30 15:01:45 +02001791void snd_hda_ctls_clear(struct hda_codec *codec)
1792{
1793 int i;
Jaroslav Kysela3911a4c2009-11-11 13:43:01 +01001794 struct hda_nid_item *items = codec->mixers.list;
Takashi Iwaid13bd412008-07-30 15:01:45 +02001795 for (i = 0; i < codec->mixers.used; i++)
Jaroslav Kysela3911a4c2009-11-11 13:43:01 +01001796 snd_ctl_remove(codec->bus->card, items[i].kctl);
Takashi Iwaid13bd412008-07-30 15:01:45 +02001797 snd_array_free(&codec->mixers);
Jaroslav Kysela5b0cb1d2009-12-08 16:13:32 +01001798 snd_array_free(&codec->nids);
Takashi Iwaid13bd412008-07-30 15:01:45 +02001799}
1800
Takashi Iwaia65d6292009-02-23 16:57:04 +01001801/* pseudo device locking
1802 * toggle card->shutdown to allow/disallow the device access (as a hack)
1803 */
1804static int hda_lock_devices(struct snd_card *card)
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001805{
Takashi Iwaia65d6292009-02-23 16:57:04 +01001806 spin_lock(&card->files_lock);
1807 if (card->shutdown) {
1808 spin_unlock(&card->files_lock);
1809 return -EINVAL;
1810 }
1811 card->shutdown = 1;
1812 spin_unlock(&card->files_lock);
1813 return 0;
1814}
1815
1816static void hda_unlock_devices(struct snd_card *card)
1817{
1818 spin_lock(&card->files_lock);
1819 card->shutdown = 0;
1820 spin_unlock(&card->files_lock);
1821}
1822
Takashi Iwaid5191e52009-11-16 14:58:17 +01001823/**
1824 * snd_hda_codec_reset - Clear all objects assigned to the codec
1825 * @codec: HD-audio codec
1826 *
1827 * This frees the all PCM and control elements assigned to the codec, and
1828 * clears the caches and restores the pin default configurations.
1829 *
1830 * When a device is being used, it returns -EBSY. If successfully freed,
1831 * returns zero.
1832 */
Takashi Iwaia65d6292009-02-23 16:57:04 +01001833int snd_hda_codec_reset(struct hda_codec *codec)
1834{
1835 struct snd_card *card = codec->bus->card;
1836 int i, pcm;
1837
1838 if (hda_lock_devices(card) < 0)
1839 return -EBUSY;
1840 /* check whether the codec isn't used by any mixer or PCM streams */
1841 if (!list_empty(&card->ctl_files)) {
1842 hda_unlock_devices(card);
1843 return -EBUSY;
1844 }
1845 for (pcm = 0; pcm < codec->num_pcms; pcm++) {
1846 struct hda_pcm *cpcm = &codec->pcm_info[pcm];
1847 if (!cpcm->pcm)
1848 continue;
1849 if (cpcm->pcm->streams[0].substream_opened ||
1850 cpcm->pcm->streams[1].substream_opened) {
1851 hda_unlock_devices(card);
1852 return -EBUSY;
1853 }
1854 }
1855
1856 /* OK, let it free */
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001857
1858#ifdef CONFIG_SND_HDA_POWER_SAVE
1859 cancel_delayed_work(&codec->power_work);
Takashi Iwai6acaed32009-01-12 10:09:24 +01001860 flush_workqueue(codec->bus->workq);
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001861#endif
1862 snd_hda_ctls_clear(codec);
1863 /* relase PCMs */
1864 for (i = 0; i < codec->num_pcms; i++) {
Takashi Iwai529bd6c2008-11-27 14:17:01 +01001865 if (codec->pcm_info[i].pcm) {
Takashi Iwaia65d6292009-02-23 16:57:04 +01001866 snd_device_free(card, codec->pcm_info[i].pcm);
Takashi Iwai529bd6c2008-11-27 14:17:01 +01001867 clear_bit(codec->pcm_info[i].device,
1868 codec->bus->pcm_dev_bits);
1869 }
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001870 }
1871 if (codec->patch_ops.free)
1872 codec->patch_ops.free(codec);
Takashi Iwai56d17712008-11-28 14:36:23 +01001873 codec->proc_widget_hook = NULL;
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001874 codec->spec = NULL;
1875 free_hda_cache(&codec->amp_cache);
1876 free_hda_cache(&codec->cmd_cache);
Takashi Iwai827057f2008-12-19 10:12:02 +01001877 init_hda_cache(&codec->amp_cache, sizeof(struct hda_amp_info));
1878 init_hda_cache(&codec->cmd_cache, sizeof(struct hda_cache_head));
Takashi Iwai346ff702009-02-23 09:42:57 +01001879 /* free only driver_pins so that init_pins + user_pins are restored */
1880 snd_array_free(&codec->driver_pins);
Takashi Iwai3be14142009-02-20 14:11:16 +01001881 restore_pincfgs(codec);
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001882 codec->num_pcms = 0;
1883 codec->pcm_info = NULL;
1884 codec->preset = NULL;
Takashi Iwaid1f1af22009-03-02 10:35:29 +01001885 memset(&codec->patch_ops, 0, sizeof(codec->patch_ops));
1886 codec->slave_dig_outs = NULL;
1887 codec->spdif_status_reset = 0;
Takashi Iwai1289e9e2008-11-27 15:47:11 +01001888 module_put(codec->owner);
1889 codec->owner = NULL;
Takashi Iwaia65d6292009-02-23 16:57:04 +01001890
1891 /* allow device access again */
1892 hda_unlock_devices(card);
1893 return 0;
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001894}
1895
Takashi Iwaid5191e52009-11-16 14:58:17 +01001896/**
1897 * snd_hda_add_vmaster - create a virtual master control and add slaves
1898 * @codec: HD-audio codec
1899 * @name: vmaster control name
1900 * @tlv: TLV data (optional)
1901 * @slaves: slave control names (optional)
1902 *
1903 * Create a virtual master control with the given name. The TLV data
1904 * must be either NULL or a valid data.
1905 *
1906 * @slaves is a NULL-terminated array of strings, each of which is a
1907 * slave control name. All controls with these names are assigned to
1908 * the new virtual master control.
1909 *
1910 * This function returns zero if successful or a negative error code.
1911 */
Takashi Iwai2134ea42008-01-10 16:53:55 +01001912int snd_hda_add_vmaster(struct hda_codec *codec, char *name,
1913 unsigned int *tlv, const char **slaves)
1914{
1915 struct snd_kcontrol *kctl;
1916 const char **s;
1917 int err;
1918
Takashi Iwai2f085542008-02-22 18:43:50 +01001919 for (s = slaves; *s && !snd_hda_find_mixer_ctl(codec, *s); s++)
1920 ;
1921 if (!*s) {
1922 snd_printdd("No slave found for %s\n", name);
1923 return 0;
1924 }
Takashi Iwai2134ea42008-01-10 16:53:55 +01001925 kctl = snd_ctl_make_virtual_master(name, tlv);
1926 if (!kctl)
1927 return -ENOMEM;
Jaroslav Kysela3911a4c2009-11-11 13:43:01 +01001928 err = snd_hda_ctl_add(codec, 0, kctl);
Takashi Iwai2134ea42008-01-10 16:53:55 +01001929 if (err < 0)
1930 return err;
1931
1932 for (s = slaves; *s; s++) {
1933 struct snd_kcontrol *sctl;
Takashi Iwai7a411ee2009-03-06 10:08:14 +01001934 int i = 0;
1935 for (;;) {
1936 sctl = _snd_hda_find_mixer_ctl(codec, *s, i);
1937 if (!sctl) {
1938 if (!i)
1939 snd_printdd("Cannot find slave %s, "
1940 "skipped\n", *s);
1941 break;
1942 }
1943 err = snd_ctl_add_slave(kctl, sctl);
1944 if (err < 0)
1945 return err;
1946 i++;
Takashi Iwai2134ea42008-01-10 16:53:55 +01001947 }
Takashi Iwai2134ea42008-01-10 16:53:55 +01001948 }
1949 return 0;
1950}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001951EXPORT_SYMBOL_HDA(snd_hda_add_vmaster);
Takashi Iwai2134ea42008-01-10 16:53:55 +01001952
Takashi Iwaid5191e52009-11-16 14:58:17 +01001953/**
1954 * snd_hda_mixer_amp_switch_info - Info callback for a standard AMP mixer switch
1955 *
1956 * The control element is supposed to have the private_value field
1957 * set up via HDA_COMPOSE_AMP_VAL*() or related macros.
1958 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02001959int snd_hda_mixer_amp_switch_info(struct snd_kcontrol *kcontrol,
1960 struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001961{
1962 int chs = get_amp_channels(kcontrol);
1963
1964 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
1965 uinfo->count = chs == 3 ? 2 : 1;
1966 uinfo->value.integer.min = 0;
1967 uinfo->value.integer.max = 1;
1968 return 0;
1969}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001970EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_switch_info);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001971
Takashi Iwaid5191e52009-11-16 14:58:17 +01001972/**
1973 * snd_hda_mixer_amp_switch_get - Get callback for a standard AMP mixer switch
1974 *
1975 * The control element is supposed to have the private_value field
1976 * set up via HDA_COMPOSE_AMP_VAL*() or related macros.
1977 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02001978int snd_hda_mixer_amp_switch_get(struct snd_kcontrol *kcontrol,
1979 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001980{
1981 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1982 hda_nid_t nid = get_amp_nid(kcontrol);
1983 int chs = get_amp_channels(kcontrol);
1984 int dir = get_amp_direction(kcontrol);
1985 int idx = get_amp_index(kcontrol);
1986 long *valp = ucontrol->value.integer.value;
1987
1988 if (chs & 1)
Takashi Iwai0ba21762007-04-16 11:29:14 +02001989 *valp++ = (snd_hda_codec_amp_read(codec, nid, 0, dir, idx) &
Takashi Iwai47fd8302007-08-10 17:11:07 +02001990 HDA_AMP_MUTE) ? 0 : 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001991 if (chs & 2)
Takashi Iwai0ba21762007-04-16 11:29:14 +02001992 *valp = (snd_hda_codec_amp_read(codec, nid, 1, dir, idx) &
Takashi Iwai47fd8302007-08-10 17:11:07 +02001993 HDA_AMP_MUTE) ? 0 : 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001994 return 0;
1995}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001996EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_switch_get);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001997
Takashi Iwaid5191e52009-11-16 14:58:17 +01001998/**
1999 * snd_hda_mixer_amp_switch_put - Put callback for a standard AMP mixer switch
2000 *
2001 * The control element is supposed to have the private_value field
2002 * set up via HDA_COMPOSE_AMP_VAL*() or related macros.
2003 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02002004int snd_hda_mixer_amp_switch_put(struct snd_kcontrol *kcontrol,
2005 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002006{
2007 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2008 hda_nid_t nid = get_amp_nid(kcontrol);
2009 int chs = get_amp_channels(kcontrol);
2010 int dir = get_amp_direction(kcontrol);
2011 int idx = get_amp_index(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002012 long *valp = ucontrol->value.integer.value;
2013 int change = 0;
2014
Takashi Iwaicb53c622007-08-10 17:21:45 +02002015 snd_hda_power_up(codec);
Nicolas Grazianob9f5a892005-07-29 12:17:20 +02002016 if (chs & 1) {
Takashi Iwai4a19fae2005-06-08 14:43:58 +02002017 change = snd_hda_codec_amp_update(codec, nid, 0, dir, idx,
Takashi Iwai47fd8302007-08-10 17:11:07 +02002018 HDA_AMP_MUTE,
2019 *valp ? 0 : HDA_AMP_MUTE);
Nicolas Grazianob9f5a892005-07-29 12:17:20 +02002020 valp++;
2021 }
Takashi Iwai4a19fae2005-06-08 14:43:58 +02002022 if (chs & 2)
2023 change |= snd_hda_codec_amp_update(codec, nid, 1, dir, idx,
Takashi Iwai47fd8302007-08-10 17:11:07 +02002024 HDA_AMP_MUTE,
2025 *valp ? 0 : HDA_AMP_MUTE);
Takashi Iwaicb53c622007-08-10 17:21:45 +02002026#ifdef CONFIG_SND_HDA_POWER_SAVE
2027 if (codec->patch_ops.check_power_status)
2028 codec->patch_ops.check_power_status(codec, nid);
2029#endif
2030 snd_hda_power_down(codec);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002031 return change;
2032}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002033EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_switch_put);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002034
Takashi Iwai67d634c2009-11-16 15:35:59 +01002035#ifdef CONFIG_SND_HDA_INPUT_BEEP
Takashi Iwaid5191e52009-11-16 14:58:17 +01002036/**
2037 * snd_hda_mixer_amp_switch_put_beep - Put callback for a beep AMP switch
2038 *
2039 * This function calls snd_hda_enable_beep_device(), which behaves differently
2040 * depending on beep_mode option.
2041 */
Jaroslav Kysela123c07a2009-10-21 14:48:23 +02002042int snd_hda_mixer_amp_switch_put_beep(struct snd_kcontrol *kcontrol,
2043 struct snd_ctl_elem_value *ucontrol)
2044{
2045 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2046 long *valp = ucontrol->value.integer.value;
2047
2048 snd_hda_enable_beep_device(codec, *valp);
2049 return snd_hda_mixer_amp_switch_put(kcontrol, ucontrol);
2050}
2051EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_switch_put_beep);
Takashi Iwai67d634c2009-11-16 15:35:59 +01002052#endif /* CONFIG_SND_HDA_INPUT_BEEP */
Jaroslav Kysela123c07a2009-10-21 14:48:23 +02002053
Linus Torvalds1da177e2005-04-16 15:20:36 -07002054/*
Takashi Iwai985be542005-11-02 18:26:49 +01002055 * bound volume controls
2056 *
2057 * bind multiple volumes (# indices, from 0)
2058 */
2059
2060#define AMP_VAL_IDX_SHIFT 19
2061#define AMP_VAL_IDX_MASK (0x0f<<19)
2062
Takashi Iwaid5191e52009-11-16 14:58:17 +01002063/**
2064 * snd_hda_mixer_bind_switch_get - Get callback for a bound volume control
2065 *
2066 * The control element is supposed to have the private_value field
2067 * set up via HDA_BIND_MUTE*() macros.
2068 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02002069int snd_hda_mixer_bind_switch_get(struct snd_kcontrol *kcontrol,
2070 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai985be542005-11-02 18:26:49 +01002071{
2072 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2073 unsigned long pval;
2074 int err;
2075
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08002076 mutex_lock(&codec->control_mutex);
Takashi Iwai985be542005-11-02 18:26:49 +01002077 pval = kcontrol->private_value;
2078 kcontrol->private_value = pval & ~AMP_VAL_IDX_MASK; /* index 0 */
2079 err = snd_hda_mixer_amp_switch_get(kcontrol, ucontrol);
2080 kcontrol->private_value = pval;
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08002081 mutex_unlock(&codec->control_mutex);
Takashi Iwai985be542005-11-02 18:26:49 +01002082 return err;
2083}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002084EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_switch_get);
Takashi Iwai985be542005-11-02 18:26:49 +01002085
Takashi Iwaid5191e52009-11-16 14:58:17 +01002086/**
2087 * snd_hda_mixer_bind_switch_put - Put callback for a bound volume control
2088 *
2089 * The control element is supposed to have the private_value field
2090 * set up via HDA_BIND_MUTE*() macros.
2091 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02002092int snd_hda_mixer_bind_switch_put(struct snd_kcontrol *kcontrol,
2093 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai985be542005-11-02 18:26:49 +01002094{
2095 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2096 unsigned long pval;
2097 int i, indices, err = 0, change = 0;
2098
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08002099 mutex_lock(&codec->control_mutex);
Takashi Iwai985be542005-11-02 18:26:49 +01002100 pval = kcontrol->private_value;
2101 indices = (pval & AMP_VAL_IDX_MASK) >> AMP_VAL_IDX_SHIFT;
2102 for (i = 0; i < indices; i++) {
Takashi Iwai0ba21762007-04-16 11:29:14 +02002103 kcontrol->private_value = (pval & ~AMP_VAL_IDX_MASK) |
2104 (i << AMP_VAL_IDX_SHIFT);
Takashi Iwai985be542005-11-02 18:26:49 +01002105 err = snd_hda_mixer_amp_switch_put(kcontrol, ucontrol);
2106 if (err < 0)
2107 break;
2108 change |= err;
2109 }
2110 kcontrol->private_value = pval;
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08002111 mutex_unlock(&codec->control_mutex);
Takashi Iwai985be542005-11-02 18:26:49 +01002112 return err < 0 ? err : change;
2113}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002114EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_switch_put);
Takashi Iwai985be542005-11-02 18:26:49 +01002115
Takashi Iwaid5191e52009-11-16 14:58:17 +01002116/**
2117 * snd_hda_mixer_bind_ctls_info - Info callback for a generic bound control
2118 *
2119 * The control element is supposed to have the private_value field
2120 * set up via HDA_BIND_VOL() or HDA_BIND_SW() macros.
Takashi Iwai532d5382007-07-27 19:02:40 +02002121 */
2122int snd_hda_mixer_bind_ctls_info(struct snd_kcontrol *kcontrol,
2123 struct snd_ctl_elem_info *uinfo)
2124{
2125 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2126 struct hda_bind_ctls *c;
2127 int err;
2128
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08002129 mutex_lock(&codec->control_mutex);
Serge A. Suchkov14c65f92008-02-22 18:43:16 +01002130 c = (struct hda_bind_ctls *)kcontrol->private_value;
Takashi Iwai532d5382007-07-27 19:02:40 +02002131 kcontrol->private_value = *c->values;
2132 err = c->ops->info(kcontrol, uinfo);
2133 kcontrol->private_value = (long)c;
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08002134 mutex_unlock(&codec->control_mutex);
Takashi Iwai532d5382007-07-27 19:02:40 +02002135 return err;
2136}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002137EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_ctls_info);
Takashi Iwai532d5382007-07-27 19:02:40 +02002138
Takashi Iwaid5191e52009-11-16 14:58:17 +01002139/**
2140 * snd_hda_mixer_bind_ctls_get - Get callback for a generic bound control
2141 *
2142 * The control element is supposed to have the private_value field
2143 * set up via HDA_BIND_VOL() or HDA_BIND_SW() macros.
2144 */
Takashi Iwai532d5382007-07-27 19:02:40 +02002145int snd_hda_mixer_bind_ctls_get(struct snd_kcontrol *kcontrol,
2146 struct snd_ctl_elem_value *ucontrol)
2147{
2148 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2149 struct hda_bind_ctls *c;
2150 int err;
2151
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08002152 mutex_lock(&codec->control_mutex);
Serge A. Suchkov14c65f92008-02-22 18:43:16 +01002153 c = (struct hda_bind_ctls *)kcontrol->private_value;
Takashi Iwai532d5382007-07-27 19:02:40 +02002154 kcontrol->private_value = *c->values;
2155 err = c->ops->get(kcontrol, ucontrol);
2156 kcontrol->private_value = (long)c;
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08002157 mutex_unlock(&codec->control_mutex);
Takashi Iwai532d5382007-07-27 19:02:40 +02002158 return err;
2159}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002160EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_ctls_get);
Takashi Iwai532d5382007-07-27 19:02:40 +02002161
Takashi Iwaid5191e52009-11-16 14:58:17 +01002162/**
2163 * snd_hda_mixer_bind_ctls_put - Put callback for a generic bound control
2164 *
2165 * The control element is supposed to have the private_value field
2166 * set up via HDA_BIND_VOL() or HDA_BIND_SW() macros.
2167 */
Takashi Iwai532d5382007-07-27 19:02:40 +02002168int snd_hda_mixer_bind_ctls_put(struct snd_kcontrol *kcontrol,
2169 struct snd_ctl_elem_value *ucontrol)
2170{
2171 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2172 struct hda_bind_ctls *c;
2173 unsigned long *vals;
2174 int err = 0, change = 0;
2175
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08002176 mutex_lock(&codec->control_mutex);
Serge A. Suchkov14c65f92008-02-22 18:43:16 +01002177 c = (struct hda_bind_ctls *)kcontrol->private_value;
Takashi Iwai532d5382007-07-27 19:02:40 +02002178 for (vals = c->values; *vals; vals++) {
2179 kcontrol->private_value = *vals;
2180 err = c->ops->put(kcontrol, ucontrol);
2181 if (err < 0)
2182 break;
2183 change |= err;
2184 }
2185 kcontrol->private_value = (long)c;
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08002186 mutex_unlock(&codec->control_mutex);
Takashi Iwai532d5382007-07-27 19:02:40 +02002187 return err < 0 ? err : change;
2188}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002189EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_ctls_put);
Takashi Iwai532d5382007-07-27 19:02:40 +02002190
Takashi Iwaid5191e52009-11-16 14:58:17 +01002191/**
2192 * snd_hda_mixer_bind_tlv - TLV callback for a generic bound control
2193 *
2194 * The control element is supposed to have the private_value field
2195 * set up via HDA_BIND_VOL() macro.
2196 */
Takashi Iwai532d5382007-07-27 19:02:40 +02002197int snd_hda_mixer_bind_tlv(struct snd_kcontrol *kcontrol, int op_flag,
2198 unsigned int size, unsigned int __user *tlv)
2199{
2200 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2201 struct hda_bind_ctls *c;
2202 int err;
2203
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08002204 mutex_lock(&codec->control_mutex);
Serge A. Suchkov14c65f92008-02-22 18:43:16 +01002205 c = (struct hda_bind_ctls *)kcontrol->private_value;
Takashi Iwai532d5382007-07-27 19:02:40 +02002206 kcontrol->private_value = *c->values;
2207 err = c->ops->tlv(kcontrol, op_flag, size, tlv);
2208 kcontrol->private_value = (long)c;
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08002209 mutex_unlock(&codec->control_mutex);
Takashi Iwai532d5382007-07-27 19:02:40 +02002210 return err;
2211}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002212EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_tlv);
Takashi Iwai532d5382007-07-27 19:02:40 +02002213
2214struct hda_ctl_ops snd_hda_bind_vol = {
2215 .info = snd_hda_mixer_amp_volume_info,
2216 .get = snd_hda_mixer_amp_volume_get,
2217 .put = snd_hda_mixer_amp_volume_put,
2218 .tlv = snd_hda_mixer_amp_tlv
2219};
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002220EXPORT_SYMBOL_HDA(snd_hda_bind_vol);
Takashi Iwai532d5382007-07-27 19:02:40 +02002221
2222struct hda_ctl_ops snd_hda_bind_sw = {
2223 .info = snd_hda_mixer_amp_switch_info,
2224 .get = snd_hda_mixer_amp_switch_get,
2225 .put = snd_hda_mixer_amp_switch_put,
2226 .tlv = snd_hda_mixer_amp_tlv
2227};
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002228EXPORT_SYMBOL_HDA(snd_hda_bind_sw);
Takashi Iwai532d5382007-07-27 19:02:40 +02002229
2230/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002231 * SPDIF out controls
2232 */
2233
Takashi Iwai0ba21762007-04-16 11:29:14 +02002234static int snd_hda_spdif_mask_info(struct snd_kcontrol *kcontrol,
2235 struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002236{
2237 uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
2238 uinfo->count = 1;
2239 return 0;
2240}
2241
Takashi Iwai0ba21762007-04-16 11:29:14 +02002242static int snd_hda_spdif_cmask_get(struct snd_kcontrol *kcontrol,
2243 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002244{
2245 ucontrol->value.iec958.status[0] = IEC958_AES0_PROFESSIONAL |
2246 IEC958_AES0_NONAUDIO |
2247 IEC958_AES0_CON_EMPHASIS_5015 |
2248 IEC958_AES0_CON_NOT_COPYRIGHT;
2249 ucontrol->value.iec958.status[1] = IEC958_AES1_CON_CATEGORY |
2250 IEC958_AES1_CON_ORIGINAL;
2251 return 0;
2252}
2253
Takashi Iwai0ba21762007-04-16 11:29:14 +02002254static int snd_hda_spdif_pmask_get(struct snd_kcontrol *kcontrol,
2255 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002256{
2257 ucontrol->value.iec958.status[0] = IEC958_AES0_PROFESSIONAL |
2258 IEC958_AES0_NONAUDIO |
2259 IEC958_AES0_PRO_EMPHASIS_5015;
2260 return 0;
2261}
2262
Takashi Iwai0ba21762007-04-16 11:29:14 +02002263static int snd_hda_spdif_default_get(struct snd_kcontrol *kcontrol,
2264 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002265{
2266 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2267
2268 ucontrol->value.iec958.status[0] = codec->spdif_status & 0xff;
2269 ucontrol->value.iec958.status[1] = (codec->spdif_status >> 8) & 0xff;
2270 ucontrol->value.iec958.status[2] = (codec->spdif_status >> 16) & 0xff;
2271 ucontrol->value.iec958.status[3] = (codec->spdif_status >> 24) & 0xff;
2272
2273 return 0;
2274}
2275
2276/* convert from SPDIF status bits to HDA SPDIF bits
2277 * bit 0 (DigEn) is always set zero (to be filled later)
2278 */
2279static unsigned short convert_from_spdif_status(unsigned int sbits)
2280{
2281 unsigned short val = 0;
2282
2283 if (sbits & IEC958_AES0_PROFESSIONAL)
Takashi Iwai0ba21762007-04-16 11:29:14 +02002284 val |= AC_DIG1_PROFESSIONAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002285 if (sbits & IEC958_AES0_NONAUDIO)
Takashi Iwai0ba21762007-04-16 11:29:14 +02002286 val |= AC_DIG1_NONAUDIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002287 if (sbits & IEC958_AES0_PROFESSIONAL) {
Takashi Iwai0ba21762007-04-16 11:29:14 +02002288 if ((sbits & IEC958_AES0_PRO_EMPHASIS) ==
2289 IEC958_AES0_PRO_EMPHASIS_5015)
2290 val |= AC_DIG1_EMPHASIS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002291 } else {
Takashi Iwai0ba21762007-04-16 11:29:14 +02002292 if ((sbits & IEC958_AES0_CON_EMPHASIS) ==
2293 IEC958_AES0_CON_EMPHASIS_5015)
2294 val |= AC_DIG1_EMPHASIS;
2295 if (!(sbits & IEC958_AES0_CON_NOT_COPYRIGHT))
2296 val |= AC_DIG1_COPYRIGHT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002297 if (sbits & (IEC958_AES1_CON_ORIGINAL << 8))
Takashi Iwai0ba21762007-04-16 11:29:14 +02002298 val |= AC_DIG1_LEVEL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002299 val |= sbits & (IEC958_AES1_CON_CATEGORY << 8);
2300 }
2301 return val;
2302}
2303
2304/* convert to SPDIF status bits from HDA SPDIF bits
2305 */
2306static unsigned int convert_to_spdif_status(unsigned short val)
2307{
2308 unsigned int sbits = 0;
2309
Takashi Iwai0ba21762007-04-16 11:29:14 +02002310 if (val & AC_DIG1_NONAUDIO)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002311 sbits |= IEC958_AES0_NONAUDIO;
Takashi Iwai0ba21762007-04-16 11:29:14 +02002312 if (val & AC_DIG1_PROFESSIONAL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002313 sbits |= IEC958_AES0_PROFESSIONAL;
2314 if (sbits & IEC958_AES0_PROFESSIONAL) {
Takashi Iwai0ba21762007-04-16 11:29:14 +02002315 if (sbits & AC_DIG1_EMPHASIS)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002316 sbits |= IEC958_AES0_PRO_EMPHASIS_5015;
2317 } else {
Takashi Iwai0ba21762007-04-16 11:29:14 +02002318 if (val & AC_DIG1_EMPHASIS)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002319 sbits |= IEC958_AES0_CON_EMPHASIS_5015;
Takashi Iwai0ba21762007-04-16 11:29:14 +02002320 if (!(val & AC_DIG1_COPYRIGHT))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002321 sbits |= IEC958_AES0_CON_NOT_COPYRIGHT;
Takashi Iwai0ba21762007-04-16 11:29:14 +02002322 if (val & AC_DIG1_LEVEL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002323 sbits |= (IEC958_AES1_CON_ORIGINAL << 8);
2324 sbits |= val & (0x7f << 8);
2325 }
2326 return sbits;
2327}
2328
Takashi Iwai2f728532008-09-25 16:32:41 +02002329/* set digital convert verbs both for the given NID and its slaves */
2330static void set_dig_out(struct hda_codec *codec, hda_nid_t nid,
2331 int verb, int val)
2332{
2333 hda_nid_t *d;
2334
Takashi Iwai9e976972008-11-25 08:17:20 +01002335 snd_hda_codec_write_cache(codec, nid, 0, verb, val);
Takashi Iwai2f728532008-09-25 16:32:41 +02002336 d = codec->slave_dig_outs;
2337 if (!d)
2338 return;
2339 for (; *d; d++)
Takashi Iwai9e976972008-11-25 08:17:20 +01002340 snd_hda_codec_write_cache(codec, *d, 0, verb, val);
Takashi Iwai2f728532008-09-25 16:32:41 +02002341}
2342
2343static inline void set_dig_out_convert(struct hda_codec *codec, hda_nid_t nid,
2344 int dig1, int dig2)
2345{
2346 if (dig1 != -1)
2347 set_dig_out(codec, nid, AC_VERB_SET_DIGI_CONVERT_1, dig1);
2348 if (dig2 != -1)
2349 set_dig_out(codec, nid, AC_VERB_SET_DIGI_CONVERT_2, dig2);
2350}
2351
Takashi Iwai0ba21762007-04-16 11:29:14 +02002352static int snd_hda_spdif_default_put(struct snd_kcontrol *kcontrol,
2353 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002354{
2355 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2356 hda_nid_t nid = kcontrol->private_value;
2357 unsigned short val;
2358 int change;
2359
Ingo Molnar62932df2006-01-16 16:34:20 +01002360 mutex_lock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002361 codec->spdif_status = ucontrol->value.iec958.status[0] |
2362 ((unsigned int)ucontrol->value.iec958.status[1] << 8) |
2363 ((unsigned int)ucontrol->value.iec958.status[2] << 16) |
2364 ((unsigned int)ucontrol->value.iec958.status[3] << 24);
2365 val = convert_from_spdif_status(codec->spdif_status);
2366 val |= codec->spdif_ctls & 1;
2367 change = codec->spdif_ctls != val;
2368 codec->spdif_ctls = val;
2369
Takashi Iwai2f728532008-09-25 16:32:41 +02002370 if (change)
2371 set_dig_out_convert(codec, nid, val & 0xff, (val >> 8) & 0xff);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002372
Ingo Molnar62932df2006-01-16 16:34:20 +01002373 mutex_unlock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002374 return change;
2375}
2376
Takashi Iwaia5ce8892007-07-23 15:42:26 +02002377#define snd_hda_spdif_out_switch_info snd_ctl_boolean_mono_info
Linus Torvalds1da177e2005-04-16 15:20:36 -07002378
Takashi Iwai0ba21762007-04-16 11:29:14 +02002379static int snd_hda_spdif_out_switch_get(struct snd_kcontrol *kcontrol,
2380 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002381{
2382 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2383
Takashi Iwai0ba21762007-04-16 11:29:14 +02002384 ucontrol->value.integer.value[0] = codec->spdif_ctls & AC_DIG1_ENABLE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002385 return 0;
2386}
2387
Takashi Iwai0ba21762007-04-16 11:29:14 +02002388static int snd_hda_spdif_out_switch_put(struct snd_kcontrol *kcontrol,
2389 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002390{
2391 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2392 hda_nid_t nid = kcontrol->private_value;
2393 unsigned short val;
2394 int change;
2395
Ingo Molnar62932df2006-01-16 16:34:20 +01002396 mutex_lock(&codec->spdif_mutex);
Takashi Iwai0ba21762007-04-16 11:29:14 +02002397 val = codec->spdif_ctls & ~AC_DIG1_ENABLE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002398 if (ucontrol->value.integer.value[0])
Takashi Iwai0ba21762007-04-16 11:29:14 +02002399 val |= AC_DIG1_ENABLE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002400 change = codec->spdif_ctls != val;
Takashi Iwai82beb8f2007-08-10 17:09:26 +02002401 if (change) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002402 codec->spdif_ctls = val;
Takashi Iwai2f728532008-09-25 16:32:41 +02002403 set_dig_out_convert(codec, nid, val & 0xff, -1);
Takashi Iwai0ba21762007-04-16 11:29:14 +02002404 /* unmute amp switch (if any) */
2405 if ((get_wcaps(codec, nid) & AC_WCAP_OUT_AMP) &&
Takashi Iwai47fd8302007-08-10 17:11:07 +02002406 (val & AC_DIG1_ENABLE))
2407 snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0,
2408 HDA_AMP_MUTE, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002409 }
Ingo Molnar62932df2006-01-16 16:34:20 +01002410 mutex_unlock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002411 return change;
2412}
2413
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01002414static struct snd_kcontrol_new dig_mixes[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002415 {
2416 .access = SNDRV_CTL_ELEM_ACCESS_READ,
2417 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2418 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,CON_MASK),
2419 .info = snd_hda_spdif_mask_info,
2420 .get = snd_hda_spdif_cmask_get,
2421 },
2422 {
2423 .access = SNDRV_CTL_ELEM_ACCESS_READ,
2424 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2425 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,PRO_MASK),
2426 .info = snd_hda_spdif_mask_info,
2427 .get = snd_hda_spdif_pmask_get,
2428 },
2429 {
2430 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2431 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT),
2432 .info = snd_hda_spdif_mask_info,
2433 .get = snd_hda_spdif_default_get,
2434 .put = snd_hda_spdif_default_put,
2435 },
2436 {
2437 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2438 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,SWITCH),
2439 .info = snd_hda_spdif_out_switch_info,
2440 .get = snd_hda_spdif_out_switch_get,
2441 .put = snd_hda_spdif_out_switch_put,
2442 },
2443 { } /* end */
2444};
2445
Takashi Iwai09f99702008-02-04 12:31:13 +01002446#define SPDIF_MAX_IDX 4 /* 4 instances should be enough to probe */
2447
Linus Torvalds1da177e2005-04-16 15:20:36 -07002448/**
2449 * snd_hda_create_spdif_out_ctls - create Output SPDIF-related controls
2450 * @codec: the HDA codec
2451 * @nid: audio out widget NID
2452 *
2453 * Creates controls related with the SPDIF output.
2454 * Called from each patch supporting the SPDIF out.
2455 *
2456 * Returns 0 if successful, or a negative error code.
2457 */
Takashi Iwai12f288b2007-08-02 15:51:59 +02002458int snd_hda_create_spdif_out_ctls(struct hda_codec *codec, hda_nid_t nid)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002459{
2460 int err;
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01002461 struct snd_kcontrol *kctl;
2462 struct snd_kcontrol_new *dig_mix;
Takashi Iwai09f99702008-02-04 12:31:13 +01002463 int idx;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002464
Takashi Iwai09f99702008-02-04 12:31:13 +01002465 for (idx = 0; idx < SPDIF_MAX_IDX; idx++) {
2466 if (!_snd_hda_find_mixer_ctl(codec, "IEC958 Playback Switch",
2467 idx))
2468 break;
2469 }
2470 if (idx >= SPDIF_MAX_IDX) {
2471 printk(KERN_ERR "hda_codec: too many IEC958 outputs\n");
2472 return -EBUSY;
2473 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002474 for (dig_mix = dig_mixes; dig_mix->name; dig_mix++) {
2475 kctl = snd_ctl_new1(dig_mix, codec);
Takashi Iwaib91f0802008-11-04 08:43:08 +01002476 if (!kctl)
2477 return -ENOMEM;
Takashi Iwai09f99702008-02-04 12:31:13 +01002478 kctl->id.index = idx;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002479 kctl->private_value = nid;
Jaroslav Kysela3911a4c2009-11-11 13:43:01 +01002480 err = snd_hda_ctl_add(codec, nid, kctl);
Takashi Iwai0ba21762007-04-16 11:29:14 +02002481 if (err < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002482 return err;
2483 }
Takashi Iwai0ba21762007-04-16 11:29:14 +02002484 codec->spdif_ctls =
Andrew Paprocki3982d172007-12-19 12:13:44 +01002485 snd_hda_codec_read(codec, nid, 0,
2486 AC_VERB_GET_DIGI_CONVERT_1, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002487 codec->spdif_status = convert_to_spdif_status(codec->spdif_ctls);
2488 return 0;
2489}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002490EXPORT_SYMBOL_HDA(snd_hda_create_spdif_out_ctls);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002491
2492/*
Takashi Iwai9a081602008-02-12 18:37:26 +01002493 * SPDIF sharing with analog output
2494 */
2495static int spdif_share_sw_get(struct snd_kcontrol *kcontrol,
2496 struct snd_ctl_elem_value *ucontrol)
2497{
2498 struct hda_multi_out *mout = snd_kcontrol_chip(kcontrol);
2499 ucontrol->value.integer.value[0] = mout->share_spdif;
2500 return 0;
2501}
2502
2503static int spdif_share_sw_put(struct snd_kcontrol *kcontrol,
2504 struct snd_ctl_elem_value *ucontrol)
2505{
2506 struct hda_multi_out *mout = snd_kcontrol_chip(kcontrol);
2507 mout->share_spdif = !!ucontrol->value.integer.value[0];
2508 return 0;
2509}
2510
2511static struct snd_kcontrol_new spdif_share_sw = {
2512 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2513 .name = "IEC958 Default PCM Playback Switch",
2514 .info = snd_ctl_boolean_mono_info,
2515 .get = spdif_share_sw_get,
2516 .put = spdif_share_sw_put,
2517};
2518
Takashi Iwaid5191e52009-11-16 14:58:17 +01002519/**
2520 * snd_hda_create_spdif_share_sw - create Default PCM switch
2521 * @codec: the HDA codec
2522 * @mout: multi-out instance
2523 */
Takashi Iwai9a081602008-02-12 18:37:26 +01002524int snd_hda_create_spdif_share_sw(struct hda_codec *codec,
2525 struct hda_multi_out *mout)
2526{
2527 if (!mout->dig_out_nid)
2528 return 0;
2529 /* ATTENTION: here mout is passed as private_data, instead of codec */
Jaroslav Kysela3911a4c2009-11-11 13:43:01 +01002530 return snd_hda_ctl_add(codec, mout->dig_out_nid,
2531 snd_ctl_new1(&spdif_share_sw, mout));
Takashi Iwai9a081602008-02-12 18:37:26 +01002532}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002533EXPORT_SYMBOL_HDA(snd_hda_create_spdif_share_sw);
Takashi Iwai9a081602008-02-12 18:37:26 +01002534
2535/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002536 * SPDIF input
2537 */
2538
2539#define snd_hda_spdif_in_switch_info snd_hda_spdif_out_switch_info
2540
Takashi Iwai0ba21762007-04-16 11:29:14 +02002541static int snd_hda_spdif_in_switch_get(struct snd_kcontrol *kcontrol,
2542 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002543{
2544 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2545
2546 ucontrol->value.integer.value[0] = codec->spdif_in_enable;
2547 return 0;
2548}
2549
Takashi Iwai0ba21762007-04-16 11:29:14 +02002550static int snd_hda_spdif_in_switch_put(struct snd_kcontrol *kcontrol,
2551 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002552{
2553 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2554 hda_nid_t nid = kcontrol->private_value;
2555 unsigned int val = !!ucontrol->value.integer.value[0];
2556 int change;
2557
Ingo Molnar62932df2006-01-16 16:34:20 +01002558 mutex_lock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002559 change = codec->spdif_in_enable != val;
Takashi Iwai82beb8f2007-08-10 17:09:26 +02002560 if (change) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002561 codec->spdif_in_enable = val;
Takashi Iwai82beb8f2007-08-10 17:09:26 +02002562 snd_hda_codec_write_cache(codec, nid, 0,
2563 AC_VERB_SET_DIGI_CONVERT_1, val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002564 }
Ingo Molnar62932df2006-01-16 16:34:20 +01002565 mutex_unlock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002566 return change;
2567}
2568
Takashi Iwai0ba21762007-04-16 11:29:14 +02002569static int snd_hda_spdif_in_status_get(struct snd_kcontrol *kcontrol,
2570 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002571{
2572 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2573 hda_nid_t nid = kcontrol->private_value;
2574 unsigned short val;
2575 unsigned int sbits;
2576
Andrew Paprocki3982d172007-12-19 12:13:44 +01002577 val = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_DIGI_CONVERT_1, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002578 sbits = convert_to_spdif_status(val);
2579 ucontrol->value.iec958.status[0] = sbits;
2580 ucontrol->value.iec958.status[1] = sbits >> 8;
2581 ucontrol->value.iec958.status[2] = sbits >> 16;
2582 ucontrol->value.iec958.status[3] = sbits >> 24;
2583 return 0;
2584}
2585
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01002586static struct snd_kcontrol_new dig_in_ctls[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002587 {
2588 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2589 .name = SNDRV_CTL_NAME_IEC958("",CAPTURE,SWITCH),
2590 .info = snd_hda_spdif_in_switch_info,
2591 .get = snd_hda_spdif_in_switch_get,
2592 .put = snd_hda_spdif_in_switch_put,
2593 },
2594 {
2595 .access = SNDRV_CTL_ELEM_ACCESS_READ,
2596 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2597 .name = SNDRV_CTL_NAME_IEC958("",CAPTURE,DEFAULT),
2598 .info = snd_hda_spdif_mask_info,
2599 .get = snd_hda_spdif_in_status_get,
2600 },
2601 { } /* end */
2602};
2603
2604/**
2605 * snd_hda_create_spdif_in_ctls - create Input SPDIF-related controls
2606 * @codec: the HDA codec
2607 * @nid: audio in widget NID
2608 *
2609 * Creates controls related with the SPDIF input.
2610 * Called from each patch supporting the SPDIF in.
2611 *
2612 * Returns 0 if successful, or a negative error code.
2613 */
Takashi Iwai12f288b2007-08-02 15:51:59 +02002614int snd_hda_create_spdif_in_ctls(struct hda_codec *codec, hda_nid_t nid)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002615{
2616 int err;
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01002617 struct snd_kcontrol *kctl;
2618 struct snd_kcontrol_new *dig_mix;
Takashi Iwai09f99702008-02-04 12:31:13 +01002619 int idx;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002620
Takashi Iwai09f99702008-02-04 12:31:13 +01002621 for (idx = 0; idx < SPDIF_MAX_IDX; idx++) {
2622 if (!_snd_hda_find_mixer_ctl(codec, "IEC958 Capture Switch",
2623 idx))
2624 break;
2625 }
2626 if (idx >= SPDIF_MAX_IDX) {
2627 printk(KERN_ERR "hda_codec: too many IEC958 inputs\n");
2628 return -EBUSY;
2629 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002630 for (dig_mix = dig_in_ctls; dig_mix->name; dig_mix++) {
2631 kctl = snd_ctl_new1(dig_mix, codec);
Takashi Iwaic8dcdf82009-02-06 16:21:20 +01002632 if (!kctl)
2633 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002634 kctl->private_value = nid;
Jaroslav Kysela3911a4c2009-11-11 13:43:01 +01002635 err = snd_hda_ctl_add(codec, nid, kctl);
Takashi Iwai0ba21762007-04-16 11:29:14 +02002636 if (err < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002637 return err;
2638 }
Takashi Iwai0ba21762007-04-16 11:29:14 +02002639 codec->spdif_in_enable =
Andrew Paprocki3982d172007-12-19 12:13:44 +01002640 snd_hda_codec_read(codec, nid, 0,
2641 AC_VERB_GET_DIGI_CONVERT_1, 0) &
Takashi Iwai0ba21762007-04-16 11:29:14 +02002642 AC_DIG1_ENABLE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002643 return 0;
2644}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002645EXPORT_SYMBOL_HDA(snd_hda_create_spdif_in_ctls);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002646
Takashi Iwaicb53c622007-08-10 17:21:45 +02002647#ifdef SND_HDA_NEEDS_RESUME
Takashi Iwai82beb8f2007-08-10 17:09:26 +02002648/*
2649 * command cache
2650 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002651
Takashi Iwaib3ac5632007-08-10 17:03:40 +02002652/* build a 32bit cache key with the widget id and the command parameter */
2653#define build_cmd_cache_key(nid, verb) ((verb << 8) | nid)
2654#define get_cmd_cache_nid(key) ((key) & 0xff)
2655#define get_cmd_cache_cmd(key) (((key) >> 8) & 0xffff)
2656
2657/**
2658 * snd_hda_codec_write_cache - send a single command with caching
2659 * @codec: the HDA codec
2660 * @nid: NID to send the command
2661 * @direct: direct flag
2662 * @verb: the verb to send
2663 * @parm: the parameter for the verb
2664 *
2665 * Send a single command without waiting for response.
2666 *
2667 * Returns 0 if successful, or a negative error code.
2668 */
2669int snd_hda_codec_write_cache(struct hda_codec *codec, hda_nid_t nid,
2670 int direct, unsigned int verb, unsigned int parm)
2671{
Takashi Iwaiaa2936f2009-05-26 16:07:57 +02002672 int err = snd_hda_codec_write(codec, nid, direct, verb, parm);
2673 struct hda_cache_head *c;
2674 u32 key;
Takashi Iwai33fa35e2008-11-06 16:50:40 +01002675
Takashi Iwaiaa2936f2009-05-26 16:07:57 +02002676 if (err < 0)
2677 return err;
2678 /* parm may contain the verb stuff for get/set amp */
2679 verb = verb | (parm >> 8);
2680 parm &= 0xff;
2681 key = build_cmd_cache_key(nid, verb);
2682 mutex_lock(&codec->bus->cmd_mutex);
2683 c = get_alloc_hash(&codec->cmd_cache, key);
2684 if (c)
2685 c->val = parm;
2686 mutex_unlock(&codec->bus->cmd_mutex);
2687 return 0;
Takashi Iwaib3ac5632007-08-10 17:03:40 +02002688}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002689EXPORT_SYMBOL_HDA(snd_hda_codec_write_cache);
Takashi Iwaib3ac5632007-08-10 17:03:40 +02002690
Takashi Iwaid5191e52009-11-16 14:58:17 +01002691/**
2692 * snd_hda_codec_resume_cache - Resume the all commands from the cache
2693 * @codec: HD-audio codec
2694 *
2695 * Execute all verbs recorded in the command caches to resume.
2696 */
Takashi Iwaib3ac5632007-08-10 17:03:40 +02002697void snd_hda_codec_resume_cache(struct hda_codec *codec)
2698{
Takashi Iwai603c4012008-07-30 15:01:44 +02002699 struct hda_cache_head *buffer = codec->cmd_cache.buf.list;
Takashi Iwaib3ac5632007-08-10 17:03:40 +02002700 int i;
2701
Takashi Iwai603c4012008-07-30 15:01:44 +02002702 for (i = 0; i < codec->cmd_cache.buf.used; i++, buffer++) {
Takashi Iwaib3ac5632007-08-10 17:03:40 +02002703 u32 key = buffer->key;
2704 if (!key)
2705 continue;
2706 snd_hda_codec_write(codec, get_cmd_cache_nid(key), 0,
2707 get_cmd_cache_cmd(key), buffer->val);
2708 }
2709}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002710EXPORT_SYMBOL_HDA(snd_hda_codec_resume_cache);
Takashi Iwaib3ac5632007-08-10 17:03:40 +02002711
2712/**
2713 * snd_hda_sequence_write_cache - sequence writes with caching
2714 * @codec: the HDA codec
2715 * @seq: VERB array to send
2716 *
2717 * Send the commands sequentially from the given array.
2718 * Thte commands are recorded on cache for power-save and resume.
2719 * The array must be terminated with NID=0.
2720 */
2721void snd_hda_sequence_write_cache(struct hda_codec *codec,
2722 const struct hda_verb *seq)
2723{
2724 for (; seq->nid; seq++)
2725 snd_hda_codec_write_cache(codec, seq->nid, 0, seq->verb,
2726 seq->param);
2727}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002728EXPORT_SYMBOL_HDA(snd_hda_sequence_write_cache);
Takashi Iwaicb53c622007-08-10 17:21:45 +02002729#endif /* SND_HDA_NEEDS_RESUME */
Takashi Iwaib3ac5632007-08-10 17:03:40 +02002730
Takashi Iwai54d17402005-11-21 16:33:22 +01002731/*
2732 * set power state of the codec
2733 */
2734static void hda_set_power_state(struct hda_codec *codec, hda_nid_t fg,
2735 unsigned int power_state)
2736{
Takashi Iwaicb53c622007-08-10 17:21:45 +02002737 hda_nid_t nid;
2738 int i;
Takashi Iwai54d17402005-11-21 16:33:22 +01002739
Takashi Iwai05ff7e12009-07-22 12:39:24 +02002740 /* this delay seems necessary to avoid click noise at power-down */
2741 if (power_state == AC_PWRST_D3)
2742 msleep(100);
2743 snd_hda_codec_read(codec, fg, 0, AC_VERB_SET_POWER_STATE,
Takashi Iwai54d17402005-11-21 16:33:22 +01002744 power_state);
Takashi Iwai05ff7e12009-07-22 12:39:24 +02002745 /* partial workaround for "azx_get_response timeout" */
2746 if (power_state == AC_PWRST_D0)
2747 msleep(10);
Takashi Iwai54d17402005-11-21 16:33:22 +01002748
Takashi Iwaicb53c622007-08-10 17:21:45 +02002749 nid = codec->start_nid;
2750 for (i = 0; i < codec->num_nodes; i++, nid++) {
Takashi Iwai7eba5c92007-11-14 14:53:42 +01002751 unsigned int wcaps = get_wcaps(codec, nid);
2752 if (wcaps & AC_WCAP_POWER) {
Takashi Iwaia22d5432009-07-27 12:54:26 +02002753 unsigned int wid_type = get_wcaps_type(wcaps);
Takashi Iwaia3b48c82009-04-21 13:37:29 +02002754 if (power_state == AC_PWRST_D3 &&
2755 wid_type == AC_WID_PIN) {
Takashi Iwai7eba5c92007-11-14 14:53:42 +01002756 unsigned int pincap;
2757 /*
2758 * don't power down the widget if it controls
2759 * eapd and EAPD_BTLENABLE is set.
2760 */
Takashi Iwai14bafe32009-03-23 16:35:39 +01002761 pincap = snd_hda_query_pin_caps(codec, nid);
Takashi Iwai7eba5c92007-11-14 14:53:42 +01002762 if (pincap & AC_PINCAP_EAPD) {
2763 int eapd = snd_hda_codec_read(codec,
2764 nid, 0,
2765 AC_VERB_GET_EAPD_BTLENABLE, 0);
2766 eapd &= 0x02;
Takashi Iwaia3b48c82009-04-21 13:37:29 +02002767 if (eapd)
Takashi Iwai7eba5c92007-11-14 14:53:42 +01002768 continue;
2769 }
Takashi Iwai1194b5b2007-10-10 10:04:26 +02002770 }
Takashi Iwai54d17402005-11-21 16:33:22 +01002771 snd_hda_codec_write(codec, nid, 0,
2772 AC_VERB_SET_POWER_STATE,
2773 power_state);
Takashi Iwai1194b5b2007-10-10 10:04:26 +02002774 }
Takashi Iwai54d17402005-11-21 16:33:22 +01002775 }
2776
Takashi Iwaicb53c622007-08-10 17:21:45 +02002777 if (power_state == AC_PWRST_D0) {
2778 unsigned long end_time;
2779 int state;
Takashi Iwai54d17402005-11-21 16:33:22 +01002780 msleep(10);
Takashi Iwaicb53c622007-08-10 17:21:45 +02002781 /* wait until the codec reachs to D0 */
2782 end_time = jiffies + msecs_to_jiffies(500);
2783 do {
2784 state = snd_hda_codec_read(codec, fg, 0,
2785 AC_VERB_GET_POWER_STATE, 0);
2786 if (state == power_state)
2787 break;
2788 msleep(1);
2789 } while (time_after_eq(end_time, jiffies));
2790 }
Takashi Iwai54d17402005-11-21 16:33:22 +01002791}
2792
Takashi Iwai11aeff02008-07-30 15:01:46 +02002793#ifdef CONFIG_SND_HDA_HWDEP
2794/* execute additional init verbs */
2795static void hda_exec_init_verbs(struct hda_codec *codec)
2796{
2797 if (codec->init_verbs.list)
2798 snd_hda_sequence_write(codec, codec->init_verbs.list);
2799}
2800#else
2801static inline void hda_exec_init_verbs(struct hda_codec *codec) {}
2802#endif
2803
Takashi Iwaicb53c622007-08-10 17:21:45 +02002804#ifdef SND_HDA_NEEDS_RESUME
2805/*
2806 * call suspend and power-down; used both from PM and power-save
2807 */
2808static void hda_call_codec_suspend(struct hda_codec *codec)
2809{
2810 if (codec->patch_ops.suspend)
2811 codec->patch_ops.suspend(codec, PMSG_SUSPEND);
2812 hda_set_power_state(codec,
2813 codec->afg ? codec->afg : codec->mfg,
2814 AC_PWRST_D3);
2815#ifdef CONFIG_SND_HDA_POWER_SAVE
Takashi Iwaia2f63092009-11-11 09:34:25 +01002816 snd_hda_update_power_acct(codec);
Takashi Iwaicb53c622007-08-10 17:21:45 +02002817 cancel_delayed_work(&codec->power_work);
Takashi Iwai95e99fd2007-08-13 15:29:04 +02002818 codec->power_on = 0;
Takashi Iwaia221e282007-08-16 16:35:33 +02002819 codec->power_transition = 0;
Takashi Iwaia2f63092009-11-11 09:34:25 +01002820 codec->power_jiffies = jiffies;
Takashi Iwaicb53c622007-08-10 17:21:45 +02002821#endif
2822}
2823
2824/*
2825 * kick up codec; used both from PM and power-save
2826 */
2827static void hda_call_codec_resume(struct hda_codec *codec)
2828{
2829 hda_set_power_state(codec,
2830 codec->afg ? codec->afg : codec->mfg,
2831 AC_PWRST_D0);
Takashi Iwai3be14142009-02-20 14:11:16 +01002832 restore_pincfgs(codec); /* restore all current pin configs */
Takashi Iwai11aeff02008-07-30 15:01:46 +02002833 hda_exec_init_verbs(codec);
Takashi Iwaicb53c622007-08-10 17:21:45 +02002834 if (codec->patch_ops.resume)
2835 codec->patch_ops.resume(codec);
2836 else {
Takashi Iwai9d99f312007-08-14 15:15:52 +02002837 if (codec->patch_ops.init)
2838 codec->patch_ops.init(codec);
Takashi Iwaicb53c622007-08-10 17:21:45 +02002839 snd_hda_codec_resume_amp(codec);
2840 snd_hda_codec_resume_cache(codec);
2841 }
2842}
2843#endif /* SND_HDA_NEEDS_RESUME */
2844
Takashi Iwai54d17402005-11-21 16:33:22 +01002845
Linus Torvalds1da177e2005-04-16 15:20:36 -07002846/**
2847 * snd_hda_build_controls - build mixer controls
2848 * @bus: the BUS
2849 *
2850 * Creates mixer controls for each codec included in the bus.
2851 *
2852 * Returns 0 if successful, otherwise a negative error code.
2853 */
Takashi Iwai1289e9e2008-11-27 15:47:11 +01002854int /*__devinit*/ snd_hda_build_controls(struct hda_bus *bus)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002855{
Takashi Iwai0ba21762007-04-16 11:29:14 +02002856 struct hda_codec *codec;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002857
Takashi Iwai0ba21762007-04-16 11:29:14 +02002858 list_for_each_entry(codec, &bus->codec_list, list) {
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02002859 int err = snd_hda_codec_build_controls(codec);
Takashi Iwaif93d4612009-03-02 10:44:15 +01002860 if (err < 0) {
2861 printk(KERN_ERR "hda_codec: cannot build controls"
2862 "for #%d (error %d)\n", codec->addr, err);
2863 err = snd_hda_codec_reset(codec);
2864 if (err < 0) {
2865 printk(KERN_ERR
2866 "hda_codec: cannot revert codec\n");
2867 return err;
2868 }
2869 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002870 }
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02002871 return 0;
2872}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002873EXPORT_SYMBOL_HDA(snd_hda_build_controls);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002874
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02002875int snd_hda_codec_build_controls(struct hda_codec *codec)
2876{
2877 int err = 0;
Takashi Iwai11aeff02008-07-30 15:01:46 +02002878 hda_exec_init_verbs(codec);
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02002879 /* continue to initialize... */
2880 if (codec->patch_ops.init)
2881 err = codec->patch_ops.init(codec);
2882 if (!err && codec->patch_ops.build_controls)
2883 err = codec->patch_ops.build_controls(codec);
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02002884 if (err < 0)
2885 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002886 return 0;
2887}
2888
Linus Torvalds1da177e2005-04-16 15:20:36 -07002889/*
2890 * stream formats
2891 */
Takashi Iwaibefdf312005-08-22 13:57:55 +02002892struct hda_rate_tbl {
2893 unsigned int hz;
2894 unsigned int alsa_bits;
2895 unsigned int hda_fmt;
2896};
2897
2898static struct hda_rate_tbl rate_bits[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002899 /* rate in Hz, ALSA rate bitmask, HDA format value */
Nicolas Graziano9d8f53f2005-08-22 13:47:16 +02002900
2901 /* autodetected value used in snd_hda_query_supported_pcm */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002902 { 8000, SNDRV_PCM_RATE_8000, 0x0500 }, /* 1/6 x 48 */
2903 { 11025, SNDRV_PCM_RATE_11025, 0x4300 }, /* 1/4 x 44 */
2904 { 16000, SNDRV_PCM_RATE_16000, 0x0200 }, /* 1/3 x 48 */
2905 { 22050, SNDRV_PCM_RATE_22050, 0x4100 }, /* 1/2 x 44 */
2906 { 32000, SNDRV_PCM_RATE_32000, 0x0a00 }, /* 2/3 x 48 */
2907 { 44100, SNDRV_PCM_RATE_44100, 0x4000 }, /* 44 */
2908 { 48000, SNDRV_PCM_RATE_48000, 0x0000 }, /* 48 */
2909 { 88200, SNDRV_PCM_RATE_88200, 0x4800 }, /* 2 x 44 */
2910 { 96000, SNDRV_PCM_RATE_96000, 0x0800 }, /* 2 x 48 */
2911 { 176400, SNDRV_PCM_RATE_176400, 0x5800 },/* 4 x 44 */
2912 { 192000, SNDRV_PCM_RATE_192000, 0x1800 }, /* 4 x 48 */
Takashi Iwaia961f9f2007-04-12 13:08:09 +02002913#define AC_PAR_PCM_RATE_BITS 11
2914 /* up to bits 10, 384kHZ isn't supported properly */
2915
2916 /* not autodetected value */
2917 { 9600, SNDRV_PCM_RATE_KNOT, 0x0400 }, /* 1/5 x 48 */
Nicolas Graziano9d8f53f2005-08-22 13:47:16 +02002918
Takashi Iwaibefdf312005-08-22 13:57:55 +02002919 { 0 } /* terminator */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002920};
2921
2922/**
2923 * snd_hda_calc_stream_format - calculate format bitset
2924 * @rate: the sample rate
2925 * @channels: the number of channels
2926 * @format: the PCM format (SNDRV_PCM_FORMAT_XXX)
2927 * @maxbps: the max. bps
2928 *
2929 * Calculate the format bitset from the given rate, channels and th PCM format.
2930 *
2931 * Return zero if invalid.
2932 */
2933unsigned int snd_hda_calc_stream_format(unsigned int rate,
2934 unsigned int channels,
2935 unsigned int format,
2936 unsigned int maxbps)
2937{
2938 int i;
2939 unsigned int val = 0;
2940
Takashi Iwaibefdf312005-08-22 13:57:55 +02002941 for (i = 0; rate_bits[i].hz; i++)
2942 if (rate_bits[i].hz == rate) {
2943 val = rate_bits[i].hda_fmt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002944 break;
2945 }
Takashi Iwai0ba21762007-04-16 11:29:14 +02002946 if (!rate_bits[i].hz) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002947 snd_printdd("invalid rate %d\n", rate);
2948 return 0;
2949 }
2950
2951 if (channels == 0 || channels > 8) {
2952 snd_printdd("invalid channels %d\n", channels);
2953 return 0;
2954 }
2955 val |= channels - 1;
2956
2957 switch (snd_pcm_format_width(format)) {
2958 case 8: val |= 0x00; break;
2959 case 16: val |= 0x10; break;
2960 case 20:
2961 case 24:
2962 case 32:
Takashi Iwaib0bb3aa2009-07-03 23:25:37 +02002963 if (maxbps >= 32 || format == SNDRV_PCM_FORMAT_FLOAT_LE)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002964 val |= 0x40;
2965 else if (maxbps >= 24)
2966 val |= 0x30;
2967 else
2968 val |= 0x20;
2969 break;
2970 default:
Takashi Iwai0ba21762007-04-16 11:29:14 +02002971 snd_printdd("invalid format width %d\n",
2972 snd_pcm_format_width(format));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002973 return 0;
2974 }
2975
2976 return val;
2977}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002978EXPORT_SYMBOL_HDA(snd_hda_calc_stream_format);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002979
Takashi Iwai92c7c8a2009-03-24 07:32:14 +01002980static unsigned int get_pcm_param(struct hda_codec *codec, hda_nid_t nid)
2981{
2982 unsigned int val = 0;
2983 if (nid != codec->afg &&
2984 (get_wcaps(codec, nid) & AC_WCAP_FORMAT_OVRD))
2985 val = snd_hda_param_read(codec, nid, AC_PAR_PCM);
2986 if (!val || val == -1)
2987 val = snd_hda_param_read(codec, codec->afg, AC_PAR_PCM);
2988 if (!val || val == -1)
2989 return 0;
2990 return val;
2991}
2992
2993static unsigned int query_pcm_param(struct hda_codec *codec, hda_nid_t nid)
2994{
2995 return query_caps_hash(codec, nid, HDA_HASH_PARPCM_KEY(nid),
2996 get_pcm_param);
2997}
2998
2999static unsigned int get_stream_param(struct hda_codec *codec, hda_nid_t nid)
3000{
3001 unsigned int streams = snd_hda_param_read(codec, nid, AC_PAR_STREAM);
3002 if (!streams || streams == -1)
3003 streams = snd_hda_param_read(codec, codec->afg, AC_PAR_STREAM);
3004 if (!streams || streams == -1)
3005 return 0;
3006 return streams;
3007}
3008
3009static unsigned int query_stream_param(struct hda_codec *codec, hda_nid_t nid)
3010{
3011 return query_caps_hash(codec, nid, HDA_HASH_PARSTR_KEY(nid),
3012 get_stream_param);
3013}
3014
Linus Torvalds1da177e2005-04-16 15:20:36 -07003015/**
3016 * snd_hda_query_supported_pcm - query the supported PCM rates and formats
3017 * @codec: the HDA codec
3018 * @nid: NID to query
3019 * @ratesp: the pointer to store the detected rate bitflags
3020 * @formatsp: the pointer to store the detected formats
3021 * @bpsp: the pointer to store the detected format widths
3022 *
3023 * Queries the supported PCM rates and formats. The NULL @ratesp, @formatsp
3024 * or @bsps argument is ignored.
3025 *
3026 * Returns 0 if successful, otherwise a negative error code.
3027 */
Takashi Iwai986862bd2008-11-27 12:40:13 +01003028static int snd_hda_query_supported_pcm(struct hda_codec *codec, hda_nid_t nid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003029 u32 *ratesp, u64 *formatsp, unsigned int *bpsp)
3030{
Jaroslav Kyselaee504712009-03-17 14:30:31 +01003031 unsigned int i, val, wcaps;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003032
Jaroslav Kyselaee504712009-03-17 14:30:31 +01003033 wcaps = get_wcaps(codec, nid);
Takashi Iwai92c7c8a2009-03-24 07:32:14 +01003034 val = query_pcm_param(codec, nid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003035
3036 if (ratesp) {
3037 u32 rates = 0;
Takashi Iwaia961f9f2007-04-12 13:08:09 +02003038 for (i = 0; i < AC_PAR_PCM_RATE_BITS; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003039 if (val & (1 << i))
Takashi Iwaibefdf312005-08-22 13:57:55 +02003040 rates |= rate_bits[i].alsa_bits;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003041 }
Jaroslav Kyselaee504712009-03-17 14:30:31 +01003042 if (rates == 0) {
3043 snd_printk(KERN_ERR "hda_codec: rates == 0 "
3044 "(nid=0x%x, val=0x%x, ovrd=%i)\n",
3045 nid, val,
3046 (wcaps & AC_WCAP_FORMAT_OVRD) ? 1 : 0);
3047 return -EIO;
3048 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003049 *ratesp = rates;
3050 }
3051
3052 if (formatsp || bpsp) {
3053 u64 formats = 0;
Jaroslav Kyselaee504712009-03-17 14:30:31 +01003054 unsigned int streams, bps;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003055
Takashi Iwai92c7c8a2009-03-24 07:32:14 +01003056 streams = query_stream_param(codec, nid);
3057 if (!streams)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003058 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003059
3060 bps = 0;
3061 if (streams & AC_SUPFMT_PCM) {
3062 if (val & AC_SUPPCM_BITS_8) {
3063 formats |= SNDRV_PCM_FMTBIT_U8;
3064 bps = 8;
3065 }
3066 if (val & AC_SUPPCM_BITS_16) {
3067 formats |= SNDRV_PCM_FMTBIT_S16_LE;
3068 bps = 16;
3069 }
3070 if (wcaps & AC_WCAP_DIGITAL) {
3071 if (val & AC_SUPPCM_BITS_32)
3072 formats |= SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_LE;
3073 if (val & (AC_SUPPCM_BITS_20|AC_SUPPCM_BITS_24))
3074 formats |= SNDRV_PCM_FMTBIT_S32_LE;
3075 if (val & AC_SUPPCM_BITS_24)
3076 bps = 24;
3077 else if (val & AC_SUPPCM_BITS_20)
3078 bps = 20;
Takashi Iwai0ba21762007-04-16 11:29:14 +02003079 } else if (val & (AC_SUPPCM_BITS_20|AC_SUPPCM_BITS_24|
3080 AC_SUPPCM_BITS_32)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003081 formats |= SNDRV_PCM_FMTBIT_S32_LE;
3082 if (val & AC_SUPPCM_BITS_32)
3083 bps = 32;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003084 else if (val & AC_SUPPCM_BITS_24)
3085 bps = 24;
Nicolas Graziano33ef76512006-09-19 14:23:14 +02003086 else if (val & AC_SUPPCM_BITS_20)
3087 bps = 20;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003088 }
3089 }
Takashi Iwaib5025c52009-07-01 18:05:27 +02003090 if (streams & AC_SUPFMT_FLOAT32) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003091 formats |= SNDRV_PCM_FMTBIT_FLOAT_LE;
Takashi Iwaib0bb3aa2009-07-03 23:25:37 +02003092 if (!bps)
3093 bps = 32;
Takashi Iwaib5025c52009-07-01 18:05:27 +02003094 }
3095 if (streams == AC_SUPFMT_AC3) {
Takashi Iwai0ba21762007-04-16 11:29:14 +02003096 /* should be exclusive */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003097 /* temporary hack: we have still no proper support
3098 * for the direct AC3 stream...
3099 */
3100 formats |= SNDRV_PCM_FMTBIT_U8;
3101 bps = 8;
3102 }
Jaroslav Kyselaee504712009-03-17 14:30:31 +01003103 if (formats == 0) {
3104 snd_printk(KERN_ERR "hda_codec: formats == 0 "
3105 "(nid=0x%x, val=0x%x, ovrd=%i, "
3106 "streams=0x%x)\n",
3107 nid, val,
3108 (wcaps & AC_WCAP_FORMAT_OVRD) ? 1 : 0,
3109 streams);
3110 return -EIO;
3111 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003112 if (formatsp)
3113 *formatsp = formats;
3114 if (bpsp)
3115 *bpsp = bps;
3116 }
3117
3118 return 0;
3119}
3120
3121/**
Takashi Iwaid5191e52009-11-16 14:58:17 +01003122 * snd_hda_is_supported_format - Check the validity of the format
3123 * @codec: HD-audio codec
3124 * @nid: NID to check
3125 * @format: the HD-audio format value to check
3126 *
3127 * Check whether the given node supports the format value.
Linus Torvalds1da177e2005-04-16 15:20:36 -07003128 *
3129 * Returns 1 if supported, 0 if not.
3130 */
3131int snd_hda_is_supported_format(struct hda_codec *codec, hda_nid_t nid,
3132 unsigned int format)
3133{
3134 int i;
3135 unsigned int val = 0, rate, stream;
3136
Takashi Iwai92c7c8a2009-03-24 07:32:14 +01003137 val = query_pcm_param(codec, nid);
3138 if (!val)
3139 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003140
3141 rate = format & 0xff00;
Takashi Iwaia961f9f2007-04-12 13:08:09 +02003142 for (i = 0; i < AC_PAR_PCM_RATE_BITS; i++)
Takashi Iwaibefdf312005-08-22 13:57:55 +02003143 if (rate_bits[i].hda_fmt == rate) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003144 if (val & (1 << i))
3145 break;
3146 return 0;
3147 }
Takashi Iwaia961f9f2007-04-12 13:08:09 +02003148 if (i >= AC_PAR_PCM_RATE_BITS)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003149 return 0;
3150
Takashi Iwai92c7c8a2009-03-24 07:32:14 +01003151 stream = query_stream_param(codec, nid);
3152 if (!stream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003153 return 0;
3154
3155 if (stream & AC_SUPFMT_PCM) {
3156 switch (format & 0xf0) {
3157 case 0x00:
Takashi Iwai0ba21762007-04-16 11:29:14 +02003158 if (!(val & AC_SUPPCM_BITS_8))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003159 return 0;
3160 break;
3161 case 0x10:
Takashi Iwai0ba21762007-04-16 11:29:14 +02003162 if (!(val & AC_SUPPCM_BITS_16))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003163 return 0;
3164 break;
3165 case 0x20:
Takashi Iwai0ba21762007-04-16 11:29:14 +02003166 if (!(val & AC_SUPPCM_BITS_20))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003167 return 0;
3168 break;
3169 case 0x30:
Takashi Iwai0ba21762007-04-16 11:29:14 +02003170 if (!(val & AC_SUPPCM_BITS_24))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003171 return 0;
3172 break;
3173 case 0x40:
Takashi Iwai0ba21762007-04-16 11:29:14 +02003174 if (!(val & AC_SUPPCM_BITS_32))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003175 return 0;
3176 break;
3177 default:
3178 return 0;
3179 }
3180 } else {
3181 /* FIXME: check for float32 and AC3? */
3182 }
3183
3184 return 1;
3185}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003186EXPORT_SYMBOL_HDA(snd_hda_is_supported_format);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003187
3188/*
3189 * PCM stuff
3190 */
3191static int hda_pcm_default_open_close(struct hda_pcm_stream *hinfo,
3192 struct hda_codec *codec,
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01003193 struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003194{
3195 return 0;
3196}
3197
3198static int hda_pcm_default_prepare(struct hda_pcm_stream *hinfo,
3199 struct hda_codec *codec,
3200 unsigned int stream_tag,
3201 unsigned int format,
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01003202 struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003203{
3204 snd_hda_codec_setup_stream(codec, hinfo->nid, stream_tag, 0, format);
3205 return 0;
3206}
3207
3208static int hda_pcm_default_cleanup(struct hda_pcm_stream *hinfo,
3209 struct hda_codec *codec,
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01003210 struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003211{
Takashi Iwai888afa12008-03-18 09:57:50 +01003212 snd_hda_codec_cleanup_stream(codec, hinfo->nid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003213 return 0;
3214}
3215
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02003216static int set_pcm_default_values(struct hda_codec *codec,
3217 struct hda_pcm_stream *info)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003218{
Jaroslav Kyselaee504712009-03-17 14:30:31 +01003219 int err;
3220
Takashi Iwai0ba21762007-04-16 11:29:14 +02003221 /* query support PCM information from the given NID */
3222 if (info->nid && (!info->rates || !info->formats)) {
Jaroslav Kyselaee504712009-03-17 14:30:31 +01003223 err = snd_hda_query_supported_pcm(codec, info->nid,
Takashi Iwai0ba21762007-04-16 11:29:14 +02003224 info->rates ? NULL : &info->rates,
3225 info->formats ? NULL : &info->formats,
3226 info->maxbps ? NULL : &info->maxbps);
Jaroslav Kyselaee504712009-03-17 14:30:31 +01003227 if (err < 0)
3228 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003229 }
3230 if (info->ops.open == NULL)
3231 info->ops.open = hda_pcm_default_open_close;
3232 if (info->ops.close == NULL)
3233 info->ops.close = hda_pcm_default_open_close;
3234 if (info->ops.prepare == NULL) {
Takashi Iwaida3cec32008-08-08 17:12:14 +02003235 if (snd_BUG_ON(!info->nid))
3236 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003237 info->ops.prepare = hda_pcm_default_prepare;
3238 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003239 if (info->ops.cleanup == NULL) {
Takashi Iwaida3cec32008-08-08 17:12:14 +02003240 if (snd_BUG_ON(!info->nid))
3241 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003242 info->ops.cleanup = hda_pcm_default_cleanup;
3243 }
3244 return 0;
3245}
3246
Takashi Iwaid5191e52009-11-16 14:58:17 +01003247/* global */
Jaroslav Kyselae3303232009-11-10 14:53:02 +01003248const char *snd_hda_pcm_type_name[HDA_PCM_NTYPES] = {
3249 "Audio", "SPDIF", "HDMI", "Modem"
3250};
3251
Takashi Iwai176d5332008-07-30 15:01:44 +02003252/*
Takashi Iwai529bd6c2008-11-27 14:17:01 +01003253 * get the empty PCM device number to assign
3254 */
3255static int get_empty_pcm_device(struct hda_bus *bus, int type)
3256{
Wu Fengguangf5d6def2009-10-30 11:38:26 +01003257 /* audio device indices; not linear to keep compatibility */
3258 static int audio_idx[HDA_PCM_NTYPES][5] = {
3259 [HDA_PCM_TYPE_AUDIO] = { 0, 2, 4, 5, -1 },
3260 [HDA_PCM_TYPE_SPDIF] = { 1, -1 },
Wu Fengguang92608ba2009-10-30 11:40:03 +01003261 [HDA_PCM_TYPE_HDMI] = { 3, 7, 8, 9, -1 },
Wu Fengguangf5d6def2009-10-30 11:38:26 +01003262 [HDA_PCM_TYPE_MODEM] = { 6, -1 },
Takashi Iwai529bd6c2008-11-27 14:17:01 +01003263 };
Wu Fengguangf5d6def2009-10-30 11:38:26 +01003264 int i;
Takashi Iwai529bd6c2008-11-27 14:17:01 +01003265
Wu Fengguangf5d6def2009-10-30 11:38:26 +01003266 if (type >= HDA_PCM_NTYPES) {
Takashi Iwai529bd6c2008-11-27 14:17:01 +01003267 snd_printk(KERN_WARNING "Invalid PCM type %d\n", type);
3268 return -EINVAL;
3269 }
Wu Fengguangf5d6def2009-10-30 11:38:26 +01003270
3271 for (i = 0; audio_idx[type][i] >= 0 ; i++)
3272 if (!test_and_set_bit(audio_idx[type][i], bus->pcm_dev_bits))
3273 return audio_idx[type][i];
3274
Jaroslav Kyselae3303232009-11-10 14:53:02 +01003275 snd_printk(KERN_WARNING "Too many %s devices\n", snd_hda_pcm_type_name[type]);
Wu Fengguangf5d6def2009-10-30 11:38:26 +01003276 return -EAGAIN;
Takashi Iwai529bd6c2008-11-27 14:17:01 +01003277}
3278
3279/*
Takashi Iwai176d5332008-07-30 15:01:44 +02003280 * attach a new PCM stream
3281 */
Takashi Iwai529bd6c2008-11-27 14:17:01 +01003282static int snd_hda_attach_pcm(struct hda_codec *codec, struct hda_pcm *pcm)
Takashi Iwai176d5332008-07-30 15:01:44 +02003283{
Takashi Iwai33fa35e2008-11-06 16:50:40 +01003284 struct hda_bus *bus = codec->bus;
Takashi Iwai176d5332008-07-30 15:01:44 +02003285 struct hda_pcm_stream *info;
3286 int stream, err;
3287
Takashi Iwaib91f0802008-11-04 08:43:08 +01003288 if (snd_BUG_ON(!pcm->name))
Takashi Iwai176d5332008-07-30 15:01:44 +02003289 return -EINVAL;
3290 for (stream = 0; stream < 2; stream++) {
3291 info = &pcm->stream[stream];
3292 if (info->substreams) {
3293 err = set_pcm_default_values(codec, info);
3294 if (err < 0)
3295 return err;
3296 }
3297 }
Takashi Iwai33fa35e2008-11-06 16:50:40 +01003298 return bus->ops.attach_pcm(bus, codec, pcm);
Takashi Iwai176d5332008-07-30 15:01:44 +02003299}
3300
Takashi Iwai529bd6c2008-11-27 14:17:01 +01003301/* assign all PCMs of the given codec */
3302int snd_hda_codec_build_pcms(struct hda_codec *codec)
3303{
3304 unsigned int pcm;
3305 int err;
3306
3307 if (!codec->num_pcms) {
3308 if (!codec->patch_ops.build_pcms)
3309 return 0;
3310 err = codec->patch_ops.build_pcms(codec);
Takashi Iwai6e655bf2009-03-02 10:46:03 +01003311 if (err < 0) {
3312 printk(KERN_ERR "hda_codec: cannot build PCMs"
3313 "for #%d (error %d)\n", codec->addr, err);
3314 err = snd_hda_codec_reset(codec);
3315 if (err < 0) {
3316 printk(KERN_ERR
3317 "hda_codec: cannot revert codec\n");
3318 return err;
3319 }
3320 }
Takashi Iwai529bd6c2008-11-27 14:17:01 +01003321 }
3322 for (pcm = 0; pcm < codec->num_pcms; pcm++) {
3323 struct hda_pcm *cpcm = &codec->pcm_info[pcm];
3324 int dev;
3325
3326 if (!cpcm->stream[0].substreams && !cpcm->stream[1].substreams)
Takashi Iwai41b5b012009-01-20 18:21:23 +01003327 continue; /* no substreams assigned */
Takashi Iwai529bd6c2008-11-27 14:17:01 +01003328
3329 if (!cpcm->pcm) {
3330 dev = get_empty_pcm_device(codec->bus, cpcm->pcm_type);
3331 if (dev < 0)
Takashi Iwai6e655bf2009-03-02 10:46:03 +01003332 continue; /* no fatal error */
Takashi Iwai529bd6c2008-11-27 14:17:01 +01003333 cpcm->device = dev;
3334 err = snd_hda_attach_pcm(codec, cpcm);
Takashi Iwai6e655bf2009-03-02 10:46:03 +01003335 if (err < 0) {
3336 printk(KERN_ERR "hda_codec: cannot attach "
3337 "PCM stream %d for codec #%d\n",
3338 dev, codec->addr);
3339 continue; /* no fatal error */
3340 }
Takashi Iwai529bd6c2008-11-27 14:17:01 +01003341 }
3342 }
3343 return 0;
3344}
3345
Linus Torvalds1da177e2005-04-16 15:20:36 -07003346/**
3347 * snd_hda_build_pcms - build PCM information
3348 * @bus: the BUS
3349 *
3350 * Create PCM information for each codec included in the bus.
3351 *
3352 * The build_pcms codec patch is requested to set up codec->num_pcms and
3353 * codec->pcm_info properly. The array is referred by the top-level driver
3354 * to create its PCM instances.
3355 * The allocated codec->pcm_info should be released in codec->patch_ops.free
3356 * callback.
3357 *
3358 * At least, substreams, channels_min and channels_max must be filled for
3359 * each stream. substreams = 0 indicates that the stream doesn't exist.
3360 * When rates and/or formats are zero, the supported values are queried
3361 * from the given nid. The nid is used also by the default ops.prepare
3362 * and ops.cleanup callbacks.
3363 *
3364 * The driver needs to call ops.open in its open callback. Similarly,
3365 * ops.close is supposed to be called in the close callback.
3366 * ops.prepare should be called in the prepare or hw_params callback
3367 * with the proper parameters for set up.
3368 * ops.cleanup should be called in hw_free for clean up of streams.
3369 *
3370 * This function returns 0 if successfull, or a negative error code.
3371 */
Takashi Iwai529bd6c2008-11-27 14:17:01 +01003372int __devinit snd_hda_build_pcms(struct hda_bus *bus)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003373{
Takashi Iwai0ba21762007-04-16 11:29:14 +02003374 struct hda_codec *codec;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003375
Takashi Iwai0ba21762007-04-16 11:29:14 +02003376 list_for_each_entry(codec, &bus->codec_list, list) {
Takashi Iwai529bd6c2008-11-27 14:17:01 +01003377 int err = snd_hda_codec_build_pcms(codec);
3378 if (err < 0)
3379 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003380 }
3381 return 0;
3382}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003383EXPORT_SYMBOL_HDA(snd_hda_build_pcms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003384
Linus Torvalds1da177e2005-04-16 15:20:36 -07003385/**
3386 * snd_hda_check_board_config - compare the current codec with the config table
3387 * @codec: the HDA codec
Takashi Iwaif5fcc132006-11-24 17:07:44 +01003388 * @num_configs: number of config enums
3389 * @models: array of model name strings
Linus Torvalds1da177e2005-04-16 15:20:36 -07003390 * @tbl: configuration table, terminated by null entries
3391 *
3392 * Compares the modelname or PCI subsystem id of the current codec with the
3393 * given configuration table. If a matching entry is found, returns its
3394 * config value (supposed to be 0 or positive).
3395 *
3396 * If no entries are matching, the function returns a negative value.
3397 */
Takashi Iwai12f288b2007-08-02 15:51:59 +02003398int snd_hda_check_board_config(struct hda_codec *codec,
3399 int num_configs, const char **models,
3400 const struct snd_pci_quirk *tbl)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003401{
Takashi Iwaif44ac832008-07-30 15:01:45 +02003402 if (codec->modelname && models) {
Takashi Iwaif5fcc132006-11-24 17:07:44 +01003403 int i;
3404 for (i = 0; i < num_configs; i++) {
3405 if (models[i] &&
Takashi Iwaif44ac832008-07-30 15:01:45 +02003406 !strcmp(codec->modelname, models[i])) {
Takashi Iwaif5fcc132006-11-24 17:07:44 +01003407 snd_printd(KERN_INFO "hda_codec: model '%s' is "
3408 "selected\n", models[i]);
3409 return i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003410 }
3411 }
3412 }
3413
Takashi Iwaif5fcc132006-11-24 17:07:44 +01003414 if (!codec->bus->pci || !tbl)
3415 return -1;
3416
3417 tbl = snd_pci_quirk_lookup(codec->bus->pci, tbl);
3418 if (!tbl)
3419 return -1;
3420 if (tbl->value >= 0 && tbl->value < num_configs) {
Takashi Iwai62cf8722008-05-20 12:15:15 +02003421#ifdef CONFIG_SND_DEBUG_VERBOSE
Takashi Iwaif5fcc132006-11-24 17:07:44 +01003422 char tmp[10];
3423 const char *model = NULL;
3424 if (models)
3425 model = models[tbl->value];
3426 if (!model) {
3427 sprintf(tmp, "#%d", tbl->value);
3428 model = tmp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003429 }
Takashi Iwaif5fcc132006-11-24 17:07:44 +01003430 snd_printdd(KERN_INFO "hda_codec: model '%s' is selected "
3431 "for config %x:%x (%s)\n",
3432 model, tbl->subvendor, tbl->subdevice,
3433 (tbl->name ? tbl->name : "Unknown device"));
3434#endif
3435 return tbl->value;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003436 }
3437 return -1;
3438}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003439EXPORT_SYMBOL_HDA(snd_hda_check_board_config);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003440
3441/**
Mauro Carvalho Chehab2eda3442008-08-11 10:18:39 +02003442 * snd_hda_check_board_codec_sid_config - compare the current codec
3443 subsystem ID with the
3444 config table
3445
3446 This is important for Gateway notebooks with SB450 HDA Audio
3447 where the vendor ID of the PCI device is:
3448 ATI Technologies Inc SB450 HDA Audio [1002:437b]
3449 and the vendor/subvendor are found only at the codec.
3450
3451 * @codec: the HDA codec
3452 * @num_configs: number of config enums
3453 * @models: array of model name strings
3454 * @tbl: configuration table, terminated by null entries
3455 *
3456 * Compares the modelname or PCI subsystem id of the current codec with the
3457 * given configuration table. If a matching entry is found, returns its
3458 * config value (supposed to be 0 or positive).
3459 *
3460 * If no entries are matching, the function returns a negative value.
3461 */
3462int snd_hda_check_board_codec_sid_config(struct hda_codec *codec,
3463 int num_configs, const char **models,
3464 const struct snd_pci_quirk *tbl)
3465{
3466 const struct snd_pci_quirk *q;
3467
3468 /* Search for codec ID */
3469 for (q = tbl; q->subvendor; q++) {
3470 unsigned long vendorid = (q->subdevice) | (q->subvendor << 16);
3471
3472 if (vendorid == codec->subsystem_id)
3473 break;
3474 }
3475
3476 if (!q->subvendor)
3477 return -1;
3478
3479 tbl = q;
3480
3481 if (tbl->value >= 0 && tbl->value < num_configs) {
Takashi Iwaid94ff6b2009-09-02 00:20:21 +02003482#ifdef CONFIG_SND_DEBUG_VERBOSE
Mauro Carvalho Chehab2eda3442008-08-11 10:18:39 +02003483 char tmp[10];
3484 const char *model = NULL;
3485 if (models)
3486 model = models[tbl->value];
3487 if (!model) {
3488 sprintf(tmp, "#%d", tbl->value);
3489 model = tmp;
3490 }
3491 snd_printdd(KERN_INFO "hda_codec: model '%s' is selected "
3492 "for config %x:%x (%s)\n",
3493 model, tbl->subvendor, tbl->subdevice,
3494 (tbl->name ? tbl->name : "Unknown device"));
3495#endif
3496 return tbl->value;
3497 }
3498 return -1;
3499}
3500EXPORT_SYMBOL_HDA(snd_hda_check_board_codec_sid_config);
3501
3502/**
Linus Torvalds1da177e2005-04-16 15:20:36 -07003503 * snd_hda_add_new_ctls - create controls from the array
3504 * @codec: the HDA codec
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01003505 * @knew: the array of struct snd_kcontrol_new
Linus Torvalds1da177e2005-04-16 15:20:36 -07003506 *
3507 * This helper function creates and add new controls in the given array.
3508 * The array must be terminated with an empty entry as terminator.
3509 *
3510 * Returns 0 if successful, or a negative error code.
3511 */
Takashi Iwai12f288b2007-08-02 15:51:59 +02003512int snd_hda_add_new_ctls(struct hda_codec *codec, struct snd_kcontrol_new *knew)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003513{
Jaroslav Kysela4d02d1b2009-11-12 10:15:48 +01003514 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003515
3516 for (; knew->name; knew++) {
Takashi Iwai54d17402005-11-21 16:33:22 +01003517 struct snd_kcontrol *kctl;
Jaroslav Kysela5b0cb1d2009-12-08 16:13:32 +01003518 if (knew->iface == -1) /* skip this codec private value */
3519 continue;
Takashi Iwai54d17402005-11-21 16:33:22 +01003520 kctl = snd_ctl_new1(knew, codec);
Takashi Iwai0ba21762007-04-16 11:29:14 +02003521 if (!kctl)
Takashi Iwai54d17402005-11-21 16:33:22 +01003522 return -ENOMEM;
Jaroslav Kysela3911a4c2009-11-11 13:43:01 +01003523 err = snd_hda_ctl_add(codec, 0, kctl);
Takashi Iwai54d17402005-11-21 16:33:22 +01003524 if (err < 0) {
Takashi Iwai0ba21762007-04-16 11:29:14 +02003525 if (!codec->addr)
Takashi Iwai54d17402005-11-21 16:33:22 +01003526 return err;
3527 kctl = snd_ctl_new1(knew, codec);
Takashi Iwai0ba21762007-04-16 11:29:14 +02003528 if (!kctl)
Takashi Iwai54d17402005-11-21 16:33:22 +01003529 return -ENOMEM;
3530 kctl->id.device = codec->addr;
Jaroslav Kysela3911a4c2009-11-11 13:43:01 +01003531 err = snd_hda_ctl_add(codec, 0, kctl);
Takashi Iwai0ba21762007-04-16 11:29:14 +02003532 if (err < 0)
Takashi Iwai54d17402005-11-21 16:33:22 +01003533 return err;
3534 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003535 }
3536 return 0;
3537}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003538EXPORT_SYMBOL_HDA(snd_hda_add_new_ctls);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003539
Jaroslav Kysela5b0cb1d2009-12-08 16:13:32 +01003540/**
3541 * snd_hda_add_nids - assign nids to controls from the array
3542 * @codec: the HDA codec
3543 * @kctl: struct snd_kcontrol
3544 * @index: index to kctl
3545 * @nids: the array of hda_nid_t
3546 * @size: count of hda_nid_t items
3547 *
3548 * This helper function assigns NIDs in the given array to a control element.
3549 *
3550 * Returns 0 if successful, or a negative error code.
3551 */
3552int snd_hda_add_nids(struct hda_codec *codec, struct snd_kcontrol *kctl,
3553 unsigned int index, hda_nid_t *nids, unsigned int size)
3554{
3555 int err;
3556
3557 for ( ; size > 0; size--, nids++) {
3558 err = snd_hda_add_nid(codec, kctl, index, *nids);
3559 if (err < 0)
3560 return err;
3561 }
3562 return 0;
3563}
3564EXPORT_SYMBOL_HDA(snd_hda_add_nids);
3565
Takashi Iwaicb53c622007-08-10 17:21:45 +02003566#ifdef CONFIG_SND_HDA_POWER_SAVE
3567static void hda_set_power_state(struct hda_codec *codec, hda_nid_t fg,
3568 unsigned int power_state);
3569
3570static void hda_power_work(struct work_struct *work)
3571{
3572 struct hda_codec *codec =
3573 container_of(work, struct hda_codec, power_work.work);
Takashi Iwai33fa35e2008-11-06 16:50:40 +01003574 struct hda_bus *bus = codec->bus;
Takashi Iwaicb53c622007-08-10 17:21:45 +02003575
Maxim Levitsky2e492462007-09-03 15:26:57 +02003576 if (!codec->power_on || codec->power_count) {
3577 codec->power_transition = 0;
Takashi Iwaicb53c622007-08-10 17:21:45 +02003578 return;
Maxim Levitsky2e492462007-09-03 15:26:57 +02003579 }
Takashi Iwaicb53c622007-08-10 17:21:45 +02003580
3581 hda_call_codec_suspend(codec);
Takashi Iwai33fa35e2008-11-06 16:50:40 +01003582 if (bus->ops.pm_notify)
3583 bus->ops.pm_notify(bus);
Takashi Iwaicb53c622007-08-10 17:21:45 +02003584}
3585
3586static void hda_keep_power_on(struct hda_codec *codec)
3587{
3588 codec->power_count++;
3589 codec->power_on = 1;
Takashi Iwaia2f63092009-11-11 09:34:25 +01003590 codec->power_jiffies = jiffies;
3591}
3592
Takashi Iwaid5191e52009-11-16 14:58:17 +01003593/* update the power on/off account with the current jiffies */
Takashi Iwaia2f63092009-11-11 09:34:25 +01003594void snd_hda_update_power_acct(struct hda_codec *codec)
3595{
3596 unsigned long delta = jiffies - codec->power_jiffies;
3597 if (codec->power_on)
3598 codec->power_on_acct += delta;
3599 else
3600 codec->power_off_acct += delta;
3601 codec->power_jiffies += delta;
Takashi Iwaicb53c622007-08-10 17:21:45 +02003602}
3603
Takashi Iwaid5191e52009-11-16 14:58:17 +01003604/**
3605 * snd_hda_power_up - Power-up the codec
3606 * @codec: HD-audio codec
3607 *
3608 * Increment the power-up counter and power up the hardware really when
3609 * not turned on yet.
3610 */
Takashi Iwaicb53c622007-08-10 17:21:45 +02003611void snd_hda_power_up(struct hda_codec *codec)
3612{
Takashi Iwai33fa35e2008-11-06 16:50:40 +01003613 struct hda_bus *bus = codec->bus;
3614
Takashi Iwaicb53c622007-08-10 17:21:45 +02003615 codec->power_count++;
Takashi Iwaia221e282007-08-16 16:35:33 +02003616 if (codec->power_on || codec->power_transition)
Takashi Iwaicb53c622007-08-10 17:21:45 +02003617 return;
3618
Takashi Iwaia2f63092009-11-11 09:34:25 +01003619 snd_hda_update_power_acct(codec);
Takashi Iwaicb53c622007-08-10 17:21:45 +02003620 codec->power_on = 1;
Takashi Iwaia2f63092009-11-11 09:34:25 +01003621 codec->power_jiffies = jiffies;
Takashi Iwai33fa35e2008-11-06 16:50:40 +01003622 if (bus->ops.pm_notify)
3623 bus->ops.pm_notify(bus);
Takashi Iwaicb53c622007-08-10 17:21:45 +02003624 hda_call_codec_resume(codec);
3625 cancel_delayed_work(&codec->power_work);
Takashi Iwaia221e282007-08-16 16:35:33 +02003626 codec->power_transition = 0;
Takashi Iwaicb53c622007-08-10 17:21:45 +02003627}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003628EXPORT_SYMBOL_HDA(snd_hda_power_up);
Takashi Iwai1289e9e2008-11-27 15:47:11 +01003629
3630#define power_save(codec) \
3631 ((codec)->bus->power_save ? *(codec)->bus->power_save : 0)
Takashi Iwaicb53c622007-08-10 17:21:45 +02003632
Takashi Iwaid5191e52009-11-16 14:58:17 +01003633/**
3634 * snd_hda_power_down - Power-down the codec
3635 * @codec: HD-audio codec
3636 *
3637 * Decrement the power-up counter and schedules the power-off work if
3638 * the counter rearches to zero.
3639 */
Takashi Iwaicb53c622007-08-10 17:21:45 +02003640void snd_hda_power_down(struct hda_codec *codec)
3641{
3642 --codec->power_count;
Takashi Iwaia221e282007-08-16 16:35:33 +02003643 if (!codec->power_on || codec->power_count || codec->power_transition)
Takashi Iwaicb53c622007-08-10 17:21:45 +02003644 return;
Takashi Iwaifee2fba2008-11-27 12:43:28 +01003645 if (power_save(codec)) {
Takashi Iwaia221e282007-08-16 16:35:33 +02003646 codec->power_transition = 1; /* avoid reentrance */
Takashi Iwaic107b412009-01-13 17:46:37 +01003647 queue_delayed_work(codec->bus->workq, &codec->power_work,
Takashi Iwaifee2fba2008-11-27 12:43:28 +01003648 msecs_to_jiffies(power_save(codec) * 1000));
Takashi Iwaia221e282007-08-16 16:35:33 +02003649 }
Takashi Iwaicb53c622007-08-10 17:21:45 +02003650}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003651EXPORT_SYMBOL_HDA(snd_hda_power_down);
Takashi Iwaicb53c622007-08-10 17:21:45 +02003652
Takashi Iwaid5191e52009-11-16 14:58:17 +01003653/**
3654 * snd_hda_check_amp_list_power - Check the amp list and update the power
3655 * @codec: HD-audio codec
3656 * @check: the object containing an AMP list and the status
3657 * @nid: NID to check / update
3658 *
3659 * Check whether the given NID is in the amp list. If it's in the list,
3660 * check the current AMP status, and update the the power-status according
3661 * to the mute status.
3662 *
3663 * This function is supposed to be set or called from the check_power_status
3664 * patch ops.
3665 */
Takashi Iwaicb53c622007-08-10 17:21:45 +02003666int snd_hda_check_amp_list_power(struct hda_codec *codec,
3667 struct hda_loopback_check *check,
3668 hda_nid_t nid)
3669{
3670 struct hda_amp_list *p;
3671 int ch, v;
3672
3673 if (!check->amplist)
3674 return 0;
3675 for (p = check->amplist; p->nid; p++) {
3676 if (p->nid == nid)
3677 break;
3678 }
3679 if (!p->nid)
3680 return 0; /* nothing changed */
3681
3682 for (p = check->amplist; p->nid; p++) {
3683 for (ch = 0; ch < 2; ch++) {
3684 v = snd_hda_codec_amp_read(codec, p->nid, ch, p->dir,
3685 p->idx);
3686 if (!(v & HDA_AMP_MUTE) && v > 0) {
3687 if (!check->power_on) {
3688 check->power_on = 1;
3689 snd_hda_power_up(codec);
3690 }
3691 return 1;
3692 }
3693 }
3694 }
3695 if (check->power_on) {
3696 check->power_on = 0;
3697 snd_hda_power_down(codec);
3698 }
3699 return 0;
3700}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003701EXPORT_SYMBOL_HDA(snd_hda_check_amp_list_power);
Takashi Iwaicb53c622007-08-10 17:21:45 +02003702#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07003703
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01003704/*
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01003705 * Channel mode helper
3706 */
Takashi Iwaid5191e52009-11-16 14:58:17 +01003707
3708/**
3709 * snd_hda_ch_mode_info - Info callback helper for the channel mode enum
3710 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003711int snd_hda_ch_mode_info(struct hda_codec *codec,
3712 struct snd_ctl_elem_info *uinfo,
3713 const struct hda_channel_mode *chmode,
3714 int num_chmodes)
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01003715{
3716 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
3717 uinfo->count = 1;
3718 uinfo->value.enumerated.items = num_chmodes;
3719 if (uinfo->value.enumerated.item >= num_chmodes)
3720 uinfo->value.enumerated.item = num_chmodes - 1;
3721 sprintf(uinfo->value.enumerated.name, "%dch",
3722 chmode[uinfo->value.enumerated.item].channels);
3723 return 0;
3724}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003725EXPORT_SYMBOL_HDA(snd_hda_ch_mode_info);
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01003726
Takashi Iwaid5191e52009-11-16 14:58:17 +01003727/**
3728 * snd_hda_ch_mode_get - Get callback helper for the channel mode enum
3729 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003730int snd_hda_ch_mode_get(struct hda_codec *codec,
3731 struct snd_ctl_elem_value *ucontrol,
3732 const struct hda_channel_mode *chmode,
3733 int num_chmodes,
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01003734 int max_channels)
3735{
3736 int i;
3737
3738 for (i = 0; i < num_chmodes; i++) {
3739 if (max_channels == chmode[i].channels) {
3740 ucontrol->value.enumerated.item[0] = i;
3741 break;
3742 }
3743 }
3744 return 0;
3745}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003746EXPORT_SYMBOL_HDA(snd_hda_ch_mode_get);
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01003747
Takashi Iwaid5191e52009-11-16 14:58:17 +01003748/**
3749 * snd_hda_ch_mode_put - Put callback helper for the channel mode enum
3750 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003751int snd_hda_ch_mode_put(struct hda_codec *codec,
3752 struct snd_ctl_elem_value *ucontrol,
3753 const struct hda_channel_mode *chmode,
3754 int num_chmodes,
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01003755 int *max_channelsp)
3756{
3757 unsigned int mode;
3758
3759 mode = ucontrol->value.enumerated.item[0];
Takashi Iwai68ea7b22007-11-15 15:54:38 +01003760 if (mode >= num_chmodes)
3761 return -EINVAL;
Takashi Iwai82beb8f2007-08-10 17:09:26 +02003762 if (*max_channelsp == chmode[mode].channels)
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01003763 return 0;
3764 /* change the current channel setting */
3765 *max_channelsp = chmode[mode].channels;
3766 if (chmode[mode].sequence)
Takashi Iwai82beb8f2007-08-10 17:09:26 +02003767 snd_hda_sequence_write_cache(codec, chmode[mode].sequence);
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01003768 return 1;
3769}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003770EXPORT_SYMBOL_HDA(snd_hda_ch_mode_put);
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01003771
Linus Torvalds1da177e2005-04-16 15:20:36 -07003772/*
3773 * input MUX helper
3774 */
Takashi Iwaid5191e52009-11-16 14:58:17 +01003775
3776/**
3777 * snd_hda_input_mux_info_info - Info callback helper for the input-mux enum
3778 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003779int snd_hda_input_mux_info(const struct hda_input_mux *imux,
3780 struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003781{
3782 unsigned int index;
3783
3784 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
3785 uinfo->count = 1;
3786 uinfo->value.enumerated.items = imux->num_items;
Takashi Iwai5513b0c2007-10-09 11:58:41 +02003787 if (!imux->num_items)
3788 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003789 index = uinfo->value.enumerated.item;
3790 if (index >= imux->num_items)
3791 index = imux->num_items - 1;
3792 strcpy(uinfo->value.enumerated.name, imux->items[index].label);
3793 return 0;
3794}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003795EXPORT_SYMBOL_HDA(snd_hda_input_mux_info);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003796
Takashi Iwaid5191e52009-11-16 14:58:17 +01003797/**
3798 * snd_hda_input_mux_info_put - Put callback helper for the input-mux enum
3799 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003800int snd_hda_input_mux_put(struct hda_codec *codec,
3801 const struct hda_input_mux *imux,
3802 struct snd_ctl_elem_value *ucontrol,
3803 hda_nid_t nid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003804 unsigned int *cur_val)
3805{
3806 unsigned int idx;
3807
Takashi Iwai5513b0c2007-10-09 11:58:41 +02003808 if (!imux->num_items)
3809 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003810 idx = ucontrol->value.enumerated.item[0];
3811 if (idx >= imux->num_items)
3812 idx = imux->num_items - 1;
Takashi Iwai82beb8f2007-08-10 17:09:26 +02003813 if (*cur_val == idx)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003814 return 0;
Takashi Iwai82beb8f2007-08-10 17:09:26 +02003815 snd_hda_codec_write_cache(codec, nid, 0, AC_VERB_SET_CONNECT_SEL,
3816 imux->items[idx].index);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003817 *cur_val = idx;
3818 return 1;
3819}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003820EXPORT_SYMBOL_HDA(snd_hda_input_mux_put);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003821
3822
3823/*
3824 * Multi-channel / digital-out PCM helper functions
3825 */
3826
Takashi Iwai6b97eb42007-04-05 14:51:48 +02003827/* setup SPDIF output stream */
3828static void setup_dig_out_stream(struct hda_codec *codec, hda_nid_t nid,
3829 unsigned int stream_tag, unsigned int format)
3830{
3831 /* turn off SPDIF once; otherwise the IEC958 bits won't be updated */
Takashi Iwai2f728532008-09-25 16:32:41 +02003832 if (codec->spdif_status_reset && (codec->spdif_ctls & AC_DIG1_ENABLE))
3833 set_dig_out_convert(codec, nid,
3834 codec->spdif_ctls & ~AC_DIG1_ENABLE & 0xff,
3835 -1);
Takashi Iwai6b97eb42007-04-05 14:51:48 +02003836 snd_hda_codec_setup_stream(codec, nid, stream_tag, 0, format);
Takashi Iwai2f728532008-09-25 16:32:41 +02003837 if (codec->slave_dig_outs) {
3838 hda_nid_t *d;
3839 for (d = codec->slave_dig_outs; *d; d++)
3840 snd_hda_codec_setup_stream(codec, *d, stream_tag, 0,
3841 format);
Matthew Ranostayde51ca12008-09-07 14:31:40 -04003842 }
Takashi Iwai2f728532008-09-25 16:32:41 +02003843 /* turn on again (if needed) */
3844 if (codec->spdif_status_reset && (codec->spdif_ctls & AC_DIG1_ENABLE))
3845 set_dig_out_convert(codec, nid,
3846 codec->spdif_ctls & 0xff, -1);
3847}
Matthew Ranostayde51ca12008-09-07 14:31:40 -04003848
Takashi Iwai2f728532008-09-25 16:32:41 +02003849static void cleanup_dig_out_stream(struct hda_codec *codec, hda_nid_t nid)
3850{
3851 snd_hda_codec_cleanup_stream(codec, nid);
3852 if (codec->slave_dig_outs) {
3853 hda_nid_t *d;
3854 for (d = codec->slave_dig_outs; *d; d++)
3855 snd_hda_codec_cleanup_stream(codec, *d);
3856 }
Takashi Iwai6b97eb42007-04-05 14:51:48 +02003857}
3858
Takashi Iwaid5191e52009-11-16 14:58:17 +01003859/**
3860 * snd_hda_bus_reboot_notify - call the reboot notifier of each codec
3861 * @bus: HD-audio bus
3862 */
Takashi Iwaifb8d1a32009-11-10 16:02:29 +01003863void snd_hda_bus_reboot_notify(struct hda_bus *bus)
3864{
3865 struct hda_codec *codec;
3866
3867 if (!bus)
3868 return;
3869 list_for_each_entry(codec, &bus->codec_list, list) {
3870#ifdef CONFIG_SND_HDA_POWER_SAVE
3871 if (!codec->power_on)
3872 continue;
3873#endif
3874 if (codec->patch_ops.reboot_notify)
3875 codec->patch_ops.reboot_notify(codec);
3876 }
3877}
Takashi Iwai8f217a22009-11-10 18:26:12 +01003878EXPORT_SYMBOL_HDA(snd_hda_bus_reboot_notify);
Takashi Iwaifb8d1a32009-11-10 16:02:29 +01003879
Takashi Iwaid5191e52009-11-16 14:58:17 +01003880/**
3881 * snd_hda_multi_out_dig_open - open the digital out in the exclusive mode
Linus Torvalds1da177e2005-04-16 15:20:36 -07003882 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003883int snd_hda_multi_out_dig_open(struct hda_codec *codec,
3884 struct hda_multi_out *mout)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003885{
Ingo Molnar62932df2006-01-16 16:34:20 +01003886 mutex_lock(&codec->spdif_mutex);
Takashi Iwai5930ca42007-04-16 11:23:56 +02003887 if (mout->dig_out_used == HDA_DIG_ANALOG_DUP)
3888 /* already opened as analog dup; reset it once */
Takashi Iwai2f728532008-09-25 16:32:41 +02003889 cleanup_dig_out_stream(codec, mout->dig_out_nid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003890 mout->dig_out_used = HDA_DIG_EXCLUSIVE;
Ingo Molnar62932df2006-01-16 16:34:20 +01003891 mutex_unlock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003892 return 0;
3893}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003894EXPORT_SYMBOL_HDA(snd_hda_multi_out_dig_open);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003895
Takashi Iwaid5191e52009-11-16 14:58:17 +01003896/**
3897 * snd_hda_multi_out_dig_prepare - prepare the digital out stream
3898 */
Takashi Iwai6b97eb42007-04-05 14:51:48 +02003899int snd_hda_multi_out_dig_prepare(struct hda_codec *codec,
3900 struct hda_multi_out *mout,
3901 unsigned int stream_tag,
3902 unsigned int format,
3903 struct snd_pcm_substream *substream)
3904{
3905 mutex_lock(&codec->spdif_mutex);
3906 setup_dig_out_stream(codec, mout->dig_out_nid, stream_tag, format);
3907 mutex_unlock(&codec->spdif_mutex);
3908 return 0;
3909}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003910EXPORT_SYMBOL_HDA(snd_hda_multi_out_dig_prepare);
Takashi Iwai6b97eb42007-04-05 14:51:48 +02003911
Takashi Iwaid5191e52009-11-16 14:58:17 +01003912/**
3913 * snd_hda_multi_out_dig_cleanup - clean-up the digital out stream
3914 */
Takashi Iwai9411e212009-02-13 11:32:28 +01003915int snd_hda_multi_out_dig_cleanup(struct hda_codec *codec,
3916 struct hda_multi_out *mout)
3917{
3918 mutex_lock(&codec->spdif_mutex);
3919 cleanup_dig_out_stream(codec, mout->dig_out_nid);
3920 mutex_unlock(&codec->spdif_mutex);
3921 return 0;
3922}
3923EXPORT_SYMBOL_HDA(snd_hda_multi_out_dig_cleanup);
3924
Takashi Iwaid5191e52009-11-16 14:58:17 +01003925/**
3926 * snd_hda_multi_out_dig_close - release the digital out stream
Linus Torvalds1da177e2005-04-16 15:20:36 -07003927 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003928int snd_hda_multi_out_dig_close(struct hda_codec *codec,
3929 struct hda_multi_out *mout)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003930{
Ingo Molnar62932df2006-01-16 16:34:20 +01003931 mutex_lock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003932 mout->dig_out_used = 0;
Ingo Molnar62932df2006-01-16 16:34:20 +01003933 mutex_unlock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003934 return 0;
3935}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003936EXPORT_SYMBOL_HDA(snd_hda_multi_out_dig_close);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003937
Takashi Iwaid5191e52009-11-16 14:58:17 +01003938/**
3939 * snd_hda_multi_out_analog_open - open analog outputs
3940 *
3941 * Open analog outputs and set up the hw-constraints.
3942 * If the digital outputs can be opened as slave, open the digital
3943 * outputs, too.
Linus Torvalds1da177e2005-04-16 15:20:36 -07003944 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003945int snd_hda_multi_out_analog_open(struct hda_codec *codec,
3946 struct hda_multi_out *mout,
Takashi Iwai9a081602008-02-12 18:37:26 +01003947 struct snd_pcm_substream *substream,
3948 struct hda_pcm_stream *hinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003949{
Takashi Iwai9a081602008-02-12 18:37:26 +01003950 struct snd_pcm_runtime *runtime = substream->runtime;
3951 runtime->hw.channels_max = mout->max_channels;
3952 if (mout->dig_out_nid) {
3953 if (!mout->analog_rates) {
3954 mout->analog_rates = hinfo->rates;
3955 mout->analog_formats = hinfo->formats;
3956 mout->analog_maxbps = hinfo->maxbps;
3957 } else {
3958 runtime->hw.rates = mout->analog_rates;
3959 runtime->hw.formats = mout->analog_formats;
3960 hinfo->maxbps = mout->analog_maxbps;
3961 }
3962 if (!mout->spdif_rates) {
3963 snd_hda_query_supported_pcm(codec, mout->dig_out_nid,
3964 &mout->spdif_rates,
3965 &mout->spdif_formats,
3966 &mout->spdif_maxbps);
3967 }
3968 mutex_lock(&codec->spdif_mutex);
3969 if (mout->share_spdif) {
Takashi Iwai022b4662009-07-03 23:03:30 +02003970 if ((runtime->hw.rates & mout->spdif_rates) &&
3971 (runtime->hw.formats & mout->spdif_formats)) {
3972 runtime->hw.rates &= mout->spdif_rates;
3973 runtime->hw.formats &= mout->spdif_formats;
3974 if (mout->spdif_maxbps < hinfo->maxbps)
3975 hinfo->maxbps = mout->spdif_maxbps;
3976 } else {
3977 mout->share_spdif = 0;
3978 /* FIXME: need notify? */
3979 }
Takashi Iwai9a081602008-02-12 18:37:26 +01003980 }
Frederik Deweerdteaa99852008-04-14 13:11:44 +02003981 mutex_unlock(&codec->spdif_mutex);
Takashi Iwai9a081602008-02-12 18:37:26 +01003982 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003983 return snd_pcm_hw_constraint_step(substream->runtime, 0,
3984 SNDRV_PCM_HW_PARAM_CHANNELS, 2);
3985}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003986EXPORT_SYMBOL_HDA(snd_hda_multi_out_analog_open);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003987
Takashi Iwaid5191e52009-11-16 14:58:17 +01003988/**
3989 * snd_hda_multi_out_analog_prepare - Preapre the analog outputs.
3990 *
3991 * Set up the i/o for analog out.
3992 * When the digital out is available, copy the front out to digital out, too.
Linus Torvalds1da177e2005-04-16 15:20:36 -07003993 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003994int snd_hda_multi_out_analog_prepare(struct hda_codec *codec,
3995 struct hda_multi_out *mout,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003996 unsigned int stream_tag,
3997 unsigned int format,
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01003998 struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003999{
4000 hda_nid_t *nids = mout->dac_nids;
4001 int chs = substream->runtime->channels;
4002 int i;
4003
Ingo Molnar62932df2006-01-16 16:34:20 +01004004 mutex_lock(&codec->spdif_mutex);
Takashi Iwai9a081602008-02-12 18:37:26 +01004005 if (mout->dig_out_nid && mout->share_spdif &&
4006 mout->dig_out_used != HDA_DIG_EXCLUSIVE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004007 if (chs == 2 &&
Takashi Iwai0ba21762007-04-16 11:29:14 +02004008 snd_hda_is_supported_format(codec, mout->dig_out_nid,
4009 format) &&
4010 !(codec->spdif_status & IEC958_AES0_NONAUDIO)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004011 mout->dig_out_used = HDA_DIG_ANALOG_DUP;
Takashi Iwai6b97eb42007-04-05 14:51:48 +02004012 setup_dig_out_stream(codec, mout->dig_out_nid,
4013 stream_tag, format);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004014 } else {
4015 mout->dig_out_used = 0;
Takashi Iwai2f728532008-09-25 16:32:41 +02004016 cleanup_dig_out_stream(codec, mout->dig_out_nid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004017 }
4018 }
Ingo Molnar62932df2006-01-16 16:34:20 +01004019 mutex_unlock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004020
4021 /* front */
Takashi Iwai0ba21762007-04-16 11:29:14 +02004022 snd_hda_codec_setup_stream(codec, nids[HDA_FRONT], stream_tag,
4023 0, format);
Takashi Iwaid29240c2007-10-26 12:35:56 +02004024 if (!mout->no_share_stream &&
4025 mout->hp_nid && mout->hp_nid != nids[HDA_FRONT])
Linus Torvalds1da177e2005-04-16 15:20:36 -07004026 /* headphone out will just decode front left/right (stereo) */
Takashi Iwai0ba21762007-04-16 11:29:14 +02004027 snd_hda_codec_setup_stream(codec, mout->hp_nid, stream_tag,
4028 0, format);
Takashi Iwai82bc9552006-03-21 11:24:42 +01004029 /* extra outputs copied from front */
4030 for (i = 0; i < ARRAY_SIZE(mout->extra_out_nid); i++)
Takashi Iwaid29240c2007-10-26 12:35:56 +02004031 if (!mout->no_share_stream && mout->extra_out_nid[i])
Takashi Iwai82bc9552006-03-21 11:24:42 +01004032 snd_hda_codec_setup_stream(codec,
4033 mout->extra_out_nid[i],
4034 stream_tag, 0, format);
4035
Linus Torvalds1da177e2005-04-16 15:20:36 -07004036 /* surrounds */
4037 for (i = 1; i < mout->num_dacs; i++) {
Takashi Iwai4b3acaf2005-06-10 19:48:10 +02004038 if (chs >= (i + 1) * 2) /* independent out */
Takashi Iwai0ba21762007-04-16 11:29:14 +02004039 snd_hda_codec_setup_stream(codec, nids[i], stream_tag,
4040 i * 2, format);
Takashi Iwaid29240c2007-10-26 12:35:56 +02004041 else if (!mout->no_share_stream) /* copy front */
Takashi Iwai0ba21762007-04-16 11:29:14 +02004042 snd_hda_codec_setup_stream(codec, nids[i], stream_tag,
4043 0, format);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004044 }
4045 return 0;
4046}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01004047EXPORT_SYMBOL_HDA(snd_hda_multi_out_analog_prepare);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004048
Takashi Iwaid5191e52009-11-16 14:58:17 +01004049/**
4050 * snd_hda_multi_out_analog_cleanup - clean up the setting for analog out
Linus Torvalds1da177e2005-04-16 15:20:36 -07004051 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02004052int snd_hda_multi_out_analog_cleanup(struct hda_codec *codec,
4053 struct hda_multi_out *mout)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004054{
4055 hda_nid_t *nids = mout->dac_nids;
4056 int i;
4057
4058 for (i = 0; i < mout->num_dacs; i++)
Takashi Iwai888afa12008-03-18 09:57:50 +01004059 snd_hda_codec_cleanup_stream(codec, nids[i]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004060 if (mout->hp_nid)
Takashi Iwai888afa12008-03-18 09:57:50 +01004061 snd_hda_codec_cleanup_stream(codec, mout->hp_nid);
Takashi Iwai82bc9552006-03-21 11:24:42 +01004062 for (i = 0; i < ARRAY_SIZE(mout->extra_out_nid); i++)
4063 if (mout->extra_out_nid[i])
Takashi Iwai888afa12008-03-18 09:57:50 +01004064 snd_hda_codec_cleanup_stream(codec,
4065 mout->extra_out_nid[i]);
Ingo Molnar62932df2006-01-16 16:34:20 +01004066 mutex_lock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004067 if (mout->dig_out_nid && mout->dig_out_used == HDA_DIG_ANALOG_DUP) {
Takashi Iwai2f728532008-09-25 16:32:41 +02004068 cleanup_dig_out_stream(codec, mout->dig_out_nid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004069 mout->dig_out_used = 0;
4070 }
Ingo Molnar62932df2006-01-16 16:34:20 +01004071 mutex_unlock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004072 return 0;
4073}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01004074EXPORT_SYMBOL_HDA(snd_hda_multi_out_analog_cleanup);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004075
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004076/*
Wu Fengguang6b345002008-10-07 14:21:41 +08004077 * Helper for automatic pin configuration
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004078 */
Kailang Yangdf694da2005-12-05 19:42:22 +01004079
Takashi Iwai12f288b2007-08-02 15:51:59 +02004080static int is_in_nid_list(hda_nid_t nid, hda_nid_t *list)
Kailang Yangdf694da2005-12-05 19:42:22 +01004081{
4082 for (; *list; list++)
4083 if (*list == nid)
4084 return 1;
4085 return 0;
4086}
4087
Steve Longerbeam81937d32007-05-08 15:33:03 +02004088
4089/*
4090 * Sort an associated group of pins according to their sequence numbers.
4091 */
4092static void sort_pins_by_sequence(hda_nid_t * pins, short * sequences,
4093 int num_pins)
4094{
4095 int i, j;
4096 short seq;
4097 hda_nid_t nid;
4098
4099 for (i = 0; i < num_pins; i++) {
4100 for (j = i + 1; j < num_pins; j++) {
4101 if (sequences[i] > sequences[j]) {
4102 seq = sequences[i];
4103 sequences[i] = sequences[j];
4104 sequences[j] = seq;
4105 nid = pins[i];
4106 pins[i] = pins[j];
4107 pins[j] = nid;
4108 }
4109 }
4110 }
4111}
4112
4113
Takashi Iwai82bc9552006-03-21 11:24:42 +01004114/*
4115 * Parse all pin widgets and store the useful pin nids to cfg
4116 *
4117 * The number of line-outs or any primary output is stored in line_outs,
4118 * and the corresponding output pins are assigned to line_out_pins[],
4119 * in the order of front, rear, CLFE, side, ...
4120 *
4121 * If more extra outputs (speaker and headphone) are found, the pins are
Takashi Iwaieb06ed82006-09-20 17:10:27 +02004122 * assisnged to hp_pins[] and speaker_pins[], respectively. If no line-out jack
Takashi Iwai82bc9552006-03-21 11:24:42 +01004123 * is detected, one of speaker of HP pins is assigned as the primary
4124 * output, i.e. to line_out_pins[0]. So, line_outs is always positive
4125 * if any analog output exists.
4126 *
4127 * The analog input pins are assigned to input_pins array.
4128 * The digital input/output pins are assigned to dig_in_pin and dig_out_pin,
4129 * respectively.
4130 */
Takashi Iwai12f288b2007-08-02 15:51:59 +02004131int snd_hda_parse_pin_def_config(struct hda_codec *codec,
4132 struct auto_pin_cfg *cfg,
4133 hda_nid_t *ignore_nids)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004134{
Takashi Iwai0ef6ce72008-01-22 15:35:37 +01004135 hda_nid_t nid, end_nid;
Steve Longerbeam81937d32007-05-08 15:33:03 +02004136 short seq, assoc_line_out, assoc_speaker;
4137 short sequences_line_out[ARRAY_SIZE(cfg->line_out_pins)];
4138 short sequences_speaker[ARRAY_SIZE(cfg->speaker_pins)];
Takashi Iwaif889fa92007-10-31 15:49:32 +01004139 short sequences_hp[ARRAY_SIZE(cfg->hp_pins)];
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004140
4141 memset(cfg, 0, sizeof(*cfg));
4142
Steve Longerbeam81937d32007-05-08 15:33:03 +02004143 memset(sequences_line_out, 0, sizeof(sequences_line_out));
4144 memset(sequences_speaker, 0, sizeof(sequences_speaker));
Takashi Iwaif889fa92007-10-31 15:49:32 +01004145 memset(sequences_hp, 0, sizeof(sequences_hp));
Steve Longerbeam81937d32007-05-08 15:33:03 +02004146 assoc_line_out = assoc_speaker = 0;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004147
Takashi Iwai0ef6ce72008-01-22 15:35:37 +01004148 end_nid = codec->start_nid + codec->num_nodes;
4149 for (nid = codec->start_nid; nid < end_nid; nid++) {
Takashi Iwai54d17402005-11-21 16:33:22 +01004150 unsigned int wid_caps = get_wcaps(codec, nid);
Takashi Iwaia22d5432009-07-27 12:54:26 +02004151 unsigned int wid_type = get_wcaps_type(wid_caps);
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004152 unsigned int def_conf;
4153 short assoc, loc;
4154
4155 /* read all default configuration for pin complex */
4156 if (wid_type != AC_WID_PIN)
4157 continue;
Kailang Yangdf694da2005-12-05 19:42:22 +01004158 /* ignore the given nids (e.g. pc-beep returns error) */
4159 if (ignore_nids && is_in_nid_list(nid, ignore_nids))
4160 continue;
4161
Takashi Iwaic17a1ab2009-02-23 09:28:12 +01004162 def_conf = snd_hda_codec_get_pincfg(codec, nid);
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004163 if (get_defcfg_connect(def_conf) == AC_JACK_PORT_NONE)
4164 continue;
4165 loc = get_defcfg_location(def_conf);
4166 switch (get_defcfg_device(def_conf)) {
4167 case AC_JACK_LINE_OUT:
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004168 seq = get_defcfg_sequence(def_conf);
4169 assoc = get_defcfg_association(def_conf);
Matthew Ranostay90da78b2008-01-24 11:48:01 +01004170
4171 if (!(wid_caps & AC_WCAP_STEREO))
4172 if (!cfg->mono_out_pin)
4173 cfg->mono_out_pin = nid;
Takashi Iwai0ba21762007-04-16 11:29:14 +02004174 if (!assoc)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004175 continue;
Takashi Iwai0ba21762007-04-16 11:29:14 +02004176 if (!assoc_line_out)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004177 assoc_line_out = assoc;
4178 else if (assoc_line_out != assoc)
4179 continue;
4180 if (cfg->line_outs >= ARRAY_SIZE(cfg->line_out_pins))
4181 continue;
4182 cfg->line_out_pins[cfg->line_outs] = nid;
Steve Longerbeam81937d32007-05-08 15:33:03 +02004183 sequences_line_out[cfg->line_outs] = seq;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004184 cfg->line_outs++;
4185 break;
Takashi Iwai8d88bc32005-11-17 11:09:23 +01004186 case AC_JACK_SPEAKER:
Steve Longerbeam81937d32007-05-08 15:33:03 +02004187 seq = get_defcfg_sequence(def_conf);
4188 assoc = get_defcfg_association(def_conf);
4189 if (! assoc)
4190 continue;
4191 if (! assoc_speaker)
4192 assoc_speaker = assoc;
4193 else if (assoc_speaker != assoc)
4194 continue;
Takashi Iwai82bc9552006-03-21 11:24:42 +01004195 if (cfg->speaker_outs >= ARRAY_SIZE(cfg->speaker_pins))
4196 continue;
4197 cfg->speaker_pins[cfg->speaker_outs] = nid;
Steve Longerbeam81937d32007-05-08 15:33:03 +02004198 sequences_speaker[cfg->speaker_outs] = seq;
Takashi Iwai82bc9552006-03-21 11:24:42 +01004199 cfg->speaker_outs++;
Takashi Iwai8d88bc32005-11-17 11:09:23 +01004200 break;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004201 case AC_JACK_HP_OUT:
Takashi Iwaif889fa92007-10-31 15:49:32 +01004202 seq = get_defcfg_sequence(def_conf);
4203 assoc = get_defcfg_association(def_conf);
Takashi Iwaieb06ed82006-09-20 17:10:27 +02004204 if (cfg->hp_outs >= ARRAY_SIZE(cfg->hp_pins))
4205 continue;
4206 cfg->hp_pins[cfg->hp_outs] = nid;
Takashi Iwaif889fa92007-10-31 15:49:32 +01004207 sequences_hp[cfg->hp_outs] = (assoc << 4) | seq;
Takashi Iwaieb06ed82006-09-20 17:10:27 +02004208 cfg->hp_outs++;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004209 break;
Takashi Iwai314634b2006-09-21 11:56:18 +02004210 case AC_JACK_MIC_IN: {
4211 int preferred, alt;
4212 if (loc == AC_JACK_LOC_FRONT) {
4213 preferred = AUTO_PIN_FRONT_MIC;
4214 alt = AUTO_PIN_MIC;
4215 } else {
4216 preferred = AUTO_PIN_MIC;
4217 alt = AUTO_PIN_FRONT_MIC;
4218 }
4219 if (!cfg->input_pins[preferred])
4220 cfg->input_pins[preferred] = nid;
4221 else if (!cfg->input_pins[alt])
4222 cfg->input_pins[alt] = nid;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004223 break;
Takashi Iwai314634b2006-09-21 11:56:18 +02004224 }
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004225 case AC_JACK_LINE_IN:
4226 if (loc == AC_JACK_LOC_FRONT)
4227 cfg->input_pins[AUTO_PIN_FRONT_LINE] = nid;
4228 else
4229 cfg->input_pins[AUTO_PIN_LINE] = nid;
4230 break;
4231 case AC_JACK_CD:
4232 cfg->input_pins[AUTO_PIN_CD] = nid;
4233 break;
4234 case AC_JACK_AUX:
4235 cfg->input_pins[AUTO_PIN_AUX] = nid;
4236 break;
4237 case AC_JACK_SPDIF_OUT:
Takashi Iwai1b52ae72009-01-20 17:17:29 +01004238 case AC_JACK_DIG_OTHER_OUT:
Takashi Iwai0852d7a2009-02-11 11:35:15 +01004239 if (cfg->dig_outs >= ARRAY_SIZE(cfg->dig_out_pins))
4240 continue;
4241 cfg->dig_out_pins[cfg->dig_outs] = nid;
4242 cfg->dig_out_type[cfg->dig_outs] =
4243 (loc == AC_JACK_LOC_HDMI) ?
4244 HDA_PCM_TYPE_HDMI : HDA_PCM_TYPE_SPDIF;
4245 cfg->dig_outs++;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004246 break;
4247 case AC_JACK_SPDIF_IN:
Takashi Iwai1b52ae72009-01-20 17:17:29 +01004248 case AC_JACK_DIG_OTHER_IN:
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004249 cfg->dig_in_pin = nid;
Takashi Iwai2297bd62009-01-20 18:24:13 +01004250 if (loc == AC_JACK_LOC_HDMI)
4251 cfg->dig_in_type = HDA_PCM_TYPE_HDMI;
4252 else
4253 cfg->dig_in_type = HDA_PCM_TYPE_SPDIF;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004254 break;
4255 }
4256 }
4257
Takashi Iwai5832fcf2008-02-12 18:30:12 +01004258 /* FIX-UP:
4259 * If no line-out is defined but multiple HPs are found,
4260 * some of them might be the real line-outs.
4261 */
4262 if (!cfg->line_outs && cfg->hp_outs > 1) {
4263 int i = 0;
4264 while (i < cfg->hp_outs) {
4265 /* The real HPs should have the sequence 0x0f */
4266 if ((sequences_hp[i] & 0x0f) == 0x0f) {
4267 i++;
4268 continue;
4269 }
4270 /* Move it to the line-out table */
4271 cfg->line_out_pins[cfg->line_outs] = cfg->hp_pins[i];
4272 sequences_line_out[cfg->line_outs] = sequences_hp[i];
4273 cfg->line_outs++;
4274 cfg->hp_outs--;
4275 memmove(cfg->hp_pins + i, cfg->hp_pins + i + 1,
4276 sizeof(cfg->hp_pins[0]) * (cfg->hp_outs - i));
4277 memmove(sequences_hp + i - 1, sequences_hp + i,
4278 sizeof(sequences_hp[0]) * (cfg->hp_outs - i));
4279 }
4280 }
4281
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004282 /* sort by sequence */
Steve Longerbeam81937d32007-05-08 15:33:03 +02004283 sort_pins_by_sequence(cfg->line_out_pins, sequences_line_out,
4284 cfg->line_outs);
4285 sort_pins_by_sequence(cfg->speaker_pins, sequences_speaker,
4286 cfg->speaker_outs);
Takashi Iwaif889fa92007-10-31 15:49:32 +01004287 sort_pins_by_sequence(cfg->hp_pins, sequences_hp,
4288 cfg->hp_outs);
Steve Longerbeam81937d32007-05-08 15:33:03 +02004289
Takashi Iwaif889fa92007-10-31 15:49:32 +01004290 /* if we have only one mic, make it AUTO_PIN_MIC */
4291 if (!cfg->input_pins[AUTO_PIN_MIC] &&
4292 cfg->input_pins[AUTO_PIN_FRONT_MIC]) {
4293 cfg->input_pins[AUTO_PIN_MIC] =
4294 cfg->input_pins[AUTO_PIN_FRONT_MIC];
4295 cfg->input_pins[AUTO_PIN_FRONT_MIC] = 0;
4296 }
4297 /* ditto for line-in */
4298 if (!cfg->input_pins[AUTO_PIN_LINE] &&
4299 cfg->input_pins[AUTO_PIN_FRONT_LINE]) {
4300 cfg->input_pins[AUTO_PIN_LINE] =
4301 cfg->input_pins[AUTO_PIN_FRONT_LINE];
4302 cfg->input_pins[AUTO_PIN_FRONT_LINE] = 0;
4303 }
4304
Steve Longerbeam81937d32007-05-08 15:33:03 +02004305 /*
4306 * FIX-UP: if no line-outs are detected, try to use speaker or HP pin
4307 * as a primary output
4308 */
4309 if (!cfg->line_outs) {
4310 if (cfg->speaker_outs) {
4311 cfg->line_outs = cfg->speaker_outs;
4312 memcpy(cfg->line_out_pins, cfg->speaker_pins,
4313 sizeof(cfg->speaker_pins));
4314 cfg->speaker_outs = 0;
4315 memset(cfg->speaker_pins, 0, sizeof(cfg->speaker_pins));
4316 cfg->line_out_type = AUTO_PIN_SPEAKER_OUT;
4317 } else if (cfg->hp_outs) {
4318 cfg->line_outs = cfg->hp_outs;
4319 memcpy(cfg->line_out_pins, cfg->hp_pins,
4320 sizeof(cfg->hp_pins));
4321 cfg->hp_outs = 0;
4322 memset(cfg->hp_pins, 0, sizeof(cfg->hp_pins));
4323 cfg->line_out_type = AUTO_PIN_HP_OUT;
4324 }
4325 }
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004326
Takashi Iwaicb8e2f82005-07-29 11:54:32 +02004327 /* Reorder the surround channels
4328 * ALSA sequence is front/surr/clfe/side
4329 * HDA sequence is:
4330 * 4-ch: front/surr => OK as it is
4331 * 6-ch: front/clfe/surr
Takashi Iwai9422db42007-04-20 16:11:43 +02004332 * 8-ch: front/clfe/rear/side|fc
Takashi Iwaicb8e2f82005-07-29 11:54:32 +02004333 */
4334 switch (cfg->line_outs) {
4335 case 3:
Takashi Iwaicb8e2f82005-07-29 11:54:32 +02004336 case 4:
4337 nid = cfg->line_out_pins[1];
Takashi Iwai9422db42007-04-20 16:11:43 +02004338 cfg->line_out_pins[1] = cfg->line_out_pins[2];
Takashi Iwaicb8e2f82005-07-29 11:54:32 +02004339 cfg->line_out_pins[2] = nid;
4340 break;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004341 }
4342
Takashi Iwai82bc9552006-03-21 11:24:42 +01004343 /*
4344 * debug prints of the parsed results
4345 */
4346 snd_printd("autoconfig: line_outs=%d (0x%x/0x%x/0x%x/0x%x/0x%x)\n",
4347 cfg->line_outs, cfg->line_out_pins[0], cfg->line_out_pins[1],
4348 cfg->line_out_pins[2], cfg->line_out_pins[3],
4349 cfg->line_out_pins[4]);
4350 snd_printd(" speaker_outs=%d (0x%x/0x%x/0x%x/0x%x/0x%x)\n",
4351 cfg->speaker_outs, cfg->speaker_pins[0],
4352 cfg->speaker_pins[1], cfg->speaker_pins[2],
4353 cfg->speaker_pins[3], cfg->speaker_pins[4]);
Takashi Iwaieb06ed82006-09-20 17:10:27 +02004354 snd_printd(" hp_outs=%d (0x%x/0x%x/0x%x/0x%x/0x%x)\n",
4355 cfg->hp_outs, cfg->hp_pins[0],
4356 cfg->hp_pins[1], cfg->hp_pins[2],
4357 cfg->hp_pins[3], cfg->hp_pins[4]);
Matthew Ranostay90da78b2008-01-24 11:48:01 +01004358 snd_printd(" mono: mono_out=0x%x\n", cfg->mono_out_pin);
Takashi Iwai0852d7a2009-02-11 11:35:15 +01004359 if (cfg->dig_outs)
4360 snd_printd(" dig-out=0x%x/0x%x\n",
4361 cfg->dig_out_pins[0], cfg->dig_out_pins[1]);
Takashi Iwai82bc9552006-03-21 11:24:42 +01004362 snd_printd(" inputs: mic=0x%x, fmic=0x%x, line=0x%x, fline=0x%x,"
4363 " cd=0x%x, aux=0x%x\n",
4364 cfg->input_pins[AUTO_PIN_MIC],
4365 cfg->input_pins[AUTO_PIN_FRONT_MIC],
4366 cfg->input_pins[AUTO_PIN_LINE],
4367 cfg->input_pins[AUTO_PIN_FRONT_LINE],
4368 cfg->input_pins[AUTO_PIN_CD],
4369 cfg->input_pins[AUTO_PIN_AUX]);
Takashi Iwai32d2c7f2009-02-11 11:33:13 +01004370 if (cfg->dig_in_pin)
Takashi Iwai89ce9e82009-01-20 17:15:57 +01004371 snd_printd(" dig-in=0x%x\n", cfg->dig_in_pin);
Takashi Iwai82bc9552006-03-21 11:24:42 +01004372
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004373 return 0;
4374}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01004375EXPORT_SYMBOL_HDA(snd_hda_parse_pin_def_config);
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004376
Takashi Iwai4a471b72005-12-07 13:56:29 +01004377/* labels for input pins */
4378const char *auto_pin_cfg_labels[AUTO_PIN_LAST] = {
4379 "Mic", "Front Mic", "Line", "Front Line", "CD", "Aux"
4380};
Takashi Iwaiff7a3262008-11-28 15:17:06 +01004381EXPORT_SYMBOL_HDA(auto_pin_cfg_labels);
Takashi Iwai4a471b72005-12-07 13:56:29 +01004382
4383
Linus Torvalds1da177e2005-04-16 15:20:36 -07004384#ifdef CONFIG_PM
4385/*
4386 * power management
4387 */
4388
4389/**
4390 * snd_hda_suspend - suspend the codecs
4391 * @bus: the HDA bus
Linus Torvalds1da177e2005-04-16 15:20:36 -07004392 *
4393 * Returns 0 if successful.
4394 */
Takashi Iwai8dd78332009-06-02 01:16:07 +02004395int snd_hda_suspend(struct hda_bus *bus)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004396{
Takashi Iwai0ba21762007-04-16 11:29:14 +02004397 struct hda_codec *codec;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004398
Takashi Iwai0ba21762007-04-16 11:29:14 +02004399 list_for_each_entry(codec, &bus->codec_list, list) {
Takashi Iwai0b7a2e92007-08-14 15:18:26 +02004400#ifdef CONFIG_SND_HDA_POWER_SAVE
4401 if (!codec->power_on)
4402 continue;
4403#endif
Takashi Iwaicb53c622007-08-10 17:21:45 +02004404 hda_call_codec_suspend(codec);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004405 }
4406 return 0;
4407}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01004408EXPORT_SYMBOL_HDA(snd_hda_suspend);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004409
4410/**
4411 * snd_hda_resume - resume the codecs
4412 * @bus: the HDA bus
Linus Torvalds1da177e2005-04-16 15:20:36 -07004413 *
4414 * Returns 0 if successful.
Takashi Iwaicb53c622007-08-10 17:21:45 +02004415 *
4416 * This fucntion is defined only when POWER_SAVE isn't set.
4417 * In the power-save mode, the codec is resumed dynamically.
Linus Torvalds1da177e2005-04-16 15:20:36 -07004418 */
4419int snd_hda_resume(struct hda_bus *bus)
4420{
Takashi Iwai0ba21762007-04-16 11:29:14 +02004421 struct hda_codec *codec;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004422
Takashi Iwai0ba21762007-04-16 11:29:14 +02004423 list_for_each_entry(codec, &bus->codec_list, list) {
Maxim Levitskyd804ad92007-09-03 15:28:04 +02004424 if (snd_hda_codec_needs_resume(codec))
4425 hda_call_codec_resume(codec);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004426 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004427 return 0;
4428}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01004429EXPORT_SYMBOL_HDA(snd_hda_resume);
Takashi Iwai1289e9e2008-11-27 15:47:11 +01004430#endif /* CONFIG_PM */
Takashi Iwaib2e18592008-07-30 15:01:44 +02004431
4432/*
4433 * generic arrays
4434 */
4435
Takashi Iwaid5191e52009-11-16 14:58:17 +01004436/**
4437 * snd_array_new - get a new element from the given array
4438 * @array: the array object
4439 *
4440 * Get a new element from the given array. If it exceeds the
4441 * pre-allocated array size, re-allocate the array.
4442 *
4443 * Returns NULL if allocation failed.
Takashi Iwaib2e18592008-07-30 15:01:44 +02004444 */
4445void *snd_array_new(struct snd_array *array)
4446{
4447 if (array->used >= array->alloced) {
4448 int num = array->alloced + array->alloc_align;
Takashi Iwaib910d9a2008-11-07 00:26:52 +01004449 void *nlist;
4450 if (snd_BUG_ON(num >= 4096))
4451 return NULL;
4452 nlist = kcalloc(num + 1, array->elem_size, GFP_KERNEL);
Takashi Iwaib2e18592008-07-30 15:01:44 +02004453 if (!nlist)
4454 return NULL;
4455 if (array->list) {
4456 memcpy(nlist, array->list,
4457 array->elem_size * array->alloced);
4458 kfree(array->list);
4459 }
4460 array->list = nlist;
4461 array->alloced = num;
4462 }
Takashi Iwaif43aa022008-11-10 16:24:26 +01004463 return snd_array_elem(array, array->used++);
Takashi Iwaib2e18592008-07-30 15:01:44 +02004464}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01004465EXPORT_SYMBOL_HDA(snd_array_new);
Takashi Iwaib2e18592008-07-30 15:01:44 +02004466
Takashi Iwaid5191e52009-11-16 14:58:17 +01004467/**
4468 * snd_array_free - free the given array elements
4469 * @array: the array object
4470 */
Takashi Iwaib2e18592008-07-30 15:01:44 +02004471void snd_array_free(struct snd_array *array)
4472{
4473 kfree(array->list);
4474 array->used = 0;
4475 array->alloced = 0;
4476 array->list = NULL;
4477}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01004478EXPORT_SYMBOL_HDA(snd_array_free);
Takashi Iwaib2022262008-11-21 21:24:03 +01004479
Takashi Iwaid5191e52009-11-16 14:58:17 +01004480/**
4481 * snd_print_pcm_rates - Print the supported PCM rates to the string buffer
4482 * @pcm: PCM caps bits
4483 * @buf: the string buffer to write
4484 * @buflen: the max buffer length
4485 *
Takashi Iwaib2022262008-11-21 21:24:03 +01004486 * used by hda_proc.c and hda_eld.c
4487 */
4488void snd_print_pcm_rates(int pcm, char *buf, int buflen)
4489{
4490 static unsigned int rates[] = {
4491 8000, 11025, 16000, 22050, 32000, 44100, 48000, 88200,
4492 96000, 176400, 192000, 384000
4493 };
4494 int i, j;
4495
4496 for (i = 0, j = 0; i < ARRAY_SIZE(rates); i++)
4497 if (pcm & (1 << i))
4498 j += snprintf(buf + j, buflen - j, " %d", rates[i]);
4499
4500 buf[j] = '\0'; /* necessary when j == 0 */
4501}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01004502EXPORT_SYMBOL_HDA(snd_print_pcm_rates);
Takashi Iwaib2022262008-11-21 21:24:03 +01004503
Takashi Iwaid5191e52009-11-16 14:58:17 +01004504/**
4505 * snd_print_pcm_bits - Print the supported PCM fmt bits to the string buffer
4506 * @pcm: PCM caps bits
4507 * @buf: the string buffer to write
4508 * @buflen: the max buffer length
4509 *
4510 * used by hda_proc.c and hda_eld.c
4511 */
Takashi Iwaib2022262008-11-21 21:24:03 +01004512void snd_print_pcm_bits(int pcm, char *buf, int buflen)
4513{
4514 static unsigned int bits[] = { 8, 16, 20, 24, 32 };
4515 int i, j;
4516
4517 for (i = 0, j = 0; i < ARRAY_SIZE(bits); i++)
4518 if (pcm & (AC_SUPPCM_BITS_8 << i))
4519 j += snprintf(buf + j, buflen - j, " %d", bits[i]);
4520
4521 buf[j] = '\0'; /* necessary when j == 0 */
4522}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01004523EXPORT_SYMBOL_HDA(snd_print_pcm_bits);
Takashi Iwai1289e9e2008-11-27 15:47:11 +01004524
4525MODULE_DESCRIPTION("HDA codec core");
4526MODULE_LICENSE("GPL");