blob: 94ae69f209251f304e045dbbbe9f4a7919a01b8e [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 Iwai92ee6162009-12-27 11:18:59 +0100902/**
903 * snd_hda_shutup_pins - Shut up all pins
904 * @codec: the HDA codec
905 *
906 * Clear all pin controls to shup up before suspend for avoiding click noise.
907 * The controls aren't cached so that they can be resumed properly.
908 */
909void snd_hda_shutup_pins(struct hda_codec *codec)
910{
911 int i;
912 for (i = 0; i < codec->init_pins.used; i++) {
913 struct hda_pincfg *pin = snd_array_elem(&codec->init_pins, i);
914 /* use read here for syncing after issuing each verb */
915 snd_hda_codec_read(codec, pin->nid, 0,
916 AC_VERB_SET_PIN_WIDGET_CONTROL, 0);
917 }
918}
919EXPORT_SYMBOL_HDA(snd_hda_shutup_pins);
920
Takashi Iwai01751f52007-08-10 16:59:39 +0200921static void init_hda_cache(struct hda_cache_rec *cache,
922 unsigned int record_size);
Takashi Iwai1fcaee62007-08-23 00:01:09 +0200923static void free_hda_cache(struct hda_cache_rec *cache);
Takashi Iwai01751f52007-08-10 16:59:39 +0200924
Takashi Iwai3be14142009-02-20 14:11:16 +0100925/* restore the initial pin cfgs and release all pincfg lists */
926static void restore_init_pincfgs(struct hda_codec *codec)
927{
Takashi Iwai346ff702009-02-23 09:42:57 +0100928 /* first free driver_pins and user_pins, then call restore_pincfg
Takashi Iwai3be14142009-02-20 14:11:16 +0100929 * so that only the values in init_pins are restored
930 */
Takashi Iwai346ff702009-02-23 09:42:57 +0100931 snd_array_free(&codec->driver_pins);
Takashi Iwai3be14142009-02-20 14:11:16 +0100932#ifdef CONFIG_SND_HDA_HWDEP
Takashi Iwai346ff702009-02-23 09:42:57 +0100933 snd_array_free(&codec->user_pins);
Takashi Iwai3be14142009-02-20 14:11:16 +0100934#endif
935 restore_pincfgs(codec);
936 snd_array_free(&codec->init_pins);
937}
938
Takashi Iwai54d17402005-11-21 16:33:22 +0100939/*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700940 * codec destructor
941 */
942static void snd_hda_codec_free(struct hda_codec *codec)
943{
Takashi Iwai0ba21762007-04-16 11:29:14 +0200944 if (!codec)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700945 return;
Takashi Iwai3be14142009-02-20 14:11:16 +0100946 restore_init_pincfgs(codec);
Takashi Iwaicb53c622007-08-10 17:21:45 +0200947#ifdef CONFIG_SND_HDA_POWER_SAVE
948 cancel_delayed_work(&codec->power_work);
Takashi Iwai6acaed32009-01-12 10:09:24 +0100949 flush_workqueue(codec->bus->workq);
Takashi Iwaicb53c622007-08-10 17:21:45 +0200950#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700951 list_del(&codec->list);
Takashi Iwaid13bd412008-07-30 15:01:45 +0200952 snd_array_free(&codec->mixers);
Jaroslav Kysela5b0cb1d2009-12-08 16:13:32 +0100953 snd_array_free(&codec->nids);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700954 codec->bus->caddr_tbl[codec->addr] = NULL;
955 if (codec->patch_ops.free)
956 codec->patch_ops.free(codec);
Takashi Iwai1289e9e2008-11-27 15:47:11 +0100957 module_put(codec->owner);
Takashi Iwai01751f52007-08-10 16:59:39 +0200958 free_hda_cache(&codec->amp_cache);
Takashi Iwaib3ac5632007-08-10 17:03:40 +0200959 free_hda_cache(&codec->cmd_cache);
Takashi Iwai812a2cc2009-05-16 10:00:49 +0200960 kfree(codec->vendor_name);
961 kfree(codec->chip_name);
Takashi Iwaif44ac832008-07-30 15:01:45 +0200962 kfree(codec->modelname);
Takashi Iwai54d17402005-11-21 16:33:22 +0100963 kfree(codec->wcaps);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700964 kfree(codec);
965}
966
Takashi Iwaibb6ac722009-03-13 09:02:42 +0100967static void hda_set_power_state(struct hda_codec *codec, hda_nid_t fg,
968 unsigned int power_state);
969
Linus Torvalds1da177e2005-04-16 15:20:36 -0700970/**
971 * snd_hda_codec_new - create a HDA codec
972 * @bus: the bus to assign
973 * @codec_addr: the codec address
974 * @codecp: the pointer to store the generated codec
975 *
976 * Returns 0 if successful, or a negative error code.
977 */
Takashi Iwai1289e9e2008-11-27 15:47:11 +0100978int /*__devinit*/ snd_hda_codec_new(struct hda_bus *bus, unsigned int codec_addr,
Takashi Iwaia1e21c92009-06-17 09:33:52 +0200979 struct hda_codec **codecp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700980{
981 struct hda_codec *codec;
Jaroslav Kyselaba443682008-08-13 20:55:32 +0200982 char component[31];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700983 int err;
984
Takashi Iwaida3cec32008-08-08 17:12:14 +0200985 if (snd_BUG_ON(!bus))
986 return -EINVAL;
987 if (snd_BUG_ON(codec_addr > HDA_MAX_CODEC_ADDRESS))
988 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700989
990 if (bus->caddr_tbl[codec_addr]) {
Takashi Iwai0ba21762007-04-16 11:29:14 +0200991 snd_printk(KERN_ERR "hda_codec: "
992 "address 0x%x is already occupied\n", codec_addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700993 return -EBUSY;
994 }
995
Takashi Iwaie560d8d2005-09-09 14:21:46 +0200996 codec = kzalloc(sizeof(*codec), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700997 if (codec == NULL) {
998 snd_printk(KERN_ERR "can't allocate struct hda_codec\n");
999 return -ENOMEM;
1000 }
1001
1002 codec->bus = bus;
1003 codec->addr = codec_addr;
Ingo Molnar62932df2006-01-16 16:34:20 +01001004 mutex_init(&codec->spdif_mutex);
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001005 mutex_init(&codec->control_mutex);
Takashi Iwai01751f52007-08-10 16:59:39 +02001006 init_hda_cache(&codec->amp_cache, sizeof(struct hda_amp_info));
Takashi Iwaib3ac5632007-08-10 17:03:40 +02001007 init_hda_cache(&codec->cmd_cache, sizeof(struct hda_cache_head));
Jaroslav Kysela5b0cb1d2009-12-08 16:13:32 +01001008 snd_array_init(&codec->mixers, sizeof(struct hda_nid_item), 32);
1009 snd_array_init(&codec->nids, sizeof(struct hda_nid_item), 32);
Takashi Iwai3be14142009-02-20 14:11:16 +01001010 snd_array_init(&codec->init_pins, sizeof(struct hda_pincfg), 16);
Takashi Iwai346ff702009-02-23 09:42:57 +01001011 snd_array_init(&codec->driver_pins, sizeof(struct hda_pincfg), 16);
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001012 if (codec->bus->modelname) {
1013 codec->modelname = kstrdup(codec->bus->modelname, GFP_KERNEL);
1014 if (!codec->modelname) {
1015 snd_hda_codec_free(codec);
1016 return -ENODEV;
1017 }
1018 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001019
Takashi Iwaicb53c622007-08-10 17:21:45 +02001020#ifdef CONFIG_SND_HDA_POWER_SAVE
1021 INIT_DELAYED_WORK(&codec->power_work, hda_power_work);
1022 /* snd_hda_codec_new() marks the codec as power-up, and leave it as is.
1023 * the caller has to power down appropriatley after initialization
1024 * phase.
1025 */
1026 hda_keep_power_on(codec);
1027#endif
1028
Linus Torvalds1da177e2005-04-16 15:20:36 -07001029 list_add_tail(&codec->list, &bus->codec_list);
1030 bus->caddr_tbl[codec_addr] = codec;
1031
Takashi Iwai0ba21762007-04-16 11:29:14 +02001032 codec->vendor_id = snd_hda_param_read(codec, AC_NODE_ROOT,
1033 AC_PAR_VENDOR_ID);
Takashi Iwai111d3af2006-02-16 18:17:58 +01001034 if (codec->vendor_id == -1)
1035 /* read again, hopefully the access method was corrected
1036 * in the last read...
1037 */
1038 codec->vendor_id = snd_hda_param_read(codec, AC_NODE_ROOT,
1039 AC_PAR_VENDOR_ID);
Takashi Iwai0ba21762007-04-16 11:29:14 +02001040 codec->subsystem_id = snd_hda_param_read(codec, AC_NODE_ROOT,
1041 AC_PAR_SUBSYSTEM_ID);
1042 codec->revision_id = snd_hda_param_read(codec, AC_NODE_ROOT,
1043 AC_PAR_REV_ID);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001044
Sasha Khapyorsky673b6832005-08-11 11:00:16 +02001045 setup_fg_nodes(codec);
Takashi Iwai0ba21762007-04-16 11:29:14 +02001046 if (!codec->afg && !codec->mfg) {
Sasha Khapyorsky673b6832005-08-11 11:00:16 +02001047 snd_printdd("hda_codec: no AFG or MFG node found\n");
Takashi Iwai3be14142009-02-20 14:11:16 +01001048 err = -ENODEV;
1049 goto error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001050 }
1051
Takashi Iwai3be14142009-02-20 14:11:16 +01001052 err = read_widget_caps(codec, codec->afg ? codec->afg : codec->mfg);
1053 if (err < 0) {
Takashi Iwai54d17402005-11-21 16:33:22 +01001054 snd_printk(KERN_ERR "hda_codec: cannot malloc\n");
Takashi Iwai3be14142009-02-20 14:11:16 +01001055 goto error;
Takashi Iwai54d17402005-11-21 16:33:22 +01001056 }
Takashi Iwai3be14142009-02-20 14:11:16 +01001057 err = read_pin_defaults(codec);
1058 if (err < 0)
1059 goto error;
Takashi Iwai54d17402005-11-21 16:33:22 +01001060
Takashi Iwai0ba21762007-04-16 11:29:14 +02001061 if (!codec->subsystem_id) {
Takashi Iwai86284e42005-10-11 15:05:54 +02001062 hda_nid_t nid = codec->afg ? codec->afg : codec->mfg;
Takashi Iwai0ba21762007-04-16 11:29:14 +02001063 codec->subsystem_id =
1064 snd_hda_codec_read(codec, nid, 0,
1065 AC_VERB_GET_SUBSYSTEM_ID, 0);
Takashi Iwai86284e42005-10-11 15:05:54 +02001066 }
1067
Takashi Iwaibb6ac722009-03-13 09:02:42 +01001068 /* power-up all before initialization */
1069 hda_set_power_state(codec,
1070 codec->afg ? codec->afg : codec->mfg,
1071 AC_PWRST_D0);
1072
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001073 snd_hda_codec_proc_new(codec);
1074
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001075 snd_hda_create_hwdep(codec);
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001076
1077 sprintf(component, "HDA:%08x,%08x,%08x", codec->vendor_id,
1078 codec->subsystem_id, codec->revision_id);
1079 snd_component_add(codec->bus->card, component);
1080
1081 if (codecp)
1082 *codecp = codec;
1083 return 0;
Takashi Iwai3be14142009-02-20 14:11:16 +01001084
1085 error:
1086 snd_hda_codec_free(codec);
1087 return err;
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001088}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001089EXPORT_SYMBOL_HDA(snd_hda_codec_new);
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001090
Takashi Iwaid5191e52009-11-16 14:58:17 +01001091/**
1092 * snd_hda_codec_configure - (Re-)configure the HD-audio codec
1093 * @codec: the HDA codec
1094 *
1095 * Start parsing of the given codec tree and (re-)initialize the whole
1096 * patch instance.
1097 *
1098 * Returns 0 if successful or a negative error code.
1099 */
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001100int snd_hda_codec_configure(struct hda_codec *codec)
1101{
1102 int err;
1103
Takashi Iwaid5ad6302007-03-07 15:55:59 +01001104 codec->preset = find_codec_preset(codec);
Takashi Iwai812a2cc2009-05-16 10:00:49 +02001105 if (!codec->vendor_name || !codec->chip_name) {
Takashi Iwaif44ac832008-07-30 15:01:45 +02001106 err = get_codec_name(codec);
1107 if (err < 0)
1108 return err;
1109 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001110
Takashi Iwai82467612007-07-27 19:15:54 +02001111 if (is_generic_config(codec)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001112 err = snd_hda_parse_generic_codec(codec);
Takashi Iwai82467612007-07-27 19:15:54 +02001113 goto patched;
1114 }
Takashi Iwai82467612007-07-27 19:15:54 +02001115 if (codec->preset && codec->preset->patch) {
1116 err = codec->preset->patch(codec);
1117 goto patched;
1118 }
1119
1120 /* call the default parser */
Takashi Iwai82467612007-07-27 19:15:54 +02001121 err = snd_hda_parse_generic_codec(codec);
Takashi Iwai35a1e0c2007-10-19 08:13:40 +02001122 if (err < 0)
1123 printk(KERN_ERR "hda-codec: No codec parser is available\n");
Takashi Iwai82467612007-07-27 19:15:54 +02001124
1125 patched:
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001126 if (!err && codec->patch_ops.unsol_event)
1127 err = init_unsol_queue(codec->bus);
Takashi Iwaif62faed2009-12-23 09:27:51 +01001128 /* audio codec should override the mixer name */
1129 if (!err && (codec->afg || !*codec->bus->card->mixername))
1130 snprintf(codec->bus->card->mixername,
1131 sizeof(codec->bus->card->mixername),
1132 "%s %s", codec->vendor_name, codec->chip_name);
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001133 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001134}
Takashi Iwaia1e21c92009-06-17 09:33:52 +02001135EXPORT_SYMBOL_HDA(snd_hda_codec_configure);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001136
1137/**
1138 * snd_hda_codec_setup_stream - set up the codec for streaming
1139 * @codec: the CODEC to set up
1140 * @nid: the NID to set up
1141 * @stream_tag: stream tag to pass, it's between 0x1 and 0xf.
1142 * @channel_id: channel id to pass, zero based.
1143 * @format: stream format.
1144 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02001145void snd_hda_codec_setup_stream(struct hda_codec *codec, hda_nid_t nid,
1146 u32 stream_tag,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001147 int channel_id, int format)
1148{
Takashi Iwai0ba21762007-04-16 11:29:14 +02001149 if (!nid)
Takashi Iwaid21b37e2005-04-20 13:45:55 +02001150 return;
1151
Takashi Iwai0ba21762007-04-16 11:29:14 +02001152 snd_printdd("hda_codec_setup_stream: "
1153 "NID=0x%x, stream=0x%x, channel=%d, format=0x%x\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07001154 nid, stream_tag, channel_id, format);
1155 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CHANNEL_STREAMID,
1156 (stream_tag << 4) | channel_id);
1157 msleep(1);
1158 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_STREAM_FORMAT, format);
1159}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001160EXPORT_SYMBOL_HDA(snd_hda_codec_setup_stream);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001161
Takashi Iwaid5191e52009-11-16 14:58:17 +01001162/**
1163 * snd_hda_codec_cleanup_stream - clean up the codec for closing
1164 * @codec: the CODEC to clean up
1165 * @nid: the NID to clean up
1166 */
Takashi Iwai888afa12008-03-18 09:57:50 +01001167void snd_hda_codec_cleanup_stream(struct hda_codec *codec, hda_nid_t nid)
1168{
1169 if (!nid)
1170 return;
1171
1172 snd_printdd("hda_codec_cleanup_stream: NID=0x%x\n", nid);
1173 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CHANNEL_STREAMID, 0);
1174#if 0 /* keep the format */
1175 msleep(1);
1176 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_STREAM_FORMAT, 0);
1177#endif
1178}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001179EXPORT_SYMBOL_HDA(snd_hda_codec_cleanup_stream);
Takashi Iwai888afa12008-03-18 09:57:50 +01001180
Linus Torvalds1da177e2005-04-16 15:20:36 -07001181/*
1182 * amp access functions
1183 */
1184
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001185/* FIXME: more better hash key? */
1186#define HDA_HASH_KEY(nid,dir,idx) (u32)((nid) + ((idx) << 16) + ((dir) << 24))
Takashi Iwai1327a322009-03-23 13:07:47 +01001187#define HDA_HASH_PINCAP_KEY(nid) (u32)((nid) + (0x02 << 24))
Takashi Iwai92c7c8a2009-03-24 07:32:14 +01001188#define HDA_HASH_PARPCM_KEY(nid) (u32)((nid) + (0x03 << 24))
1189#define HDA_HASH_PARSTR_KEY(nid) (u32)((nid) + (0x04 << 24))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001190#define INFO_AMP_CAPS (1<<0)
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001191#define INFO_AMP_VOL(ch) (1 << (1 + (ch)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001192
1193/* initialize the hash table */
Takashi Iwai1289e9e2008-11-27 15:47:11 +01001194static void /*__devinit*/ init_hda_cache(struct hda_cache_rec *cache,
Takashi Iwai01751f52007-08-10 16:59:39 +02001195 unsigned int record_size)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001196{
Takashi Iwai01751f52007-08-10 16:59:39 +02001197 memset(cache, 0, sizeof(*cache));
1198 memset(cache->hash, 0xff, sizeof(cache->hash));
Takashi Iwai603c4012008-07-30 15:01:44 +02001199 snd_array_init(&cache->buf, record_size, 64);
Takashi Iwai01751f52007-08-10 16:59:39 +02001200}
1201
Takashi Iwai1fcaee62007-08-23 00:01:09 +02001202static void free_hda_cache(struct hda_cache_rec *cache)
Takashi Iwai01751f52007-08-10 16:59:39 +02001203{
Takashi Iwai603c4012008-07-30 15:01:44 +02001204 snd_array_free(&cache->buf);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001205}
1206
1207/* query the hash. allocate an entry if not found. */
Takashi Iwai01751f52007-08-10 16:59:39 +02001208static struct hda_cache_head *get_alloc_hash(struct hda_cache_rec *cache,
1209 u32 key)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001210{
Takashi Iwai01751f52007-08-10 16:59:39 +02001211 u16 idx = key % (u16)ARRAY_SIZE(cache->hash);
1212 u16 cur = cache->hash[idx];
1213 struct hda_cache_head *info;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001214
1215 while (cur != 0xffff) {
Takashi Iwaif43aa022008-11-10 16:24:26 +01001216 info = snd_array_elem(&cache->buf, cur);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001217 if (info->key == key)
1218 return info;
1219 cur = info->next;
1220 }
1221
1222 /* add a new hash entry */
Takashi Iwai603c4012008-07-30 15:01:44 +02001223 info = snd_array_new(&cache->buf);
Takashi Iwaic2174292008-11-07 00:23:30 +01001224 if (!info)
1225 return NULL;
Takashi Iwaif43aa022008-11-10 16:24:26 +01001226 cur = snd_array_index(&cache->buf, info);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001227 info->key = key;
Takashi Iwai01751f52007-08-10 16:59:39 +02001228 info->val = 0;
1229 info->next = cache->hash[idx];
1230 cache->hash[idx] = cur;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001231
1232 return info;
1233}
1234
Takashi Iwai01751f52007-08-10 16:59:39 +02001235/* query and allocate an amp hash entry */
1236static inline struct hda_amp_info *
1237get_alloc_amp_hash(struct hda_codec *codec, u32 key)
1238{
1239 return (struct hda_amp_info *)get_alloc_hash(&codec->amp_cache, key);
1240}
1241
Takashi Iwaid5191e52009-11-16 14:58:17 +01001242/**
1243 * query_amp_caps - query AMP capabilities
1244 * @codec: the HD-auio codec
1245 * @nid: the NID to query
1246 * @direction: either #HDA_INPUT or #HDA_OUTPUT
1247 *
1248 * Query AMP capabilities for the given widget and direction.
1249 * Returns the obtained capability bits.
1250 *
1251 * When cap bits have been already read, this doesn't read again but
1252 * returns the cached value.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001253 */
Matthew Ranostay09a99952008-01-24 11:49:21 +01001254u32 query_amp_caps(struct hda_codec *codec, hda_nid_t nid, int direction)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001255{
Takashi Iwai0ba21762007-04-16 11:29:14 +02001256 struct hda_amp_info *info;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001257
Takashi Iwai0ba21762007-04-16 11:29:14 +02001258 info = get_alloc_amp_hash(codec, HDA_HASH_KEY(nid, direction, 0));
1259 if (!info)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001260 return 0;
Takashi Iwai01751f52007-08-10 16:59:39 +02001261 if (!(info->head.val & INFO_AMP_CAPS)) {
Takashi Iwai0ba21762007-04-16 11:29:14 +02001262 if (!(get_wcaps(codec, nid) & AC_WCAP_AMP_OVRD))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001263 nid = codec->afg;
Takashi Iwai0ba21762007-04-16 11:29:14 +02001264 info->amp_caps = snd_hda_param_read(codec, nid,
1265 direction == HDA_OUTPUT ?
1266 AC_PAR_AMP_OUT_CAP :
1267 AC_PAR_AMP_IN_CAP);
Takashi Iwaib75e53f2007-05-10 16:56:09 +02001268 if (info->amp_caps)
Takashi Iwai01751f52007-08-10 16:59:39 +02001269 info->head.val |= INFO_AMP_CAPS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001270 }
1271 return info->amp_caps;
1272}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001273EXPORT_SYMBOL_HDA(query_amp_caps);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001274
Takashi Iwaid5191e52009-11-16 14:58:17 +01001275/**
1276 * snd_hda_override_amp_caps - Override the AMP capabilities
1277 * @codec: the CODEC to clean up
1278 * @nid: the NID to clean up
1279 * @direction: either #HDA_INPUT or #HDA_OUTPUT
1280 * @caps: the capability bits to set
1281 *
1282 * Override the cached AMP caps bits value by the given one.
1283 * This function is useful if the driver needs to adjust the AMP ranges,
1284 * e.g. limit to 0dB, etc.
1285 *
1286 * Returns zero if successful or a negative error code.
1287 */
Takashi Iwai897cc182007-05-29 19:01:37 +02001288int snd_hda_override_amp_caps(struct hda_codec *codec, hda_nid_t nid, int dir,
1289 unsigned int caps)
1290{
1291 struct hda_amp_info *info;
1292
1293 info = get_alloc_amp_hash(codec, HDA_HASH_KEY(nid, dir, 0));
1294 if (!info)
1295 return -EINVAL;
1296 info->amp_caps = caps;
Takashi Iwai01751f52007-08-10 16:59:39 +02001297 info->head.val |= INFO_AMP_CAPS;
Takashi Iwai897cc182007-05-29 19:01:37 +02001298 return 0;
1299}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001300EXPORT_SYMBOL_HDA(snd_hda_override_amp_caps);
Takashi Iwai897cc182007-05-29 19:01:37 +02001301
Takashi Iwai92c7c8a2009-03-24 07:32:14 +01001302static unsigned int
1303query_caps_hash(struct hda_codec *codec, hda_nid_t nid, u32 key,
1304 unsigned int (*func)(struct hda_codec *, hda_nid_t))
Takashi Iwai1327a322009-03-23 13:07:47 +01001305{
1306 struct hda_amp_info *info;
1307
Takashi Iwai92c7c8a2009-03-24 07:32:14 +01001308 info = get_alloc_amp_hash(codec, key);
Takashi Iwai1327a322009-03-23 13:07:47 +01001309 if (!info)
1310 return 0;
1311 if (!info->head.val) {
Takashi Iwai1327a322009-03-23 13:07:47 +01001312 info->head.val |= INFO_AMP_CAPS;
Takashi Iwai92c7c8a2009-03-24 07:32:14 +01001313 info->amp_caps = func(codec, nid);
Takashi Iwai1327a322009-03-23 13:07:47 +01001314 }
1315 return info->amp_caps;
1316}
Takashi Iwai92c7c8a2009-03-24 07:32:14 +01001317
1318static unsigned int read_pin_cap(struct hda_codec *codec, hda_nid_t nid)
1319{
1320 return snd_hda_param_read(codec, nid, AC_PAR_PIN_CAP);
1321}
1322
Takashi Iwaid5191e52009-11-16 14:58:17 +01001323/**
1324 * snd_hda_query_pin_caps - Query PIN capabilities
1325 * @codec: the HD-auio codec
1326 * @nid: the NID to query
1327 *
1328 * Query PIN capabilities for the given widget.
1329 * Returns the obtained capability bits.
1330 *
1331 * When cap bits have been already read, this doesn't read again but
1332 * returns the cached value.
1333 */
Takashi Iwai92c7c8a2009-03-24 07:32:14 +01001334u32 snd_hda_query_pin_caps(struct hda_codec *codec, hda_nid_t nid)
1335{
1336 return query_caps_hash(codec, nid, HDA_HASH_PINCAP_KEY(nid),
1337 read_pin_cap);
1338}
Takashi Iwai1327a322009-03-23 13:07:47 +01001339EXPORT_SYMBOL_HDA(snd_hda_query_pin_caps);
1340
Wu Fengguang864f92b2009-11-18 12:38:02 +08001341/**
1342 * snd_hda_pin_sense - execute pin sense measurement
1343 * @codec: the CODEC to sense
1344 * @nid: the pin NID to sense
1345 *
1346 * Execute necessary pin sense measurement and return its Presence Detect,
1347 * Impedance, ELD Valid etc. status bits.
1348 */
1349u32 snd_hda_pin_sense(struct hda_codec *codec, hda_nid_t nid)
1350{
1351 u32 pincap = snd_hda_query_pin_caps(codec, nid);
1352
1353 if (pincap & AC_PINCAP_TRIG_REQ) /* need trigger? */
1354 snd_hda_codec_read(codec, nid, 0, AC_VERB_SET_PIN_SENSE, 0);
1355
1356 return snd_hda_codec_read(codec, nid, 0,
1357 AC_VERB_GET_PIN_SENSE, 0);
1358}
1359EXPORT_SYMBOL_HDA(snd_hda_pin_sense);
1360
1361/**
1362 * snd_hda_jack_detect - query pin Presence Detect status
1363 * @codec: the CODEC to sense
1364 * @nid: the pin NID to sense
1365 *
1366 * Query and return the pin's Presence Detect status.
1367 */
1368int snd_hda_jack_detect(struct hda_codec *codec, hda_nid_t nid)
1369{
1370 u32 sense = snd_hda_pin_sense(codec, nid);
1371 return !!(sense & AC_PINSENSE_PRESENCE);
1372}
1373EXPORT_SYMBOL_HDA(snd_hda_jack_detect);
1374
Linus Torvalds1da177e2005-04-16 15:20:36 -07001375/*
1376 * read the current volume to info
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001377 * if the cache exists, read the cache value.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001378 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02001379static unsigned int get_vol_mute(struct hda_codec *codec,
1380 struct hda_amp_info *info, hda_nid_t nid,
1381 int ch, int direction, int index)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001382{
1383 u32 val, parm;
1384
Takashi Iwai01751f52007-08-10 16:59:39 +02001385 if (info->head.val & INFO_AMP_VOL(ch))
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001386 return info->vol[ch];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001387
1388 parm = ch ? AC_AMP_GET_RIGHT : AC_AMP_GET_LEFT;
1389 parm |= direction == HDA_OUTPUT ? AC_AMP_GET_OUTPUT : AC_AMP_GET_INPUT;
1390 parm |= index;
Takashi Iwai0ba21762007-04-16 11:29:14 +02001391 val = snd_hda_codec_read(codec, nid, 0,
1392 AC_VERB_GET_AMP_GAIN_MUTE, parm);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001393 info->vol[ch] = val & 0xff;
Takashi Iwai01751f52007-08-10 16:59:39 +02001394 info->head.val |= INFO_AMP_VOL(ch);
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001395 return info->vol[ch];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001396}
1397
1398/*
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001399 * write the current volume in info to the h/w and update the cache
Linus Torvalds1da177e2005-04-16 15:20:36 -07001400 */
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001401static void put_vol_mute(struct hda_codec *codec, struct hda_amp_info *info,
Takashi Iwai0ba21762007-04-16 11:29:14 +02001402 hda_nid_t nid, int ch, int direction, int index,
1403 int val)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001404{
1405 u32 parm;
1406
1407 parm = ch ? AC_AMP_SET_RIGHT : AC_AMP_SET_LEFT;
1408 parm |= direction == HDA_OUTPUT ? AC_AMP_SET_OUTPUT : AC_AMP_SET_INPUT;
1409 parm |= index << AC_AMP_SET_INDEX_SHIFT;
1410 parm |= val;
1411 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, parm);
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001412 info->vol[ch] = val;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001413}
1414
Takashi Iwaid5191e52009-11-16 14:58:17 +01001415/**
1416 * snd_hda_codec_amp_read - Read AMP value
1417 * @codec: HD-audio codec
1418 * @nid: NID to read the AMP value
1419 * @ch: channel (left=0 or right=1)
1420 * @direction: #HDA_INPUT or #HDA_OUTPUT
1421 * @index: the index value (only for input direction)
1422 *
1423 * Read AMP value. The volume is between 0 to 0x7f, 0x80 = mute bit.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001424 */
Takashi Iwai834be882006-03-01 14:16:17 +01001425int snd_hda_codec_amp_read(struct hda_codec *codec, hda_nid_t nid, int ch,
1426 int direction, int index)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001427{
Takashi Iwai0ba21762007-04-16 11:29:14 +02001428 struct hda_amp_info *info;
1429 info = get_alloc_amp_hash(codec, HDA_HASH_KEY(nid, direction, index));
1430 if (!info)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001431 return 0;
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001432 return get_vol_mute(codec, info, nid, ch, direction, index);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001433}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001434EXPORT_SYMBOL_HDA(snd_hda_codec_amp_read);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001435
Takashi Iwaid5191e52009-11-16 14:58:17 +01001436/**
1437 * snd_hda_codec_amp_update - update the AMP value
1438 * @codec: HD-audio codec
1439 * @nid: NID to read the AMP value
1440 * @ch: channel (left=0 or right=1)
1441 * @direction: #HDA_INPUT or #HDA_OUTPUT
1442 * @idx: the index value (only for input direction)
1443 * @mask: bit mask to set
1444 * @val: the bits value to set
1445 *
1446 * Update the AMP value with a bit mask.
1447 * Returns 0 if the value is unchanged, 1 if changed.
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001448 */
Takashi Iwai834be882006-03-01 14:16:17 +01001449int snd_hda_codec_amp_update(struct hda_codec *codec, hda_nid_t nid, int ch,
1450 int direction, int idx, int mask, int val)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001451{
Takashi Iwai0ba21762007-04-16 11:29:14 +02001452 struct hda_amp_info *info;
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001453
Takashi Iwai0ba21762007-04-16 11:29:14 +02001454 info = get_alloc_amp_hash(codec, HDA_HASH_KEY(nid, direction, idx));
1455 if (!info)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001456 return 0;
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001457 val &= mask;
1458 val |= get_vol_mute(codec, info, nid, ch, direction, idx) & ~mask;
Takashi Iwai82beb8f2007-08-10 17:09:26 +02001459 if (info->vol[ch] == val)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001460 return 0;
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001461 put_vol_mute(codec, info, nid, ch, direction, idx, val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001462 return 1;
1463}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001464EXPORT_SYMBOL_HDA(snd_hda_codec_amp_update);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001465
Takashi Iwaid5191e52009-11-16 14:58:17 +01001466/**
1467 * snd_hda_codec_amp_stereo - update the AMP stereo values
1468 * @codec: HD-audio codec
1469 * @nid: NID to read the AMP value
1470 * @direction: #HDA_INPUT or #HDA_OUTPUT
1471 * @idx: the index value (only for input direction)
1472 * @mask: bit mask to set
1473 * @val: the bits value to set
1474 *
1475 * Update the AMP values like snd_hda_codec_amp_update(), but for a
1476 * stereo widget with the same mask and value.
Takashi Iwai47fd8302007-08-10 17:11:07 +02001477 */
1478int snd_hda_codec_amp_stereo(struct hda_codec *codec, hda_nid_t nid,
1479 int direction, int idx, int mask, int val)
1480{
1481 int ch, ret = 0;
1482 for (ch = 0; ch < 2; ch++)
1483 ret |= snd_hda_codec_amp_update(codec, nid, ch, direction,
1484 idx, mask, val);
1485 return ret;
1486}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001487EXPORT_SYMBOL_HDA(snd_hda_codec_amp_stereo);
Takashi Iwai47fd8302007-08-10 17:11:07 +02001488
Takashi Iwaicb53c622007-08-10 17:21:45 +02001489#ifdef SND_HDA_NEEDS_RESUME
Takashi Iwaid5191e52009-11-16 14:58:17 +01001490/**
1491 * snd_hda_codec_resume_amp - Resume all AMP commands from the cache
1492 * @codec: HD-audio codec
1493 *
1494 * Resume the all amp commands from the cache.
1495 */
Takashi Iwaib3ac5632007-08-10 17:03:40 +02001496void snd_hda_codec_resume_amp(struct hda_codec *codec)
1497{
Takashi Iwai603c4012008-07-30 15:01:44 +02001498 struct hda_amp_info *buffer = codec->amp_cache.buf.list;
Takashi Iwaib3ac5632007-08-10 17:03:40 +02001499 int i;
1500
Takashi Iwai603c4012008-07-30 15:01:44 +02001501 for (i = 0; i < codec->amp_cache.buf.used; i++, buffer++) {
Takashi Iwaib3ac5632007-08-10 17:03:40 +02001502 u32 key = buffer->head.key;
1503 hda_nid_t nid;
1504 unsigned int idx, dir, ch;
1505 if (!key)
1506 continue;
1507 nid = key & 0xff;
1508 idx = (key >> 16) & 0xff;
1509 dir = (key >> 24) & 0xff;
1510 for (ch = 0; ch < 2; ch++) {
1511 if (!(buffer->head.val & INFO_AMP_VOL(ch)))
1512 continue;
1513 put_vol_mute(codec, buffer, nid, ch, dir, idx,
1514 buffer->vol[ch]);
1515 }
1516 }
1517}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001518EXPORT_SYMBOL_HDA(snd_hda_codec_resume_amp);
Takashi Iwaicb53c622007-08-10 17:21:45 +02001519#endif /* SND_HDA_NEEDS_RESUME */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001520
Takashi Iwaid5191e52009-11-16 14:58:17 +01001521/**
1522 * snd_hda_mixer_amp_volume_info - Info callback for a standard AMP mixer
1523 *
1524 * The control element is supposed to have the private_value field
1525 * set up via HDA_COMPOSE_AMP_VAL*() or related macros.
1526 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02001527int snd_hda_mixer_amp_volume_info(struct snd_kcontrol *kcontrol,
1528 struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001529{
1530 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1531 u16 nid = get_amp_nid(kcontrol);
1532 u8 chs = get_amp_channels(kcontrol);
1533 int dir = get_amp_direction(kcontrol);
Takashi Iwai29fdbec2009-01-20 13:07:55 +01001534 unsigned int ofs = get_amp_offset(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001535 u32 caps;
1536
1537 caps = query_amp_caps(codec, nid, dir);
Takashi Iwai0ba21762007-04-16 11:29:14 +02001538 /* num steps */
1539 caps = (caps & AC_AMPCAP_NUM_STEPS) >> AC_AMPCAP_NUM_STEPS_SHIFT;
1540 if (!caps) {
1541 printk(KERN_WARNING "hda_codec: "
Takashi Iwai9c8f2ab2008-01-11 16:12:23 +01001542 "num_steps = 0 for NID=0x%x (ctl = %s)\n", nid,
1543 kcontrol->id.name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001544 return -EINVAL;
1545 }
Takashi Iwai29fdbec2009-01-20 13:07:55 +01001546 if (ofs < caps)
1547 caps -= ofs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001548 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
1549 uinfo->count = chs == 3 ? 2 : 1;
1550 uinfo->value.integer.min = 0;
1551 uinfo->value.integer.max = caps;
1552 return 0;
1553}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001554EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_volume_info);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001555
Takashi Iwai29fdbec2009-01-20 13:07:55 +01001556
1557static inline unsigned int
1558read_amp_value(struct hda_codec *codec, hda_nid_t nid,
1559 int ch, int dir, int idx, unsigned int ofs)
1560{
1561 unsigned int val;
1562 val = snd_hda_codec_amp_read(codec, nid, ch, dir, idx);
1563 val &= HDA_AMP_VOLMASK;
1564 if (val >= ofs)
1565 val -= ofs;
1566 else
1567 val = 0;
1568 return val;
1569}
1570
1571static inline int
1572update_amp_value(struct hda_codec *codec, hda_nid_t nid,
1573 int ch, int dir, int idx, unsigned int ofs,
1574 unsigned int val)
1575{
1576 if (val > 0)
1577 val += ofs;
1578 return snd_hda_codec_amp_update(codec, nid, ch, dir, idx,
1579 HDA_AMP_VOLMASK, val);
1580}
1581
Takashi Iwaid5191e52009-11-16 14:58:17 +01001582/**
1583 * snd_hda_mixer_amp_volume_get - Get callback for a standard AMP mixer volume
1584 *
1585 * The control element is supposed to have the private_value field
1586 * set up via HDA_COMPOSE_AMP_VAL*() or related macros.
1587 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02001588int snd_hda_mixer_amp_volume_get(struct snd_kcontrol *kcontrol,
1589 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001590{
1591 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1592 hda_nid_t nid = get_amp_nid(kcontrol);
1593 int chs = get_amp_channels(kcontrol);
1594 int dir = get_amp_direction(kcontrol);
1595 int idx = get_amp_index(kcontrol);
Takashi Iwai29fdbec2009-01-20 13:07:55 +01001596 unsigned int ofs = get_amp_offset(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001597 long *valp = ucontrol->value.integer.value;
1598
1599 if (chs & 1)
Takashi Iwai29fdbec2009-01-20 13:07:55 +01001600 *valp++ = read_amp_value(codec, nid, 0, dir, idx, ofs);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001601 if (chs & 2)
Takashi Iwai29fdbec2009-01-20 13:07:55 +01001602 *valp = read_amp_value(codec, nid, 1, dir, idx, ofs);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001603 return 0;
1604}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001605EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_volume_get);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001606
Takashi Iwaid5191e52009-11-16 14:58:17 +01001607/**
1608 * snd_hda_mixer_amp_volume_put - Put callback for a standard AMP mixer volume
1609 *
1610 * The control element is supposed to have the private_value field
1611 * set up via HDA_COMPOSE_AMP_VAL*() or related macros.
1612 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02001613int snd_hda_mixer_amp_volume_put(struct snd_kcontrol *kcontrol,
1614 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001615{
1616 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1617 hda_nid_t nid = get_amp_nid(kcontrol);
1618 int chs = get_amp_channels(kcontrol);
1619 int dir = get_amp_direction(kcontrol);
1620 int idx = get_amp_index(kcontrol);
Takashi Iwai29fdbec2009-01-20 13:07:55 +01001621 unsigned int ofs = get_amp_offset(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001622 long *valp = ucontrol->value.integer.value;
1623 int change = 0;
1624
Takashi Iwaicb53c622007-08-10 17:21:45 +02001625 snd_hda_power_up(codec);
Nicolas Grazianob9f5a892005-07-29 12:17:20 +02001626 if (chs & 1) {
Takashi Iwai29fdbec2009-01-20 13:07:55 +01001627 change = update_amp_value(codec, nid, 0, dir, idx, ofs, *valp);
Nicolas Grazianob9f5a892005-07-29 12:17:20 +02001628 valp++;
1629 }
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001630 if (chs & 2)
Takashi Iwai29fdbec2009-01-20 13:07:55 +01001631 change |= update_amp_value(codec, nid, 1, dir, idx, ofs, *valp);
Takashi Iwaicb53c622007-08-10 17:21:45 +02001632 snd_hda_power_down(codec);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001633 return change;
1634}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001635EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_volume_put);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001636
Takashi Iwaid5191e52009-11-16 14:58:17 +01001637/**
1638 * snd_hda_mixer_amp_volume_put - TLV callback for a standard AMP mixer volume
1639 *
1640 * The control element is supposed to have the private_value field
1641 * set up via HDA_COMPOSE_AMP_VAL*() or related macros.
1642 */
Jaroslav Kysela302e9c52006-07-05 17:39:49 +02001643int snd_hda_mixer_amp_tlv(struct snd_kcontrol *kcontrol, int op_flag,
1644 unsigned int size, unsigned int __user *_tlv)
1645{
1646 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1647 hda_nid_t nid = get_amp_nid(kcontrol);
1648 int dir = get_amp_direction(kcontrol);
Takashi Iwai29fdbec2009-01-20 13:07:55 +01001649 unsigned int ofs = get_amp_offset(kcontrol);
Jaroslav Kysela302e9c52006-07-05 17:39:49 +02001650 u32 caps, val1, val2;
1651
1652 if (size < 4 * sizeof(unsigned int))
1653 return -ENOMEM;
1654 caps = query_amp_caps(codec, nid, dir);
Takashi Iwai0ba21762007-04-16 11:29:14 +02001655 val2 = (caps & AC_AMPCAP_STEP_SIZE) >> AC_AMPCAP_STEP_SIZE_SHIFT;
1656 val2 = (val2 + 1) * 25;
Jaroslav Kysela302e9c52006-07-05 17:39:49 +02001657 val1 = -((caps & AC_AMPCAP_OFFSET) >> AC_AMPCAP_OFFSET_SHIFT);
Takashi Iwai29fdbec2009-01-20 13:07:55 +01001658 val1 += ofs;
Jaroslav Kysela302e9c52006-07-05 17:39:49 +02001659 val1 = ((int)val1) * ((int)val2);
Jaroslav Kysela302e9c52006-07-05 17:39:49 +02001660 if (put_user(SNDRV_CTL_TLVT_DB_SCALE, _tlv))
1661 return -EFAULT;
1662 if (put_user(2 * sizeof(unsigned int), _tlv + 1))
1663 return -EFAULT;
1664 if (put_user(val1, _tlv + 2))
1665 return -EFAULT;
1666 if (put_user(val2, _tlv + 3))
1667 return -EFAULT;
1668 return 0;
1669}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001670EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_tlv);
Jaroslav Kysela302e9c52006-07-05 17:39:49 +02001671
Takashi Iwaid5191e52009-11-16 14:58:17 +01001672/**
1673 * snd_hda_set_vmaster_tlv - Set TLV for a virtual master control
1674 * @codec: HD-audio codec
1675 * @nid: NID of a reference widget
1676 * @dir: #HDA_INPUT or #HDA_OUTPUT
1677 * @tlv: TLV data to be stored, at least 4 elements
1678 *
1679 * Set (static) TLV data for a virtual master volume using the AMP caps
1680 * obtained from the reference NID.
1681 * The volume range is recalculated as if the max volume is 0dB.
Takashi Iwai2134ea42008-01-10 16:53:55 +01001682 */
1683void snd_hda_set_vmaster_tlv(struct hda_codec *codec, hda_nid_t nid, int dir,
1684 unsigned int *tlv)
1685{
1686 u32 caps;
1687 int nums, step;
1688
1689 caps = query_amp_caps(codec, nid, dir);
1690 nums = (caps & AC_AMPCAP_NUM_STEPS) >> AC_AMPCAP_NUM_STEPS_SHIFT;
1691 step = (caps & AC_AMPCAP_STEP_SIZE) >> AC_AMPCAP_STEP_SIZE_SHIFT;
1692 step = (step + 1) * 25;
1693 tlv[0] = SNDRV_CTL_TLVT_DB_SCALE;
1694 tlv[1] = 2 * sizeof(unsigned int);
1695 tlv[2] = -nums * step;
1696 tlv[3] = step;
1697}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001698EXPORT_SYMBOL_HDA(snd_hda_set_vmaster_tlv);
Takashi Iwai2134ea42008-01-10 16:53:55 +01001699
1700/* find a mixer control element with the given name */
Takashi Iwai09f99702008-02-04 12:31:13 +01001701static struct snd_kcontrol *
1702_snd_hda_find_mixer_ctl(struct hda_codec *codec,
1703 const char *name, int idx)
Takashi Iwai2134ea42008-01-10 16:53:55 +01001704{
1705 struct snd_ctl_elem_id id;
1706 memset(&id, 0, sizeof(id));
1707 id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
Takashi Iwai09f99702008-02-04 12:31:13 +01001708 id.index = idx;
Takashi Iwai18cb7102009-04-16 10:22:24 +02001709 if (snd_BUG_ON(strlen(name) >= sizeof(id.name)))
1710 return NULL;
Takashi Iwai2134ea42008-01-10 16:53:55 +01001711 strcpy(id.name, name);
1712 return snd_ctl_find_id(codec->bus->card, &id);
1713}
1714
Takashi Iwaid5191e52009-11-16 14:58:17 +01001715/**
1716 * snd_hda_find_mixer_ctl - Find a mixer control element with the given name
1717 * @codec: HD-audio codec
1718 * @name: ctl id name string
1719 *
1720 * Get the control element with the given id string and IFACE_MIXER.
1721 */
Takashi Iwai09f99702008-02-04 12:31:13 +01001722struct snd_kcontrol *snd_hda_find_mixer_ctl(struct hda_codec *codec,
1723 const char *name)
1724{
1725 return _snd_hda_find_mixer_ctl(codec, name, 0);
1726}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001727EXPORT_SYMBOL_HDA(snd_hda_find_mixer_ctl);
Takashi Iwai09f99702008-02-04 12:31:13 +01001728
Takashi Iwaid5191e52009-11-16 14:58:17 +01001729/**
Jaroslav Kysela5b0cb1d2009-12-08 16:13:32 +01001730 * snd_hda_ctl_add - Add a control element and assign to the codec
Takashi Iwaid5191e52009-11-16 14:58:17 +01001731 * @codec: HD-audio codec
1732 * @nid: corresponding NID (optional)
1733 * @kctl: the control element to assign
1734 *
1735 * Add the given control element to an array inside the codec instance.
1736 * All control elements belonging to a codec are supposed to be added
1737 * by this function so that a proper clean-up works at the free or
1738 * reconfiguration time.
1739 *
1740 * If non-zero @nid is passed, the NID is assigned to the control element.
1741 * The assignment is shown in the codec proc file.
1742 *
1743 * snd_hda_ctl_add() checks the control subdev id field whether
1744 * #HDA_SUBDEV_NID_FLAG bit is set. If set (and @nid is zero), the lower
Jaroslav Kysela9e3fd872009-12-08 17:45:25 +01001745 * bits value is taken as the NID to assign. The #HDA_NID_ITEM_AMP bit
1746 * specifies if kctl->private_value is a HDA amplifier value.
Takashi Iwaid5191e52009-11-16 14:58:17 +01001747 */
Jaroslav Kysela3911a4c2009-11-11 13:43:01 +01001748int snd_hda_ctl_add(struct hda_codec *codec, hda_nid_t nid,
1749 struct snd_kcontrol *kctl)
Takashi Iwaid13bd412008-07-30 15:01:45 +02001750{
1751 int err;
Jaroslav Kysela9e3fd872009-12-08 17:45:25 +01001752 unsigned short flags = 0;
Jaroslav Kysela3911a4c2009-11-11 13:43:01 +01001753 struct hda_nid_item *item;
Takashi Iwaid13bd412008-07-30 15:01:45 +02001754
Jaroslav Kysela5e26dfd2009-12-10 13:57:01 +01001755 if (kctl->id.subdevice & HDA_SUBDEV_AMP_FLAG) {
Jaroslav Kysela9e3fd872009-12-08 17:45:25 +01001756 flags |= HDA_NID_ITEM_AMP;
Jaroslav Kysela5e26dfd2009-12-10 13:57:01 +01001757 if (nid == 0)
1758 nid = get_amp_nid_(kctl->private_value);
1759 }
Jaroslav Kysela9e3fd872009-12-08 17:45:25 +01001760 if ((kctl->id.subdevice & HDA_SUBDEV_NID_FLAG) != 0 && nid == 0)
1761 nid = kctl->id.subdevice & 0xffff;
Jaroslav Kysela5e26dfd2009-12-10 13:57:01 +01001762 if (kctl->id.subdevice & (HDA_SUBDEV_NID_FLAG|HDA_SUBDEV_AMP_FLAG))
Jaroslav Kysela4d02d1b2009-11-12 10:15:48 +01001763 kctl->id.subdevice = 0;
Takashi Iwaid13bd412008-07-30 15:01:45 +02001764 err = snd_ctl_add(codec->bus->card, kctl);
1765 if (err < 0)
1766 return err;
Jaroslav Kysela3911a4c2009-11-11 13:43:01 +01001767 item = snd_array_new(&codec->mixers);
1768 if (!item)
Takashi Iwaid13bd412008-07-30 15:01:45 +02001769 return -ENOMEM;
Jaroslav Kysela3911a4c2009-11-11 13:43:01 +01001770 item->kctl = kctl;
1771 item->nid = nid;
Jaroslav Kysela9e3fd872009-12-08 17:45:25 +01001772 item->flags = flags;
Takashi Iwaid13bd412008-07-30 15:01:45 +02001773 return 0;
1774}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001775EXPORT_SYMBOL_HDA(snd_hda_ctl_add);
Takashi Iwaid13bd412008-07-30 15:01:45 +02001776
Takashi Iwaid5191e52009-11-16 14:58:17 +01001777/**
Jaroslav Kysela5b0cb1d2009-12-08 16:13:32 +01001778 * snd_hda_add_nid - Assign a NID to a control element
1779 * @codec: HD-audio codec
1780 * @nid: corresponding NID (optional)
1781 * @kctl: the control element to assign
1782 * @index: index to kctl
1783 *
1784 * Add the given control element to an array inside the codec instance.
1785 * This function is used when #snd_hda_ctl_add cannot be used for 1:1
1786 * NID:KCTL mapping - for example "Capture Source" selector.
1787 */
1788int snd_hda_add_nid(struct hda_codec *codec, struct snd_kcontrol *kctl,
1789 unsigned int index, hda_nid_t nid)
1790{
1791 struct hda_nid_item *item;
1792
1793 if (nid > 0) {
1794 item = snd_array_new(&codec->nids);
1795 if (!item)
1796 return -ENOMEM;
1797 item->kctl = kctl;
1798 item->index = index;
1799 item->nid = nid;
1800 return 0;
1801 }
1802 return -EINVAL;
1803}
1804EXPORT_SYMBOL_HDA(snd_hda_add_nid);
1805
1806/**
Takashi Iwaid5191e52009-11-16 14:58:17 +01001807 * snd_hda_ctls_clear - Clear all controls assigned to the given codec
1808 * @codec: HD-audio codec
1809 */
Takashi Iwaid13bd412008-07-30 15:01:45 +02001810void snd_hda_ctls_clear(struct hda_codec *codec)
1811{
1812 int i;
Jaroslav Kysela3911a4c2009-11-11 13:43:01 +01001813 struct hda_nid_item *items = codec->mixers.list;
Takashi Iwaid13bd412008-07-30 15:01:45 +02001814 for (i = 0; i < codec->mixers.used; i++)
Jaroslav Kysela3911a4c2009-11-11 13:43:01 +01001815 snd_ctl_remove(codec->bus->card, items[i].kctl);
Takashi Iwaid13bd412008-07-30 15:01:45 +02001816 snd_array_free(&codec->mixers);
Jaroslav Kysela5b0cb1d2009-12-08 16:13:32 +01001817 snd_array_free(&codec->nids);
Takashi Iwaid13bd412008-07-30 15:01:45 +02001818}
1819
Takashi Iwaia65d6292009-02-23 16:57:04 +01001820/* pseudo device locking
1821 * toggle card->shutdown to allow/disallow the device access (as a hack)
1822 */
1823static int hda_lock_devices(struct snd_card *card)
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001824{
Takashi Iwaia65d6292009-02-23 16:57:04 +01001825 spin_lock(&card->files_lock);
1826 if (card->shutdown) {
1827 spin_unlock(&card->files_lock);
1828 return -EINVAL;
1829 }
1830 card->shutdown = 1;
1831 spin_unlock(&card->files_lock);
1832 return 0;
1833}
1834
1835static void hda_unlock_devices(struct snd_card *card)
1836{
1837 spin_lock(&card->files_lock);
1838 card->shutdown = 0;
1839 spin_unlock(&card->files_lock);
1840}
1841
Takashi Iwaid5191e52009-11-16 14:58:17 +01001842/**
1843 * snd_hda_codec_reset - Clear all objects assigned to the codec
1844 * @codec: HD-audio codec
1845 *
1846 * This frees the all PCM and control elements assigned to the codec, and
1847 * clears the caches and restores the pin default configurations.
1848 *
1849 * When a device is being used, it returns -EBSY. If successfully freed,
1850 * returns zero.
1851 */
Takashi Iwaia65d6292009-02-23 16:57:04 +01001852int snd_hda_codec_reset(struct hda_codec *codec)
1853{
1854 struct snd_card *card = codec->bus->card;
1855 int i, pcm;
1856
1857 if (hda_lock_devices(card) < 0)
1858 return -EBUSY;
1859 /* check whether the codec isn't used by any mixer or PCM streams */
1860 if (!list_empty(&card->ctl_files)) {
1861 hda_unlock_devices(card);
1862 return -EBUSY;
1863 }
1864 for (pcm = 0; pcm < codec->num_pcms; pcm++) {
1865 struct hda_pcm *cpcm = &codec->pcm_info[pcm];
1866 if (!cpcm->pcm)
1867 continue;
1868 if (cpcm->pcm->streams[0].substream_opened ||
1869 cpcm->pcm->streams[1].substream_opened) {
1870 hda_unlock_devices(card);
1871 return -EBUSY;
1872 }
1873 }
1874
1875 /* OK, let it free */
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001876
1877#ifdef CONFIG_SND_HDA_POWER_SAVE
1878 cancel_delayed_work(&codec->power_work);
Takashi Iwai6acaed32009-01-12 10:09:24 +01001879 flush_workqueue(codec->bus->workq);
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001880#endif
1881 snd_hda_ctls_clear(codec);
1882 /* relase PCMs */
1883 for (i = 0; i < codec->num_pcms; i++) {
Takashi Iwai529bd6c2008-11-27 14:17:01 +01001884 if (codec->pcm_info[i].pcm) {
Takashi Iwaia65d6292009-02-23 16:57:04 +01001885 snd_device_free(card, codec->pcm_info[i].pcm);
Takashi Iwai529bd6c2008-11-27 14:17:01 +01001886 clear_bit(codec->pcm_info[i].device,
1887 codec->bus->pcm_dev_bits);
1888 }
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001889 }
1890 if (codec->patch_ops.free)
1891 codec->patch_ops.free(codec);
Takashi Iwai56d17712008-11-28 14:36:23 +01001892 codec->proc_widget_hook = NULL;
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001893 codec->spec = NULL;
1894 free_hda_cache(&codec->amp_cache);
1895 free_hda_cache(&codec->cmd_cache);
Takashi Iwai827057f2008-12-19 10:12:02 +01001896 init_hda_cache(&codec->amp_cache, sizeof(struct hda_amp_info));
1897 init_hda_cache(&codec->cmd_cache, sizeof(struct hda_cache_head));
Takashi Iwai346ff702009-02-23 09:42:57 +01001898 /* free only driver_pins so that init_pins + user_pins are restored */
1899 snd_array_free(&codec->driver_pins);
Takashi Iwai3be14142009-02-20 14:11:16 +01001900 restore_pincfgs(codec);
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001901 codec->num_pcms = 0;
1902 codec->pcm_info = NULL;
1903 codec->preset = NULL;
Takashi Iwaid1f1af22009-03-02 10:35:29 +01001904 memset(&codec->patch_ops, 0, sizeof(codec->patch_ops));
1905 codec->slave_dig_outs = NULL;
1906 codec->spdif_status_reset = 0;
Takashi Iwai1289e9e2008-11-27 15:47:11 +01001907 module_put(codec->owner);
1908 codec->owner = NULL;
Takashi Iwaia65d6292009-02-23 16:57:04 +01001909
1910 /* allow device access again */
1911 hda_unlock_devices(card);
1912 return 0;
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001913}
1914
Takashi Iwaid5191e52009-11-16 14:58:17 +01001915/**
1916 * snd_hda_add_vmaster - create a virtual master control and add slaves
1917 * @codec: HD-audio codec
1918 * @name: vmaster control name
1919 * @tlv: TLV data (optional)
1920 * @slaves: slave control names (optional)
1921 *
1922 * Create a virtual master control with the given name. The TLV data
1923 * must be either NULL or a valid data.
1924 *
1925 * @slaves is a NULL-terminated array of strings, each of which is a
1926 * slave control name. All controls with these names are assigned to
1927 * the new virtual master control.
1928 *
1929 * This function returns zero if successful or a negative error code.
1930 */
Takashi Iwai2134ea42008-01-10 16:53:55 +01001931int snd_hda_add_vmaster(struct hda_codec *codec, char *name,
1932 unsigned int *tlv, const char **slaves)
1933{
1934 struct snd_kcontrol *kctl;
1935 const char **s;
1936 int err;
1937
Takashi Iwai2f085542008-02-22 18:43:50 +01001938 for (s = slaves; *s && !snd_hda_find_mixer_ctl(codec, *s); s++)
1939 ;
1940 if (!*s) {
1941 snd_printdd("No slave found for %s\n", name);
1942 return 0;
1943 }
Takashi Iwai2134ea42008-01-10 16:53:55 +01001944 kctl = snd_ctl_make_virtual_master(name, tlv);
1945 if (!kctl)
1946 return -ENOMEM;
Jaroslav Kysela3911a4c2009-11-11 13:43:01 +01001947 err = snd_hda_ctl_add(codec, 0, kctl);
Takashi Iwai2134ea42008-01-10 16:53:55 +01001948 if (err < 0)
1949 return err;
1950
1951 for (s = slaves; *s; s++) {
1952 struct snd_kcontrol *sctl;
Takashi Iwai7a411ee2009-03-06 10:08:14 +01001953 int i = 0;
1954 for (;;) {
1955 sctl = _snd_hda_find_mixer_ctl(codec, *s, i);
1956 if (!sctl) {
1957 if (!i)
1958 snd_printdd("Cannot find slave %s, "
1959 "skipped\n", *s);
1960 break;
1961 }
1962 err = snd_ctl_add_slave(kctl, sctl);
1963 if (err < 0)
1964 return err;
1965 i++;
Takashi Iwai2134ea42008-01-10 16:53:55 +01001966 }
Takashi Iwai2134ea42008-01-10 16:53:55 +01001967 }
1968 return 0;
1969}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001970EXPORT_SYMBOL_HDA(snd_hda_add_vmaster);
Takashi Iwai2134ea42008-01-10 16:53:55 +01001971
Takashi Iwaid5191e52009-11-16 14:58:17 +01001972/**
1973 * snd_hda_mixer_amp_switch_info - Info 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_info(struct snd_kcontrol *kcontrol,
1979 struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001980{
1981 int chs = get_amp_channels(kcontrol);
1982
1983 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
1984 uinfo->count = chs == 3 ? 2 : 1;
1985 uinfo->value.integer.min = 0;
1986 uinfo->value.integer.max = 1;
1987 return 0;
1988}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001989EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_switch_info);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001990
Takashi Iwaid5191e52009-11-16 14:58:17 +01001991/**
1992 * snd_hda_mixer_amp_switch_get - Get callback for a standard AMP mixer switch
1993 *
1994 * The control element is supposed to have the private_value field
1995 * set up via HDA_COMPOSE_AMP_VAL*() or related macros.
1996 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02001997int snd_hda_mixer_amp_switch_get(struct snd_kcontrol *kcontrol,
1998 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001999{
2000 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2001 hda_nid_t nid = get_amp_nid(kcontrol);
2002 int chs = get_amp_channels(kcontrol);
2003 int dir = get_amp_direction(kcontrol);
2004 int idx = get_amp_index(kcontrol);
2005 long *valp = ucontrol->value.integer.value;
2006
2007 if (chs & 1)
Takashi Iwai0ba21762007-04-16 11:29:14 +02002008 *valp++ = (snd_hda_codec_amp_read(codec, nid, 0, dir, idx) &
Takashi Iwai47fd8302007-08-10 17:11:07 +02002009 HDA_AMP_MUTE) ? 0 : 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002010 if (chs & 2)
Takashi Iwai0ba21762007-04-16 11:29:14 +02002011 *valp = (snd_hda_codec_amp_read(codec, nid, 1, dir, idx) &
Takashi Iwai47fd8302007-08-10 17:11:07 +02002012 HDA_AMP_MUTE) ? 0 : 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002013 return 0;
2014}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002015EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_switch_get);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002016
Takashi Iwaid5191e52009-11-16 14:58:17 +01002017/**
2018 * snd_hda_mixer_amp_switch_put - Put callback for a standard AMP mixer switch
2019 *
2020 * The control element is supposed to have the private_value field
2021 * set up via HDA_COMPOSE_AMP_VAL*() or related macros.
2022 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02002023int snd_hda_mixer_amp_switch_put(struct snd_kcontrol *kcontrol,
2024 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002025{
2026 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2027 hda_nid_t nid = get_amp_nid(kcontrol);
2028 int chs = get_amp_channels(kcontrol);
2029 int dir = get_amp_direction(kcontrol);
2030 int idx = get_amp_index(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002031 long *valp = ucontrol->value.integer.value;
2032 int change = 0;
2033
Takashi Iwaicb53c622007-08-10 17:21:45 +02002034 snd_hda_power_up(codec);
Nicolas Grazianob9f5a892005-07-29 12:17:20 +02002035 if (chs & 1) {
Takashi Iwai4a19fae2005-06-08 14:43:58 +02002036 change = snd_hda_codec_amp_update(codec, nid, 0, dir, idx,
Takashi Iwai47fd8302007-08-10 17:11:07 +02002037 HDA_AMP_MUTE,
2038 *valp ? 0 : HDA_AMP_MUTE);
Nicolas Grazianob9f5a892005-07-29 12:17:20 +02002039 valp++;
2040 }
Takashi Iwai4a19fae2005-06-08 14:43:58 +02002041 if (chs & 2)
2042 change |= snd_hda_codec_amp_update(codec, nid, 1, dir, idx,
Takashi Iwai47fd8302007-08-10 17:11:07 +02002043 HDA_AMP_MUTE,
2044 *valp ? 0 : HDA_AMP_MUTE);
Takashi Iwaicb53c622007-08-10 17:21:45 +02002045#ifdef CONFIG_SND_HDA_POWER_SAVE
2046 if (codec->patch_ops.check_power_status)
2047 codec->patch_ops.check_power_status(codec, nid);
2048#endif
2049 snd_hda_power_down(codec);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002050 return change;
2051}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002052EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_switch_put);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002053
Takashi Iwai67d634c2009-11-16 15:35:59 +01002054#ifdef CONFIG_SND_HDA_INPUT_BEEP
Takashi Iwaid5191e52009-11-16 14:58:17 +01002055/**
2056 * snd_hda_mixer_amp_switch_put_beep - Put callback for a beep AMP switch
2057 *
2058 * This function calls snd_hda_enable_beep_device(), which behaves differently
2059 * depending on beep_mode option.
2060 */
Jaroslav Kysela123c07a2009-10-21 14:48:23 +02002061int snd_hda_mixer_amp_switch_put_beep(struct snd_kcontrol *kcontrol,
2062 struct snd_ctl_elem_value *ucontrol)
2063{
2064 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2065 long *valp = ucontrol->value.integer.value;
2066
2067 snd_hda_enable_beep_device(codec, *valp);
2068 return snd_hda_mixer_amp_switch_put(kcontrol, ucontrol);
2069}
2070EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_switch_put_beep);
Takashi Iwai67d634c2009-11-16 15:35:59 +01002071#endif /* CONFIG_SND_HDA_INPUT_BEEP */
Jaroslav Kysela123c07a2009-10-21 14:48:23 +02002072
Linus Torvalds1da177e2005-04-16 15:20:36 -07002073/*
Takashi Iwai985be542005-11-02 18:26:49 +01002074 * bound volume controls
2075 *
2076 * bind multiple volumes (# indices, from 0)
2077 */
2078
2079#define AMP_VAL_IDX_SHIFT 19
2080#define AMP_VAL_IDX_MASK (0x0f<<19)
2081
Takashi Iwaid5191e52009-11-16 14:58:17 +01002082/**
2083 * snd_hda_mixer_bind_switch_get - Get callback for a bound volume control
2084 *
2085 * The control element is supposed to have the private_value field
2086 * set up via HDA_BIND_MUTE*() macros.
2087 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02002088int snd_hda_mixer_bind_switch_get(struct snd_kcontrol *kcontrol,
2089 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai985be542005-11-02 18:26:49 +01002090{
2091 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2092 unsigned long pval;
2093 int err;
2094
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08002095 mutex_lock(&codec->control_mutex);
Takashi Iwai985be542005-11-02 18:26:49 +01002096 pval = kcontrol->private_value;
2097 kcontrol->private_value = pval & ~AMP_VAL_IDX_MASK; /* index 0 */
2098 err = snd_hda_mixer_amp_switch_get(kcontrol, ucontrol);
2099 kcontrol->private_value = pval;
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08002100 mutex_unlock(&codec->control_mutex);
Takashi Iwai985be542005-11-02 18:26:49 +01002101 return err;
2102}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002103EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_switch_get);
Takashi Iwai985be542005-11-02 18:26:49 +01002104
Takashi Iwaid5191e52009-11-16 14:58:17 +01002105/**
2106 * snd_hda_mixer_bind_switch_put - Put callback for a bound volume control
2107 *
2108 * The control element is supposed to have the private_value field
2109 * set up via HDA_BIND_MUTE*() macros.
2110 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02002111int snd_hda_mixer_bind_switch_put(struct snd_kcontrol *kcontrol,
2112 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai985be542005-11-02 18:26:49 +01002113{
2114 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2115 unsigned long pval;
2116 int i, indices, err = 0, change = 0;
2117
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08002118 mutex_lock(&codec->control_mutex);
Takashi Iwai985be542005-11-02 18:26:49 +01002119 pval = kcontrol->private_value;
2120 indices = (pval & AMP_VAL_IDX_MASK) >> AMP_VAL_IDX_SHIFT;
2121 for (i = 0; i < indices; i++) {
Takashi Iwai0ba21762007-04-16 11:29:14 +02002122 kcontrol->private_value = (pval & ~AMP_VAL_IDX_MASK) |
2123 (i << AMP_VAL_IDX_SHIFT);
Takashi Iwai985be542005-11-02 18:26:49 +01002124 err = snd_hda_mixer_amp_switch_put(kcontrol, ucontrol);
2125 if (err < 0)
2126 break;
2127 change |= err;
2128 }
2129 kcontrol->private_value = pval;
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08002130 mutex_unlock(&codec->control_mutex);
Takashi Iwai985be542005-11-02 18:26:49 +01002131 return err < 0 ? err : change;
2132}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002133EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_switch_put);
Takashi Iwai985be542005-11-02 18:26:49 +01002134
Takashi Iwaid5191e52009-11-16 14:58:17 +01002135/**
2136 * snd_hda_mixer_bind_ctls_info - Info callback for a generic bound control
2137 *
2138 * The control element is supposed to have the private_value field
2139 * set up via HDA_BIND_VOL() or HDA_BIND_SW() macros.
Takashi Iwai532d5382007-07-27 19:02:40 +02002140 */
2141int snd_hda_mixer_bind_ctls_info(struct snd_kcontrol *kcontrol,
2142 struct snd_ctl_elem_info *uinfo)
2143{
2144 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2145 struct hda_bind_ctls *c;
2146 int err;
2147
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08002148 mutex_lock(&codec->control_mutex);
Serge A. Suchkov14c65f92008-02-22 18:43:16 +01002149 c = (struct hda_bind_ctls *)kcontrol->private_value;
Takashi Iwai532d5382007-07-27 19:02:40 +02002150 kcontrol->private_value = *c->values;
2151 err = c->ops->info(kcontrol, uinfo);
2152 kcontrol->private_value = (long)c;
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08002153 mutex_unlock(&codec->control_mutex);
Takashi Iwai532d5382007-07-27 19:02:40 +02002154 return err;
2155}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002156EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_ctls_info);
Takashi Iwai532d5382007-07-27 19:02:40 +02002157
Takashi Iwaid5191e52009-11-16 14:58:17 +01002158/**
2159 * snd_hda_mixer_bind_ctls_get - Get callback for a generic bound control
2160 *
2161 * The control element is supposed to have the private_value field
2162 * set up via HDA_BIND_VOL() or HDA_BIND_SW() macros.
2163 */
Takashi Iwai532d5382007-07-27 19:02:40 +02002164int snd_hda_mixer_bind_ctls_get(struct snd_kcontrol *kcontrol,
2165 struct snd_ctl_elem_value *ucontrol)
2166{
2167 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2168 struct hda_bind_ctls *c;
2169 int err;
2170
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08002171 mutex_lock(&codec->control_mutex);
Serge A. Suchkov14c65f92008-02-22 18:43:16 +01002172 c = (struct hda_bind_ctls *)kcontrol->private_value;
Takashi Iwai532d5382007-07-27 19:02:40 +02002173 kcontrol->private_value = *c->values;
2174 err = c->ops->get(kcontrol, ucontrol);
2175 kcontrol->private_value = (long)c;
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08002176 mutex_unlock(&codec->control_mutex);
Takashi Iwai532d5382007-07-27 19:02:40 +02002177 return err;
2178}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002179EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_ctls_get);
Takashi Iwai532d5382007-07-27 19:02:40 +02002180
Takashi Iwaid5191e52009-11-16 14:58:17 +01002181/**
2182 * snd_hda_mixer_bind_ctls_put - Put callback for a generic bound control
2183 *
2184 * The control element is supposed to have the private_value field
2185 * set up via HDA_BIND_VOL() or HDA_BIND_SW() macros.
2186 */
Takashi Iwai532d5382007-07-27 19:02:40 +02002187int snd_hda_mixer_bind_ctls_put(struct snd_kcontrol *kcontrol,
2188 struct snd_ctl_elem_value *ucontrol)
2189{
2190 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2191 struct hda_bind_ctls *c;
2192 unsigned long *vals;
2193 int err = 0, change = 0;
2194
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08002195 mutex_lock(&codec->control_mutex);
Serge A. Suchkov14c65f92008-02-22 18:43:16 +01002196 c = (struct hda_bind_ctls *)kcontrol->private_value;
Takashi Iwai532d5382007-07-27 19:02:40 +02002197 for (vals = c->values; *vals; vals++) {
2198 kcontrol->private_value = *vals;
2199 err = c->ops->put(kcontrol, ucontrol);
2200 if (err < 0)
2201 break;
2202 change |= err;
2203 }
2204 kcontrol->private_value = (long)c;
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08002205 mutex_unlock(&codec->control_mutex);
Takashi Iwai532d5382007-07-27 19:02:40 +02002206 return err < 0 ? err : change;
2207}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002208EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_ctls_put);
Takashi Iwai532d5382007-07-27 19:02:40 +02002209
Takashi Iwaid5191e52009-11-16 14:58:17 +01002210/**
2211 * snd_hda_mixer_bind_tlv - TLV callback for a generic bound control
2212 *
2213 * The control element is supposed to have the private_value field
2214 * set up via HDA_BIND_VOL() macro.
2215 */
Takashi Iwai532d5382007-07-27 19:02:40 +02002216int snd_hda_mixer_bind_tlv(struct snd_kcontrol *kcontrol, int op_flag,
2217 unsigned int size, unsigned int __user *tlv)
2218{
2219 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2220 struct hda_bind_ctls *c;
2221 int err;
2222
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08002223 mutex_lock(&codec->control_mutex);
Serge A. Suchkov14c65f92008-02-22 18:43:16 +01002224 c = (struct hda_bind_ctls *)kcontrol->private_value;
Takashi Iwai532d5382007-07-27 19:02:40 +02002225 kcontrol->private_value = *c->values;
2226 err = c->ops->tlv(kcontrol, op_flag, size, tlv);
2227 kcontrol->private_value = (long)c;
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08002228 mutex_unlock(&codec->control_mutex);
Takashi Iwai532d5382007-07-27 19:02:40 +02002229 return err;
2230}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002231EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_tlv);
Takashi Iwai532d5382007-07-27 19:02:40 +02002232
2233struct hda_ctl_ops snd_hda_bind_vol = {
2234 .info = snd_hda_mixer_amp_volume_info,
2235 .get = snd_hda_mixer_amp_volume_get,
2236 .put = snd_hda_mixer_amp_volume_put,
2237 .tlv = snd_hda_mixer_amp_tlv
2238};
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002239EXPORT_SYMBOL_HDA(snd_hda_bind_vol);
Takashi Iwai532d5382007-07-27 19:02:40 +02002240
2241struct hda_ctl_ops snd_hda_bind_sw = {
2242 .info = snd_hda_mixer_amp_switch_info,
2243 .get = snd_hda_mixer_amp_switch_get,
2244 .put = snd_hda_mixer_amp_switch_put,
2245 .tlv = snd_hda_mixer_amp_tlv
2246};
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002247EXPORT_SYMBOL_HDA(snd_hda_bind_sw);
Takashi Iwai532d5382007-07-27 19:02:40 +02002248
2249/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002250 * SPDIF out controls
2251 */
2252
Takashi Iwai0ba21762007-04-16 11:29:14 +02002253static int snd_hda_spdif_mask_info(struct snd_kcontrol *kcontrol,
2254 struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002255{
2256 uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
2257 uinfo->count = 1;
2258 return 0;
2259}
2260
Takashi Iwai0ba21762007-04-16 11:29:14 +02002261static int snd_hda_spdif_cmask_get(struct snd_kcontrol *kcontrol,
2262 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002263{
2264 ucontrol->value.iec958.status[0] = IEC958_AES0_PROFESSIONAL |
2265 IEC958_AES0_NONAUDIO |
2266 IEC958_AES0_CON_EMPHASIS_5015 |
2267 IEC958_AES0_CON_NOT_COPYRIGHT;
2268 ucontrol->value.iec958.status[1] = IEC958_AES1_CON_CATEGORY |
2269 IEC958_AES1_CON_ORIGINAL;
2270 return 0;
2271}
2272
Takashi Iwai0ba21762007-04-16 11:29:14 +02002273static int snd_hda_spdif_pmask_get(struct snd_kcontrol *kcontrol,
2274 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002275{
2276 ucontrol->value.iec958.status[0] = IEC958_AES0_PROFESSIONAL |
2277 IEC958_AES0_NONAUDIO |
2278 IEC958_AES0_PRO_EMPHASIS_5015;
2279 return 0;
2280}
2281
Takashi Iwai0ba21762007-04-16 11:29:14 +02002282static int snd_hda_spdif_default_get(struct snd_kcontrol *kcontrol,
2283 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002284{
2285 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2286
2287 ucontrol->value.iec958.status[0] = codec->spdif_status & 0xff;
2288 ucontrol->value.iec958.status[1] = (codec->spdif_status >> 8) & 0xff;
2289 ucontrol->value.iec958.status[2] = (codec->spdif_status >> 16) & 0xff;
2290 ucontrol->value.iec958.status[3] = (codec->spdif_status >> 24) & 0xff;
2291
2292 return 0;
2293}
2294
2295/* convert from SPDIF status bits to HDA SPDIF bits
2296 * bit 0 (DigEn) is always set zero (to be filled later)
2297 */
2298static unsigned short convert_from_spdif_status(unsigned int sbits)
2299{
2300 unsigned short val = 0;
2301
2302 if (sbits & IEC958_AES0_PROFESSIONAL)
Takashi Iwai0ba21762007-04-16 11:29:14 +02002303 val |= AC_DIG1_PROFESSIONAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002304 if (sbits & IEC958_AES0_NONAUDIO)
Takashi Iwai0ba21762007-04-16 11:29:14 +02002305 val |= AC_DIG1_NONAUDIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002306 if (sbits & IEC958_AES0_PROFESSIONAL) {
Takashi Iwai0ba21762007-04-16 11:29:14 +02002307 if ((sbits & IEC958_AES0_PRO_EMPHASIS) ==
2308 IEC958_AES0_PRO_EMPHASIS_5015)
2309 val |= AC_DIG1_EMPHASIS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002310 } else {
Takashi Iwai0ba21762007-04-16 11:29:14 +02002311 if ((sbits & IEC958_AES0_CON_EMPHASIS) ==
2312 IEC958_AES0_CON_EMPHASIS_5015)
2313 val |= AC_DIG1_EMPHASIS;
2314 if (!(sbits & IEC958_AES0_CON_NOT_COPYRIGHT))
2315 val |= AC_DIG1_COPYRIGHT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002316 if (sbits & (IEC958_AES1_CON_ORIGINAL << 8))
Takashi Iwai0ba21762007-04-16 11:29:14 +02002317 val |= AC_DIG1_LEVEL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002318 val |= sbits & (IEC958_AES1_CON_CATEGORY << 8);
2319 }
2320 return val;
2321}
2322
2323/* convert to SPDIF status bits from HDA SPDIF bits
2324 */
2325static unsigned int convert_to_spdif_status(unsigned short val)
2326{
2327 unsigned int sbits = 0;
2328
Takashi Iwai0ba21762007-04-16 11:29:14 +02002329 if (val & AC_DIG1_NONAUDIO)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002330 sbits |= IEC958_AES0_NONAUDIO;
Takashi Iwai0ba21762007-04-16 11:29:14 +02002331 if (val & AC_DIG1_PROFESSIONAL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002332 sbits |= IEC958_AES0_PROFESSIONAL;
2333 if (sbits & IEC958_AES0_PROFESSIONAL) {
Takashi Iwai0ba21762007-04-16 11:29:14 +02002334 if (sbits & AC_DIG1_EMPHASIS)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002335 sbits |= IEC958_AES0_PRO_EMPHASIS_5015;
2336 } else {
Takashi Iwai0ba21762007-04-16 11:29:14 +02002337 if (val & AC_DIG1_EMPHASIS)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002338 sbits |= IEC958_AES0_CON_EMPHASIS_5015;
Takashi Iwai0ba21762007-04-16 11:29:14 +02002339 if (!(val & AC_DIG1_COPYRIGHT))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002340 sbits |= IEC958_AES0_CON_NOT_COPYRIGHT;
Takashi Iwai0ba21762007-04-16 11:29:14 +02002341 if (val & AC_DIG1_LEVEL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002342 sbits |= (IEC958_AES1_CON_ORIGINAL << 8);
2343 sbits |= val & (0x7f << 8);
2344 }
2345 return sbits;
2346}
2347
Takashi Iwai2f728532008-09-25 16:32:41 +02002348/* set digital convert verbs both for the given NID and its slaves */
2349static void set_dig_out(struct hda_codec *codec, hda_nid_t nid,
2350 int verb, int val)
2351{
2352 hda_nid_t *d;
2353
Takashi Iwai9e976972008-11-25 08:17:20 +01002354 snd_hda_codec_write_cache(codec, nid, 0, verb, val);
Takashi Iwai2f728532008-09-25 16:32:41 +02002355 d = codec->slave_dig_outs;
2356 if (!d)
2357 return;
2358 for (; *d; d++)
Takashi Iwai9e976972008-11-25 08:17:20 +01002359 snd_hda_codec_write_cache(codec, *d, 0, verb, val);
Takashi Iwai2f728532008-09-25 16:32:41 +02002360}
2361
2362static inline void set_dig_out_convert(struct hda_codec *codec, hda_nid_t nid,
2363 int dig1, int dig2)
2364{
2365 if (dig1 != -1)
2366 set_dig_out(codec, nid, AC_VERB_SET_DIGI_CONVERT_1, dig1);
2367 if (dig2 != -1)
2368 set_dig_out(codec, nid, AC_VERB_SET_DIGI_CONVERT_2, dig2);
2369}
2370
Takashi Iwai0ba21762007-04-16 11:29:14 +02002371static int snd_hda_spdif_default_put(struct snd_kcontrol *kcontrol,
2372 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002373{
2374 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2375 hda_nid_t nid = kcontrol->private_value;
2376 unsigned short val;
2377 int change;
2378
Ingo Molnar62932df2006-01-16 16:34:20 +01002379 mutex_lock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002380 codec->spdif_status = ucontrol->value.iec958.status[0] |
2381 ((unsigned int)ucontrol->value.iec958.status[1] << 8) |
2382 ((unsigned int)ucontrol->value.iec958.status[2] << 16) |
2383 ((unsigned int)ucontrol->value.iec958.status[3] << 24);
2384 val = convert_from_spdif_status(codec->spdif_status);
2385 val |= codec->spdif_ctls & 1;
2386 change = codec->spdif_ctls != val;
2387 codec->spdif_ctls = val;
2388
Takashi Iwai2f728532008-09-25 16:32:41 +02002389 if (change)
2390 set_dig_out_convert(codec, nid, val & 0xff, (val >> 8) & 0xff);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002391
Ingo Molnar62932df2006-01-16 16:34:20 +01002392 mutex_unlock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002393 return change;
2394}
2395
Takashi Iwaia5ce8892007-07-23 15:42:26 +02002396#define snd_hda_spdif_out_switch_info snd_ctl_boolean_mono_info
Linus Torvalds1da177e2005-04-16 15:20:36 -07002397
Takashi Iwai0ba21762007-04-16 11:29:14 +02002398static int snd_hda_spdif_out_switch_get(struct snd_kcontrol *kcontrol,
2399 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002400{
2401 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2402
Takashi Iwai0ba21762007-04-16 11:29:14 +02002403 ucontrol->value.integer.value[0] = codec->spdif_ctls & AC_DIG1_ENABLE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002404 return 0;
2405}
2406
Takashi Iwai0ba21762007-04-16 11:29:14 +02002407static int snd_hda_spdif_out_switch_put(struct snd_kcontrol *kcontrol,
2408 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002409{
2410 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2411 hda_nid_t nid = kcontrol->private_value;
2412 unsigned short val;
2413 int change;
2414
Ingo Molnar62932df2006-01-16 16:34:20 +01002415 mutex_lock(&codec->spdif_mutex);
Takashi Iwai0ba21762007-04-16 11:29:14 +02002416 val = codec->spdif_ctls & ~AC_DIG1_ENABLE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002417 if (ucontrol->value.integer.value[0])
Takashi Iwai0ba21762007-04-16 11:29:14 +02002418 val |= AC_DIG1_ENABLE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002419 change = codec->spdif_ctls != val;
Takashi Iwai82beb8f2007-08-10 17:09:26 +02002420 if (change) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002421 codec->spdif_ctls = val;
Takashi Iwai2f728532008-09-25 16:32:41 +02002422 set_dig_out_convert(codec, nid, val & 0xff, -1);
Takashi Iwai0ba21762007-04-16 11:29:14 +02002423 /* unmute amp switch (if any) */
2424 if ((get_wcaps(codec, nid) & AC_WCAP_OUT_AMP) &&
Takashi Iwai47fd8302007-08-10 17:11:07 +02002425 (val & AC_DIG1_ENABLE))
2426 snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0,
2427 HDA_AMP_MUTE, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002428 }
Ingo Molnar62932df2006-01-16 16:34:20 +01002429 mutex_unlock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002430 return change;
2431}
2432
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01002433static struct snd_kcontrol_new dig_mixes[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002434 {
2435 .access = SNDRV_CTL_ELEM_ACCESS_READ,
2436 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2437 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,CON_MASK),
2438 .info = snd_hda_spdif_mask_info,
2439 .get = snd_hda_spdif_cmask_get,
2440 },
2441 {
2442 .access = SNDRV_CTL_ELEM_ACCESS_READ,
2443 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2444 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,PRO_MASK),
2445 .info = snd_hda_spdif_mask_info,
2446 .get = snd_hda_spdif_pmask_get,
2447 },
2448 {
2449 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2450 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT),
2451 .info = snd_hda_spdif_mask_info,
2452 .get = snd_hda_spdif_default_get,
2453 .put = snd_hda_spdif_default_put,
2454 },
2455 {
2456 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2457 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,SWITCH),
2458 .info = snd_hda_spdif_out_switch_info,
2459 .get = snd_hda_spdif_out_switch_get,
2460 .put = snd_hda_spdif_out_switch_put,
2461 },
2462 { } /* end */
2463};
2464
Takashi Iwai09f99702008-02-04 12:31:13 +01002465#define SPDIF_MAX_IDX 4 /* 4 instances should be enough to probe */
2466
Linus Torvalds1da177e2005-04-16 15:20:36 -07002467/**
2468 * snd_hda_create_spdif_out_ctls - create Output SPDIF-related controls
2469 * @codec: the HDA codec
2470 * @nid: audio out widget NID
2471 *
2472 * Creates controls related with the SPDIF output.
2473 * Called from each patch supporting the SPDIF out.
2474 *
2475 * Returns 0 if successful, or a negative error code.
2476 */
Takashi Iwai12f288b2007-08-02 15:51:59 +02002477int snd_hda_create_spdif_out_ctls(struct hda_codec *codec, hda_nid_t nid)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002478{
2479 int err;
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01002480 struct snd_kcontrol *kctl;
2481 struct snd_kcontrol_new *dig_mix;
Takashi Iwai09f99702008-02-04 12:31:13 +01002482 int idx;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002483
Takashi Iwai09f99702008-02-04 12:31:13 +01002484 for (idx = 0; idx < SPDIF_MAX_IDX; idx++) {
2485 if (!_snd_hda_find_mixer_ctl(codec, "IEC958 Playback Switch",
2486 idx))
2487 break;
2488 }
2489 if (idx >= SPDIF_MAX_IDX) {
2490 printk(KERN_ERR "hda_codec: too many IEC958 outputs\n");
2491 return -EBUSY;
2492 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002493 for (dig_mix = dig_mixes; dig_mix->name; dig_mix++) {
2494 kctl = snd_ctl_new1(dig_mix, codec);
Takashi Iwaib91f0802008-11-04 08:43:08 +01002495 if (!kctl)
2496 return -ENOMEM;
Takashi Iwai09f99702008-02-04 12:31:13 +01002497 kctl->id.index = idx;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002498 kctl->private_value = nid;
Jaroslav Kysela3911a4c2009-11-11 13:43:01 +01002499 err = snd_hda_ctl_add(codec, nid, kctl);
Takashi Iwai0ba21762007-04-16 11:29:14 +02002500 if (err < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002501 return err;
2502 }
Takashi Iwai0ba21762007-04-16 11:29:14 +02002503 codec->spdif_ctls =
Andrew Paprocki3982d172007-12-19 12:13:44 +01002504 snd_hda_codec_read(codec, nid, 0,
2505 AC_VERB_GET_DIGI_CONVERT_1, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002506 codec->spdif_status = convert_to_spdif_status(codec->spdif_ctls);
2507 return 0;
2508}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002509EXPORT_SYMBOL_HDA(snd_hda_create_spdif_out_ctls);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002510
2511/*
Takashi Iwai9a081602008-02-12 18:37:26 +01002512 * SPDIF sharing with analog output
2513 */
2514static int spdif_share_sw_get(struct snd_kcontrol *kcontrol,
2515 struct snd_ctl_elem_value *ucontrol)
2516{
2517 struct hda_multi_out *mout = snd_kcontrol_chip(kcontrol);
2518 ucontrol->value.integer.value[0] = mout->share_spdif;
2519 return 0;
2520}
2521
2522static int spdif_share_sw_put(struct snd_kcontrol *kcontrol,
2523 struct snd_ctl_elem_value *ucontrol)
2524{
2525 struct hda_multi_out *mout = snd_kcontrol_chip(kcontrol);
2526 mout->share_spdif = !!ucontrol->value.integer.value[0];
2527 return 0;
2528}
2529
2530static struct snd_kcontrol_new spdif_share_sw = {
2531 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2532 .name = "IEC958 Default PCM Playback Switch",
2533 .info = snd_ctl_boolean_mono_info,
2534 .get = spdif_share_sw_get,
2535 .put = spdif_share_sw_put,
2536};
2537
Takashi Iwaid5191e52009-11-16 14:58:17 +01002538/**
2539 * snd_hda_create_spdif_share_sw - create Default PCM switch
2540 * @codec: the HDA codec
2541 * @mout: multi-out instance
2542 */
Takashi Iwai9a081602008-02-12 18:37:26 +01002543int snd_hda_create_spdif_share_sw(struct hda_codec *codec,
2544 struct hda_multi_out *mout)
2545{
2546 if (!mout->dig_out_nid)
2547 return 0;
2548 /* ATTENTION: here mout is passed as private_data, instead of codec */
Jaroslav Kysela3911a4c2009-11-11 13:43:01 +01002549 return snd_hda_ctl_add(codec, mout->dig_out_nid,
2550 snd_ctl_new1(&spdif_share_sw, mout));
Takashi Iwai9a081602008-02-12 18:37:26 +01002551}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002552EXPORT_SYMBOL_HDA(snd_hda_create_spdif_share_sw);
Takashi Iwai9a081602008-02-12 18:37:26 +01002553
2554/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002555 * SPDIF input
2556 */
2557
2558#define snd_hda_spdif_in_switch_info snd_hda_spdif_out_switch_info
2559
Takashi Iwai0ba21762007-04-16 11:29:14 +02002560static int snd_hda_spdif_in_switch_get(struct snd_kcontrol *kcontrol,
2561 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002562{
2563 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2564
2565 ucontrol->value.integer.value[0] = codec->spdif_in_enable;
2566 return 0;
2567}
2568
Takashi Iwai0ba21762007-04-16 11:29:14 +02002569static int snd_hda_spdif_in_switch_put(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 int val = !!ucontrol->value.integer.value[0];
2575 int change;
2576
Ingo Molnar62932df2006-01-16 16:34:20 +01002577 mutex_lock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002578 change = codec->spdif_in_enable != val;
Takashi Iwai82beb8f2007-08-10 17:09:26 +02002579 if (change) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002580 codec->spdif_in_enable = val;
Takashi Iwai82beb8f2007-08-10 17:09:26 +02002581 snd_hda_codec_write_cache(codec, nid, 0,
2582 AC_VERB_SET_DIGI_CONVERT_1, val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002583 }
Ingo Molnar62932df2006-01-16 16:34:20 +01002584 mutex_unlock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002585 return change;
2586}
2587
Takashi Iwai0ba21762007-04-16 11:29:14 +02002588static int snd_hda_spdif_in_status_get(struct snd_kcontrol *kcontrol,
2589 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002590{
2591 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2592 hda_nid_t nid = kcontrol->private_value;
2593 unsigned short val;
2594 unsigned int sbits;
2595
Andrew Paprocki3982d172007-12-19 12:13:44 +01002596 val = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_DIGI_CONVERT_1, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002597 sbits = convert_to_spdif_status(val);
2598 ucontrol->value.iec958.status[0] = sbits;
2599 ucontrol->value.iec958.status[1] = sbits >> 8;
2600 ucontrol->value.iec958.status[2] = sbits >> 16;
2601 ucontrol->value.iec958.status[3] = sbits >> 24;
2602 return 0;
2603}
2604
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01002605static struct snd_kcontrol_new dig_in_ctls[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002606 {
2607 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2608 .name = SNDRV_CTL_NAME_IEC958("",CAPTURE,SWITCH),
2609 .info = snd_hda_spdif_in_switch_info,
2610 .get = snd_hda_spdif_in_switch_get,
2611 .put = snd_hda_spdif_in_switch_put,
2612 },
2613 {
2614 .access = SNDRV_CTL_ELEM_ACCESS_READ,
2615 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2616 .name = SNDRV_CTL_NAME_IEC958("",CAPTURE,DEFAULT),
2617 .info = snd_hda_spdif_mask_info,
2618 .get = snd_hda_spdif_in_status_get,
2619 },
2620 { } /* end */
2621};
2622
2623/**
2624 * snd_hda_create_spdif_in_ctls - create Input SPDIF-related controls
2625 * @codec: the HDA codec
2626 * @nid: audio in widget NID
2627 *
2628 * Creates controls related with the SPDIF input.
2629 * Called from each patch supporting the SPDIF in.
2630 *
2631 * Returns 0 if successful, or a negative error code.
2632 */
Takashi Iwai12f288b2007-08-02 15:51:59 +02002633int snd_hda_create_spdif_in_ctls(struct hda_codec *codec, hda_nid_t nid)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002634{
2635 int err;
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01002636 struct snd_kcontrol *kctl;
2637 struct snd_kcontrol_new *dig_mix;
Takashi Iwai09f99702008-02-04 12:31:13 +01002638 int idx;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002639
Takashi Iwai09f99702008-02-04 12:31:13 +01002640 for (idx = 0; idx < SPDIF_MAX_IDX; idx++) {
2641 if (!_snd_hda_find_mixer_ctl(codec, "IEC958 Capture Switch",
2642 idx))
2643 break;
2644 }
2645 if (idx >= SPDIF_MAX_IDX) {
2646 printk(KERN_ERR "hda_codec: too many IEC958 inputs\n");
2647 return -EBUSY;
2648 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002649 for (dig_mix = dig_in_ctls; dig_mix->name; dig_mix++) {
2650 kctl = snd_ctl_new1(dig_mix, codec);
Takashi Iwaic8dcdf82009-02-06 16:21:20 +01002651 if (!kctl)
2652 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002653 kctl->private_value = nid;
Jaroslav Kysela3911a4c2009-11-11 13:43:01 +01002654 err = snd_hda_ctl_add(codec, nid, kctl);
Takashi Iwai0ba21762007-04-16 11:29:14 +02002655 if (err < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002656 return err;
2657 }
Takashi Iwai0ba21762007-04-16 11:29:14 +02002658 codec->spdif_in_enable =
Andrew Paprocki3982d172007-12-19 12:13:44 +01002659 snd_hda_codec_read(codec, nid, 0,
2660 AC_VERB_GET_DIGI_CONVERT_1, 0) &
Takashi Iwai0ba21762007-04-16 11:29:14 +02002661 AC_DIG1_ENABLE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002662 return 0;
2663}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002664EXPORT_SYMBOL_HDA(snd_hda_create_spdif_in_ctls);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002665
Takashi Iwaicb53c622007-08-10 17:21:45 +02002666#ifdef SND_HDA_NEEDS_RESUME
Takashi Iwai82beb8f2007-08-10 17:09:26 +02002667/*
2668 * command cache
2669 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002670
Takashi Iwaib3ac5632007-08-10 17:03:40 +02002671/* build a 32bit cache key with the widget id and the command parameter */
2672#define build_cmd_cache_key(nid, verb) ((verb << 8) | nid)
2673#define get_cmd_cache_nid(key) ((key) & 0xff)
2674#define get_cmd_cache_cmd(key) (((key) >> 8) & 0xffff)
2675
2676/**
2677 * snd_hda_codec_write_cache - send a single command with caching
2678 * @codec: the HDA codec
2679 * @nid: NID to send the command
2680 * @direct: direct flag
2681 * @verb: the verb to send
2682 * @parm: the parameter for the verb
2683 *
2684 * Send a single command without waiting for response.
2685 *
2686 * Returns 0 if successful, or a negative error code.
2687 */
2688int snd_hda_codec_write_cache(struct hda_codec *codec, hda_nid_t nid,
2689 int direct, unsigned int verb, unsigned int parm)
2690{
Takashi Iwaiaa2936f2009-05-26 16:07:57 +02002691 int err = snd_hda_codec_write(codec, nid, direct, verb, parm);
2692 struct hda_cache_head *c;
2693 u32 key;
Takashi Iwai33fa35e2008-11-06 16:50:40 +01002694
Takashi Iwaiaa2936f2009-05-26 16:07:57 +02002695 if (err < 0)
2696 return err;
2697 /* parm may contain the verb stuff for get/set amp */
2698 verb = verb | (parm >> 8);
2699 parm &= 0xff;
2700 key = build_cmd_cache_key(nid, verb);
2701 mutex_lock(&codec->bus->cmd_mutex);
2702 c = get_alloc_hash(&codec->cmd_cache, key);
2703 if (c)
2704 c->val = parm;
2705 mutex_unlock(&codec->bus->cmd_mutex);
2706 return 0;
Takashi Iwaib3ac5632007-08-10 17:03:40 +02002707}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002708EXPORT_SYMBOL_HDA(snd_hda_codec_write_cache);
Takashi Iwaib3ac5632007-08-10 17:03:40 +02002709
Takashi Iwaid5191e52009-11-16 14:58:17 +01002710/**
2711 * snd_hda_codec_resume_cache - Resume the all commands from the cache
2712 * @codec: HD-audio codec
2713 *
2714 * Execute all verbs recorded in the command caches to resume.
2715 */
Takashi Iwaib3ac5632007-08-10 17:03:40 +02002716void snd_hda_codec_resume_cache(struct hda_codec *codec)
2717{
Takashi Iwai603c4012008-07-30 15:01:44 +02002718 struct hda_cache_head *buffer = codec->cmd_cache.buf.list;
Takashi Iwaib3ac5632007-08-10 17:03:40 +02002719 int i;
2720
Takashi Iwai603c4012008-07-30 15:01:44 +02002721 for (i = 0; i < codec->cmd_cache.buf.used; i++, buffer++) {
Takashi Iwaib3ac5632007-08-10 17:03:40 +02002722 u32 key = buffer->key;
2723 if (!key)
2724 continue;
2725 snd_hda_codec_write(codec, get_cmd_cache_nid(key), 0,
2726 get_cmd_cache_cmd(key), buffer->val);
2727 }
2728}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002729EXPORT_SYMBOL_HDA(snd_hda_codec_resume_cache);
Takashi Iwaib3ac5632007-08-10 17:03:40 +02002730
2731/**
2732 * snd_hda_sequence_write_cache - sequence writes with caching
2733 * @codec: the HDA codec
2734 * @seq: VERB array to send
2735 *
2736 * Send the commands sequentially from the given array.
2737 * Thte commands are recorded on cache for power-save and resume.
2738 * The array must be terminated with NID=0.
2739 */
2740void snd_hda_sequence_write_cache(struct hda_codec *codec,
2741 const struct hda_verb *seq)
2742{
2743 for (; seq->nid; seq++)
2744 snd_hda_codec_write_cache(codec, seq->nid, 0, seq->verb,
2745 seq->param);
2746}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002747EXPORT_SYMBOL_HDA(snd_hda_sequence_write_cache);
Takashi Iwaicb53c622007-08-10 17:21:45 +02002748#endif /* SND_HDA_NEEDS_RESUME */
Takashi Iwaib3ac5632007-08-10 17:03:40 +02002749
Takashi Iwai54d17402005-11-21 16:33:22 +01002750/*
2751 * set power state of the codec
2752 */
2753static void hda_set_power_state(struct hda_codec *codec, hda_nid_t fg,
2754 unsigned int power_state)
2755{
Takashi Iwaicb53c622007-08-10 17:21:45 +02002756 hda_nid_t nid;
2757 int i;
Takashi Iwai54d17402005-11-21 16:33:22 +01002758
Takashi Iwai05ff7e12009-07-22 12:39:24 +02002759 /* this delay seems necessary to avoid click noise at power-down */
2760 if (power_state == AC_PWRST_D3)
2761 msleep(100);
2762 snd_hda_codec_read(codec, fg, 0, AC_VERB_SET_POWER_STATE,
Takashi Iwai54d17402005-11-21 16:33:22 +01002763 power_state);
Takashi Iwai05ff7e12009-07-22 12:39:24 +02002764 /* partial workaround for "azx_get_response timeout" */
2765 if (power_state == AC_PWRST_D0)
2766 msleep(10);
Takashi Iwai54d17402005-11-21 16:33:22 +01002767
Takashi Iwaicb53c622007-08-10 17:21:45 +02002768 nid = codec->start_nid;
2769 for (i = 0; i < codec->num_nodes; i++, nid++) {
Takashi Iwai7eba5c92007-11-14 14:53:42 +01002770 unsigned int wcaps = get_wcaps(codec, nid);
2771 if (wcaps & AC_WCAP_POWER) {
Takashi Iwaia22d5432009-07-27 12:54:26 +02002772 unsigned int wid_type = get_wcaps_type(wcaps);
Takashi Iwaia3b48c82009-04-21 13:37:29 +02002773 if (power_state == AC_PWRST_D3 &&
2774 wid_type == AC_WID_PIN) {
Takashi Iwai7eba5c92007-11-14 14:53:42 +01002775 unsigned int pincap;
2776 /*
2777 * don't power down the widget if it controls
2778 * eapd and EAPD_BTLENABLE is set.
2779 */
Takashi Iwai14bafe32009-03-23 16:35:39 +01002780 pincap = snd_hda_query_pin_caps(codec, nid);
Takashi Iwai7eba5c92007-11-14 14:53:42 +01002781 if (pincap & AC_PINCAP_EAPD) {
2782 int eapd = snd_hda_codec_read(codec,
2783 nid, 0,
2784 AC_VERB_GET_EAPD_BTLENABLE, 0);
2785 eapd &= 0x02;
Takashi Iwaia3b48c82009-04-21 13:37:29 +02002786 if (eapd)
Takashi Iwai7eba5c92007-11-14 14:53:42 +01002787 continue;
2788 }
Takashi Iwai1194b5b2007-10-10 10:04:26 +02002789 }
Takashi Iwai54d17402005-11-21 16:33:22 +01002790 snd_hda_codec_write(codec, nid, 0,
2791 AC_VERB_SET_POWER_STATE,
2792 power_state);
Takashi Iwai1194b5b2007-10-10 10:04:26 +02002793 }
Takashi Iwai54d17402005-11-21 16:33:22 +01002794 }
2795
Takashi Iwaicb53c622007-08-10 17:21:45 +02002796 if (power_state == AC_PWRST_D0) {
2797 unsigned long end_time;
2798 int state;
Takashi Iwai54d17402005-11-21 16:33:22 +01002799 msleep(10);
Takashi Iwaicb53c622007-08-10 17:21:45 +02002800 /* wait until the codec reachs to D0 */
2801 end_time = jiffies + msecs_to_jiffies(500);
2802 do {
2803 state = snd_hda_codec_read(codec, fg, 0,
2804 AC_VERB_GET_POWER_STATE, 0);
2805 if (state == power_state)
2806 break;
2807 msleep(1);
2808 } while (time_after_eq(end_time, jiffies));
2809 }
Takashi Iwai54d17402005-11-21 16:33:22 +01002810}
2811
Takashi Iwai11aeff02008-07-30 15:01:46 +02002812#ifdef CONFIG_SND_HDA_HWDEP
2813/* execute additional init verbs */
2814static void hda_exec_init_verbs(struct hda_codec *codec)
2815{
2816 if (codec->init_verbs.list)
2817 snd_hda_sequence_write(codec, codec->init_verbs.list);
2818}
2819#else
2820static inline void hda_exec_init_verbs(struct hda_codec *codec) {}
2821#endif
2822
Takashi Iwaicb53c622007-08-10 17:21:45 +02002823#ifdef SND_HDA_NEEDS_RESUME
2824/*
2825 * call suspend and power-down; used both from PM and power-save
2826 */
2827static void hda_call_codec_suspend(struct hda_codec *codec)
2828{
2829 if (codec->patch_ops.suspend)
2830 codec->patch_ops.suspend(codec, PMSG_SUSPEND);
2831 hda_set_power_state(codec,
2832 codec->afg ? codec->afg : codec->mfg,
2833 AC_PWRST_D3);
2834#ifdef CONFIG_SND_HDA_POWER_SAVE
Takashi Iwaia2f63092009-11-11 09:34:25 +01002835 snd_hda_update_power_acct(codec);
Takashi Iwaicb53c622007-08-10 17:21:45 +02002836 cancel_delayed_work(&codec->power_work);
Takashi Iwai95e99fd2007-08-13 15:29:04 +02002837 codec->power_on = 0;
Takashi Iwaia221e282007-08-16 16:35:33 +02002838 codec->power_transition = 0;
Takashi Iwaia2f63092009-11-11 09:34:25 +01002839 codec->power_jiffies = jiffies;
Takashi Iwaicb53c622007-08-10 17:21:45 +02002840#endif
2841}
2842
2843/*
2844 * kick up codec; used both from PM and power-save
2845 */
2846static void hda_call_codec_resume(struct hda_codec *codec)
2847{
2848 hda_set_power_state(codec,
2849 codec->afg ? codec->afg : codec->mfg,
2850 AC_PWRST_D0);
Takashi Iwai3be14142009-02-20 14:11:16 +01002851 restore_pincfgs(codec); /* restore all current pin configs */
Takashi Iwai11aeff02008-07-30 15:01:46 +02002852 hda_exec_init_verbs(codec);
Takashi Iwaicb53c622007-08-10 17:21:45 +02002853 if (codec->patch_ops.resume)
2854 codec->patch_ops.resume(codec);
2855 else {
Takashi Iwai9d99f312007-08-14 15:15:52 +02002856 if (codec->patch_ops.init)
2857 codec->patch_ops.init(codec);
Takashi Iwaicb53c622007-08-10 17:21:45 +02002858 snd_hda_codec_resume_amp(codec);
2859 snd_hda_codec_resume_cache(codec);
2860 }
2861}
2862#endif /* SND_HDA_NEEDS_RESUME */
2863
Takashi Iwai54d17402005-11-21 16:33:22 +01002864
Linus Torvalds1da177e2005-04-16 15:20:36 -07002865/**
2866 * snd_hda_build_controls - build mixer controls
2867 * @bus: the BUS
2868 *
2869 * Creates mixer controls for each codec included in the bus.
2870 *
2871 * Returns 0 if successful, otherwise a negative error code.
2872 */
Takashi Iwai1289e9e2008-11-27 15:47:11 +01002873int /*__devinit*/ snd_hda_build_controls(struct hda_bus *bus)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002874{
Takashi Iwai0ba21762007-04-16 11:29:14 +02002875 struct hda_codec *codec;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002876
Takashi Iwai0ba21762007-04-16 11:29:14 +02002877 list_for_each_entry(codec, &bus->codec_list, list) {
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02002878 int err = snd_hda_codec_build_controls(codec);
Takashi Iwaif93d4612009-03-02 10:44:15 +01002879 if (err < 0) {
2880 printk(KERN_ERR "hda_codec: cannot build controls"
2881 "for #%d (error %d)\n", codec->addr, err);
2882 err = snd_hda_codec_reset(codec);
2883 if (err < 0) {
2884 printk(KERN_ERR
2885 "hda_codec: cannot revert codec\n");
2886 return err;
2887 }
2888 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002889 }
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02002890 return 0;
2891}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002892EXPORT_SYMBOL_HDA(snd_hda_build_controls);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002893
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02002894int snd_hda_codec_build_controls(struct hda_codec *codec)
2895{
2896 int err = 0;
Takashi Iwai11aeff02008-07-30 15:01:46 +02002897 hda_exec_init_verbs(codec);
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02002898 /* continue to initialize... */
2899 if (codec->patch_ops.init)
2900 err = codec->patch_ops.init(codec);
2901 if (!err && codec->patch_ops.build_controls)
2902 err = codec->patch_ops.build_controls(codec);
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02002903 if (err < 0)
2904 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002905 return 0;
2906}
2907
Linus Torvalds1da177e2005-04-16 15:20:36 -07002908/*
2909 * stream formats
2910 */
Takashi Iwaibefdf312005-08-22 13:57:55 +02002911struct hda_rate_tbl {
2912 unsigned int hz;
2913 unsigned int alsa_bits;
2914 unsigned int hda_fmt;
2915};
2916
2917static struct hda_rate_tbl rate_bits[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002918 /* rate in Hz, ALSA rate bitmask, HDA format value */
Nicolas Graziano9d8f53f2005-08-22 13:47:16 +02002919
2920 /* autodetected value used in snd_hda_query_supported_pcm */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002921 { 8000, SNDRV_PCM_RATE_8000, 0x0500 }, /* 1/6 x 48 */
2922 { 11025, SNDRV_PCM_RATE_11025, 0x4300 }, /* 1/4 x 44 */
2923 { 16000, SNDRV_PCM_RATE_16000, 0x0200 }, /* 1/3 x 48 */
2924 { 22050, SNDRV_PCM_RATE_22050, 0x4100 }, /* 1/2 x 44 */
2925 { 32000, SNDRV_PCM_RATE_32000, 0x0a00 }, /* 2/3 x 48 */
2926 { 44100, SNDRV_PCM_RATE_44100, 0x4000 }, /* 44 */
2927 { 48000, SNDRV_PCM_RATE_48000, 0x0000 }, /* 48 */
2928 { 88200, SNDRV_PCM_RATE_88200, 0x4800 }, /* 2 x 44 */
2929 { 96000, SNDRV_PCM_RATE_96000, 0x0800 }, /* 2 x 48 */
2930 { 176400, SNDRV_PCM_RATE_176400, 0x5800 },/* 4 x 44 */
2931 { 192000, SNDRV_PCM_RATE_192000, 0x1800 }, /* 4 x 48 */
Takashi Iwaia961f9f2007-04-12 13:08:09 +02002932#define AC_PAR_PCM_RATE_BITS 11
2933 /* up to bits 10, 384kHZ isn't supported properly */
2934
2935 /* not autodetected value */
2936 { 9600, SNDRV_PCM_RATE_KNOT, 0x0400 }, /* 1/5 x 48 */
Nicolas Graziano9d8f53f2005-08-22 13:47:16 +02002937
Takashi Iwaibefdf312005-08-22 13:57:55 +02002938 { 0 } /* terminator */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002939};
2940
2941/**
2942 * snd_hda_calc_stream_format - calculate format bitset
2943 * @rate: the sample rate
2944 * @channels: the number of channels
2945 * @format: the PCM format (SNDRV_PCM_FORMAT_XXX)
2946 * @maxbps: the max. bps
2947 *
2948 * Calculate the format bitset from the given rate, channels and th PCM format.
2949 *
2950 * Return zero if invalid.
2951 */
2952unsigned int snd_hda_calc_stream_format(unsigned int rate,
2953 unsigned int channels,
2954 unsigned int format,
2955 unsigned int maxbps)
2956{
2957 int i;
2958 unsigned int val = 0;
2959
Takashi Iwaibefdf312005-08-22 13:57:55 +02002960 for (i = 0; rate_bits[i].hz; i++)
2961 if (rate_bits[i].hz == rate) {
2962 val = rate_bits[i].hda_fmt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002963 break;
2964 }
Takashi Iwai0ba21762007-04-16 11:29:14 +02002965 if (!rate_bits[i].hz) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002966 snd_printdd("invalid rate %d\n", rate);
2967 return 0;
2968 }
2969
2970 if (channels == 0 || channels > 8) {
2971 snd_printdd("invalid channels %d\n", channels);
2972 return 0;
2973 }
2974 val |= channels - 1;
2975
2976 switch (snd_pcm_format_width(format)) {
2977 case 8: val |= 0x00; break;
2978 case 16: val |= 0x10; break;
2979 case 20:
2980 case 24:
2981 case 32:
Takashi Iwaib0bb3aa2009-07-03 23:25:37 +02002982 if (maxbps >= 32 || format == SNDRV_PCM_FORMAT_FLOAT_LE)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002983 val |= 0x40;
2984 else if (maxbps >= 24)
2985 val |= 0x30;
2986 else
2987 val |= 0x20;
2988 break;
2989 default:
Takashi Iwai0ba21762007-04-16 11:29:14 +02002990 snd_printdd("invalid format width %d\n",
2991 snd_pcm_format_width(format));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002992 return 0;
2993 }
2994
2995 return val;
2996}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002997EXPORT_SYMBOL_HDA(snd_hda_calc_stream_format);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002998
Takashi Iwai92c7c8a2009-03-24 07:32:14 +01002999static unsigned int get_pcm_param(struct hda_codec *codec, hda_nid_t nid)
3000{
3001 unsigned int val = 0;
3002 if (nid != codec->afg &&
3003 (get_wcaps(codec, nid) & AC_WCAP_FORMAT_OVRD))
3004 val = snd_hda_param_read(codec, nid, AC_PAR_PCM);
3005 if (!val || val == -1)
3006 val = snd_hda_param_read(codec, codec->afg, AC_PAR_PCM);
3007 if (!val || val == -1)
3008 return 0;
3009 return val;
3010}
3011
3012static unsigned int query_pcm_param(struct hda_codec *codec, hda_nid_t nid)
3013{
3014 return query_caps_hash(codec, nid, HDA_HASH_PARPCM_KEY(nid),
3015 get_pcm_param);
3016}
3017
3018static unsigned int get_stream_param(struct hda_codec *codec, hda_nid_t nid)
3019{
3020 unsigned int streams = snd_hda_param_read(codec, nid, AC_PAR_STREAM);
3021 if (!streams || streams == -1)
3022 streams = snd_hda_param_read(codec, codec->afg, AC_PAR_STREAM);
3023 if (!streams || streams == -1)
3024 return 0;
3025 return streams;
3026}
3027
3028static unsigned int query_stream_param(struct hda_codec *codec, hda_nid_t nid)
3029{
3030 return query_caps_hash(codec, nid, HDA_HASH_PARSTR_KEY(nid),
3031 get_stream_param);
3032}
3033
Linus Torvalds1da177e2005-04-16 15:20:36 -07003034/**
3035 * snd_hda_query_supported_pcm - query the supported PCM rates and formats
3036 * @codec: the HDA codec
3037 * @nid: NID to query
3038 * @ratesp: the pointer to store the detected rate bitflags
3039 * @formatsp: the pointer to store the detected formats
3040 * @bpsp: the pointer to store the detected format widths
3041 *
3042 * Queries the supported PCM rates and formats. The NULL @ratesp, @formatsp
3043 * or @bsps argument is ignored.
3044 *
3045 * Returns 0 if successful, otherwise a negative error code.
3046 */
Takashi Iwai986862bd2008-11-27 12:40:13 +01003047static int snd_hda_query_supported_pcm(struct hda_codec *codec, hda_nid_t nid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003048 u32 *ratesp, u64 *formatsp, unsigned int *bpsp)
3049{
Jaroslav Kyselaee504712009-03-17 14:30:31 +01003050 unsigned int i, val, wcaps;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003051
Jaroslav Kyselaee504712009-03-17 14:30:31 +01003052 wcaps = get_wcaps(codec, nid);
Takashi Iwai92c7c8a2009-03-24 07:32:14 +01003053 val = query_pcm_param(codec, nid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003054
3055 if (ratesp) {
3056 u32 rates = 0;
Takashi Iwaia961f9f2007-04-12 13:08:09 +02003057 for (i = 0; i < AC_PAR_PCM_RATE_BITS; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003058 if (val & (1 << i))
Takashi Iwaibefdf312005-08-22 13:57:55 +02003059 rates |= rate_bits[i].alsa_bits;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003060 }
Jaroslav Kyselaee504712009-03-17 14:30:31 +01003061 if (rates == 0) {
3062 snd_printk(KERN_ERR "hda_codec: rates == 0 "
3063 "(nid=0x%x, val=0x%x, ovrd=%i)\n",
3064 nid, val,
3065 (wcaps & AC_WCAP_FORMAT_OVRD) ? 1 : 0);
3066 return -EIO;
3067 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003068 *ratesp = rates;
3069 }
3070
3071 if (formatsp || bpsp) {
3072 u64 formats = 0;
Jaroslav Kyselaee504712009-03-17 14:30:31 +01003073 unsigned int streams, bps;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003074
Takashi Iwai92c7c8a2009-03-24 07:32:14 +01003075 streams = query_stream_param(codec, nid);
3076 if (!streams)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003077 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003078
3079 bps = 0;
3080 if (streams & AC_SUPFMT_PCM) {
3081 if (val & AC_SUPPCM_BITS_8) {
3082 formats |= SNDRV_PCM_FMTBIT_U8;
3083 bps = 8;
3084 }
3085 if (val & AC_SUPPCM_BITS_16) {
3086 formats |= SNDRV_PCM_FMTBIT_S16_LE;
3087 bps = 16;
3088 }
3089 if (wcaps & AC_WCAP_DIGITAL) {
3090 if (val & AC_SUPPCM_BITS_32)
3091 formats |= SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_LE;
3092 if (val & (AC_SUPPCM_BITS_20|AC_SUPPCM_BITS_24))
3093 formats |= SNDRV_PCM_FMTBIT_S32_LE;
3094 if (val & AC_SUPPCM_BITS_24)
3095 bps = 24;
3096 else if (val & AC_SUPPCM_BITS_20)
3097 bps = 20;
Takashi Iwai0ba21762007-04-16 11:29:14 +02003098 } else if (val & (AC_SUPPCM_BITS_20|AC_SUPPCM_BITS_24|
3099 AC_SUPPCM_BITS_32)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003100 formats |= SNDRV_PCM_FMTBIT_S32_LE;
3101 if (val & AC_SUPPCM_BITS_32)
3102 bps = 32;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003103 else if (val & AC_SUPPCM_BITS_24)
3104 bps = 24;
Nicolas Graziano33ef76512006-09-19 14:23:14 +02003105 else if (val & AC_SUPPCM_BITS_20)
3106 bps = 20;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003107 }
3108 }
Takashi Iwaib5025c52009-07-01 18:05:27 +02003109 if (streams & AC_SUPFMT_FLOAT32) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003110 formats |= SNDRV_PCM_FMTBIT_FLOAT_LE;
Takashi Iwaib0bb3aa2009-07-03 23:25:37 +02003111 if (!bps)
3112 bps = 32;
Takashi Iwaib5025c52009-07-01 18:05:27 +02003113 }
3114 if (streams == AC_SUPFMT_AC3) {
Takashi Iwai0ba21762007-04-16 11:29:14 +02003115 /* should be exclusive */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003116 /* temporary hack: we have still no proper support
3117 * for the direct AC3 stream...
3118 */
3119 formats |= SNDRV_PCM_FMTBIT_U8;
3120 bps = 8;
3121 }
Jaroslav Kyselaee504712009-03-17 14:30:31 +01003122 if (formats == 0) {
3123 snd_printk(KERN_ERR "hda_codec: formats == 0 "
3124 "(nid=0x%x, val=0x%x, ovrd=%i, "
3125 "streams=0x%x)\n",
3126 nid, val,
3127 (wcaps & AC_WCAP_FORMAT_OVRD) ? 1 : 0,
3128 streams);
3129 return -EIO;
3130 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003131 if (formatsp)
3132 *formatsp = formats;
3133 if (bpsp)
3134 *bpsp = bps;
3135 }
3136
3137 return 0;
3138}
3139
3140/**
Takashi Iwaid5191e52009-11-16 14:58:17 +01003141 * snd_hda_is_supported_format - Check the validity of the format
3142 * @codec: HD-audio codec
3143 * @nid: NID to check
3144 * @format: the HD-audio format value to check
3145 *
3146 * Check whether the given node supports the format value.
Linus Torvalds1da177e2005-04-16 15:20:36 -07003147 *
3148 * Returns 1 if supported, 0 if not.
3149 */
3150int snd_hda_is_supported_format(struct hda_codec *codec, hda_nid_t nid,
3151 unsigned int format)
3152{
3153 int i;
3154 unsigned int val = 0, rate, stream;
3155
Takashi Iwai92c7c8a2009-03-24 07:32:14 +01003156 val = query_pcm_param(codec, nid);
3157 if (!val)
3158 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003159
3160 rate = format & 0xff00;
Takashi Iwaia961f9f2007-04-12 13:08:09 +02003161 for (i = 0; i < AC_PAR_PCM_RATE_BITS; i++)
Takashi Iwaibefdf312005-08-22 13:57:55 +02003162 if (rate_bits[i].hda_fmt == rate) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003163 if (val & (1 << i))
3164 break;
3165 return 0;
3166 }
Takashi Iwaia961f9f2007-04-12 13:08:09 +02003167 if (i >= AC_PAR_PCM_RATE_BITS)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003168 return 0;
3169
Takashi Iwai92c7c8a2009-03-24 07:32:14 +01003170 stream = query_stream_param(codec, nid);
3171 if (!stream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003172 return 0;
3173
3174 if (stream & AC_SUPFMT_PCM) {
3175 switch (format & 0xf0) {
3176 case 0x00:
Takashi Iwai0ba21762007-04-16 11:29:14 +02003177 if (!(val & AC_SUPPCM_BITS_8))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003178 return 0;
3179 break;
3180 case 0x10:
Takashi Iwai0ba21762007-04-16 11:29:14 +02003181 if (!(val & AC_SUPPCM_BITS_16))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003182 return 0;
3183 break;
3184 case 0x20:
Takashi Iwai0ba21762007-04-16 11:29:14 +02003185 if (!(val & AC_SUPPCM_BITS_20))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003186 return 0;
3187 break;
3188 case 0x30:
Takashi Iwai0ba21762007-04-16 11:29:14 +02003189 if (!(val & AC_SUPPCM_BITS_24))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003190 return 0;
3191 break;
3192 case 0x40:
Takashi Iwai0ba21762007-04-16 11:29:14 +02003193 if (!(val & AC_SUPPCM_BITS_32))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003194 return 0;
3195 break;
3196 default:
3197 return 0;
3198 }
3199 } else {
3200 /* FIXME: check for float32 and AC3? */
3201 }
3202
3203 return 1;
3204}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003205EXPORT_SYMBOL_HDA(snd_hda_is_supported_format);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003206
3207/*
3208 * PCM stuff
3209 */
3210static int hda_pcm_default_open_close(struct hda_pcm_stream *hinfo,
3211 struct hda_codec *codec,
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01003212 struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003213{
3214 return 0;
3215}
3216
3217static int hda_pcm_default_prepare(struct hda_pcm_stream *hinfo,
3218 struct hda_codec *codec,
3219 unsigned int stream_tag,
3220 unsigned int format,
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01003221 struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003222{
3223 snd_hda_codec_setup_stream(codec, hinfo->nid, stream_tag, 0, format);
3224 return 0;
3225}
3226
3227static int hda_pcm_default_cleanup(struct hda_pcm_stream *hinfo,
3228 struct hda_codec *codec,
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01003229 struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003230{
Takashi Iwai888afa12008-03-18 09:57:50 +01003231 snd_hda_codec_cleanup_stream(codec, hinfo->nid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003232 return 0;
3233}
3234
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02003235static int set_pcm_default_values(struct hda_codec *codec,
3236 struct hda_pcm_stream *info)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003237{
Jaroslav Kyselaee504712009-03-17 14:30:31 +01003238 int err;
3239
Takashi Iwai0ba21762007-04-16 11:29:14 +02003240 /* query support PCM information from the given NID */
3241 if (info->nid && (!info->rates || !info->formats)) {
Jaroslav Kyselaee504712009-03-17 14:30:31 +01003242 err = snd_hda_query_supported_pcm(codec, info->nid,
Takashi Iwai0ba21762007-04-16 11:29:14 +02003243 info->rates ? NULL : &info->rates,
3244 info->formats ? NULL : &info->formats,
3245 info->maxbps ? NULL : &info->maxbps);
Jaroslav Kyselaee504712009-03-17 14:30:31 +01003246 if (err < 0)
3247 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003248 }
3249 if (info->ops.open == NULL)
3250 info->ops.open = hda_pcm_default_open_close;
3251 if (info->ops.close == NULL)
3252 info->ops.close = hda_pcm_default_open_close;
3253 if (info->ops.prepare == NULL) {
Takashi Iwaida3cec32008-08-08 17:12:14 +02003254 if (snd_BUG_ON(!info->nid))
3255 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003256 info->ops.prepare = hda_pcm_default_prepare;
3257 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003258 if (info->ops.cleanup == NULL) {
Takashi Iwaida3cec32008-08-08 17:12:14 +02003259 if (snd_BUG_ON(!info->nid))
3260 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003261 info->ops.cleanup = hda_pcm_default_cleanup;
3262 }
3263 return 0;
3264}
3265
Takashi Iwaid5191e52009-11-16 14:58:17 +01003266/* global */
Jaroslav Kyselae3303232009-11-10 14:53:02 +01003267const char *snd_hda_pcm_type_name[HDA_PCM_NTYPES] = {
3268 "Audio", "SPDIF", "HDMI", "Modem"
3269};
3270
Takashi Iwai176d5332008-07-30 15:01:44 +02003271/*
Takashi Iwai529bd6c2008-11-27 14:17:01 +01003272 * get the empty PCM device number to assign
3273 */
3274static int get_empty_pcm_device(struct hda_bus *bus, int type)
3275{
Wu Fengguangf5d6def52009-10-30 11:38:26 +01003276 /* audio device indices; not linear to keep compatibility */
3277 static int audio_idx[HDA_PCM_NTYPES][5] = {
3278 [HDA_PCM_TYPE_AUDIO] = { 0, 2, 4, 5, -1 },
3279 [HDA_PCM_TYPE_SPDIF] = { 1, -1 },
Wu Fengguang92608ba2009-10-30 11:40:03 +01003280 [HDA_PCM_TYPE_HDMI] = { 3, 7, 8, 9, -1 },
Wu Fengguangf5d6def52009-10-30 11:38:26 +01003281 [HDA_PCM_TYPE_MODEM] = { 6, -1 },
Takashi Iwai529bd6c2008-11-27 14:17:01 +01003282 };
Wu Fengguangf5d6def52009-10-30 11:38:26 +01003283 int i;
Takashi Iwai529bd6c2008-11-27 14:17:01 +01003284
Wu Fengguangf5d6def52009-10-30 11:38:26 +01003285 if (type >= HDA_PCM_NTYPES) {
Takashi Iwai529bd6c2008-11-27 14:17:01 +01003286 snd_printk(KERN_WARNING "Invalid PCM type %d\n", type);
3287 return -EINVAL;
3288 }
Wu Fengguangf5d6def52009-10-30 11:38:26 +01003289
3290 for (i = 0; audio_idx[type][i] >= 0 ; i++)
3291 if (!test_and_set_bit(audio_idx[type][i], bus->pcm_dev_bits))
3292 return audio_idx[type][i];
3293
Jaroslav Kyselae3303232009-11-10 14:53:02 +01003294 snd_printk(KERN_WARNING "Too many %s devices\n", snd_hda_pcm_type_name[type]);
Wu Fengguangf5d6def52009-10-30 11:38:26 +01003295 return -EAGAIN;
Takashi Iwai529bd6c2008-11-27 14:17:01 +01003296}
3297
3298/*
Takashi Iwai176d5332008-07-30 15:01:44 +02003299 * attach a new PCM stream
3300 */
Takashi Iwai529bd6c2008-11-27 14:17:01 +01003301static int snd_hda_attach_pcm(struct hda_codec *codec, struct hda_pcm *pcm)
Takashi Iwai176d5332008-07-30 15:01:44 +02003302{
Takashi Iwai33fa35e2008-11-06 16:50:40 +01003303 struct hda_bus *bus = codec->bus;
Takashi Iwai176d5332008-07-30 15:01:44 +02003304 struct hda_pcm_stream *info;
3305 int stream, err;
3306
Takashi Iwaib91f0802008-11-04 08:43:08 +01003307 if (snd_BUG_ON(!pcm->name))
Takashi Iwai176d5332008-07-30 15:01:44 +02003308 return -EINVAL;
3309 for (stream = 0; stream < 2; stream++) {
3310 info = &pcm->stream[stream];
3311 if (info->substreams) {
3312 err = set_pcm_default_values(codec, info);
3313 if (err < 0)
3314 return err;
3315 }
3316 }
Takashi Iwai33fa35e2008-11-06 16:50:40 +01003317 return bus->ops.attach_pcm(bus, codec, pcm);
Takashi Iwai176d5332008-07-30 15:01:44 +02003318}
3319
Takashi Iwai529bd6c2008-11-27 14:17:01 +01003320/* assign all PCMs of the given codec */
3321int snd_hda_codec_build_pcms(struct hda_codec *codec)
3322{
3323 unsigned int pcm;
3324 int err;
3325
3326 if (!codec->num_pcms) {
3327 if (!codec->patch_ops.build_pcms)
3328 return 0;
3329 err = codec->patch_ops.build_pcms(codec);
Takashi Iwai6e655bf2009-03-02 10:46:03 +01003330 if (err < 0) {
3331 printk(KERN_ERR "hda_codec: cannot build PCMs"
3332 "for #%d (error %d)\n", codec->addr, err);
3333 err = snd_hda_codec_reset(codec);
3334 if (err < 0) {
3335 printk(KERN_ERR
3336 "hda_codec: cannot revert codec\n");
3337 return err;
3338 }
3339 }
Takashi Iwai529bd6c2008-11-27 14:17:01 +01003340 }
3341 for (pcm = 0; pcm < codec->num_pcms; pcm++) {
3342 struct hda_pcm *cpcm = &codec->pcm_info[pcm];
3343 int dev;
3344
3345 if (!cpcm->stream[0].substreams && !cpcm->stream[1].substreams)
Takashi Iwai41b5b012009-01-20 18:21:23 +01003346 continue; /* no substreams assigned */
Takashi Iwai529bd6c2008-11-27 14:17:01 +01003347
3348 if (!cpcm->pcm) {
3349 dev = get_empty_pcm_device(codec->bus, cpcm->pcm_type);
3350 if (dev < 0)
Takashi Iwai6e655bf2009-03-02 10:46:03 +01003351 continue; /* no fatal error */
Takashi Iwai529bd6c2008-11-27 14:17:01 +01003352 cpcm->device = dev;
3353 err = snd_hda_attach_pcm(codec, cpcm);
Takashi Iwai6e655bf2009-03-02 10:46:03 +01003354 if (err < 0) {
3355 printk(KERN_ERR "hda_codec: cannot attach "
3356 "PCM stream %d for codec #%d\n",
3357 dev, codec->addr);
3358 continue; /* no fatal error */
3359 }
Takashi Iwai529bd6c2008-11-27 14:17:01 +01003360 }
3361 }
3362 return 0;
3363}
3364
Linus Torvalds1da177e2005-04-16 15:20:36 -07003365/**
3366 * snd_hda_build_pcms - build PCM information
3367 * @bus: the BUS
3368 *
3369 * Create PCM information for each codec included in the bus.
3370 *
3371 * The build_pcms codec patch is requested to set up codec->num_pcms and
3372 * codec->pcm_info properly. The array is referred by the top-level driver
3373 * to create its PCM instances.
3374 * The allocated codec->pcm_info should be released in codec->patch_ops.free
3375 * callback.
3376 *
3377 * At least, substreams, channels_min and channels_max must be filled for
3378 * each stream. substreams = 0 indicates that the stream doesn't exist.
3379 * When rates and/or formats are zero, the supported values are queried
3380 * from the given nid. The nid is used also by the default ops.prepare
3381 * and ops.cleanup callbacks.
3382 *
3383 * The driver needs to call ops.open in its open callback. Similarly,
3384 * ops.close is supposed to be called in the close callback.
3385 * ops.prepare should be called in the prepare or hw_params callback
3386 * with the proper parameters for set up.
3387 * ops.cleanup should be called in hw_free for clean up of streams.
3388 *
3389 * This function returns 0 if successfull, or a negative error code.
3390 */
Takashi Iwai529bd6c2008-11-27 14:17:01 +01003391int __devinit snd_hda_build_pcms(struct hda_bus *bus)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003392{
Takashi Iwai0ba21762007-04-16 11:29:14 +02003393 struct hda_codec *codec;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003394
Takashi Iwai0ba21762007-04-16 11:29:14 +02003395 list_for_each_entry(codec, &bus->codec_list, list) {
Takashi Iwai529bd6c2008-11-27 14:17:01 +01003396 int err = snd_hda_codec_build_pcms(codec);
3397 if (err < 0)
3398 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003399 }
3400 return 0;
3401}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003402EXPORT_SYMBOL_HDA(snd_hda_build_pcms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003403
Linus Torvalds1da177e2005-04-16 15:20:36 -07003404/**
3405 * snd_hda_check_board_config - compare the current codec with the config table
3406 * @codec: the HDA codec
Takashi Iwaif5fcc132006-11-24 17:07:44 +01003407 * @num_configs: number of config enums
3408 * @models: array of model name strings
Linus Torvalds1da177e2005-04-16 15:20:36 -07003409 * @tbl: configuration table, terminated by null entries
3410 *
3411 * Compares the modelname or PCI subsystem id of the current codec with the
3412 * given configuration table. If a matching entry is found, returns its
3413 * config value (supposed to be 0 or positive).
3414 *
3415 * If no entries are matching, the function returns a negative value.
3416 */
Takashi Iwai12f288b2007-08-02 15:51:59 +02003417int snd_hda_check_board_config(struct hda_codec *codec,
3418 int num_configs, const char **models,
3419 const struct snd_pci_quirk *tbl)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003420{
Takashi Iwaif44ac832008-07-30 15:01:45 +02003421 if (codec->modelname && models) {
Takashi Iwaif5fcc132006-11-24 17:07:44 +01003422 int i;
3423 for (i = 0; i < num_configs; i++) {
3424 if (models[i] &&
Takashi Iwaif44ac832008-07-30 15:01:45 +02003425 !strcmp(codec->modelname, models[i])) {
Takashi Iwaif5fcc132006-11-24 17:07:44 +01003426 snd_printd(KERN_INFO "hda_codec: model '%s' is "
3427 "selected\n", models[i]);
3428 return i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003429 }
3430 }
3431 }
3432
Takashi Iwaif5fcc132006-11-24 17:07:44 +01003433 if (!codec->bus->pci || !tbl)
3434 return -1;
3435
3436 tbl = snd_pci_quirk_lookup(codec->bus->pci, tbl);
3437 if (!tbl)
3438 return -1;
3439 if (tbl->value >= 0 && tbl->value < num_configs) {
Takashi Iwai62cf8722008-05-20 12:15:15 +02003440#ifdef CONFIG_SND_DEBUG_VERBOSE
Takashi Iwaif5fcc132006-11-24 17:07:44 +01003441 char tmp[10];
3442 const char *model = NULL;
3443 if (models)
3444 model = models[tbl->value];
3445 if (!model) {
3446 sprintf(tmp, "#%d", tbl->value);
3447 model = tmp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003448 }
Takashi Iwaif5fcc132006-11-24 17:07:44 +01003449 snd_printdd(KERN_INFO "hda_codec: model '%s' is selected "
3450 "for config %x:%x (%s)\n",
3451 model, tbl->subvendor, tbl->subdevice,
3452 (tbl->name ? tbl->name : "Unknown device"));
3453#endif
3454 return tbl->value;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003455 }
3456 return -1;
3457}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003458EXPORT_SYMBOL_HDA(snd_hda_check_board_config);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003459
3460/**
Mauro Carvalho Chehab2eda3442008-08-11 10:18:39 +02003461 * snd_hda_check_board_codec_sid_config - compare the current codec
3462 subsystem ID with the
3463 config table
3464
3465 This is important for Gateway notebooks with SB450 HDA Audio
3466 where the vendor ID of the PCI device is:
3467 ATI Technologies Inc SB450 HDA Audio [1002:437b]
3468 and the vendor/subvendor are found only at the codec.
3469
3470 * @codec: the HDA codec
3471 * @num_configs: number of config enums
3472 * @models: array of model name strings
3473 * @tbl: configuration table, terminated by null entries
3474 *
3475 * Compares the modelname or PCI subsystem id of the current codec with the
3476 * given configuration table. If a matching entry is found, returns its
3477 * config value (supposed to be 0 or positive).
3478 *
3479 * If no entries are matching, the function returns a negative value.
3480 */
3481int snd_hda_check_board_codec_sid_config(struct hda_codec *codec,
3482 int num_configs, const char **models,
3483 const struct snd_pci_quirk *tbl)
3484{
3485 const struct snd_pci_quirk *q;
3486
3487 /* Search for codec ID */
3488 for (q = tbl; q->subvendor; q++) {
3489 unsigned long vendorid = (q->subdevice) | (q->subvendor << 16);
3490
3491 if (vendorid == codec->subsystem_id)
3492 break;
3493 }
3494
3495 if (!q->subvendor)
3496 return -1;
3497
3498 tbl = q;
3499
3500 if (tbl->value >= 0 && tbl->value < num_configs) {
Takashi Iwaid94ff6b2009-09-02 00:20:21 +02003501#ifdef CONFIG_SND_DEBUG_VERBOSE
Mauro Carvalho Chehab2eda3442008-08-11 10:18:39 +02003502 char tmp[10];
3503 const char *model = NULL;
3504 if (models)
3505 model = models[tbl->value];
3506 if (!model) {
3507 sprintf(tmp, "#%d", tbl->value);
3508 model = tmp;
3509 }
3510 snd_printdd(KERN_INFO "hda_codec: model '%s' is selected "
3511 "for config %x:%x (%s)\n",
3512 model, tbl->subvendor, tbl->subdevice,
3513 (tbl->name ? tbl->name : "Unknown device"));
3514#endif
3515 return tbl->value;
3516 }
3517 return -1;
3518}
3519EXPORT_SYMBOL_HDA(snd_hda_check_board_codec_sid_config);
3520
3521/**
Linus Torvalds1da177e2005-04-16 15:20:36 -07003522 * snd_hda_add_new_ctls - create controls from the array
3523 * @codec: the HDA codec
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01003524 * @knew: the array of struct snd_kcontrol_new
Linus Torvalds1da177e2005-04-16 15:20:36 -07003525 *
3526 * This helper function creates and add new controls in the given array.
3527 * The array must be terminated with an empty entry as terminator.
3528 *
3529 * Returns 0 if successful, or a negative error code.
3530 */
Takashi Iwai12f288b2007-08-02 15:51:59 +02003531int snd_hda_add_new_ctls(struct hda_codec *codec, struct snd_kcontrol_new *knew)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003532{
Jaroslav Kysela4d02d1b2009-11-12 10:15:48 +01003533 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003534
3535 for (; knew->name; knew++) {
Takashi Iwai54d17402005-11-21 16:33:22 +01003536 struct snd_kcontrol *kctl;
Jaroslav Kysela5b0cb1d2009-12-08 16:13:32 +01003537 if (knew->iface == -1) /* skip this codec private value */
3538 continue;
Takashi Iwai54d17402005-11-21 16:33:22 +01003539 kctl = snd_ctl_new1(knew, codec);
Takashi Iwai0ba21762007-04-16 11:29:14 +02003540 if (!kctl)
Takashi Iwai54d17402005-11-21 16:33:22 +01003541 return -ENOMEM;
Jaroslav Kysela3911a4c2009-11-11 13:43:01 +01003542 err = snd_hda_ctl_add(codec, 0, kctl);
Takashi Iwai54d17402005-11-21 16:33:22 +01003543 if (err < 0) {
Takashi Iwai0ba21762007-04-16 11:29:14 +02003544 if (!codec->addr)
Takashi Iwai54d17402005-11-21 16:33:22 +01003545 return err;
3546 kctl = snd_ctl_new1(knew, codec);
Takashi Iwai0ba21762007-04-16 11:29:14 +02003547 if (!kctl)
Takashi Iwai54d17402005-11-21 16:33:22 +01003548 return -ENOMEM;
3549 kctl->id.device = codec->addr;
Jaroslav Kysela3911a4c2009-11-11 13:43:01 +01003550 err = snd_hda_ctl_add(codec, 0, kctl);
Takashi Iwai0ba21762007-04-16 11:29:14 +02003551 if (err < 0)
Takashi Iwai54d17402005-11-21 16:33:22 +01003552 return err;
3553 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003554 }
3555 return 0;
3556}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003557EXPORT_SYMBOL_HDA(snd_hda_add_new_ctls);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003558
Takashi Iwaicb53c622007-08-10 17:21:45 +02003559#ifdef CONFIG_SND_HDA_POWER_SAVE
3560static void hda_set_power_state(struct hda_codec *codec, hda_nid_t fg,
3561 unsigned int power_state);
3562
3563static void hda_power_work(struct work_struct *work)
3564{
3565 struct hda_codec *codec =
3566 container_of(work, struct hda_codec, power_work.work);
Takashi Iwai33fa35e2008-11-06 16:50:40 +01003567 struct hda_bus *bus = codec->bus;
Takashi Iwaicb53c622007-08-10 17:21:45 +02003568
Maxim Levitsky2e492462007-09-03 15:26:57 +02003569 if (!codec->power_on || codec->power_count) {
3570 codec->power_transition = 0;
Takashi Iwaicb53c622007-08-10 17:21:45 +02003571 return;
Maxim Levitsky2e492462007-09-03 15:26:57 +02003572 }
Takashi Iwaicb53c622007-08-10 17:21:45 +02003573
3574 hda_call_codec_suspend(codec);
Takashi Iwai33fa35e2008-11-06 16:50:40 +01003575 if (bus->ops.pm_notify)
3576 bus->ops.pm_notify(bus);
Takashi Iwaicb53c622007-08-10 17:21:45 +02003577}
3578
3579static void hda_keep_power_on(struct hda_codec *codec)
3580{
3581 codec->power_count++;
3582 codec->power_on = 1;
Takashi Iwaia2f63092009-11-11 09:34:25 +01003583 codec->power_jiffies = jiffies;
3584}
3585
Takashi Iwaid5191e52009-11-16 14:58:17 +01003586/* update the power on/off account with the current jiffies */
Takashi Iwaia2f63092009-11-11 09:34:25 +01003587void snd_hda_update_power_acct(struct hda_codec *codec)
3588{
3589 unsigned long delta = jiffies - codec->power_jiffies;
3590 if (codec->power_on)
3591 codec->power_on_acct += delta;
3592 else
3593 codec->power_off_acct += delta;
3594 codec->power_jiffies += delta;
Takashi Iwaicb53c622007-08-10 17:21:45 +02003595}
3596
Takashi Iwaid5191e52009-11-16 14:58:17 +01003597/**
3598 * snd_hda_power_up - Power-up the codec
3599 * @codec: HD-audio codec
3600 *
3601 * Increment the power-up counter and power up the hardware really when
3602 * not turned on yet.
3603 */
Takashi Iwaicb53c622007-08-10 17:21:45 +02003604void snd_hda_power_up(struct hda_codec *codec)
3605{
Takashi Iwai33fa35e2008-11-06 16:50:40 +01003606 struct hda_bus *bus = codec->bus;
3607
Takashi Iwaicb53c622007-08-10 17:21:45 +02003608 codec->power_count++;
Takashi Iwaia221e282007-08-16 16:35:33 +02003609 if (codec->power_on || codec->power_transition)
Takashi Iwaicb53c622007-08-10 17:21:45 +02003610 return;
3611
Takashi Iwaia2f63092009-11-11 09:34:25 +01003612 snd_hda_update_power_acct(codec);
Takashi Iwaicb53c622007-08-10 17:21:45 +02003613 codec->power_on = 1;
Takashi Iwaia2f63092009-11-11 09:34:25 +01003614 codec->power_jiffies = jiffies;
Takashi Iwai33fa35e2008-11-06 16:50:40 +01003615 if (bus->ops.pm_notify)
3616 bus->ops.pm_notify(bus);
Takashi Iwaicb53c622007-08-10 17:21:45 +02003617 hda_call_codec_resume(codec);
3618 cancel_delayed_work(&codec->power_work);
Takashi Iwaia221e282007-08-16 16:35:33 +02003619 codec->power_transition = 0;
Takashi Iwaicb53c622007-08-10 17:21:45 +02003620}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003621EXPORT_SYMBOL_HDA(snd_hda_power_up);
Takashi Iwai1289e9e2008-11-27 15:47:11 +01003622
3623#define power_save(codec) \
3624 ((codec)->bus->power_save ? *(codec)->bus->power_save : 0)
Takashi Iwaicb53c622007-08-10 17:21:45 +02003625
Takashi Iwaid5191e52009-11-16 14:58:17 +01003626/**
3627 * snd_hda_power_down - Power-down the codec
3628 * @codec: HD-audio codec
3629 *
3630 * Decrement the power-up counter and schedules the power-off work if
3631 * the counter rearches to zero.
3632 */
Takashi Iwaicb53c622007-08-10 17:21:45 +02003633void snd_hda_power_down(struct hda_codec *codec)
3634{
3635 --codec->power_count;
Takashi Iwaia221e282007-08-16 16:35:33 +02003636 if (!codec->power_on || codec->power_count || codec->power_transition)
Takashi Iwaicb53c622007-08-10 17:21:45 +02003637 return;
Takashi Iwaifee2fba2008-11-27 12:43:28 +01003638 if (power_save(codec)) {
Takashi Iwaia221e282007-08-16 16:35:33 +02003639 codec->power_transition = 1; /* avoid reentrance */
Takashi Iwaic107b412009-01-13 17:46:37 +01003640 queue_delayed_work(codec->bus->workq, &codec->power_work,
Takashi Iwaifee2fba2008-11-27 12:43:28 +01003641 msecs_to_jiffies(power_save(codec) * 1000));
Takashi Iwaia221e282007-08-16 16:35:33 +02003642 }
Takashi Iwaicb53c622007-08-10 17:21:45 +02003643}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003644EXPORT_SYMBOL_HDA(snd_hda_power_down);
Takashi Iwaicb53c622007-08-10 17:21:45 +02003645
Takashi Iwaid5191e52009-11-16 14:58:17 +01003646/**
3647 * snd_hda_check_amp_list_power - Check the amp list and update the power
3648 * @codec: HD-audio codec
3649 * @check: the object containing an AMP list and the status
3650 * @nid: NID to check / update
3651 *
3652 * Check whether the given NID is in the amp list. If it's in the list,
3653 * check the current AMP status, and update the the power-status according
3654 * to the mute status.
3655 *
3656 * This function is supposed to be set or called from the check_power_status
3657 * patch ops.
3658 */
Takashi Iwaicb53c622007-08-10 17:21:45 +02003659int snd_hda_check_amp_list_power(struct hda_codec *codec,
3660 struct hda_loopback_check *check,
3661 hda_nid_t nid)
3662{
3663 struct hda_amp_list *p;
3664 int ch, v;
3665
3666 if (!check->amplist)
3667 return 0;
3668 for (p = check->amplist; p->nid; p++) {
3669 if (p->nid == nid)
3670 break;
3671 }
3672 if (!p->nid)
3673 return 0; /* nothing changed */
3674
3675 for (p = check->amplist; p->nid; p++) {
3676 for (ch = 0; ch < 2; ch++) {
3677 v = snd_hda_codec_amp_read(codec, p->nid, ch, p->dir,
3678 p->idx);
3679 if (!(v & HDA_AMP_MUTE) && v > 0) {
3680 if (!check->power_on) {
3681 check->power_on = 1;
3682 snd_hda_power_up(codec);
3683 }
3684 return 1;
3685 }
3686 }
3687 }
3688 if (check->power_on) {
3689 check->power_on = 0;
3690 snd_hda_power_down(codec);
3691 }
3692 return 0;
3693}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003694EXPORT_SYMBOL_HDA(snd_hda_check_amp_list_power);
Takashi Iwaicb53c622007-08-10 17:21:45 +02003695#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07003696
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01003697/*
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01003698 * Channel mode helper
3699 */
Takashi Iwaid5191e52009-11-16 14:58:17 +01003700
3701/**
3702 * snd_hda_ch_mode_info - Info callback helper for the channel mode enum
3703 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003704int snd_hda_ch_mode_info(struct hda_codec *codec,
3705 struct snd_ctl_elem_info *uinfo,
3706 const struct hda_channel_mode *chmode,
3707 int num_chmodes)
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01003708{
3709 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
3710 uinfo->count = 1;
3711 uinfo->value.enumerated.items = num_chmodes;
3712 if (uinfo->value.enumerated.item >= num_chmodes)
3713 uinfo->value.enumerated.item = num_chmodes - 1;
3714 sprintf(uinfo->value.enumerated.name, "%dch",
3715 chmode[uinfo->value.enumerated.item].channels);
3716 return 0;
3717}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003718EXPORT_SYMBOL_HDA(snd_hda_ch_mode_info);
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01003719
Takashi Iwaid5191e52009-11-16 14:58:17 +01003720/**
3721 * snd_hda_ch_mode_get - Get callback helper for the channel mode enum
3722 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003723int snd_hda_ch_mode_get(struct hda_codec *codec,
3724 struct snd_ctl_elem_value *ucontrol,
3725 const struct hda_channel_mode *chmode,
3726 int num_chmodes,
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01003727 int max_channels)
3728{
3729 int i;
3730
3731 for (i = 0; i < num_chmodes; i++) {
3732 if (max_channels == chmode[i].channels) {
3733 ucontrol->value.enumerated.item[0] = i;
3734 break;
3735 }
3736 }
3737 return 0;
3738}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003739EXPORT_SYMBOL_HDA(snd_hda_ch_mode_get);
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01003740
Takashi Iwaid5191e52009-11-16 14:58:17 +01003741/**
3742 * snd_hda_ch_mode_put - Put callback helper for the channel mode enum
3743 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003744int snd_hda_ch_mode_put(struct hda_codec *codec,
3745 struct snd_ctl_elem_value *ucontrol,
3746 const struct hda_channel_mode *chmode,
3747 int num_chmodes,
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01003748 int *max_channelsp)
3749{
3750 unsigned int mode;
3751
3752 mode = ucontrol->value.enumerated.item[0];
Takashi Iwai68ea7b22007-11-15 15:54:38 +01003753 if (mode >= num_chmodes)
3754 return -EINVAL;
Takashi Iwai82beb8f2007-08-10 17:09:26 +02003755 if (*max_channelsp == chmode[mode].channels)
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01003756 return 0;
3757 /* change the current channel setting */
3758 *max_channelsp = chmode[mode].channels;
3759 if (chmode[mode].sequence)
Takashi Iwai82beb8f2007-08-10 17:09:26 +02003760 snd_hda_sequence_write_cache(codec, chmode[mode].sequence);
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01003761 return 1;
3762}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003763EXPORT_SYMBOL_HDA(snd_hda_ch_mode_put);
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01003764
Linus Torvalds1da177e2005-04-16 15:20:36 -07003765/*
3766 * input MUX helper
3767 */
Takashi Iwaid5191e52009-11-16 14:58:17 +01003768
3769/**
3770 * snd_hda_input_mux_info_info - Info callback helper for the input-mux enum
3771 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003772int snd_hda_input_mux_info(const struct hda_input_mux *imux,
3773 struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003774{
3775 unsigned int index;
3776
3777 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
3778 uinfo->count = 1;
3779 uinfo->value.enumerated.items = imux->num_items;
Takashi Iwai5513b0c2007-10-09 11:58:41 +02003780 if (!imux->num_items)
3781 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003782 index = uinfo->value.enumerated.item;
3783 if (index >= imux->num_items)
3784 index = imux->num_items - 1;
3785 strcpy(uinfo->value.enumerated.name, imux->items[index].label);
3786 return 0;
3787}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003788EXPORT_SYMBOL_HDA(snd_hda_input_mux_info);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003789
Takashi Iwaid5191e52009-11-16 14:58:17 +01003790/**
3791 * snd_hda_input_mux_info_put - Put callback helper for the input-mux enum
3792 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003793int snd_hda_input_mux_put(struct hda_codec *codec,
3794 const struct hda_input_mux *imux,
3795 struct snd_ctl_elem_value *ucontrol,
3796 hda_nid_t nid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003797 unsigned int *cur_val)
3798{
3799 unsigned int idx;
3800
Takashi Iwai5513b0c2007-10-09 11:58:41 +02003801 if (!imux->num_items)
3802 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003803 idx = ucontrol->value.enumerated.item[0];
3804 if (idx >= imux->num_items)
3805 idx = imux->num_items - 1;
Takashi Iwai82beb8f2007-08-10 17:09:26 +02003806 if (*cur_val == idx)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003807 return 0;
Takashi Iwai82beb8f2007-08-10 17:09:26 +02003808 snd_hda_codec_write_cache(codec, nid, 0, AC_VERB_SET_CONNECT_SEL,
3809 imux->items[idx].index);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003810 *cur_val = idx;
3811 return 1;
3812}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003813EXPORT_SYMBOL_HDA(snd_hda_input_mux_put);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003814
3815
3816/*
3817 * Multi-channel / digital-out PCM helper functions
3818 */
3819
Takashi Iwai6b97eb42007-04-05 14:51:48 +02003820/* setup SPDIF output stream */
3821static void setup_dig_out_stream(struct hda_codec *codec, hda_nid_t nid,
3822 unsigned int stream_tag, unsigned int format)
3823{
3824 /* turn off SPDIF once; otherwise the IEC958 bits won't be updated */
Takashi Iwai2f728532008-09-25 16:32:41 +02003825 if (codec->spdif_status_reset && (codec->spdif_ctls & AC_DIG1_ENABLE))
3826 set_dig_out_convert(codec, nid,
3827 codec->spdif_ctls & ~AC_DIG1_ENABLE & 0xff,
3828 -1);
Takashi Iwai6b97eb42007-04-05 14:51:48 +02003829 snd_hda_codec_setup_stream(codec, nid, stream_tag, 0, format);
Takashi Iwai2f728532008-09-25 16:32:41 +02003830 if (codec->slave_dig_outs) {
3831 hda_nid_t *d;
3832 for (d = codec->slave_dig_outs; *d; d++)
3833 snd_hda_codec_setup_stream(codec, *d, stream_tag, 0,
3834 format);
Matthew Ranostayde51ca12008-09-07 14:31:40 -04003835 }
Takashi Iwai2f728532008-09-25 16:32:41 +02003836 /* turn on again (if needed) */
3837 if (codec->spdif_status_reset && (codec->spdif_ctls & AC_DIG1_ENABLE))
3838 set_dig_out_convert(codec, nid,
3839 codec->spdif_ctls & 0xff, -1);
3840}
Matthew Ranostayde51ca12008-09-07 14:31:40 -04003841
Takashi Iwai2f728532008-09-25 16:32:41 +02003842static void cleanup_dig_out_stream(struct hda_codec *codec, hda_nid_t nid)
3843{
3844 snd_hda_codec_cleanup_stream(codec, nid);
3845 if (codec->slave_dig_outs) {
3846 hda_nid_t *d;
3847 for (d = codec->slave_dig_outs; *d; d++)
3848 snd_hda_codec_cleanup_stream(codec, *d);
3849 }
Takashi Iwai6b97eb42007-04-05 14:51:48 +02003850}
3851
Takashi Iwaid5191e52009-11-16 14:58:17 +01003852/**
3853 * snd_hda_bus_reboot_notify - call the reboot notifier of each codec
3854 * @bus: HD-audio bus
3855 */
Takashi Iwaifb8d1a32009-11-10 16:02:29 +01003856void snd_hda_bus_reboot_notify(struct hda_bus *bus)
3857{
3858 struct hda_codec *codec;
3859
3860 if (!bus)
3861 return;
3862 list_for_each_entry(codec, &bus->codec_list, list) {
3863#ifdef CONFIG_SND_HDA_POWER_SAVE
3864 if (!codec->power_on)
3865 continue;
3866#endif
3867 if (codec->patch_ops.reboot_notify)
3868 codec->patch_ops.reboot_notify(codec);
3869 }
3870}
Takashi Iwai8f217a22009-11-10 18:26:12 +01003871EXPORT_SYMBOL_HDA(snd_hda_bus_reboot_notify);
Takashi Iwaifb8d1a32009-11-10 16:02:29 +01003872
Takashi Iwaid5191e52009-11-16 14:58:17 +01003873/**
3874 * snd_hda_multi_out_dig_open - open the digital out in the exclusive mode
Linus Torvalds1da177e2005-04-16 15:20:36 -07003875 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003876int snd_hda_multi_out_dig_open(struct hda_codec *codec,
3877 struct hda_multi_out *mout)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003878{
Ingo Molnar62932df2006-01-16 16:34:20 +01003879 mutex_lock(&codec->spdif_mutex);
Takashi Iwai5930ca42007-04-16 11:23:56 +02003880 if (mout->dig_out_used == HDA_DIG_ANALOG_DUP)
3881 /* already opened as analog dup; reset it once */
Takashi Iwai2f728532008-09-25 16:32:41 +02003882 cleanup_dig_out_stream(codec, mout->dig_out_nid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003883 mout->dig_out_used = HDA_DIG_EXCLUSIVE;
Ingo Molnar62932df2006-01-16 16:34:20 +01003884 mutex_unlock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003885 return 0;
3886}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003887EXPORT_SYMBOL_HDA(snd_hda_multi_out_dig_open);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003888
Takashi Iwaid5191e52009-11-16 14:58:17 +01003889/**
3890 * snd_hda_multi_out_dig_prepare - prepare the digital out stream
3891 */
Takashi Iwai6b97eb42007-04-05 14:51:48 +02003892int snd_hda_multi_out_dig_prepare(struct hda_codec *codec,
3893 struct hda_multi_out *mout,
3894 unsigned int stream_tag,
3895 unsigned int format,
3896 struct snd_pcm_substream *substream)
3897{
3898 mutex_lock(&codec->spdif_mutex);
3899 setup_dig_out_stream(codec, mout->dig_out_nid, stream_tag, format);
3900 mutex_unlock(&codec->spdif_mutex);
3901 return 0;
3902}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003903EXPORT_SYMBOL_HDA(snd_hda_multi_out_dig_prepare);
Takashi Iwai6b97eb42007-04-05 14:51:48 +02003904
Takashi Iwaid5191e52009-11-16 14:58:17 +01003905/**
3906 * snd_hda_multi_out_dig_cleanup - clean-up the digital out stream
3907 */
Takashi Iwai9411e212009-02-13 11:32:28 +01003908int snd_hda_multi_out_dig_cleanup(struct hda_codec *codec,
3909 struct hda_multi_out *mout)
3910{
3911 mutex_lock(&codec->spdif_mutex);
3912 cleanup_dig_out_stream(codec, mout->dig_out_nid);
3913 mutex_unlock(&codec->spdif_mutex);
3914 return 0;
3915}
3916EXPORT_SYMBOL_HDA(snd_hda_multi_out_dig_cleanup);
3917
Takashi Iwaid5191e52009-11-16 14:58:17 +01003918/**
3919 * snd_hda_multi_out_dig_close - release the digital out stream
Linus Torvalds1da177e2005-04-16 15:20:36 -07003920 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003921int snd_hda_multi_out_dig_close(struct hda_codec *codec,
3922 struct hda_multi_out *mout)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003923{
Ingo Molnar62932df2006-01-16 16:34:20 +01003924 mutex_lock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003925 mout->dig_out_used = 0;
Ingo Molnar62932df2006-01-16 16:34:20 +01003926 mutex_unlock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003927 return 0;
3928}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003929EXPORT_SYMBOL_HDA(snd_hda_multi_out_dig_close);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003930
Takashi Iwaid5191e52009-11-16 14:58:17 +01003931/**
3932 * snd_hda_multi_out_analog_open - open analog outputs
3933 *
3934 * Open analog outputs and set up the hw-constraints.
3935 * If the digital outputs can be opened as slave, open the digital
3936 * outputs, too.
Linus Torvalds1da177e2005-04-16 15:20:36 -07003937 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003938int snd_hda_multi_out_analog_open(struct hda_codec *codec,
3939 struct hda_multi_out *mout,
Takashi Iwai9a081602008-02-12 18:37:26 +01003940 struct snd_pcm_substream *substream,
3941 struct hda_pcm_stream *hinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003942{
Takashi Iwai9a081602008-02-12 18:37:26 +01003943 struct snd_pcm_runtime *runtime = substream->runtime;
3944 runtime->hw.channels_max = mout->max_channels;
3945 if (mout->dig_out_nid) {
3946 if (!mout->analog_rates) {
3947 mout->analog_rates = hinfo->rates;
3948 mout->analog_formats = hinfo->formats;
3949 mout->analog_maxbps = hinfo->maxbps;
3950 } else {
3951 runtime->hw.rates = mout->analog_rates;
3952 runtime->hw.formats = mout->analog_formats;
3953 hinfo->maxbps = mout->analog_maxbps;
3954 }
3955 if (!mout->spdif_rates) {
3956 snd_hda_query_supported_pcm(codec, mout->dig_out_nid,
3957 &mout->spdif_rates,
3958 &mout->spdif_formats,
3959 &mout->spdif_maxbps);
3960 }
3961 mutex_lock(&codec->spdif_mutex);
3962 if (mout->share_spdif) {
Takashi Iwai022b4662009-07-03 23:03:30 +02003963 if ((runtime->hw.rates & mout->spdif_rates) &&
3964 (runtime->hw.formats & mout->spdif_formats)) {
3965 runtime->hw.rates &= mout->spdif_rates;
3966 runtime->hw.formats &= mout->spdif_formats;
3967 if (mout->spdif_maxbps < hinfo->maxbps)
3968 hinfo->maxbps = mout->spdif_maxbps;
3969 } else {
3970 mout->share_spdif = 0;
3971 /* FIXME: need notify? */
3972 }
Takashi Iwai9a081602008-02-12 18:37:26 +01003973 }
Frederik Deweerdteaa99852008-04-14 13:11:44 +02003974 mutex_unlock(&codec->spdif_mutex);
Takashi Iwai9a081602008-02-12 18:37:26 +01003975 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003976 return snd_pcm_hw_constraint_step(substream->runtime, 0,
3977 SNDRV_PCM_HW_PARAM_CHANNELS, 2);
3978}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003979EXPORT_SYMBOL_HDA(snd_hda_multi_out_analog_open);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003980
Takashi Iwaid5191e52009-11-16 14:58:17 +01003981/**
3982 * snd_hda_multi_out_analog_prepare - Preapre the analog outputs.
3983 *
3984 * Set up the i/o for analog out.
3985 * When the digital out is available, copy the front out to digital out, too.
Linus Torvalds1da177e2005-04-16 15:20:36 -07003986 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003987int snd_hda_multi_out_analog_prepare(struct hda_codec *codec,
3988 struct hda_multi_out *mout,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003989 unsigned int stream_tag,
3990 unsigned int format,
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01003991 struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003992{
3993 hda_nid_t *nids = mout->dac_nids;
3994 int chs = substream->runtime->channels;
3995 int i;
3996
Ingo Molnar62932df2006-01-16 16:34:20 +01003997 mutex_lock(&codec->spdif_mutex);
Takashi Iwai9a081602008-02-12 18:37:26 +01003998 if (mout->dig_out_nid && mout->share_spdif &&
3999 mout->dig_out_used != HDA_DIG_EXCLUSIVE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004000 if (chs == 2 &&
Takashi Iwai0ba21762007-04-16 11:29:14 +02004001 snd_hda_is_supported_format(codec, mout->dig_out_nid,
4002 format) &&
4003 !(codec->spdif_status & IEC958_AES0_NONAUDIO)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004004 mout->dig_out_used = HDA_DIG_ANALOG_DUP;
Takashi Iwai6b97eb42007-04-05 14:51:48 +02004005 setup_dig_out_stream(codec, mout->dig_out_nid,
4006 stream_tag, format);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004007 } else {
4008 mout->dig_out_used = 0;
Takashi Iwai2f728532008-09-25 16:32:41 +02004009 cleanup_dig_out_stream(codec, mout->dig_out_nid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004010 }
4011 }
Ingo Molnar62932df2006-01-16 16:34:20 +01004012 mutex_unlock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004013
4014 /* front */
Takashi Iwai0ba21762007-04-16 11:29:14 +02004015 snd_hda_codec_setup_stream(codec, nids[HDA_FRONT], stream_tag,
4016 0, format);
Takashi Iwaid29240c2007-10-26 12:35:56 +02004017 if (!mout->no_share_stream &&
4018 mout->hp_nid && mout->hp_nid != nids[HDA_FRONT])
Linus Torvalds1da177e2005-04-16 15:20:36 -07004019 /* headphone out will just decode front left/right (stereo) */
Takashi Iwai0ba21762007-04-16 11:29:14 +02004020 snd_hda_codec_setup_stream(codec, mout->hp_nid, stream_tag,
4021 0, format);
Takashi Iwai82bc9552006-03-21 11:24:42 +01004022 /* extra outputs copied from front */
4023 for (i = 0; i < ARRAY_SIZE(mout->extra_out_nid); i++)
Takashi Iwaid29240c2007-10-26 12:35:56 +02004024 if (!mout->no_share_stream && mout->extra_out_nid[i])
Takashi Iwai82bc9552006-03-21 11:24:42 +01004025 snd_hda_codec_setup_stream(codec,
4026 mout->extra_out_nid[i],
4027 stream_tag, 0, format);
4028
Linus Torvalds1da177e2005-04-16 15:20:36 -07004029 /* surrounds */
4030 for (i = 1; i < mout->num_dacs; i++) {
Takashi Iwai4b3acaf2005-06-10 19:48:10 +02004031 if (chs >= (i + 1) * 2) /* independent out */
Takashi Iwai0ba21762007-04-16 11:29:14 +02004032 snd_hda_codec_setup_stream(codec, nids[i], stream_tag,
4033 i * 2, format);
Takashi Iwaid29240c2007-10-26 12:35:56 +02004034 else if (!mout->no_share_stream) /* copy front */
Takashi Iwai0ba21762007-04-16 11:29:14 +02004035 snd_hda_codec_setup_stream(codec, nids[i], stream_tag,
4036 0, format);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004037 }
4038 return 0;
4039}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01004040EXPORT_SYMBOL_HDA(snd_hda_multi_out_analog_prepare);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004041
Takashi Iwaid5191e52009-11-16 14:58:17 +01004042/**
4043 * snd_hda_multi_out_analog_cleanup - clean up the setting for analog out
Linus Torvalds1da177e2005-04-16 15:20:36 -07004044 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02004045int snd_hda_multi_out_analog_cleanup(struct hda_codec *codec,
4046 struct hda_multi_out *mout)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004047{
4048 hda_nid_t *nids = mout->dac_nids;
4049 int i;
4050
4051 for (i = 0; i < mout->num_dacs; i++)
Takashi Iwai888afa12008-03-18 09:57:50 +01004052 snd_hda_codec_cleanup_stream(codec, nids[i]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004053 if (mout->hp_nid)
Takashi Iwai888afa12008-03-18 09:57:50 +01004054 snd_hda_codec_cleanup_stream(codec, mout->hp_nid);
Takashi Iwai82bc9552006-03-21 11:24:42 +01004055 for (i = 0; i < ARRAY_SIZE(mout->extra_out_nid); i++)
4056 if (mout->extra_out_nid[i])
Takashi Iwai888afa12008-03-18 09:57:50 +01004057 snd_hda_codec_cleanup_stream(codec,
4058 mout->extra_out_nid[i]);
Ingo Molnar62932df2006-01-16 16:34:20 +01004059 mutex_lock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004060 if (mout->dig_out_nid && mout->dig_out_used == HDA_DIG_ANALOG_DUP) {
Takashi Iwai2f728532008-09-25 16:32:41 +02004061 cleanup_dig_out_stream(codec, mout->dig_out_nid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004062 mout->dig_out_used = 0;
4063 }
Ingo Molnar62932df2006-01-16 16:34:20 +01004064 mutex_unlock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004065 return 0;
4066}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01004067EXPORT_SYMBOL_HDA(snd_hda_multi_out_analog_cleanup);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004068
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004069/*
Wu Fengguang6b345002008-10-07 14:21:41 +08004070 * Helper for automatic pin configuration
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004071 */
Kailang Yangdf694da2005-12-05 19:42:22 +01004072
Takashi Iwai12f288b2007-08-02 15:51:59 +02004073static int is_in_nid_list(hda_nid_t nid, hda_nid_t *list)
Kailang Yangdf694da2005-12-05 19:42:22 +01004074{
4075 for (; *list; list++)
4076 if (*list == nid)
4077 return 1;
4078 return 0;
4079}
4080
Steve Longerbeam81937d32007-05-08 15:33:03 +02004081
4082/*
4083 * Sort an associated group of pins according to their sequence numbers.
4084 */
4085static void sort_pins_by_sequence(hda_nid_t * pins, short * sequences,
4086 int num_pins)
4087{
4088 int i, j;
4089 short seq;
4090 hda_nid_t nid;
4091
4092 for (i = 0; i < num_pins; i++) {
4093 for (j = i + 1; j < num_pins; j++) {
4094 if (sequences[i] > sequences[j]) {
4095 seq = sequences[i];
4096 sequences[i] = sequences[j];
4097 sequences[j] = seq;
4098 nid = pins[i];
4099 pins[i] = pins[j];
4100 pins[j] = nid;
4101 }
4102 }
4103 }
4104}
4105
4106
Takashi Iwai82bc9552006-03-21 11:24:42 +01004107/*
4108 * Parse all pin widgets and store the useful pin nids to cfg
4109 *
4110 * The number of line-outs or any primary output is stored in line_outs,
4111 * and the corresponding output pins are assigned to line_out_pins[],
4112 * in the order of front, rear, CLFE, side, ...
4113 *
4114 * If more extra outputs (speaker and headphone) are found, the pins are
Takashi Iwaieb06ed82006-09-20 17:10:27 +02004115 * assisnged to hp_pins[] and speaker_pins[], respectively. If no line-out jack
Takashi Iwai82bc9552006-03-21 11:24:42 +01004116 * is detected, one of speaker of HP pins is assigned as the primary
4117 * output, i.e. to line_out_pins[0]. So, line_outs is always positive
4118 * if any analog output exists.
4119 *
4120 * The analog input pins are assigned to input_pins array.
4121 * The digital input/output pins are assigned to dig_in_pin and dig_out_pin,
4122 * respectively.
4123 */
Takashi Iwai12f288b2007-08-02 15:51:59 +02004124int snd_hda_parse_pin_def_config(struct hda_codec *codec,
4125 struct auto_pin_cfg *cfg,
4126 hda_nid_t *ignore_nids)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004127{
Takashi Iwai0ef6ce72008-01-22 15:35:37 +01004128 hda_nid_t nid, end_nid;
Steve Longerbeam81937d32007-05-08 15:33:03 +02004129 short seq, assoc_line_out, assoc_speaker;
4130 short sequences_line_out[ARRAY_SIZE(cfg->line_out_pins)];
4131 short sequences_speaker[ARRAY_SIZE(cfg->speaker_pins)];
Takashi Iwaif889fa92007-10-31 15:49:32 +01004132 short sequences_hp[ARRAY_SIZE(cfg->hp_pins)];
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004133
4134 memset(cfg, 0, sizeof(*cfg));
4135
Steve Longerbeam81937d32007-05-08 15:33:03 +02004136 memset(sequences_line_out, 0, sizeof(sequences_line_out));
4137 memset(sequences_speaker, 0, sizeof(sequences_speaker));
Takashi Iwaif889fa92007-10-31 15:49:32 +01004138 memset(sequences_hp, 0, sizeof(sequences_hp));
Steve Longerbeam81937d32007-05-08 15:33:03 +02004139 assoc_line_out = assoc_speaker = 0;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004140
Takashi Iwai0ef6ce72008-01-22 15:35:37 +01004141 end_nid = codec->start_nid + codec->num_nodes;
4142 for (nid = codec->start_nid; nid < end_nid; nid++) {
Takashi Iwai54d17402005-11-21 16:33:22 +01004143 unsigned int wid_caps = get_wcaps(codec, nid);
Takashi Iwaia22d5432009-07-27 12:54:26 +02004144 unsigned int wid_type = get_wcaps_type(wid_caps);
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004145 unsigned int def_conf;
4146 short assoc, loc;
4147
4148 /* read all default configuration for pin complex */
4149 if (wid_type != AC_WID_PIN)
4150 continue;
Kailang Yangdf694da2005-12-05 19:42:22 +01004151 /* ignore the given nids (e.g. pc-beep returns error) */
4152 if (ignore_nids && is_in_nid_list(nid, ignore_nids))
4153 continue;
4154
Takashi Iwaic17a1ab2009-02-23 09:28:12 +01004155 def_conf = snd_hda_codec_get_pincfg(codec, nid);
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004156 if (get_defcfg_connect(def_conf) == AC_JACK_PORT_NONE)
4157 continue;
4158 loc = get_defcfg_location(def_conf);
4159 switch (get_defcfg_device(def_conf)) {
4160 case AC_JACK_LINE_OUT:
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004161 seq = get_defcfg_sequence(def_conf);
4162 assoc = get_defcfg_association(def_conf);
Matthew Ranostay90da78b2008-01-24 11:48:01 +01004163
4164 if (!(wid_caps & AC_WCAP_STEREO))
4165 if (!cfg->mono_out_pin)
4166 cfg->mono_out_pin = nid;
Takashi Iwai0ba21762007-04-16 11:29:14 +02004167 if (!assoc)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004168 continue;
Takashi Iwai0ba21762007-04-16 11:29:14 +02004169 if (!assoc_line_out)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004170 assoc_line_out = assoc;
4171 else if (assoc_line_out != assoc)
4172 continue;
4173 if (cfg->line_outs >= ARRAY_SIZE(cfg->line_out_pins))
4174 continue;
4175 cfg->line_out_pins[cfg->line_outs] = nid;
Steve Longerbeam81937d32007-05-08 15:33:03 +02004176 sequences_line_out[cfg->line_outs] = seq;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004177 cfg->line_outs++;
4178 break;
Takashi Iwai8d88bc32005-11-17 11:09:23 +01004179 case AC_JACK_SPEAKER:
Steve Longerbeam81937d32007-05-08 15:33:03 +02004180 seq = get_defcfg_sequence(def_conf);
4181 assoc = get_defcfg_association(def_conf);
4182 if (! assoc)
4183 continue;
4184 if (! assoc_speaker)
4185 assoc_speaker = assoc;
4186 else if (assoc_speaker != assoc)
4187 continue;
Takashi Iwai82bc9552006-03-21 11:24:42 +01004188 if (cfg->speaker_outs >= ARRAY_SIZE(cfg->speaker_pins))
4189 continue;
4190 cfg->speaker_pins[cfg->speaker_outs] = nid;
Steve Longerbeam81937d32007-05-08 15:33:03 +02004191 sequences_speaker[cfg->speaker_outs] = seq;
Takashi Iwai82bc9552006-03-21 11:24:42 +01004192 cfg->speaker_outs++;
Takashi Iwai8d88bc32005-11-17 11:09:23 +01004193 break;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004194 case AC_JACK_HP_OUT:
Takashi Iwaif889fa92007-10-31 15:49:32 +01004195 seq = get_defcfg_sequence(def_conf);
4196 assoc = get_defcfg_association(def_conf);
Takashi Iwaieb06ed82006-09-20 17:10:27 +02004197 if (cfg->hp_outs >= ARRAY_SIZE(cfg->hp_pins))
4198 continue;
4199 cfg->hp_pins[cfg->hp_outs] = nid;
Takashi Iwaif889fa92007-10-31 15:49:32 +01004200 sequences_hp[cfg->hp_outs] = (assoc << 4) | seq;
Takashi Iwaieb06ed82006-09-20 17:10:27 +02004201 cfg->hp_outs++;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004202 break;
Takashi Iwai314634b2006-09-21 11:56:18 +02004203 case AC_JACK_MIC_IN: {
4204 int preferred, alt;
4205 if (loc == AC_JACK_LOC_FRONT) {
4206 preferred = AUTO_PIN_FRONT_MIC;
4207 alt = AUTO_PIN_MIC;
4208 } else {
4209 preferred = AUTO_PIN_MIC;
4210 alt = AUTO_PIN_FRONT_MIC;
4211 }
4212 if (!cfg->input_pins[preferred])
4213 cfg->input_pins[preferred] = nid;
4214 else if (!cfg->input_pins[alt])
4215 cfg->input_pins[alt] = nid;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004216 break;
Takashi Iwai314634b2006-09-21 11:56:18 +02004217 }
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004218 case AC_JACK_LINE_IN:
4219 if (loc == AC_JACK_LOC_FRONT)
4220 cfg->input_pins[AUTO_PIN_FRONT_LINE] = nid;
4221 else
4222 cfg->input_pins[AUTO_PIN_LINE] = nid;
4223 break;
4224 case AC_JACK_CD:
4225 cfg->input_pins[AUTO_PIN_CD] = nid;
4226 break;
4227 case AC_JACK_AUX:
4228 cfg->input_pins[AUTO_PIN_AUX] = nid;
4229 break;
4230 case AC_JACK_SPDIF_OUT:
Takashi Iwai1b52ae72009-01-20 17:17:29 +01004231 case AC_JACK_DIG_OTHER_OUT:
Takashi Iwai0852d7a2009-02-11 11:35:15 +01004232 if (cfg->dig_outs >= ARRAY_SIZE(cfg->dig_out_pins))
4233 continue;
4234 cfg->dig_out_pins[cfg->dig_outs] = nid;
4235 cfg->dig_out_type[cfg->dig_outs] =
4236 (loc == AC_JACK_LOC_HDMI) ?
4237 HDA_PCM_TYPE_HDMI : HDA_PCM_TYPE_SPDIF;
4238 cfg->dig_outs++;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004239 break;
4240 case AC_JACK_SPDIF_IN:
Takashi Iwai1b52ae72009-01-20 17:17:29 +01004241 case AC_JACK_DIG_OTHER_IN:
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004242 cfg->dig_in_pin = nid;
Takashi Iwai2297bd62009-01-20 18:24:13 +01004243 if (loc == AC_JACK_LOC_HDMI)
4244 cfg->dig_in_type = HDA_PCM_TYPE_HDMI;
4245 else
4246 cfg->dig_in_type = HDA_PCM_TYPE_SPDIF;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004247 break;
4248 }
4249 }
4250
Takashi Iwai5832fcf82008-02-12 18:30:12 +01004251 /* FIX-UP:
4252 * If no line-out is defined but multiple HPs are found,
4253 * some of them might be the real line-outs.
4254 */
4255 if (!cfg->line_outs && cfg->hp_outs > 1) {
4256 int i = 0;
4257 while (i < cfg->hp_outs) {
4258 /* The real HPs should have the sequence 0x0f */
4259 if ((sequences_hp[i] & 0x0f) == 0x0f) {
4260 i++;
4261 continue;
4262 }
4263 /* Move it to the line-out table */
4264 cfg->line_out_pins[cfg->line_outs] = cfg->hp_pins[i];
4265 sequences_line_out[cfg->line_outs] = sequences_hp[i];
4266 cfg->line_outs++;
4267 cfg->hp_outs--;
4268 memmove(cfg->hp_pins + i, cfg->hp_pins + i + 1,
4269 sizeof(cfg->hp_pins[0]) * (cfg->hp_outs - i));
4270 memmove(sequences_hp + i - 1, sequences_hp + i,
4271 sizeof(sequences_hp[0]) * (cfg->hp_outs - i));
4272 }
4273 }
4274
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004275 /* sort by sequence */
Steve Longerbeam81937d32007-05-08 15:33:03 +02004276 sort_pins_by_sequence(cfg->line_out_pins, sequences_line_out,
4277 cfg->line_outs);
4278 sort_pins_by_sequence(cfg->speaker_pins, sequences_speaker,
4279 cfg->speaker_outs);
Takashi Iwaif889fa92007-10-31 15:49:32 +01004280 sort_pins_by_sequence(cfg->hp_pins, sequences_hp,
4281 cfg->hp_outs);
Steve Longerbeam81937d32007-05-08 15:33:03 +02004282
Takashi Iwaif889fa92007-10-31 15:49:32 +01004283 /* if we have only one mic, make it AUTO_PIN_MIC */
4284 if (!cfg->input_pins[AUTO_PIN_MIC] &&
4285 cfg->input_pins[AUTO_PIN_FRONT_MIC]) {
4286 cfg->input_pins[AUTO_PIN_MIC] =
4287 cfg->input_pins[AUTO_PIN_FRONT_MIC];
4288 cfg->input_pins[AUTO_PIN_FRONT_MIC] = 0;
4289 }
4290 /* ditto for line-in */
4291 if (!cfg->input_pins[AUTO_PIN_LINE] &&
4292 cfg->input_pins[AUTO_PIN_FRONT_LINE]) {
4293 cfg->input_pins[AUTO_PIN_LINE] =
4294 cfg->input_pins[AUTO_PIN_FRONT_LINE];
4295 cfg->input_pins[AUTO_PIN_FRONT_LINE] = 0;
4296 }
4297
Steve Longerbeam81937d32007-05-08 15:33:03 +02004298 /*
4299 * FIX-UP: if no line-outs are detected, try to use speaker or HP pin
4300 * as a primary output
4301 */
4302 if (!cfg->line_outs) {
4303 if (cfg->speaker_outs) {
4304 cfg->line_outs = cfg->speaker_outs;
4305 memcpy(cfg->line_out_pins, cfg->speaker_pins,
4306 sizeof(cfg->speaker_pins));
4307 cfg->speaker_outs = 0;
4308 memset(cfg->speaker_pins, 0, sizeof(cfg->speaker_pins));
4309 cfg->line_out_type = AUTO_PIN_SPEAKER_OUT;
4310 } else if (cfg->hp_outs) {
4311 cfg->line_outs = cfg->hp_outs;
4312 memcpy(cfg->line_out_pins, cfg->hp_pins,
4313 sizeof(cfg->hp_pins));
4314 cfg->hp_outs = 0;
4315 memset(cfg->hp_pins, 0, sizeof(cfg->hp_pins));
4316 cfg->line_out_type = AUTO_PIN_HP_OUT;
4317 }
4318 }
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004319
Takashi Iwaicb8e2f82005-07-29 11:54:32 +02004320 /* Reorder the surround channels
4321 * ALSA sequence is front/surr/clfe/side
4322 * HDA sequence is:
4323 * 4-ch: front/surr => OK as it is
4324 * 6-ch: front/clfe/surr
Takashi Iwai9422db42007-04-20 16:11:43 +02004325 * 8-ch: front/clfe/rear/side|fc
Takashi Iwaicb8e2f82005-07-29 11:54:32 +02004326 */
4327 switch (cfg->line_outs) {
4328 case 3:
Takashi Iwaicb8e2f82005-07-29 11:54:32 +02004329 case 4:
4330 nid = cfg->line_out_pins[1];
Takashi Iwai9422db42007-04-20 16:11:43 +02004331 cfg->line_out_pins[1] = cfg->line_out_pins[2];
Takashi Iwaicb8e2f82005-07-29 11:54:32 +02004332 cfg->line_out_pins[2] = nid;
4333 break;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004334 }
4335
Takashi Iwai82bc9552006-03-21 11:24:42 +01004336 /*
4337 * debug prints of the parsed results
4338 */
4339 snd_printd("autoconfig: line_outs=%d (0x%x/0x%x/0x%x/0x%x/0x%x)\n",
4340 cfg->line_outs, cfg->line_out_pins[0], cfg->line_out_pins[1],
4341 cfg->line_out_pins[2], cfg->line_out_pins[3],
4342 cfg->line_out_pins[4]);
4343 snd_printd(" speaker_outs=%d (0x%x/0x%x/0x%x/0x%x/0x%x)\n",
4344 cfg->speaker_outs, cfg->speaker_pins[0],
4345 cfg->speaker_pins[1], cfg->speaker_pins[2],
4346 cfg->speaker_pins[3], cfg->speaker_pins[4]);
Takashi Iwaieb06ed82006-09-20 17:10:27 +02004347 snd_printd(" hp_outs=%d (0x%x/0x%x/0x%x/0x%x/0x%x)\n",
4348 cfg->hp_outs, cfg->hp_pins[0],
4349 cfg->hp_pins[1], cfg->hp_pins[2],
4350 cfg->hp_pins[3], cfg->hp_pins[4]);
Matthew Ranostay90da78b2008-01-24 11:48:01 +01004351 snd_printd(" mono: mono_out=0x%x\n", cfg->mono_out_pin);
Takashi Iwai0852d7a2009-02-11 11:35:15 +01004352 if (cfg->dig_outs)
4353 snd_printd(" dig-out=0x%x/0x%x\n",
4354 cfg->dig_out_pins[0], cfg->dig_out_pins[1]);
Takashi Iwai82bc9552006-03-21 11:24:42 +01004355 snd_printd(" inputs: mic=0x%x, fmic=0x%x, line=0x%x, fline=0x%x,"
4356 " cd=0x%x, aux=0x%x\n",
4357 cfg->input_pins[AUTO_PIN_MIC],
4358 cfg->input_pins[AUTO_PIN_FRONT_MIC],
4359 cfg->input_pins[AUTO_PIN_LINE],
4360 cfg->input_pins[AUTO_PIN_FRONT_LINE],
4361 cfg->input_pins[AUTO_PIN_CD],
4362 cfg->input_pins[AUTO_PIN_AUX]);
Takashi Iwai32d2c7f2009-02-11 11:33:13 +01004363 if (cfg->dig_in_pin)
Takashi Iwai89ce9e82009-01-20 17:15:57 +01004364 snd_printd(" dig-in=0x%x\n", cfg->dig_in_pin);
Takashi Iwai82bc9552006-03-21 11:24:42 +01004365
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004366 return 0;
4367}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01004368EXPORT_SYMBOL_HDA(snd_hda_parse_pin_def_config);
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004369
Takashi Iwai4a471b72005-12-07 13:56:29 +01004370/* labels for input pins */
4371const char *auto_pin_cfg_labels[AUTO_PIN_LAST] = {
4372 "Mic", "Front Mic", "Line", "Front Line", "CD", "Aux"
4373};
Takashi Iwaiff7a3262008-11-28 15:17:06 +01004374EXPORT_SYMBOL_HDA(auto_pin_cfg_labels);
Takashi Iwai4a471b72005-12-07 13:56:29 +01004375
4376
Linus Torvalds1da177e2005-04-16 15:20:36 -07004377#ifdef CONFIG_PM
4378/*
4379 * power management
4380 */
4381
4382/**
4383 * snd_hda_suspend - suspend the codecs
4384 * @bus: the HDA bus
Linus Torvalds1da177e2005-04-16 15:20:36 -07004385 *
4386 * Returns 0 if successful.
4387 */
Takashi Iwai8dd78332009-06-02 01:16:07 +02004388int snd_hda_suspend(struct hda_bus *bus)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004389{
Takashi Iwai0ba21762007-04-16 11:29:14 +02004390 struct hda_codec *codec;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004391
Takashi Iwai0ba21762007-04-16 11:29:14 +02004392 list_for_each_entry(codec, &bus->codec_list, list) {
Takashi Iwai0b7a2e92007-08-14 15:18:26 +02004393#ifdef CONFIG_SND_HDA_POWER_SAVE
4394 if (!codec->power_on)
4395 continue;
4396#endif
Takashi Iwaicb53c622007-08-10 17:21:45 +02004397 hda_call_codec_suspend(codec);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004398 }
4399 return 0;
4400}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01004401EXPORT_SYMBOL_HDA(snd_hda_suspend);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004402
4403/**
4404 * snd_hda_resume - resume the codecs
4405 * @bus: the HDA bus
Linus Torvalds1da177e2005-04-16 15:20:36 -07004406 *
4407 * Returns 0 if successful.
Takashi Iwaicb53c622007-08-10 17:21:45 +02004408 *
4409 * This fucntion is defined only when POWER_SAVE isn't set.
4410 * In the power-save mode, the codec is resumed dynamically.
Linus Torvalds1da177e2005-04-16 15:20:36 -07004411 */
4412int snd_hda_resume(struct hda_bus *bus)
4413{
Takashi Iwai0ba21762007-04-16 11:29:14 +02004414 struct hda_codec *codec;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004415
Takashi Iwai0ba21762007-04-16 11:29:14 +02004416 list_for_each_entry(codec, &bus->codec_list, list) {
Maxim Levitskyd804ad92007-09-03 15:28:04 +02004417 if (snd_hda_codec_needs_resume(codec))
4418 hda_call_codec_resume(codec);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004419 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004420 return 0;
4421}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01004422EXPORT_SYMBOL_HDA(snd_hda_resume);
Takashi Iwai1289e9e2008-11-27 15:47:11 +01004423#endif /* CONFIG_PM */
Takashi Iwaib2e18592008-07-30 15:01:44 +02004424
4425/*
4426 * generic arrays
4427 */
4428
Takashi Iwaid5191e52009-11-16 14:58:17 +01004429/**
4430 * snd_array_new - get a new element from the given array
4431 * @array: the array object
4432 *
4433 * Get a new element from the given array. If it exceeds the
4434 * pre-allocated array size, re-allocate the array.
4435 *
4436 * Returns NULL if allocation failed.
Takashi Iwaib2e18592008-07-30 15:01:44 +02004437 */
4438void *snd_array_new(struct snd_array *array)
4439{
4440 if (array->used >= array->alloced) {
4441 int num = array->alloced + array->alloc_align;
Takashi Iwaib910d9a2008-11-07 00:26:52 +01004442 void *nlist;
4443 if (snd_BUG_ON(num >= 4096))
4444 return NULL;
4445 nlist = kcalloc(num + 1, array->elem_size, GFP_KERNEL);
Takashi Iwaib2e18592008-07-30 15:01:44 +02004446 if (!nlist)
4447 return NULL;
4448 if (array->list) {
4449 memcpy(nlist, array->list,
4450 array->elem_size * array->alloced);
4451 kfree(array->list);
4452 }
4453 array->list = nlist;
4454 array->alloced = num;
4455 }
Takashi Iwaif43aa022008-11-10 16:24:26 +01004456 return snd_array_elem(array, array->used++);
Takashi Iwaib2e18592008-07-30 15:01:44 +02004457}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01004458EXPORT_SYMBOL_HDA(snd_array_new);
Takashi Iwaib2e18592008-07-30 15:01:44 +02004459
Takashi Iwaid5191e52009-11-16 14:58:17 +01004460/**
4461 * snd_array_free - free the given array elements
4462 * @array: the array object
4463 */
Takashi Iwaib2e18592008-07-30 15:01:44 +02004464void snd_array_free(struct snd_array *array)
4465{
4466 kfree(array->list);
4467 array->used = 0;
4468 array->alloced = 0;
4469 array->list = NULL;
4470}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01004471EXPORT_SYMBOL_HDA(snd_array_free);
Takashi Iwaib2022262008-11-21 21:24:03 +01004472
Takashi Iwaid5191e52009-11-16 14:58:17 +01004473/**
4474 * snd_print_pcm_rates - Print the supported PCM rates to the string buffer
4475 * @pcm: PCM caps bits
4476 * @buf: the string buffer to write
4477 * @buflen: the max buffer length
4478 *
Takashi Iwaib2022262008-11-21 21:24:03 +01004479 * used by hda_proc.c and hda_eld.c
4480 */
4481void snd_print_pcm_rates(int pcm, char *buf, int buflen)
4482{
4483 static unsigned int rates[] = {
4484 8000, 11025, 16000, 22050, 32000, 44100, 48000, 88200,
4485 96000, 176400, 192000, 384000
4486 };
4487 int i, j;
4488
4489 for (i = 0, j = 0; i < ARRAY_SIZE(rates); i++)
4490 if (pcm & (1 << i))
4491 j += snprintf(buf + j, buflen - j, " %d", rates[i]);
4492
4493 buf[j] = '\0'; /* necessary when j == 0 */
4494}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01004495EXPORT_SYMBOL_HDA(snd_print_pcm_rates);
Takashi Iwaib2022262008-11-21 21:24:03 +01004496
Takashi Iwaid5191e52009-11-16 14:58:17 +01004497/**
4498 * snd_print_pcm_bits - Print the supported PCM fmt bits to the string buffer
4499 * @pcm: PCM caps bits
4500 * @buf: the string buffer to write
4501 * @buflen: the max buffer length
4502 *
4503 * used by hda_proc.c and hda_eld.c
4504 */
Takashi Iwaib2022262008-11-21 21:24:03 +01004505void snd_print_pcm_bits(int pcm, char *buf, int buflen)
4506{
4507 static unsigned int bits[] = { 8, 16, 20, 24, 32 };
4508 int i, j;
4509
4510 for (i = 0, j = 0; i < ARRAY_SIZE(bits); i++)
4511 if (pcm & (AC_SUPPCM_BITS_8 << i))
4512 j += snprintf(buf + j, buflen - j, " %d", bits[i]);
4513
4514 buf[j] = '\0'; /* necessary when j == 0 */
4515}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01004516EXPORT_SYMBOL_HDA(snd_print_pcm_bits);
Takashi Iwai1289e9e2008-11-27 15:47:11 +01004517
4518MODULE_DESCRIPTION("HDA codec core");
4519MODULE_LICENSE("GPL");