blob: 76d3c4c049dbea96edbbf7db4faf78e799f9da96 [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 Iwaic8b6bf9b2005-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 Iwaib94d3532008-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 Iwaic8b6bf9b2005-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 Iwaib82855a2009-12-27 11:24:56 +0100827 if (get_wcaps_type(get_wcaps(codec, nid)) != AC_WID_PIN)
828 return -EINVAL;
829
Takashi Iwai5e7b8e02009-02-23 09:45:59 +0100830 oldcfg = snd_hda_codec_get_pincfg(codec, nid);
Takashi Iwai3be14142009-02-20 14:11:16 +0100831 pin = look_up_pincfg(codec, list, nid);
832 if (!pin) {
833 pin = snd_array_new(list);
834 if (!pin)
835 return -ENOMEM;
836 pin->nid = nid;
837 }
838 pin->cfg = cfg;
Takashi Iwai5e7b8e02009-02-23 09:45:59 +0100839
840 /* change only when needed; e.g. if the pincfg is already present
841 * in user_pins[], don't write it
842 */
843 cfg = snd_hda_codec_get_pincfg(codec, nid);
844 if (oldcfg != cfg)
845 set_pincfg(codec, nid, cfg);
Takashi Iwai3be14142009-02-20 14:11:16 +0100846 return 0;
847}
848
Takashi Iwaid5191e52009-11-16 14:58:17 +0100849/**
850 * snd_hda_codec_set_pincfg - Override a pin default configuration
851 * @codec: the HDA codec
852 * @nid: NID to set the pin config
853 * @cfg: the pin default config value
854 *
855 * Override a pin default configuration value in the cache.
856 * This value can be read by snd_hda_codec_get_pincfg() in a higher
857 * priority than the real hardware value.
858 */
Takashi Iwai3be14142009-02-20 14:11:16 +0100859int snd_hda_codec_set_pincfg(struct hda_codec *codec,
860 hda_nid_t nid, unsigned int cfg)
861{
Takashi Iwai346ff702009-02-23 09:42:57 +0100862 return snd_hda_add_pincfg(codec, &codec->driver_pins, nid, cfg);
Takashi Iwai3be14142009-02-20 14:11:16 +0100863}
864EXPORT_SYMBOL_HDA(snd_hda_codec_set_pincfg);
865
Takashi Iwaid5191e52009-11-16 14:58:17 +0100866/**
867 * snd_hda_codec_get_pincfg - Obtain a pin-default configuration
868 * @codec: the HDA codec
869 * @nid: NID to get the pin config
870 *
871 * Get the current pin config value of the given pin NID.
872 * If the pincfg value is cached or overridden via sysfs or driver,
873 * returns the cached value.
874 */
Takashi Iwai3be14142009-02-20 14:11:16 +0100875unsigned int snd_hda_codec_get_pincfg(struct hda_codec *codec, hda_nid_t nid)
876{
877 struct hda_pincfg *pin;
878
Takashi Iwai3be14142009-02-20 14:11:16 +0100879#ifdef CONFIG_SND_HDA_HWDEP
Takashi Iwai346ff702009-02-23 09:42:57 +0100880 pin = look_up_pincfg(codec, &codec->user_pins, nid);
Takashi Iwai3be14142009-02-20 14:11:16 +0100881 if (pin)
882 return pin->cfg;
883#endif
Takashi Iwai5e7b8e02009-02-23 09:45:59 +0100884 pin = look_up_pincfg(codec, &codec->driver_pins, nid);
885 if (pin)
886 return pin->cfg;
Takashi Iwai3be14142009-02-20 14:11:16 +0100887 pin = look_up_pincfg(codec, &codec->init_pins, nid);
888 if (pin)
889 return pin->cfg;
890 return 0;
891}
892EXPORT_SYMBOL_HDA(snd_hda_codec_get_pincfg);
893
894/* restore all current pin configs */
895static void restore_pincfgs(struct hda_codec *codec)
896{
897 int i;
898 for (i = 0; i < codec->init_pins.used; i++) {
899 struct hda_pincfg *pin = snd_array_elem(&codec->init_pins, i);
900 set_pincfg(codec, pin->nid,
901 snd_hda_codec_get_pincfg(codec, pin->nid));
902 }
903}
Takashi Iwai54d17402005-11-21 16:33:22 +0100904
Takashi Iwai92ee6162009-12-27 11:18:59 +0100905/**
906 * snd_hda_shutup_pins - Shut up all pins
907 * @codec: the HDA codec
908 *
909 * Clear all pin controls to shup up before suspend for avoiding click noise.
910 * The controls aren't cached so that they can be resumed properly.
911 */
912void snd_hda_shutup_pins(struct hda_codec *codec)
913{
914 int i;
915 for (i = 0; i < codec->init_pins.used; i++) {
916 struct hda_pincfg *pin = snd_array_elem(&codec->init_pins, i);
917 /* use read here for syncing after issuing each verb */
918 snd_hda_codec_read(codec, pin->nid, 0,
919 AC_VERB_SET_PIN_WIDGET_CONTROL, 0);
920 }
921}
922EXPORT_SYMBOL_HDA(snd_hda_shutup_pins);
923
Takashi Iwai01751f52007-08-10 16:59:39 +0200924static void init_hda_cache(struct hda_cache_rec *cache,
925 unsigned int record_size);
Takashi Iwai1fcaee62007-08-23 00:01:09 +0200926static void free_hda_cache(struct hda_cache_rec *cache);
Takashi Iwai01751f52007-08-10 16:59:39 +0200927
Takashi Iwai3be14142009-02-20 14:11:16 +0100928/* restore the initial pin cfgs and release all pincfg lists */
929static void restore_init_pincfgs(struct hda_codec *codec)
930{
Takashi Iwai346ff702009-02-23 09:42:57 +0100931 /* first free driver_pins and user_pins, then call restore_pincfg
Takashi Iwai3be14142009-02-20 14:11:16 +0100932 * so that only the values in init_pins are restored
933 */
Takashi Iwai346ff702009-02-23 09:42:57 +0100934 snd_array_free(&codec->driver_pins);
Takashi Iwai3be14142009-02-20 14:11:16 +0100935#ifdef CONFIG_SND_HDA_HWDEP
Takashi Iwai346ff702009-02-23 09:42:57 +0100936 snd_array_free(&codec->user_pins);
Takashi Iwai3be14142009-02-20 14:11:16 +0100937#endif
938 restore_pincfgs(codec);
939 snd_array_free(&codec->init_pins);
940}
941
Takashi Iwai54d17402005-11-21 16:33:22 +0100942/*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700943 * codec destructor
944 */
945static void snd_hda_codec_free(struct hda_codec *codec)
946{
Takashi Iwai0ba21762007-04-16 11:29:14 +0200947 if (!codec)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700948 return;
Takashi Iwai3be14142009-02-20 14:11:16 +0100949 restore_init_pincfgs(codec);
Takashi Iwaicb53c622007-08-10 17:21:45 +0200950#ifdef CONFIG_SND_HDA_POWER_SAVE
951 cancel_delayed_work(&codec->power_work);
Takashi Iwai6acaed32009-01-12 10:09:24 +0100952 flush_workqueue(codec->bus->workq);
Takashi Iwaicb53c622007-08-10 17:21:45 +0200953#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700954 list_del(&codec->list);
Takashi Iwaid13bd412008-07-30 15:01:45 +0200955 snd_array_free(&codec->mixers);
Jaroslav Kysela5b0cb1d2009-12-08 16:13:32 +0100956 snd_array_free(&codec->nids);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700957 codec->bus->caddr_tbl[codec->addr] = NULL;
958 if (codec->patch_ops.free)
959 codec->patch_ops.free(codec);
Takashi Iwai1289e9e2008-11-27 15:47:11 +0100960 module_put(codec->owner);
Takashi Iwai01751f52007-08-10 16:59:39 +0200961 free_hda_cache(&codec->amp_cache);
Takashi Iwaib3ac5632007-08-10 17:03:40 +0200962 free_hda_cache(&codec->cmd_cache);
Takashi Iwai812a2cc2009-05-16 10:00:49 +0200963 kfree(codec->vendor_name);
964 kfree(codec->chip_name);
Takashi Iwaif44ac832008-07-30 15:01:45 +0200965 kfree(codec->modelname);
Takashi Iwai54d17402005-11-21 16:33:22 +0100966 kfree(codec->wcaps);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700967 kfree(codec);
968}
969
Takashi Iwaibb6ac722009-03-13 09:02:42 +0100970static void hda_set_power_state(struct hda_codec *codec, hda_nid_t fg,
971 unsigned int power_state);
972
Linus Torvalds1da177e2005-04-16 15:20:36 -0700973/**
974 * snd_hda_codec_new - create a HDA codec
975 * @bus: the bus to assign
976 * @codec_addr: the codec address
977 * @codecp: the pointer to store the generated codec
978 *
979 * Returns 0 if successful, or a negative error code.
980 */
Takashi Iwai1289e9e2008-11-27 15:47:11 +0100981int /*__devinit*/ snd_hda_codec_new(struct hda_bus *bus, unsigned int codec_addr,
Takashi Iwaia1e21c92009-06-17 09:33:52 +0200982 struct hda_codec **codecp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700983{
984 struct hda_codec *codec;
Jaroslav Kyselaba443682008-08-13 20:55:32 +0200985 char component[31];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700986 int err;
987
Takashi Iwaida3cec32008-08-08 17:12:14 +0200988 if (snd_BUG_ON(!bus))
989 return -EINVAL;
990 if (snd_BUG_ON(codec_addr > HDA_MAX_CODEC_ADDRESS))
991 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700992
993 if (bus->caddr_tbl[codec_addr]) {
Takashi Iwai0ba21762007-04-16 11:29:14 +0200994 snd_printk(KERN_ERR "hda_codec: "
995 "address 0x%x is already occupied\n", codec_addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700996 return -EBUSY;
997 }
998
Takashi Iwaie560d8d2005-09-09 14:21:46 +0200999 codec = kzalloc(sizeof(*codec), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001000 if (codec == NULL) {
1001 snd_printk(KERN_ERR "can't allocate struct hda_codec\n");
1002 return -ENOMEM;
1003 }
1004
1005 codec->bus = bus;
1006 codec->addr = codec_addr;
Ingo Molnar62932df2006-01-16 16:34:20 +01001007 mutex_init(&codec->spdif_mutex);
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001008 mutex_init(&codec->control_mutex);
Takashi Iwai01751f52007-08-10 16:59:39 +02001009 init_hda_cache(&codec->amp_cache, sizeof(struct hda_amp_info));
Takashi Iwaib3ac5632007-08-10 17:03:40 +02001010 init_hda_cache(&codec->cmd_cache, sizeof(struct hda_cache_head));
Jaroslav Kysela5b0cb1d2009-12-08 16:13:32 +01001011 snd_array_init(&codec->mixers, sizeof(struct hda_nid_item), 32);
1012 snd_array_init(&codec->nids, sizeof(struct hda_nid_item), 32);
Takashi Iwai3be14142009-02-20 14:11:16 +01001013 snd_array_init(&codec->init_pins, sizeof(struct hda_pincfg), 16);
Takashi Iwai346ff702009-02-23 09:42:57 +01001014 snd_array_init(&codec->driver_pins, sizeof(struct hda_pincfg), 16);
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001015 if (codec->bus->modelname) {
1016 codec->modelname = kstrdup(codec->bus->modelname, GFP_KERNEL);
1017 if (!codec->modelname) {
1018 snd_hda_codec_free(codec);
1019 return -ENODEV;
1020 }
1021 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001022
Takashi Iwaicb53c622007-08-10 17:21:45 +02001023#ifdef CONFIG_SND_HDA_POWER_SAVE
1024 INIT_DELAYED_WORK(&codec->power_work, hda_power_work);
1025 /* snd_hda_codec_new() marks the codec as power-up, and leave it as is.
1026 * the caller has to power down appropriatley after initialization
1027 * phase.
1028 */
1029 hda_keep_power_on(codec);
1030#endif
1031
Linus Torvalds1da177e2005-04-16 15:20:36 -07001032 list_add_tail(&codec->list, &bus->codec_list);
1033 bus->caddr_tbl[codec_addr] = codec;
1034
Takashi Iwai0ba21762007-04-16 11:29:14 +02001035 codec->vendor_id = snd_hda_param_read(codec, AC_NODE_ROOT,
1036 AC_PAR_VENDOR_ID);
Takashi Iwai111d3af2006-02-16 18:17:58 +01001037 if (codec->vendor_id == -1)
1038 /* read again, hopefully the access method was corrected
1039 * in the last read...
1040 */
1041 codec->vendor_id = snd_hda_param_read(codec, AC_NODE_ROOT,
1042 AC_PAR_VENDOR_ID);
Takashi Iwai0ba21762007-04-16 11:29:14 +02001043 codec->subsystem_id = snd_hda_param_read(codec, AC_NODE_ROOT,
1044 AC_PAR_SUBSYSTEM_ID);
1045 codec->revision_id = snd_hda_param_read(codec, AC_NODE_ROOT,
1046 AC_PAR_REV_ID);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001047
Sasha Khapyorsky673b6832005-08-11 11:00:16 +02001048 setup_fg_nodes(codec);
Takashi Iwai0ba21762007-04-16 11:29:14 +02001049 if (!codec->afg && !codec->mfg) {
Sasha Khapyorsky673b6832005-08-11 11:00:16 +02001050 snd_printdd("hda_codec: no AFG or MFG node found\n");
Takashi Iwai3be14142009-02-20 14:11:16 +01001051 err = -ENODEV;
1052 goto error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001053 }
1054
Takashi Iwai3be14142009-02-20 14:11:16 +01001055 err = read_widget_caps(codec, codec->afg ? codec->afg : codec->mfg);
1056 if (err < 0) {
Takashi Iwai54d17402005-11-21 16:33:22 +01001057 snd_printk(KERN_ERR "hda_codec: cannot malloc\n");
Takashi Iwai3be14142009-02-20 14:11:16 +01001058 goto error;
Takashi Iwai54d17402005-11-21 16:33:22 +01001059 }
Takashi Iwai3be14142009-02-20 14:11:16 +01001060 err = read_pin_defaults(codec);
1061 if (err < 0)
1062 goto error;
Takashi Iwai54d17402005-11-21 16:33:22 +01001063
Takashi Iwai0ba21762007-04-16 11:29:14 +02001064 if (!codec->subsystem_id) {
Takashi Iwai86284e42005-10-11 15:05:54 +02001065 hda_nid_t nid = codec->afg ? codec->afg : codec->mfg;
Takashi Iwai0ba21762007-04-16 11:29:14 +02001066 codec->subsystem_id =
1067 snd_hda_codec_read(codec, nid, 0,
1068 AC_VERB_GET_SUBSYSTEM_ID, 0);
Takashi Iwai86284e42005-10-11 15:05:54 +02001069 }
1070
Takashi Iwaibb6ac722009-03-13 09:02:42 +01001071 /* power-up all before initialization */
1072 hda_set_power_state(codec,
1073 codec->afg ? codec->afg : codec->mfg,
1074 AC_PWRST_D0);
1075
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001076 snd_hda_codec_proc_new(codec);
1077
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001078 snd_hda_create_hwdep(codec);
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001079
1080 sprintf(component, "HDA:%08x,%08x,%08x", codec->vendor_id,
1081 codec->subsystem_id, codec->revision_id);
1082 snd_component_add(codec->bus->card, component);
1083
1084 if (codecp)
1085 *codecp = codec;
1086 return 0;
Takashi Iwai3be14142009-02-20 14:11:16 +01001087
1088 error:
1089 snd_hda_codec_free(codec);
1090 return err;
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001091}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001092EXPORT_SYMBOL_HDA(snd_hda_codec_new);
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001093
Takashi Iwaid5191e52009-11-16 14:58:17 +01001094/**
1095 * snd_hda_codec_configure - (Re-)configure the HD-audio codec
1096 * @codec: the HDA codec
1097 *
1098 * Start parsing of the given codec tree and (re-)initialize the whole
1099 * patch instance.
1100 *
1101 * Returns 0 if successful or a negative error code.
1102 */
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001103int snd_hda_codec_configure(struct hda_codec *codec)
1104{
1105 int err;
1106
Takashi Iwaid5ad6302007-03-07 15:55:59 +01001107 codec->preset = find_codec_preset(codec);
Takashi Iwai812a2cc2009-05-16 10:00:49 +02001108 if (!codec->vendor_name || !codec->chip_name) {
Takashi Iwaif44ac832008-07-30 15:01:45 +02001109 err = get_codec_name(codec);
1110 if (err < 0)
1111 return err;
1112 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001113
Takashi Iwai82467612007-07-27 19:15:54 +02001114 if (is_generic_config(codec)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001115 err = snd_hda_parse_generic_codec(codec);
Takashi Iwai82467612007-07-27 19:15:54 +02001116 goto patched;
1117 }
Takashi Iwai82467612007-07-27 19:15:54 +02001118 if (codec->preset && codec->preset->patch) {
1119 err = codec->preset->patch(codec);
1120 goto patched;
1121 }
1122
1123 /* call the default parser */
Takashi Iwai82467612007-07-27 19:15:54 +02001124 err = snd_hda_parse_generic_codec(codec);
Takashi Iwai35a1e0c2007-10-19 08:13:40 +02001125 if (err < 0)
1126 printk(KERN_ERR "hda-codec: No codec parser is available\n");
Takashi Iwai82467612007-07-27 19:15:54 +02001127
1128 patched:
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001129 if (!err && codec->patch_ops.unsol_event)
1130 err = init_unsol_queue(codec->bus);
Takashi Iwaif62faed2009-12-23 09:27:51 +01001131 /* audio codec should override the mixer name */
1132 if (!err && (codec->afg || !*codec->bus->card->mixername))
1133 snprintf(codec->bus->card->mixername,
1134 sizeof(codec->bus->card->mixername),
1135 "%s %s", codec->vendor_name, codec->chip_name);
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001136 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001137}
Takashi Iwaia1e21c92009-06-17 09:33:52 +02001138EXPORT_SYMBOL_HDA(snd_hda_codec_configure);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001139
1140/**
1141 * snd_hda_codec_setup_stream - set up the codec for streaming
1142 * @codec: the CODEC to set up
1143 * @nid: the NID to set up
1144 * @stream_tag: stream tag to pass, it's between 0x1 and 0xf.
1145 * @channel_id: channel id to pass, zero based.
1146 * @format: stream format.
1147 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02001148void snd_hda_codec_setup_stream(struct hda_codec *codec, hda_nid_t nid,
1149 u32 stream_tag,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001150 int channel_id, int format)
1151{
Takashi Iwai0ba21762007-04-16 11:29:14 +02001152 if (!nid)
Takashi Iwaid21b37e2005-04-20 13:45:55 +02001153 return;
1154
Takashi Iwai0ba21762007-04-16 11:29:14 +02001155 snd_printdd("hda_codec_setup_stream: "
1156 "NID=0x%x, stream=0x%x, channel=%d, format=0x%x\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07001157 nid, stream_tag, channel_id, format);
1158 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CHANNEL_STREAMID,
1159 (stream_tag << 4) | channel_id);
1160 msleep(1);
1161 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_STREAM_FORMAT, format);
1162}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001163EXPORT_SYMBOL_HDA(snd_hda_codec_setup_stream);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001164
Takashi Iwaid5191e52009-11-16 14:58:17 +01001165/**
1166 * snd_hda_codec_cleanup_stream - clean up the codec for closing
1167 * @codec: the CODEC to clean up
1168 * @nid: the NID to clean up
1169 */
Takashi Iwai888afa12008-03-18 09:57:50 +01001170void snd_hda_codec_cleanup_stream(struct hda_codec *codec, hda_nid_t nid)
1171{
1172 if (!nid)
1173 return;
1174
1175 snd_printdd("hda_codec_cleanup_stream: NID=0x%x\n", nid);
1176 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CHANNEL_STREAMID, 0);
1177#if 0 /* keep the format */
1178 msleep(1);
1179 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_STREAM_FORMAT, 0);
1180#endif
1181}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001182EXPORT_SYMBOL_HDA(snd_hda_codec_cleanup_stream);
Takashi Iwai888afa12008-03-18 09:57:50 +01001183
Linus Torvalds1da177e2005-04-16 15:20:36 -07001184/*
1185 * amp access functions
1186 */
1187
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001188/* FIXME: more better hash key? */
1189#define HDA_HASH_KEY(nid,dir,idx) (u32)((nid) + ((idx) << 16) + ((dir) << 24))
Takashi Iwai1327a322009-03-23 13:07:47 +01001190#define HDA_HASH_PINCAP_KEY(nid) (u32)((nid) + (0x02 << 24))
Takashi Iwai92c7c8a2009-03-24 07:32:14 +01001191#define HDA_HASH_PARPCM_KEY(nid) (u32)((nid) + (0x03 << 24))
1192#define HDA_HASH_PARSTR_KEY(nid) (u32)((nid) + (0x04 << 24))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001193#define INFO_AMP_CAPS (1<<0)
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001194#define INFO_AMP_VOL(ch) (1 << (1 + (ch)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001195
1196/* initialize the hash table */
Takashi Iwai1289e9e2008-11-27 15:47:11 +01001197static void /*__devinit*/ init_hda_cache(struct hda_cache_rec *cache,
Takashi Iwai01751f52007-08-10 16:59:39 +02001198 unsigned int record_size)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001199{
Takashi Iwai01751f52007-08-10 16:59:39 +02001200 memset(cache, 0, sizeof(*cache));
1201 memset(cache->hash, 0xff, sizeof(cache->hash));
Takashi Iwai603c4012008-07-30 15:01:44 +02001202 snd_array_init(&cache->buf, record_size, 64);
Takashi Iwai01751f52007-08-10 16:59:39 +02001203}
1204
Takashi Iwai1fcaee62007-08-23 00:01:09 +02001205static void free_hda_cache(struct hda_cache_rec *cache)
Takashi Iwai01751f52007-08-10 16:59:39 +02001206{
Takashi Iwai603c4012008-07-30 15:01:44 +02001207 snd_array_free(&cache->buf);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001208}
1209
1210/* query the hash. allocate an entry if not found. */
Takashi Iwai01751f52007-08-10 16:59:39 +02001211static struct hda_cache_head *get_alloc_hash(struct hda_cache_rec *cache,
1212 u32 key)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001213{
Takashi Iwai01751f52007-08-10 16:59:39 +02001214 u16 idx = key % (u16)ARRAY_SIZE(cache->hash);
1215 u16 cur = cache->hash[idx];
1216 struct hda_cache_head *info;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001217
1218 while (cur != 0xffff) {
Takashi Iwaif43aa022008-11-10 16:24:26 +01001219 info = snd_array_elem(&cache->buf, cur);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001220 if (info->key == key)
1221 return info;
1222 cur = info->next;
1223 }
1224
1225 /* add a new hash entry */
Takashi Iwai603c4012008-07-30 15:01:44 +02001226 info = snd_array_new(&cache->buf);
Takashi Iwaic2174292008-11-07 00:23:30 +01001227 if (!info)
1228 return NULL;
Takashi Iwaif43aa022008-11-10 16:24:26 +01001229 cur = snd_array_index(&cache->buf, info);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001230 info->key = key;
Takashi Iwai01751f52007-08-10 16:59:39 +02001231 info->val = 0;
1232 info->next = cache->hash[idx];
1233 cache->hash[idx] = cur;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001234
1235 return info;
1236}
1237
Takashi Iwai01751f52007-08-10 16:59:39 +02001238/* query and allocate an amp hash entry */
1239static inline struct hda_amp_info *
1240get_alloc_amp_hash(struct hda_codec *codec, u32 key)
1241{
1242 return (struct hda_amp_info *)get_alloc_hash(&codec->amp_cache, key);
1243}
1244
Takashi Iwaid5191e52009-11-16 14:58:17 +01001245/**
1246 * query_amp_caps - query AMP capabilities
1247 * @codec: the HD-auio codec
1248 * @nid: the NID to query
1249 * @direction: either #HDA_INPUT or #HDA_OUTPUT
1250 *
1251 * Query AMP capabilities for the given widget and direction.
1252 * Returns the obtained capability bits.
1253 *
1254 * When cap bits have been already read, this doesn't read again but
1255 * returns the cached value.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001256 */
Matthew Ranostay09a99952008-01-24 11:49:21 +01001257u32 query_amp_caps(struct hda_codec *codec, hda_nid_t nid, int direction)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001258{
Takashi Iwai0ba21762007-04-16 11:29:14 +02001259 struct hda_amp_info *info;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001260
Takashi Iwai0ba21762007-04-16 11:29:14 +02001261 info = get_alloc_amp_hash(codec, HDA_HASH_KEY(nid, direction, 0));
1262 if (!info)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001263 return 0;
Takashi Iwai01751f52007-08-10 16:59:39 +02001264 if (!(info->head.val & INFO_AMP_CAPS)) {
Takashi Iwai0ba21762007-04-16 11:29:14 +02001265 if (!(get_wcaps(codec, nid) & AC_WCAP_AMP_OVRD))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001266 nid = codec->afg;
Takashi Iwai0ba21762007-04-16 11:29:14 +02001267 info->amp_caps = snd_hda_param_read(codec, nid,
1268 direction == HDA_OUTPUT ?
1269 AC_PAR_AMP_OUT_CAP :
1270 AC_PAR_AMP_IN_CAP);
Takashi Iwaib75e53f2007-05-10 16:56:09 +02001271 if (info->amp_caps)
Takashi Iwai01751f52007-08-10 16:59:39 +02001272 info->head.val |= INFO_AMP_CAPS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001273 }
1274 return info->amp_caps;
1275}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001276EXPORT_SYMBOL_HDA(query_amp_caps);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001277
Takashi Iwaid5191e52009-11-16 14:58:17 +01001278/**
1279 * snd_hda_override_amp_caps - Override the AMP capabilities
1280 * @codec: the CODEC to clean up
1281 * @nid: the NID to clean up
1282 * @direction: either #HDA_INPUT or #HDA_OUTPUT
1283 * @caps: the capability bits to set
1284 *
1285 * Override the cached AMP caps bits value by the given one.
1286 * This function is useful if the driver needs to adjust the AMP ranges,
1287 * e.g. limit to 0dB, etc.
1288 *
1289 * Returns zero if successful or a negative error code.
1290 */
Takashi Iwai897cc182007-05-29 19:01:37 +02001291int snd_hda_override_amp_caps(struct hda_codec *codec, hda_nid_t nid, int dir,
1292 unsigned int caps)
1293{
1294 struct hda_amp_info *info;
1295
1296 info = get_alloc_amp_hash(codec, HDA_HASH_KEY(nid, dir, 0));
1297 if (!info)
1298 return -EINVAL;
1299 info->amp_caps = caps;
Takashi Iwai01751f52007-08-10 16:59:39 +02001300 info->head.val |= INFO_AMP_CAPS;
Takashi Iwai897cc182007-05-29 19:01:37 +02001301 return 0;
1302}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001303EXPORT_SYMBOL_HDA(snd_hda_override_amp_caps);
Takashi Iwai897cc182007-05-29 19:01:37 +02001304
Takashi Iwai92c7c8a2009-03-24 07:32:14 +01001305static unsigned int
1306query_caps_hash(struct hda_codec *codec, hda_nid_t nid, u32 key,
1307 unsigned int (*func)(struct hda_codec *, hda_nid_t))
Takashi Iwai1327a322009-03-23 13:07:47 +01001308{
1309 struct hda_amp_info *info;
1310
Takashi Iwai92c7c8a2009-03-24 07:32:14 +01001311 info = get_alloc_amp_hash(codec, key);
Takashi Iwai1327a322009-03-23 13:07:47 +01001312 if (!info)
1313 return 0;
1314 if (!info->head.val) {
Takashi Iwai1327a322009-03-23 13:07:47 +01001315 info->head.val |= INFO_AMP_CAPS;
Takashi Iwai92c7c8a2009-03-24 07:32:14 +01001316 info->amp_caps = func(codec, nid);
Takashi Iwai1327a322009-03-23 13:07:47 +01001317 }
1318 return info->amp_caps;
1319}
Takashi Iwai92c7c8a2009-03-24 07:32:14 +01001320
1321static unsigned int read_pin_cap(struct hda_codec *codec, hda_nid_t nid)
1322{
1323 return snd_hda_param_read(codec, nid, AC_PAR_PIN_CAP);
1324}
1325
Takashi Iwaid5191e52009-11-16 14:58:17 +01001326/**
1327 * snd_hda_query_pin_caps - Query PIN capabilities
1328 * @codec: the HD-auio codec
1329 * @nid: the NID to query
1330 *
1331 * Query PIN capabilities for the given widget.
1332 * Returns the obtained capability bits.
1333 *
1334 * When cap bits have been already read, this doesn't read again but
1335 * returns the cached value.
1336 */
Takashi Iwai92c7c8a2009-03-24 07:32:14 +01001337u32 snd_hda_query_pin_caps(struct hda_codec *codec, hda_nid_t nid)
1338{
1339 return query_caps_hash(codec, nid, HDA_HASH_PINCAP_KEY(nid),
1340 read_pin_cap);
1341}
Takashi Iwai1327a322009-03-23 13:07:47 +01001342EXPORT_SYMBOL_HDA(snd_hda_query_pin_caps);
1343
Wu Fengguang864f92b2009-11-18 12:38:02 +08001344/**
1345 * snd_hda_pin_sense - execute pin sense measurement
1346 * @codec: the CODEC to sense
1347 * @nid: the pin NID to sense
1348 *
1349 * Execute necessary pin sense measurement and return its Presence Detect,
1350 * Impedance, ELD Valid etc. status bits.
1351 */
1352u32 snd_hda_pin_sense(struct hda_codec *codec, hda_nid_t nid)
1353{
Takashi Iwai729d55b2009-12-25 22:49:01 +01001354 u32 pincap;
Wu Fengguang864f92b2009-11-18 12:38:02 +08001355
Takashi Iwai729d55b2009-12-25 22:49:01 +01001356 if (!codec->no_trigger_sense) {
1357 pincap = snd_hda_query_pin_caps(codec, nid);
1358 if (pincap & AC_PINCAP_TRIG_REQ) /* need trigger? */
1359 snd_hda_codec_read(codec, nid, 0, AC_VERB_SET_PIN_SENSE, 0);
1360 }
Wu Fengguang864f92b2009-11-18 12:38:02 +08001361 return snd_hda_codec_read(codec, nid, 0,
1362 AC_VERB_GET_PIN_SENSE, 0);
1363}
1364EXPORT_SYMBOL_HDA(snd_hda_pin_sense);
1365
1366/**
1367 * snd_hda_jack_detect - query pin Presence Detect status
1368 * @codec: the CODEC to sense
1369 * @nid: the pin NID to sense
1370 *
1371 * Query and return the pin's Presence Detect status.
1372 */
1373int snd_hda_jack_detect(struct hda_codec *codec, hda_nid_t nid)
1374{
1375 u32 sense = snd_hda_pin_sense(codec, nid);
1376 return !!(sense & AC_PINSENSE_PRESENCE);
1377}
1378EXPORT_SYMBOL_HDA(snd_hda_jack_detect);
1379
Linus Torvalds1da177e2005-04-16 15:20:36 -07001380/*
1381 * read the current volume to info
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001382 * if the cache exists, read the cache value.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001383 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02001384static unsigned int get_vol_mute(struct hda_codec *codec,
1385 struct hda_amp_info *info, hda_nid_t nid,
1386 int ch, int direction, int index)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001387{
1388 u32 val, parm;
1389
Takashi Iwai01751f52007-08-10 16:59:39 +02001390 if (info->head.val & INFO_AMP_VOL(ch))
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001391 return info->vol[ch];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001392
1393 parm = ch ? AC_AMP_GET_RIGHT : AC_AMP_GET_LEFT;
1394 parm |= direction == HDA_OUTPUT ? AC_AMP_GET_OUTPUT : AC_AMP_GET_INPUT;
1395 parm |= index;
Takashi Iwai0ba21762007-04-16 11:29:14 +02001396 val = snd_hda_codec_read(codec, nid, 0,
1397 AC_VERB_GET_AMP_GAIN_MUTE, parm);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001398 info->vol[ch] = val & 0xff;
Takashi Iwai01751f52007-08-10 16:59:39 +02001399 info->head.val |= INFO_AMP_VOL(ch);
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001400 return info->vol[ch];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001401}
1402
1403/*
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001404 * write the current volume in info to the h/w and update the cache
Linus Torvalds1da177e2005-04-16 15:20:36 -07001405 */
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001406static void put_vol_mute(struct hda_codec *codec, struct hda_amp_info *info,
Takashi Iwai0ba21762007-04-16 11:29:14 +02001407 hda_nid_t nid, int ch, int direction, int index,
1408 int val)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001409{
1410 u32 parm;
1411
1412 parm = ch ? AC_AMP_SET_RIGHT : AC_AMP_SET_LEFT;
1413 parm |= direction == HDA_OUTPUT ? AC_AMP_SET_OUTPUT : AC_AMP_SET_INPUT;
1414 parm |= index << AC_AMP_SET_INDEX_SHIFT;
1415 parm |= val;
1416 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, parm);
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001417 info->vol[ch] = val;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001418}
1419
Takashi Iwaid5191e52009-11-16 14:58:17 +01001420/**
1421 * snd_hda_codec_amp_read - Read AMP value
1422 * @codec: HD-audio codec
1423 * @nid: NID to read the AMP value
1424 * @ch: channel (left=0 or right=1)
1425 * @direction: #HDA_INPUT or #HDA_OUTPUT
1426 * @index: the index value (only for input direction)
1427 *
1428 * Read AMP value. The volume is between 0 to 0x7f, 0x80 = mute bit.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001429 */
Takashi Iwai834be882006-03-01 14:16:17 +01001430int snd_hda_codec_amp_read(struct hda_codec *codec, hda_nid_t nid, int ch,
1431 int direction, int index)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001432{
Takashi Iwai0ba21762007-04-16 11:29:14 +02001433 struct hda_amp_info *info;
1434 info = get_alloc_amp_hash(codec, HDA_HASH_KEY(nid, direction, index));
1435 if (!info)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001436 return 0;
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001437 return get_vol_mute(codec, info, nid, ch, direction, index);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001438}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001439EXPORT_SYMBOL_HDA(snd_hda_codec_amp_read);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001440
Takashi Iwaid5191e52009-11-16 14:58:17 +01001441/**
1442 * snd_hda_codec_amp_update - update the AMP value
1443 * @codec: HD-audio codec
1444 * @nid: NID to read the AMP value
1445 * @ch: channel (left=0 or right=1)
1446 * @direction: #HDA_INPUT or #HDA_OUTPUT
1447 * @idx: the index value (only for input direction)
1448 * @mask: bit mask to set
1449 * @val: the bits value to set
1450 *
1451 * Update the AMP value with a bit mask.
1452 * Returns 0 if the value is unchanged, 1 if changed.
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001453 */
Takashi Iwai834be882006-03-01 14:16:17 +01001454int snd_hda_codec_amp_update(struct hda_codec *codec, hda_nid_t nid, int ch,
1455 int direction, int idx, int mask, int val)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001456{
Takashi Iwai0ba21762007-04-16 11:29:14 +02001457 struct hda_amp_info *info;
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001458
Takashi Iwai0ba21762007-04-16 11:29:14 +02001459 info = get_alloc_amp_hash(codec, HDA_HASH_KEY(nid, direction, idx));
1460 if (!info)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001461 return 0;
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001462 val &= mask;
1463 val |= get_vol_mute(codec, info, nid, ch, direction, idx) & ~mask;
Takashi Iwai82beb8f2007-08-10 17:09:26 +02001464 if (info->vol[ch] == val)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001465 return 0;
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001466 put_vol_mute(codec, info, nid, ch, direction, idx, val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001467 return 1;
1468}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001469EXPORT_SYMBOL_HDA(snd_hda_codec_amp_update);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001470
Takashi Iwaid5191e52009-11-16 14:58:17 +01001471/**
1472 * snd_hda_codec_amp_stereo - update the AMP stereo values
1473 * @codec: HD-audio codec
1474 * @nid: NID to read the AMP value
1475 * @direction: #HDA_INPUT or #HDA_OUTPUT
1476 * @idx: the index value (only for input direction)
1477 * @mask: bit mask to set
1478 * @val: the bits value to set
1479 *
1480 * Update the AMP values like snd_hda_codec_amp_update(), but for a
1481 * stereo widget with the same mask and value.
Takashi Iwai47fd8302007-08-10 17:11:07 +02001482 */
1483int snd_hda_codec_amp_stereo(struct hda_codec *codec, hda_nid_t nid,
1484 int direction, int idx, int mask, int val)
1485{
1486 int ch, ret = 0;
1487 for (ch = 0; ch < 2; ch++)
1488 ret |= snd_hda_codec_amp_update(codec, nid, ch, direction,
1489 idx, mask, val);
1490 return ret;
1491}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001492EXPORT_SYMBOL_HDA(snd_hda_codec_amp_stereo);
Takashi Iwai47fd8302007-08-10 17:11:07 +02001493
Takashi Iwaicb53c622007-08-10 17:21:45 +02001494#ifdef SND_HDA_NEEDS_RESUME
Takashi Iwaid5191e52009-11-16 14:58:17 +01001495/**
1496 * snd_hda_codec_resume_amp - Resume all AMP commands from the cache
1497 * @codec: HD-audio codec
1498 *
1499 * Resume the all amp commands from the cache.
1500 */
Takashi Iwaib3ac5632007-08-10 17:03:40 +02001501void snd_hda_codec_resume_amp(struct hda_codec *codec)
1502{
Takashi Iwai603c4012008-07-30 15:01:44 +02001503 struct hda_amp_info *buffer = codec->amp_cache.buf.list;
Takashi Iwaib3ac5632007-08-10 17:03:40 +02001504 int i;
1505
Takashi Iwai603c4012008-07-30 15:01:44 +02001506 for (i = 0; i < codec->amp_cache.buf.used; i++, buffer++) {
Takashi Iwaib3ac5632007-08-10 17:03:40 +02001507 u32 key = buffer->head.key;
1508 hda_nid_t nid;
1509 unsigned int idx, dir, ch;
1510 if (!key)
1511 continue;
1512 nid = key & 0xff;
1513 idx = (key >> 16) & 0xff;
1514 dir = (key >> 24) & 0xff;
1515 for (ch = 0; ch < 2; ch++) {
1516 if (!(buffer->head.val & INFO_AMP_VOL(ch)))
1517 continue;
1518 put_vol_mute(codec, buffer, nid, ch, dir, idx,
1519 buffer->vol[ch]);
1520 }
1521 }
1522}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001523EXPORT_SYMBOL_HDA(snd_hda_codec_resume_amp);
Takashi Iwaicb53c622007-08-10 17:21:45 +02001524#endif /* SND_HDA_NEEDS_RESUME */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001525
Takashi Iwaid5191e52009-11-16 14:58:17 +01001526/**
1527 * snd_hda_mixer_amp_volume_info - Info callback for a standard AMP mixer
1528 *
1529 * The control element is supposed to have the private_value field
1530 * set up via HDA_COMPOSE_AMP_VAL*() or related macros.
1531 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02001532int snd_hda_mixer_amp_volume_info(struct snd_kcontrol *kcontrol,
1533 struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001534{
1535 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1536 u16 nid = get_amp_nid(kcontrol);
1537 u8 chs = get_amp_channels(kcontrol);
1538 int dir = get_amp_direction(kcontrol);
Takashi Iwai29fdbec2009-01-20 13:07:55 +01001539 unsigned int ofs = get_amp_offset(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001540 u32 caps;
1541
1542 caps = query_amp_caps(codec, nid, dir);
Takashi Iwai0ba21762007-04-16 11:29:14 +02001543 /* num steps */
1544 caps = (caps & AC_AMPCAP_NUM_STEPS) >> AC_AMPCAP_NUM_STEPS_SHIFT;
1545 if (!caps) {
1546 printk(KERN_WARNING "hda_codec: "
Takashi Iwai9c8f2ab2008-01-11 16:12:23 +01001547 "num_steps = 0 for NID=0x%x (ctl = %s)\n", nid,
1548 kcontrol->id.name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001549 return -EINVAL;
1550 }
Takashi Iwai29fdbec2009-01-20 13:07:55 +01001551 if (ofs < caps)
1552 caps -= ofs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001553 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
1554 uinfo->count = chs == 3 ? 2 : 1;
1555 uinfo->value.integer.min = 0;
1556 uinfo->value.integer.max = caps;
1557 return 0;
1558}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001559EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_volume_info);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001560
Takashi Iwai29fdbec2009-01-20 13:07:55 +01001561
1562static inline unsigned int
1563read_amp_value(struct hda_codec *codec, hda_nid_t nid,
1564 int ch, int dir, int idx, unsigned int ofs)
1565{
1566 unsigned int val;
1567 val = snd_hda_codec_amp_read(codec, nid, ch, dir, idx);
1568 val &= HDA_AMP_VOLMASK;
1569 if (val >= ofs)
1570 val -= ofs;
1571 else
1572 val = 0;
1573 return val;
1574}
1575
1576static inline int
1577update_amp_value(struct hda_codec *codec, hda_nid_t nid,
1578 int ch, int dir, int idx, unsigned int ofs,
1579 unsigned int val)
1580{
1581 if (val > 0)
1582 val += ofs;
1583 return snd_hda_codec_amp_update(codec, nid, ch, dir, idx,
1584 HDA_AMP_VOLMASK, val);
1585}
1586
Takashi Iwaid5191e52009-11-16 14:58:17 +01001587/**
1588 * snd_hda_mixer_amp_volume_get - Get callback for a standard AMP mixer volume
1589 *
1590 * The control element is supposed to have the private_value field
1591 * set up via HDA_COMPOSE_AMP_VAL*() or related macros.
1592 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02001593int snd_hda_mixer_amp_volume_get(struct snd_kcontrol *kcontrol,
1594 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001595{
1596 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1597 hda_nid_t nid = get_amp_nid(kcontrol);
1598 int chs = get_amp_channels(kcontrol);
1599 int dir = get_amp_direction(kcontrol);
1600 int idx = get_amp_index(kcontrol);
Takashi Iwai29fdbec2009-01-20 13:07:55 +01001601 unsigned int ofs = get_amp_offset(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001602 long *valp = ucontrol->value.integer.value;
1603
1604 if (chs & 1)
Takashi Iwai29fdbec2009-01-20 13:07:55 +01001605 *valp++ = read_amp_value(codec, nid, 0, dir, idx, ofs);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001606 if (chs & 2)
Takashi Iwai29fdbec2009-01-20 13:07:55 +01001607 *valp = read_amp_value(codec, nid, 1, dir, idx, ofs);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001608 return 0;
1609}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001610EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_volume_get);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001611
Takashi Iwaid5191e52009-11-16 14:58:17 +01001612/**
1613 * snd_hda_mixer_amp_volume_put - Put callback for a standard AMP mixer volume
1614 *
1615 * The control element is supposed to have the private_value field
1616 * set up via HDA_COMPOSE_AMP_VAL*() or related macros.
1617 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02001618int snd_hda_mixer_amp_volume_put(struct snd_kcontrol *kcontrol,
1619 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001620{
1621 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1622 hda_nid_t nid = get_amp_nid(kcontrol);
1623 int chs = get_amp_channels(kcontrol);
1624 int dir = get_amp_direction(kcontrol);
1625 int idx = get_amp_index(kcontrol);
Takashi Iwai29fdbec2009-01-20 13:07:55 +01001626 unsigned int ofs = get_amp_offset(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001627 long *valp = ucontrol->value.integer.value;
1628 int change = 0;
1629
Takashi Iwaicb53c622007-08-10 17:21:45 +02001630 snd_hda_power_up(codec);
Nicolas Grazianob9f5a892005-07-29 12:17:20 +02001631 if (chs & 1) {
Takashi Iwai29fdbec2009-01-20 13:07:55 +01001632 change = update_amp_value(codec, nid, 0, dir, idx, ofs, *valp);
Nicolas Grazianob9f5a892005-07-29 12:17:20 +02001633 valp++;
1634 }
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001635 if (chs & 2)
Takashi Iwai29fdbec2009-01-20 13:07:55 +01001636 change |= update_amp_value(codec, nid, 1, dir, idx, ofs, *valp);
Takashi Iwaicb53c622007-08-10 17:21:45 +02001637 snd_hda_power_down(codec);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001638 return change;
1639}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001640EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_volume_put);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001641
Takashi Iwaid5191e52009-11-16 14:58:17 +01001642/**
1643 * snd_hda_mixer_amp_volume_put - TLV callback for a standard AMP mixer volume
1644 *
1645 * The control element is supposed to have the private_value field
1646 * set up via HDA_COMPOSE_AMP_VAL*() or related macros.
1647 */
Jaroslav Kysela302e9c52006-07-05 17:39:49 +02001648int snd_hda_mixer_amp_tlv(struct snd_kcontrol *kcontrol, int op_flag,
1649 unsigned int size, unsigned int __user *_tlv)
1650{
1651 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1652 hda_nid_t nid = get_amp_nid(kcontrol);
1653 int dir = get_amp_direction(kcontrol);
Takashi Iwai29fdbec2009-01-20 13:07:55 +01001654 unsigned int ofs = get_amp_offset(kcontrol);
Jaroslav Kysela302e9c52006-07-05 17:39:49 +02001655 u32 caps, val1, val2;
1656
1657 if (size < 4 * sizeof(unsigned int))
1658 return -ENOMEM;
1659 caps = query_amp_caps(codec, nid, dir);
Takashi Iwai0ba21762007-04-16 11:29:14 +02001660 val2 = (caps & AC_AMPCAP_STEP_SIZE) >> AC_AMPCAP_STEP_SIZE_SHIFT;
1661 val2 = (val2 + 1) * 25;
Jaroslav Kysela302e9c52006-07-05 17:39:49 +02001662 val1 = -((caps & AC_AMPCAP_OFFSET) >> AC_AMPCAP_OFFSET_SHIFT);
Takashi Iwai29fdbec2009-01-20 13:07:55 +01001663 val1 += ofs;
Jaroslav Kysela302e9c52006-07-05 17:39:49 +02001664 val1 = ((int)val1) * ((int)val2);
Jaroslav Kysela302e9c52006-07-05 17:39:49 +02001665 if (put_user(SNDRV_CTL_TLVT_DB_SCALE, _tlv))
1666 return -EFAULT;
1667 if (put_user(2 * sizeof(unsigned int), _tlv + 1))
1668 return -EFAULT;
1669 if (put_user(val1, _tlv + 2))
1670 return -EFAULT;
1671 if (put_user(val2, _tlv + 3))
1672 return -EFAULT;
1673 return 0;
1674}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001675EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_tlv);
Jaroslav Kysela302e9c52006-07-05 17:39:49 +02001676
Takashi Iwaid5191e52009-11-16 14:58:17 +01001677/**
1678 * snd_hda_set_vmaster_tlv - Set TLV for a virtual master control
1679 * @codec: HD-audio codec
1680 * @nid: NID of a reference widget
1681 * @dir: #HDA_INPUT or #HDA_OUTPUT
1682 * @tlv: TLV data to be stored, at least 4 elements
1683 *
1684 * Set (static) TLV data for a virtual master volume using the AMP caps
1685 * obtained from the reference NID.
1686 * The volume range is recalculated as if the max volume is 0dB.
Takashi Iwai2134ea42008-01-10 16:53:55 +01001687 */
1688void snd_hda_set_vmaster_tlv(struct hda_codec *codec, hda_nid_t nid, int dir,
1689 unsigned int *tlv)
1690{
1691 u32 caps;
1692 int nums, step;
1693
1694 caps = query_amp_caps(codec, nid, dir);
1695 nums = (caps & AC_AMPCAP_NUM_STEPS) >> AC_AMPCAP_NUM_STEPS_SHIFT;
1696 step = (caps & AC_AMPCAP_STEP_SIZE) >> AC_AMPCAP_STEP_SIZE_SHIFT;
1697 step = (step + 1) * 25;
1698 tlv[0] = SNDRV_CTL_TLVT_DB_SCALE;
1699 tlv[1] = 2 * sizeof(unsigned int);
1700 tlv[2] = -nums * step;
1701 tlv[3] = step;
1702}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001703EXPORT_SYMBOL_HDA(snd_hda_set_vmaster_tlv);
Takashi Iwai2134ea42008-01-10 16:53:55 +01001704
1705/* find a mixer control element with the given name */
Takashi Iwai09f99702008-02-04 12:31:13 +01001706static struct snd_kcontrol *
1707_snd_hda_find_mixer_ctl(struct hda_codec *codec,
1708 const char *name, int idx)
Takashi Iwai2134ea42008-01-10 16:53:55 +01001709{
1710 struct snd_ctl_elem_id id;
1711 memset(&id, 0, sizeof(id));
1712 id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
Takashi Iwai09f99702008-02-04 12:31:13 +01001713 id.index = idx;
Takashi Iwai18cb7102009-04-16 10:22:24 +02001714 if (snd_BUG_ON(strlen(name) >= sizeof(id.name)))
1715 return NULL;
Takashi Iwai2134ea42008-01-10 16:53:55 +01001716 strcpy(id.name, name);
1717 return snd_ctl_find_id(codec->bus->card, &id);
1718}
1719
Takashi Iwaid5191e52009-11-16 14:58:17 +01001720/**
1721 * snd_hda_find_mixer_ctl - Find a mixer control element with the given name
1722 * @codec: HD-audio codec
1723 * @name: ctl id name string
1724 *
1725 * Get the control element with the given id string and IFACE_MIXER.
1726 */
Takashi Iwai09f99702008-02-04 12:31:13 +01001727struct snd_kcontrol *snd_hda_find_mixer_ctl(struct hda_codec *codec,
1728 const char *name)
1729{
1730 return _snd_hda_find_mixer_ctl(codec, name, 0);
1731}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001732EXPORT_SYMBOL_HDA(snd_hda_find_mixer_ctl);
Takashi Iwai09f99702008-02-04 12:31:13 +01001733
Takashi Iwaid5191e52009-11-16 14:58:17 +01001734/**
Jaroslav Kysela5b0cb1d2009-12-08 16:13:32 +01001735 * snd_hda_ctl_add - Add a control element and assign to the codec
Takashi Iwaid5191e52009-11-16 14:58:17 +01001736 * @codec: HD-audio codec
1737 * @nid: corresponding NID (optional)
1738 * @kctl: the control element to assign
1739 *
1740 * Add the given control element to an array inside the codec instance.
1741 * All control elements belonging to a codec are supposed to be added
1742 * by this function so that a proper clean-up works at the free or
1743 * reconfiguration time.
1744 *
1745 * If non-zero @nid is passed, the NID is assigned to the control element.
1746 * The assignment is shown in the codec proc file.
1747 *
1748 * snd_hda_ctl_add() checks the control subdev id field whether
1749 * #HDA_SUBDEV_NID_FLAG bit is set. If set (and @nid is zero), the lower
Jaroslav Kysela9e3fd872009-12-08 17:45:25 +01001750 * bits value is taken as the NID to assign. The #HDA_NID_ITEM_AMP bit
1751 * specifies if kctl->private_value is a HDA amplifier value.
Takashi Iwaid5191e52009-11-16 14:58:17 +01001752 */
Jaroslav Kysela3911a4c2009-11-11 13:43:01 +01001753int snd_hda_ctl_add(struct hda_codec *codec, hda_nid_t nid,
1754 struct snd_kcontrol *kctl)
Takashi Iwaid13bd412008-07-30 15:01:45 +02001755{
1756 int err;
Jaroslav Kysela9e3fd872009-12-08 17:45:25 +01001757 unsigned short flags = 0;
Jaroslav Kysela3911a4c2009-11-11 13:43:01 +01001758 struct hda_nid_item *item;
Takashi Iwaid13bd412008-07-30 15:01:45 +02001759
Jaroslav Kysela5e26dfd2009-12-10 13:57:01 +01001760 if (kctl->id.subdevice & HDA_SUBDEV_AMP_FLAG) {
Jaroslav Kysela9e3fd872009-12-08 17:45:25 +01001761 flags |= HDA_NID_ITEM_AMP;
Jaroslav Kysela5e26dfd2009-12-10 13:57:01 +01001762 if (nid == 0)
1763 nid = get_amp_nid_(kctl->private_value);
1764 }
Jaroslav Kysela9e3fd872009-12-08 17:45:25 +01001765 if ((kctl->id.subdevice & HDA_SUBDEV_NID_FLAG) != 0 && nid == 0)
1766 nid = kctl->id.subdevice & 0xffff;
Jaroslav Kysela5e26dfd2009-12-10 13:57:01 +01001767 if (kctl->id.subdevice & (HDA_SUBDEV_NID_FLAG|HDA_SUBDEV_AMP_FLAG))
Jaroslav Kysela4d02d1b2009-11-12 10:15:48 +01001768 kctl->id.subdevice = 0;
Takashi Iwaid13bd412008-07-30 15:01:45 +02001769 err = snd_ctl_add(codec->bus->card, kctl);
1770 if (err < 0)
1771 return err;
Jaroslav Kysela3911a4c2009-11-11 13:43:01 +01001772 item = snd_array_new(&codec->mixers);
1773 if (!item)
Takashi Iwaid13bd412008-07-30 15:01:45 +02001774 return -ENOMEM;
Jaroslav Kysela3911a4c2009-11-11 13:43:01 +01001775 item->kctl = kctl;
1776 item->nid = nid;
Jaroslav Kysela9e3fd872009-12-08 17:45:25 +01001777 item->flags = flags;
Takashi Iwaid13bd412008-07-30 15:01:45 +02001778 return 0;
1779}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001780EXPORT_SYMBOL_HDA(snd_hda_ctl_add);
Takashi Iwaid13bd412008-07-30 15:01:45 +02001781
Takashi Iwaid5191e52009-11-16 14:58:17 +01001782/**
Jaroslav Kysela5b0cb1d2009-12-08 16:13:32 +01001783 * snd_hda_add_nid - Assign a NID to a control element
1784 * @codec: HD-audio codec
1785 * @nid: corresponding NID (optional)
1786 * @kctl: the control element to assign
1787 * @index: index to kctl
1788 *
1789 * Add the given control element to an array inside the codec instance.
1790 * This function is used when #snd_hda_ctl_add cannot be used for 1:1
1791 * NID:KCTL mapping - for example "Capture Source" selector.
1792 */
1793int snd_hda_add_nid(struct hda_codec *codec, struct snd_kcontrol *kctl,
1794 unsigned int index, hda_nid_t nid)
1795{
1796 struct hda_nid_item *item;
1797
1798 if (nid > 0) {
1799 item = snd_array_new(&codec->nids);
1800 if (!item)
1801 return -ENOMEM;
1802 item->kctl = kctl;
1803 item->index = index;
1804 item->nid = nid;
1805 return 0;
1806 }
1807 return -EINVAL;
1808}
1809EXPORT_SYMBOL_HDA(snd_hda_add_nid);
1810
1811/**
Takashi Iwaid5191e52009-11-16 14:58:17 +01001812 * snd_hda_ctls_clear - Clear all controls assigned to the given codec
1813 * @codec: HD-audio codec
1814 */
Takashi Iwaid13bd412008-07-30 15:01:45 +02001815void snd_hda_ctls_clear(struct hda_codec *codec)
1816{
1817 int i;
Jaroslav Kysela3911a4c2009-11-11 13:43:01 +01001818 struct hda_nid_item *items = codec->mixers.list;
Takashi Iwaid13bd412008-07-30 15:01:45 +02001819 for (i = 0; i < codec->mixers.used; i++)
Jaroslav Kysela3911a4c2009-11-11 13:43:01 +01001820 snd_ctl_remove(codec->bus->card, items[i].kctl);
Takashi Iwaid13bd412008-07-30 15:01:45 +02001821 snd_array_free(&codec->mixers);
Jaroslav Kysela5b0cb1d2009-12-08 16:13:32 +01001822 snd_array_free(&codec->nids);
Takashi Iwaid13bd412008-07-30 15:01:45 +02001823}
1824
Takashi Iwaia65d6292009-02-23 16:57:04 +01001825/* pseudo device locking
1826 * toggle card->shutdown to allow/disallow the device access (as a hack)
1827 */
1828static int hda_lock_devices(struct snd_card *card)
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001829{
Takashi Iwaia65d6292009-02-23 16:57:04 +01001830 spin_lock(&card->files_lock);
1831 if (card->shutdown) {
1832 spin_unlock(&card->files_lock);
1833 return -EINVAL;
1834 }
1835 card->shutdown = 1;
1836 spin_unlock(&card->files_lock);
1837 return 0;
1838}
1839
1840static void hda_unlock_devices(struct snd_card *card)
1841{
1842 spin_lock(&card->files_lock);
1843 card->shutdown = 0;
1844 spin_unlock(&card->files_lock);
1845}
1846
Takashi Iwaid5191e52009-11-16 14:58:17 +01001847/**
1848 * snd_hda_codec_reset - Clear all objects assigned to the codec
1849 * @codec: HD-audio codec
1850 *
1851 * This frees the all PCM and control elements assigned to the codec, and
1852 * clears the caches and restores the pin default configurations.
1853 *
1854 * When a device is being used, it returns -EBSY. If successfully freed,
1855 * returns zero.
1856 */
Takashi Iwaia65d6292009-02-23 16:57:04 +01001857int snd_hda_codec_reset(struct hda_codec *codec)
1858{
1859 struct snd_card *card = codec->bus->card;
1860 int i, pcm;
1861
1862 if (hda_lock_devices(card) < 0)
1863 return -EBUSY;
1864 /* check whether the codec isn't used by any mixer or PCM streams */
1865 if (!list_empty(&card->ctl_files)) {
1866 hda_unlock_devices(card);
1867 return -EBUSY;
1868 }
1869 for (pcm = 0; pcm < codec->num_pcms; pcm++) {
1870 struct hda_pcm *cpcm = &codec->pcm_info[pcm];
1871 if (!cpcm->pcm)
1872 continue;
1873 if (cpcm->pcm->streams[0].substream_opened ||
1874 cpcm->pcm->streams[1].substream_opened) {
1875 hda_unlock_devices(card);
1876 return -EBUSY;
1877 }
1878 }
1879
1880 /* OK, let it free */
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001881
1882#ifdef CONFIG_SND_HDA_POWER_SAVE
1883 cancel_delayed_work(&codec->power_work);
Takashi Iwai6acaed32009-01-12 10:09:24 +01001884 flush_workqueue(codec->bus->workq);
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001885#endif
1886 snd_hda_ctls_clear(codec);
1887 /* relase PCMs */
1888 for (i = 0; i < codec->num_pcms; i++) {
Takashi Iwai529bd6c2008-11-27 14:17:01 +01001889 if (codec->pcm_info[i].pcm) {
Takashi Iwaia65d6292009-02-23 16:57:04 +01001890 snd_device_free(card, codec->pcm_info[i].pcm);
Takashi Iwai529bd6c2008-11-27 14:17:01 +01001891 clear_bit(codec->pcm_info[i].device,
1892 codec->bus->pcm_dev_bits);
1893 }
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001894 }
1895 if (codec->patch_ops.free)
1896 codec->patch_ops.free(codec);
Takashi Iwai56d17712008-11-28 14:36:23 +01001897 codec->proc_widget_hook = NULL;
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001898 codec->spec = NULL;
1899 free_hda_cache(&codec->amp_cache);
1900 free_hda_cache(&codec->cmd_cache);
Takashi Iwai827057f2008-12-19 10:12:02 +01001901 init_hda_cache(&codec->amp_cache, sizeof(struct hda_amp_info));
1902 init_hda_cache(&codec->cmd_cache, sizeof(struct hda_cache_head));
Takashi Iwai346ff702009-02-23 09:42:57 +01001903 /* free only driver_pins so that init_pins + user_pins are restored */
1904 snd_array_free(&codec->driver_pins);
Takashi Iwai3be14142009-02-20 14:11:16 +01001905 restore_pincfgs(codec);
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001906 codec->num_pcms = 0;
1907 codec->pcm_info = NULL;
1908 codec->preset = NULL;
Takashi Iwaid1f1af22009-03-02 10:35:29 +01001909 memset(&codec->patch_ops, 0, sizeof(codec->patch_ops));
1910 codec->slave_dig_outs = NULL;
1911 codec->spdif_status_reset = 0;
Takashi Iwai1289e9e2008-11-27 15:47:11 +01001912 module_put(codec->owner);
1913 codec->owner = NULL;
Takashi Iwaia65d6292009-02-23 16:57:04 +01001914
1915 /* allow device access again */
1916 hda_unlock_devices(card);
1917 return 0;
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001918}
1919
Takashi Iwaid5191e52009-11-16 14:58:17 +01001920/**
1921 * snd_hda_add_vmaster - create a virtual master control and add slaves
1922 * @codec: HD-audio codec
1923 * @name: vmaster control name
1924 * @tlv: TLV data (optional)
1925 * @slaves: slave control names (optional)
1926 *
1927 * Create a virtual master control with the given name. The TLV data
1928 * must be either NULL or a valid data.
1929 *
1930 * @slaves is a NULL-terminated array of strings, each of which is a
1931 * slave control name. All controls with these names are assigned to
1932 * the new virtual master control.
1933 *
1934 * This function returns zero if successful or a negative error code.
1935 */
Takashi Iwai2134ea42008-01-10 16:53:55 +01001936int snd_hda_add_vmaster(struct hda_codec *codec, char *name,
1937 unsigned int *tlv, const char **slaves)
1938{
1939 struct snd_kcontrol *kctl;
1940 const char **s;
1941 int err;
1942
Takashi Iwai2f085542008-02-22 18:43:50 +01001943 for (s = slaves; *s && !snd_hda_find_mixer_ctl(codec, *s); s++)
1944 ;
1945 if (!*s) {
1946 snd_printdd("No slave found for %s\n", name);
1947 return 0;
1948 }
Takashi Iwai2134ea42008-01-10 16:53:55 +01001949 kctl = snd_ctl_make_virtual_master(name, tlv);
1950 if (!kctl)
1951 return -ENOMEM;
Jaroslav Kysela3911a4c2009-11-11 13:43:01 +01001952 err = snd_hda_ctl_add(codec, 0, kctl);
Takashi Iwai2134ea42008-01-10 16:53:55 +01001953 if (err < 0)
1954 return err;
1955
1956 for (s = slaves; *s; s++) {
1957 struct snd_kcontrol *sctl;
Takashi Iwai7a411ee2009-03-06 10:08:14 +01001958 int i = 0;
1959 for (;;) {
1960 sctl = _snd_hda_find_mixer_ctl(codec, *s, i);
1961 if (!sctl) {
1962 if (!i)
1963 snd_printdd("Cannot find slave %s, "
1964 "skipped\n", *s);
1965 break;
1966 }
1967 err = snd_ctl_add_slave(kctl, sctl);
1968 if (err < 0)
1969 return err;
1970 i++;
Takashi Iwai2134ea42008-01-10 16:53:55 +01001971 }
Takashi Iwai2134ea42008-01-10 16:53:55 +01001972 }
1973 return 0;
1974}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001975EXPORT_SYMBOL_HDA(snd_hda_add_vmaster);
Takashi Iwai2134ea42008-01-10 16:53:55 +01001976
Takashi Iwaid5191e52009-11-16 14:58:17 +01001977/**
1978 * snd_hda_mixer_amp_switch_info - Info callback for a standard AMP mixer switch
1979 *
1980 * The control element is supposed to have the private_value field
1981 * set up via HDA_COMPOSE_AMP_VAL*() or related macros.
1982 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02001983int snd_hda_mixer_amp_switch_info(struct snd_kcontrol *kcontrol,
1984 struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001985{
1986 int chs = get_amp_channels(kcontrol);
1987
1988 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
1989 uinfo->count = chs == 3 ? 2 : 1;
1990 uinfo->value.integer.min = 0;
1991 uinfo->value.integer.max = 1;
1992 return 0;
1993}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001994EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_switch_info);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001995
Takashi Iwaid5191e52009-11-16 14:58:17 +01001996/**
1997 * snd_hda_mixer_amp_switch_get - Get callback for a standard AMP mixer switch
1998 *
1999 * The control element is supposed to have the private_value field
2000 * set up via HDA_COMPOSE_AMP_VAL*() or related macros.
2001 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02002002int snd_hda_mixer_amp_switch_get(struct snd_kcontrol *kcontrol,
2003 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002004{
2005 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2006 hda_nid_t nid = get_amp_nid(kcontrol);
2007 int chs = get_amp_channels(kcontrol);
2008 int dir = get_amp_direction(kcontrol);
2009 int idx = get_amp_index(kcontrol);
2010 long *valp = ucontrol->value.integer.value;
2011
2012 if (chs & 1)
Takashi Iwai0ba21762007-04-16 11:29:14 +02002013 *valp++ = (snd_hda_codec_amp_read(codec, nid, 0, dir, idx) &
Takashi Iwai47fd8302007-08-10 17:11:07 +02002014 HDA_AMP_MUTE) ? 0 : 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002015 if (chs & 2)
Takashi Iwai0ba21762007-04-16 11:29:14 +02002016 *valp = (snd_hda_codec_amp_read(codec, nid, 1, dir, idx) &
Takashi Iwai47fd8302007-08-10 17:11:07 +02002017 HDA_AMP_MUTE) ? 0 : 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002018 return 0;
2019}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002020EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_switch_get);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002021
Takashi Iwaid5191e52009-11-16 14:58:17 +01002022/**
2023 * snd_hda_mixer_amp_switch_put - Put callback for a standard AMP mixer switch
2024 *
2025 * The control element is supposed to have the private_value field
2026 * set up via HDA_COMPOSE_AMP_VAL*() or related macros.
2027 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02002028int snd_hda_mixer_amp_switch_put(struct snd_kcontrol *kcontrol,
2029 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002030{
2031 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2032 hda_nid_t nid = get_amp_nid(kcontrol);
2033 int chs = get_amp_channels(kcontrol);
2034 int dir = get_amp_direction(kcontrol);
2035 int idx = get_amp_index(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002036 long *valp = ucontrol->value.integer.value;
2037 int change = 0;
2038
Takashi Iwaicb53c622007-08-10 17:21:45 +02002039 snd_hda_power_up(codec);
Nicolas Grazianob9f5a892005-07-29 12:17:20 +02002040 if (chs & 1) {
Takashi Iwai4a19fae2005-06-08 14:43:58 +02002041 change = snd_hda_codec_amp_update(codec, nid, 0, dir, idx,
Takashi Iwai47fd8302007-08-10 17:11:07 +02002042 HDA_AMP_MUTE,
2043 *valp ? 0 : HDA_AMP_MUTE);
Nicolas Grazianob9f5a892005-07-29 12:17:20 +02002044 valp++;
2045 }
Takashi Iwai4a19fae2005-06-08 14:43:58 +02002046 if (chs & 2)
2047 change |= snd_hda_codec_amp_update(codec, nid, 1, dir, idx,
Takashi Iwai47fd8302007-08-10 17:11:07 +02002048 HDA_AMP_MUTE,
2049 *valp ? 0 : HDA_AMP_MUTE);
Takashi Iwaicb53c622007-08-10 17:21:45 +02002050#ifdef CONFIG_SND_HDA_POWER_SAVE
2051 if (codec->patch_ops.check_power_status)
2052 codec->patch_ops.check_power_status(codec, nid);
2053#endif
2054 snd_hda_power_down(codec);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002055 return change;
2056}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002057EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_switch_put);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002058
Takashi Iwai67d634c2009-11-16 15:35:59 +01002059#ifdef CONFIG_SND_HDA_INPUT_BEEP
Takashi Iwaid5191e52009-11-16 14:58:17 +01002060/**
2061 * snd_hda_mixer_amp_switch_put_beep - Put callback for a beep AMP switch
2062 *
2063 * This function calls snd_hda_enable_beep_device(), which behaves differently
2064 * depending on beep_mode option.
2065 */
Jaroslav Kysela123c07a2009-10-21 14:48:23 +02002066int snd_hda_mixer_amp_switch_put_beep(struct snd_kcontrol *kcontrol,
2067 struct snd_ctl_elem_value *ucontrol)
2068{
2069 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2070 long *valp = ucontrol->value.integer.value;
2071
2072 snd_hda_enable_beep_device(codec, *valp);
2073 return snd_hda_mixer_amp_switch_put(kcontrol, ucontrol);
2074}
2075EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_switch_put_beep);
Takashi Iwai67d634c2009-11-16 15:35:59 +01002076#endif /* CONFIG_SND_HDA_INPUT_BEEP */
Jaroslav Kysela123c07a2009-10-21 14:48:23 +02002077
Linus Torvalds1da177e2005-04-16 15:20:36 -07002078/*
Takashi Iwai985be542005-11-02 18:26:49 +01002079 * bound volume controls
2080 *
2081 * bind multiple volumes (# indices, from 0)
2082 */
2083
2084#define AMP_VAL_IDX_SHIFT 19
2085#define AMP_VAL_IDX_MASK (0x0f<<19)
2086
Takashi Iwaid5191e52009-11-16 14:58:17 +01002087/**
2088 * snd_hda_mixer_bind_switch_get - Get callback for a bound volume control
2089 *
2090 * The control element is supposed to have the private_value field
2091 * set up via HDA_BIND_MUTE*() macros.
2092 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02002093int snd_hda_mixer_bind_switch_get(struct snd_kcontrol *kcontrol,
2094 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai985be542005-11-02 18:26:49 +01002095{
2096 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2097 unsigned long pval;
2098 int err;
2099
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08002100 mutex_lock(&codec->control_mutex);
Takashi Iwai985be542005-11-02 18:26:49 +01002101 pval = kcontrol->private_value;
2102 kcontrol->private_value = pval & ~AMP_VAL_IDX_MASK; /* index 0 */
2103 err = snd_hda_mixer_amp_switch_get(kcontrol, ucontrol);
2104 kcontrol->private_value = pval;
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08002105 mutex_unlock(&codec->control_mutex);
Takashi Iwai985be542005-11-02 18:26:49 +01002106 return err;
2107}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002108EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_switch_get);
Takashi Iwai985be542005-11-02 18:26:49 +01002109
Takashi Iwaid5191e52009-11-16 14:58:17 +01002110/**
2111 * snd_hda_mixer_bind_switch_put - Put callback for a bound volume control
2112 *
2113 * The control element is supposed to have the private_value field
2114 * set up via HDA_BIND_MUTE*() macros.
2115 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02002116int snd_hda_mixer_bind_switch_put(struct snd_kcontrol *kcontrol,
2117 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai985be542005-11-02 18:26:49 +01002118{
2119 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2120 unsigned long pval;
2121 int i, indices, err = 0, change = 0;
2122
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08002123 mutex_lock(&codec->control_mutex);
Takashi Iwai985be542005-11-02 18:26:49 +01002124 pval = kcontrol->private_value;
2125 indices = (pval & AMP_VAL_IDX_MASK) >> AMP_VAL_IDX_SHIFT;
2126 for (i = 0; i < indices; i++) {
Takashi Iwai0ba21762007-04-16 11:29:14 +02002127 kcontrol->private_value = (pval & ~AMP_VAL_IDX_MASK) |
2128 (i << AMP_VAL_IDX_SHIFT);
Takashi Iwai985be542005-11-02 18:26:49 +01002129 err = snd_hda_mixer_amp_switch_put(kcontrol, ucontrol);
2130 if (err < 0)
2131 break;
2132 change |= err;
2133 }
2134 kcontrol->private_value = pval;
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08002135 mutex_unlock(&codec->control_mutex);
Takashi Iwai985be542005-11-02 18:26:49 +01002136 return err < 0 ? err : change;
2137}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002138EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_switch_put);
Takashi Iwai985be542005-11-02 18:26:49 +01002139
Takashi Iwaid5191e52009-11-16 14:58:17 +01002140/**
2141 * snd_hda_mixer_bind_ctls_info - Info callback for a generic bound control
2142 *
2143 * The control element is supposed to have the private_value field
2144 * set up via HDA_BIND_VOL() or HDA_BIND_SW() macros.
Takashi Iwai532d5382007-07-27 19:02:40 +02002145 */
2146int snd_hda_mixer_bind_ctls_info(struct snd_kcontrol *kcontrol,
2147 struct snd_ctl_elem_info *uinfo)
2148{
2149 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2150 struct hda_bind_ctls *c;
2151 int err;
2152
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08002153 mutex_lock(&codec->control_mutex);
Serge A. Suchkov14c65f92008-02-22 18:43:16 +01002154 c = (struct hda_bind_ctls *)kcontrol->private_value;
Takashi Iwai532d5382007-07-27 19:02:40 +02002155 kcontrol->private_value = *c->values;
2156 err = c->ops->info(kcontrol, uinfo);
2157 kcontrol->private_value = (long)c;
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08002158 mutex_unlock(&codec->control_mutex);
Takashi Iwai532d5382007-07-27 19:02:40 +02002159 return err;
2160}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002161EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_ctls_info);
Takashi Iwai532d5382007-07-27 19:02:40 +02002162
Takashi Iwaid5191e52009-11-16 14:58:17 +01002163/**
2164 * snd_hda_mixer_bind_ctls_get - Get callback for a generic bound control
2165 *
2166 * The control element is supposed to have the private_value field
2167 * set up via HDA_BIND_VOL() or HDA_BIND_SW() macros.
2168 */
Takashi Iwai532d5382007-07-27 19:02:40 +02002169int snd_hda_mixer_bind_ctls_get(struct snd_kcontrol *kcontrol,
2170 struct snd_ctl_elem_value *ucontrol)
2171{
2172 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2173 struct hda_bind_ctls *c;
2174 int err;
2175
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08002176 mutex_lock(&codec->control_mutex);
Serge A. Suchkov14c65f92008-02-22 18:43:16 +01002177 c = (struct hda_bind_ctls *)kcontrol->private_value;
Takashi Iwai532d5382007-07-27 19:02:40 +02002178 kcontrol->private_value = *c->values;
2179 err = c->ops->get(kcontrol, ucontrol);
2180 kcontrol->private_value = (long)c;
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08002181 mutex_unlock(&codec->control_mutex);
Takashi Iwai532d5382007-07-27 19:02:40 +02002182 return err;
2183}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002184EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_ctls_get);
Takashi Iwai532d5382007-07-27 19:02:40 +02002185
Takashi Iwaid5191e52009-11-16 14:58:17 +01002186/**
2187 * snd_hda_mixer_bind_ctls_put - Put callback for a generic bound control
2188 *
2189 * The control element is supposed to have the private_value field
2190 * set up via HDA_BIND_VOL() or HDA_BIND_SW() macros.
2191 */
Takashi Iwai532d5382007-07-27 19:02:40 +02002192int snd_hda_mixer_bind_ctls_put(struct snd_kcontrol *kcontrol,
2193 struct snd_ctl_elem_value *ucontrol)
2194{
2195 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2196 struct hda_bind_ctls *c;
2197 unsigned long *vals;
2198 int err = 0, change = 0;
2199
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08002200 mutex_lock(&codec->control_mutex);
Serge A. Suchkov14c65f92008-02-22 18:43:16 +01002201 c = (struct hda_bind_ctls *)kcontrol->private_value;
Takashi Iwai532d5382007-07-27 19:02:40 +02002202 for (vals = c->values; *vals; vals++) {
2203 kcontrol->private_value = *vals;
2204 err = c->ops->put(kcontrol, ucontrol);
2205 if (err < 0)
2206 break;
2207 change |= err;
2208 }
2209 kcontrol->private_value = (long)c;
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08002210 mutex_unlock(&codec->control_mutex);
Takashi Iwai532d5382007-07-27 19:02:40 +02002211 return err < 0 ? err : change;
2212}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002213EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_ctls_put);
Takashi Iwai532d5382007-07-27 19:02:40 +02002214
Takashi Iwaid5191e52009-11-16 14:58:17 +01002215/**
2216 * snd_hda_mixer_bind_tlv - TLV callback for a generic bound control
2217 *
2218 * The control element is supposed to have the private_value field
2219 * set up via HDA_BIND_VOL() macro.
2220 */
Takashi Iwai532d5382007-07-27 19:02:40 +02002221int snd_hda_mixer_bind_tlv(struct snd_kcontrol *kcontrol, int op_flag,
2222 unsigned int size, unsigned int __user *tlv)
2223{
2224 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2225 struct hda_bind_ctls *c;
2226 int err;
2227
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08002228 mutex_lock(&codec->control_mutex);
Serge A. Suchkov14c65f92008-02-22 18:43:16 +01002229 c = (struct hda_bind_ctls *)kcontrol->private_value;
Takashi Iwai532d5382007-07-27 19:02:40 +02002230 kcontrol->private_value = *c->values;
2231 err = c->ops->tlv(kcontrol, op_flag, size, tlv);
2232 kcontrol->private_value = (long)c;
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08002233 mutex_unlock(&codec->control_mutex);
Takashi Iwai532d5382007-07-27 19:02:40 +02002234 return err;
2235}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002236EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_tlv);
Takashi Iwai532d5382007-07-27 19:02:40 +02002237
2238struct hda_ctl_ops snd_hda_bind_vol = {
2239 .info = snd_hda_mixer_amp_volume_info,
2240 .get = snd_hda_mixer_amp_volume_get,
2241 .put = snd_hda_mixer_amp_volume_put,
2242 .tlv = snd_hda_mixer_amp_tlv
2243};
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002244EXPORT_SYMBOL_HDA(snd_hda_bind_vol);
Takashi Iwai532d5382007-07-27 19:02:40 +02002245
2246struct hda_ctl_ops snd_hda_bind_sw = {
2247 .info = snd_hda_mixer_amp_switch_info,
2248 .get = snd_hda_mixer_amp_switch_get,
2249 .put = snd_hda_mixer_amp_switch_put,
2250 .tlv = snd_hda_mixer_amp_tlv
2251};
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002252EXPORT_SYMBOL_HDA(snd_hda_bind_sw);
Takashi Iwai532d5382007-07-27 19:02:40 +02002253
2254/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002255 * SPDIF out controls
2256 */
2257
Takashi Iwai0ba21762007-04-16 11:29:14 +02002258static int snd_hda_spdif_mask_info(struct snd_kcontrol *kcontrol,
2259 struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002260{
2261 uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
2262 uinfo->count = 1;
2263 return 0;
2264}
2265
Takashi Iwai0ba21762007-04-16 11:29:14 +02002266static int snd_hda_spdif_cmask_get(struct snd_kcontrol *kcontrol,
2267 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002268{
2269 ucontrol->value.iec958.status[0] = IEC958_AES0_PROFESSIONAL |
2270 IEC958_AES0_NONAUDIO |
2271 IEC958_AES0_CON_EMPHASIS_5015 |
2272 IEC958_AES0_CON_NOT_COPYRIGHT;
2273 ucontrol->value.iec958.status[1] = IEC958_AES1_CON_CATEGORY |
2274 IEC958_AES1_CON_ORIGINAL;
2275 return 0;
2276}
2277
Takashi Iwai0ba21762007-04-16 11:29:14 +02002278static int snd_hda_spdif_pmask_get(struct snd_kcontrol *kcontrol,
2279 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002280{
2281 ucontrol->value.iec958.status[0] = IEC958_AES0_PROFESSIONAL |
2282 IEC958_AES0_NONAUDIO |
2283 IEC958_AES0_PRO_EMPHASIS_5015;
2284 return 0;
2285}
2286
Takashi Iwai0ba21762007-04-16 11:29:14 +02002287static int snd_hda_spdif_default_get(struct snd_kcontrol *kcontrol,
2288 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002289{
2290 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2291
2292 ucontrol->value.iec958.status[0] = codec->spdif_status & 0xff;
2293 ucontrol->value.iec958.status[1] = (codec->spdif_status >> 8) & 0xff;
2294 ucontrol->value.iec958.status[2] = (codec->spdif_status >> 16) & 0xff;
2295 ucontrol->value.iec958.status[3] = (codec->spdif_status >> 24) & 0xff;
2296
2297 return 0;
2298}
2299
2300/* convert from SPDIF status bits to HDA SPDIF bits
2301 * bit 0 (DigEn) is always set zero (to be filled later)
2302 */
2303static unsigned short convert_from_spdif_status(unsigned int sbits)
2304{
2305 unsigned short val = 0;
2306
2307 if (sbits & IEC958_AES0_PROFESSIONAL)
Takashi Iwai0ba21762007-04-16 11:29:14 +02002308 val |= AC_DIG1_PROFESSIONAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002309 if (sbits & IEC958_AES0_NONAUDIO)
Takashi Iwai0ba21762007-04-16 11:29:14 +02002310 val |= AC_DIG1_NONAUDIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002311 if (sbits & IEC958_AES0_PROFESSIONAL) {
Takashi Iwai0ba21762007-04-16 11:29:14 +02002312 if ((sbits & IEC958_AES0_PRO_EMPHASIS) ==
2313 IEC958_AES0_PRO_EMPHASIS_5015)
2314 val |= AC_DIG1_EMPHASIS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002315 } else {
Takashi Iwai0ba21762007-04-16 11:29:14 +02002316 if ((sbits & IEC958_AES0_CON_EMPHASIS) ==
2317 IEC958_AES0_CON_EMPHASIS_5015)
2318 val |= AC_DIG1_EMPHASIS;
2319 if (!(sbits & IEC958_AES0_CON_NOT_COPYRIGHT))
2320 val |= AC_DIG1_COPYRIGHT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002321 if (sbits & (IEC958_AES1_CON_ORIGINAL << 8))
Takashi Iwai0ba21762007-04-16 11:29:14 +02002322 val |= AC_DIG1_LEVEL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002323 val |= sbits & (IEC958_AES1_CON_CATEGORY << 8);
2324 }
2325 return val;
2326}
2327
2328/* convert to SPDIF status bits from HDA SPDIF bits
2329 */
2330static unsigned int convert_to_spdif_status(unsigned short val)
2331{
2332 unsigned int sbits = 0;
2333
Takashi Iwai0ba21762007-04-16 11:29:14 +02002334 if (val & AC_DIG1_NONAUDIO)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002335 sbits |= IEC958_AES0_NONAUDIO;
Takashi Iwai0ba21762007-04-16 11:29:14 +02002336 if (val & AC_DIG1_PROFESSIONAL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002337 sbits |= IEC958_AES0_PROFESSIONAL;
2338 if (sbits & IEC958_AES0_PROFESSIONAL) {
Takashi Iwai0ba21762007-04-16 11:29:14 +02002339 if (sbits & AC_DIG1_EMPHASIS)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002340 sbits |= IEC958_AES0_PRO_EMPHASIS_5015;
2341 } else {
Takashi Iwai0ba21762007-04-16 11:29:14 +02002342 if (val & AC_DIG1_EMPHASIS)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002343 sbits |= IEC958_AES0_CON_EMPHASIS_5015;
Takashi Iwai0ba21762007-04-16 11:29:14 +02002344 if (!(val & AC_DIG1_COPYRIGHT))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002345 sbits |= IEC958_AES0_CON_NOT_COPYRIGHT;
Takashi Iwai0ba21762007-04-16 11:29:14 +02002346 if (val & AC_DIG1_LEVEL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002347 sbits |= (IEC958_AES1_CON_ORIGINAL << 8);
2348 sbits |= val & (0x7f << 8);
2349 }
2350 return sbits;
2351}
2352
Takashi Iwai2f728532008-09-25 16:32:41 +02002353/* set digital convert verbs both for the given NID and its slaves */
2354static void set_dig_out(struct hda_codec *codec, hda_nid_t nid,
2355 int verb, int val)
2356{
2357 hda_nid_t *d;
2358
Takashi Iwai9e976972008-11-25 08:17:20 +01002359 snd_hda_codec_write_cache(codec, nid, 0, verb, val);
Takashi Iwai2f728532008-09-25 16:32:41 +02002360 d = codec->slave_dig_outs;
2361 if (!d)
2362 return;
2363 for (; *d; d++)
Takashi Iwai9e976972008-11-25 08:17:20 +01002364 snd_hda_codec_write_cache(codec, *d, 0, verb, val);
Takashi Iwai2f728532008-09-25 16:32:41 +02002365}
2366
2367static inline void set_dig_out_convert(struct hda_codec *codec, hda_nid_t nid,
2368 int dig1, int dig2)
2369{
2370 if (dig1 != -1)
2371 set_dig_out(codec, nid, AC_VERB_SET_DIGI_CONVERT_1, dig1);
2372 if (dig2 != -1)
2373 set_dig_out(codec, nid, AC_VERB_SET_DIGI_CONVERT_2, dig2);
2374}
2375
Takashi Iwai0ba21762007-04-16 11:29:14 +02002376static int snd_hda_spdif_default_put(struct snd_kcontrol *kcontrol,
2377 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002378{
2379 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2380 hda_nid_t nid = kcontrol->private_value;
2381 unsigned short val;
2382 int change;
2383
Ingo Molnar62932df2006-01-16 16:34:20 +01002384 mutex_lock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002385 codec->spdif_status = ucontrol->value.iec958.status[0] |
2386 ((unsigned int)ucontrol->value.iec958.status[1] << 8) |
2387 ((unsigned int)ucontrol->value.iec958.status[2] << 16) |
2388 ((unsigned int)ucontrol->value.iec958.status[3] << 24);
2389 val = convert_from_spdif_status(codec->spdif_status);
2390 val |= codec->spdif_ctls & 1;
2391 change = codec->spdif_ctls != val;
2392 codec->spdif_ctls = val;
2393
Takashi Iwai2f728532008-09-25 16:32:41 +02002394 if (change)
2395 set_dig_out_convert(codec, nid, val & 0xff, (val >> 8) & 0xff);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002396
Ingo Molnar62932df2006-01-16 16:34:20 +01002397 mutex_unlock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002398 return change;
2399}
2400
Takashi Iwaia5ce8892007-07-23 15:42:26 +02002401#define snd_hda_spdif_out_switch_info snd_ctl_boolean_mono_info
Linus Torvalds1da177e2005-04-16 15:20:36 -07002402
Takashi Iwai0ba21762007-04-16 11:29:14 +02002403static int snd_hda_spdif_out_switch_get(struct snd_kcontrol *kcontrol,
2404 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002405{
2406 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2407
Takashi Iwai0ba21762007-04-16 11:29:14 +02002408 ucontrol->value.integer.value[0] = codec->spdif_ctls & AC_DIG1_ENABLE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002409 return 0;
2410}
2411
Takashi Iwai0ba21762007-04-16 11:29:14 +02002412static int snd_hda_spdif_out_switch_put(struct snd_kcontrol *kcontrol,
2413 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002414{
2415 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2416 hda_nid_t nid = kcontrol->private_value;
2417 unsigned short val;
2418 int change;
2419
Ingo Molnar62932df2006-01-16 16:34:20 +01002420 mutex_lock(&codec->spdif_mutex);
Takashi Iwai0ba21762007-04-16 11:29:14 +02002421 val = codec->spdif_ctls & ~AC_DIG1_ENABLE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002422 if (ucontrol->value.integer.value[0])
Takashi Iwai0ba21762007-04-16 11:29:14 +02002423 val |= AC_DIG1_ENABLE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002424 change = codec->spdif_ctls != val;
Takashi Iwai82beb8f2007-08-10 17:09:26 +02002425 if (change) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002426 codec->spdif_ctls = val;
Takashi Iwai2f728532008-09-25 16:32:41 +02002427 set_dig_out_convert(codec, nid, val & 0xff, -1);
Takashi Iwai0ba21762007-04-16 11:29:14 +02002428 /* unmute amp switch (if any) */
2429 if ((get_wcaps(codec, nid) & AC_WCAP_OUT_AMP) &&
Takashi Iwai47fd8302007-08-10 17:11:07 +02002430 (val & AC_DIG1_ENABLE))
2431 snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0,
2432 HDA_AMP_MUTE, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002433 }
Ingo Molnar62932df2006-01-16 16:34:20 +01002434 mutex_unlock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002435 return change;
2436}
2437
Takashi Iwaic8b6bf9b2005-11-17 14:57:47 +01002438static struct snd_kcontrol_new dig_mixes[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002439 {
2440 .access = SNDRV_CTL_ELEM_ACCESS_READ,
2441 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2442 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,CON_MASK),
2443 .info = snd_hda_spdif_mask_info,
2444 .get = snd_hda_spdif_cmask_get,
2445 },
2446 {
2447 .access = SNDRV_CTL_ELEM_ACCESS_READ,
2448 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2449 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,PRO_MASK),
2450 .info = snd_hda_spdif_mask_info,
2451 .get = snd_hda_spdif_pmask_get,
2452 },
2453 {
2454 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2455 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT),
2456 .info = snd_hda_spdif_mask_info,
2457 .get = snd_hda_spdif_default_get,
2458 .put = snd_hda_spdif_default_put,
2459 },
2460 {
2461 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2462 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,SWITCH),
2463 .info = snd_hda_spdif_out_switch_info,
2464 .get = snd_hda_spdif_out_switch_get,
2465 .put = snd_hda_spdif_out_switch_put,
2466 },
2467 { } /* end */
2468};
2469
Takashi Iwai09f99702008-02-04 12:31:13 +01002470#define SPDIF_MAX_IDX 4 /* 4 instances should be enough to probe */
2471
Linus Torvalds1da177e2005-04-16 15:20:36 -07002472/**
2473 * snd_hda_create_spdif_out_ctls - create Output SPDIF-related controls
2474 * @codec: the HDA codec
2475 * @nid: audio out widget NID
2476 *
2477 * Creates controls related with the SPDIF output.
2478 * Called from each patch supporting the SPDIF out.
2479 *
2480 * Returns 0 if successful, or a negative error code.
2481 */
Takashi Iwai12f288b2007-08-02 15:51:59 +02002482int snd_hda_create_spdif_out_ctls(struct hda_codec *codec, hda_nid_t nid)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002483{
2484 int err;
Takashi Iwaic8b6bf9b2005-11-17 14:57:47 +01002485 struct snd_kcontrol *kctl;
2486 struct snd_kcontrol_new *dig_mix;
Takashi Iwai09f99702008-02-04 12:31:13 +01002487 int idx;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002488
Takashi Iwai09f99702008-02-04 12:31:13 +01002489 for (idx = 0; idx < SPDIF_MAX_IDX; idx++) {
2490 if (!_snd_hda_find_mixer_ctl(codec, "IEC958 Playback Switch",
2491 idx))
2492 break;
2493 }
2494 if (idx >= SPDIF_MAX_IDX) {
2495 printk(KERN_ERR "hda_codec: too many IEC958 outputs\n");
2496 return -EBUSY;
2497 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002498 for (dig_mix = dig_mixes; dig_mix->name; dig_mix++) {
2499 kctl = snd_ctl_new1(dig_mix, codec);
Takashi Iwaib91f0802008-11-04 08:43:08 +01002500 if (!kctl)
2501 return -ENOMEM;
Takashi Iwai09f99702008-02-04 12:31:13 +01002502 kctl->id.index = idx;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002503 kctl->private_value = nid;
Jaroslav Kysela3911a4c2009-11-11 13:43:01 +01002504 err = snd_hda_ctl_add(codec, nid, kctl);
Takashi Iwai0ba21762007-04-16 11:29:14 +02002505 if (err < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002506 return err;
2507 }
Takashi Iwai0ba21762007-04-16 11:29:14 +02002508 codec->spdif_ctls =
Andrew Paprocki3982d172007-12-19 12:13:44 +01002509 snd_hda_codec_read(codec, nid, 0,
2510 AC_VERB_GET_DIGI_CONVERT_1, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002511 codec->spdif_status = convert_to_spdif_status(codec->spdif_ctls);
2512 return 0;
2513}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002514EXPORT_SYMBOL_HDA(snd_hda_create_spdif_out_ctls);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002515
2516/*
Takashi Iwai9a081602008-02-12 18:37:26 +01002517 * SPDIF sharing with analog output
2518 */
2519static int spdif_share_sw_get(struct snd_kcontrol *kcontrol,
2520 struct snd_ctl_elem_value *ucontrol)
2521{
2522 struct hda_multi_out *mout = snd_kcontrol_chip(kcontrol);
2523 ucontrol->value.integer.value[0] = mout->share_spdif;
2524 return 0;
2525}
2526
2527static int spdif_share_sw_put(struct snd_kcontrol *kcontrol,
2528 struct snd_ctl_elem_value *ucontrol)
2529{
2530 struct hda_multi_out *mout = snd_kcontrol_chip(kcontrol);
2531 mout->share_spdif = !!ucontrol->value.integer.value[0];
2532 return 0;
2533}
2534
2535static struct snd_kcontrol_new spdif_share_sw = {
2536 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2537 .name = "IEC958 Default PCM Playback Switch",
2538 .info = snd_ctl_boolean_mono_info,
2539 .get = spdif_share_sw_get,
2540 .put = spdif_share_sw_put,
2541};
2542
Takashi Iwaid5191e52009-11-16 14:58:17 +01002543/**
2544 * snd_hda_create_spdif_share_sw - create Default PCM switch
2545 * @codec: the HDA codec
2546 * @mout: multi-out instance
2547 */
Takashi Iwai9a081602008-02-12 18:37:26 +01002548int snd_hda_create_spdif_share_sw(struct hda_codec *codec,
2549 struct hda_multi_out *mout)
2550{
2551 if (!mout->dig_out_nid)
2552 return 0;
2553 /* ATTENTION: here mout is passed as private_data, instead of codec */
Jaroslav Kysela3911a4c2009-11-11 13:43:01 +01002554 return snd_hda_ctl_add(codec, mout->dig_out_nid,
2555 snd_ctl_new1(&spdif_share_sw, mout));
Takashi Iwai9a081602008-02-12 18:37:26 +01002556}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002557EXPORT_SYMBOL_HDA(snd_hda_create_spdif_share_sw);
Takashi Iwai9a081602008-02-12 18:37:26 +01002558
2559/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002560 * SPDIF input
2561 */
2562
2563#define snd_hda_spdif_in_switch_info snd_hda_spdif_out_switch_info
2564
Takashi Iwai0ba21762007-04-16 11:29:14 +02002565static int snd_hda_spdif_in_switch_get(struct snd_kcontrol *kcontrol,
2566 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002567{
2568 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2569
2570 ucontrol->value.integer.value[0] = codec->spdif_in_enable;
2571 return 0;
2572}
2573
Takashi Iwai0ba21762007-04-16 11:29:14 +02002574static int snd_hda_spdif_in_switch_put(struct snd_kcontrol *kcontrol,
2575 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002576{
2577 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2578 hda_nid_t nid = kcontrol->private_value;
2579 unsigned int val = !!ucontrol->value.integer.value[0];
2580 int change;
2581
Ingo Molnar62932df2006-01-16 16:34:20 +01002582 mutex_lock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002583 change = codec->spdif_in_enable != val;
Takashi Iwai82beb8f2007-08-10 17:09:26 +02002584 if (change) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002585 codec->spdif_in_enable = val;
Takashi Iwai82beb8f2007-08-10 17:09:26 +02002586 snd_hda_codec_write_cache(codec, nid, 0,
2587 AC_VERB_SET_DIGI_CONVERT_1, val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002588 }
Ingo Molnar62932df2006-01-16 16:34:20 +01002589 mutex_unlock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002590 return change;
2591}
2592
Takashi Iwai0ba21762007-04-16 11:29:14 +02002593static int snd_hda_spdif_in_status_get(struct snd_kcontrol *kcontrol,
2594 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002595{
2596 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2597 hda_nid_t nid = kcontrol->private_value;
2598 unsigned short val;
2599 unsigned int sbits;
2600
Andrew Paprocki3982d172007-12-19 12:13:44 +01002601 val = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_DIGI_CONVERT_1, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002602 sbits = convert_to_spdif_status(val);
2603 ucontrol->value.iec958.status[0] = sbits;
2604 ucontrol->value.iec958.status[1] = sbits >> 8;
2605 ucontrol->value.iec958.status[2] = sbits >> 16;
2606 ucontrol->value.iec958.status[3] = sbits >> 24;
2607 return 0;
2608}
2609
Takashi Iwaic8b6bf9b2005-11-17 14:57:47 +01002610static struct snd_kcontrol_new dig_in_ctls[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002611 {
2612 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2613 .name = SNDRV_CTL_NAME_IEC958("",CAPTURE,SWITCH),
2614 .info = snd_hda_spdif_in_switch_info,
2615 .get = snd_hda_spdif_in_switch_get,
2616 .put = snd_hda_spdif_in_switch_put,
2617 },
2618 {
2619 .access = SNDRV_CTL_ELEM_ACCESS_READ,
2620 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2621 .name = SNDRV_CTL_NAME_IEC958("",CAPTURE,DEFAULT),
2622 .info = snd_hda_spdif_mask_info,
2623 .get = snd_hda_spdif_in_status_get,
2624 },
2625 { } /* end */
2626};
2627
2628/**
2629 * snd_hda_create_spdif_in_ctls - create Input SPDIF-related controls
2630 * @codec: the HDA codec
2631 * @nid: audio in widget NID
2632 *
2633 * Creates controls related with the SPDIF input.
2634 * Called from each patch supporting the SPDIF in.
2635 *
2636 * Returns 0 if successful, or a negative error code.
2637 */
Takashi Iwai12f288b2007-08-02 15:51:59 +02002638int snd_hda_create_spdif_in_ctls(struct hda_codec *codec, hda_nid_t nid)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002639{
2640 int err;
Takashi Iwaic8b6bf9b2005-11-17 14:57:47 +01002641 struct snd_kcontrol *kctl;
2642 struct snd_kcontrol_new *dig_mix;
Takashi Iwai09f99702008-02-04 12:31:13 +01002643 int idx;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002644
Takashi Iwai09f99702008-02-04 12:31:13 +01002645 for (idx = 0; idx < SPDIF_MAX_IDX; idx++) {
2646 if (!_snd_hda_find_mixer_ctl(codec, "IEC958 Capture Switch",
2647 idx))
2648 break;
2649 }
2650 if (idx >= SPDIF_MAX_IDX) {
2651 printk(KERN_ERR "hda_codec: too many IEC958 inputs\n");
2652 return -EBUSY;
2653 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002654 for (dig_mix = dig_in_ctls; dig_mix->name; dig_mix++) {
2655 kctl = snd_ctl_new1(dig_mix, codec);
Takashi Iwaic8dcdf82009-02-06 16:21:20 +01002656 if (!kctl)
2657 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002658 kctl->private_value = nid;
Jaroslav Kysela3911a4c2009-11-11 13:43:01 +01002659 err = snd_hda_ctl_add(codec, nid, kctl);
Takashi Iwai0ba21762007-04-16 11:29:14 +02002660 if (err < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002661 return err;
2662 }
Takashi Iwai0ba21762007-04-16 11:29:14 +02002663 codec->spdif_in_enable =
Andrew Paprocki3982d172007-12-19 12:13:44 +01002664 snd_hda_codec_read(codec, nid, 0,
2665 AC_VERB_GET_DIGI_CONVERT_1, 0) &
Takashi Iwai0ba21762007-04-16 11:29:14 +02002666 AC_DIG1_ENABLE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002667 return 0;
2668}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002669EXPORT_SYMBOL_HDA(snd_hda_create_spdif_in_ctls);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002670
Takashi Iwaicb53c622007-08-10 17:21:45 +02002671#ifdef SND_HDA_NEEDS_RESUME
Takashi Iwai82beb8f2007-08-10 17:09:26 +02002672/*
2673 * command cache
2674 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002675
Takashi Iwaib3ac5632007-08-10 17:03:40 +02002676/* build a 32bit cache key with the widget id and the command parameter */
2677#define build_cmd_cache_key(nid, verb) ((verb << 8) | nid)
2678#define get_cmd_cache_nid(key) ((key) & 0xff)
2679#define get_cmd_cache_cmd(key) (((key) >> 8) & 0xffff)
2680
2681/**
2682 * snd_hda_codec_write_cache - send a single command with caching
2683 * @codec: the HDA codec
2684 * @nid: NID to send the command
2685 * @direct: direct flag
2686 * @verb: the verb to send
2687 * @parm: the parameter for the verb
2688 *
2689 * Send a single command without waiting for response.
2690 *
2691 * Returns 0 if successful, or a negative error code.
2692 */
2693int snd_hda_codec_write_cache(struct hda_codec *codec, hda_nid_t nid,
2694 int direct, unsigned int verb, unsigned int parm)
2695{
Takashi Iwaiaa2936f2009-05-26 16:07:57 +02002696 int err = snd_hda_codec_write(codec, nid, direct, verb, parm);
2697 struct hda_cache_head *c;
2698 u32 key;
Takashi Iwai33fa35e2008-11-06 16:50:40 +01002699
Takashi Iwaiaa2936f2009-05-26 16:07:57 +02002700 if (err < 0)
2701 return err;
2702 /* parm may contain the verb stuff for get/set amp */
2703 verb = verb | (parm >> 8);
2704 parm &= 0xff;
2705 key = build_cmd_cache_key(nid, verb);
2706 mutex_lock(&codec->bus->cmd_mutex);
2707 c = get_alloc_hash(&codec->cmd_cache, key);
2708 if (c)
2709 c->val = parm;
2710 mutex_unlock(&codec->bus->cmd_mutex);
2711 return 0;
Takashi Iwaib3ac5632007-08-10 17:03:40 +02002712}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002713EXPORT_SYMBOL_HDA(snd_hda_codec_write_cache);
Takashi Iwaib3ac5632007-08-10 17:03:40 +02002714
Takashi Iwaid5191e52009-11-16 14:58:17 +01002715/**
2716 * snd_hda_codec_resume_cache - Resume the all commands from the cache
2717 * @codec: HD-audio codec
2718 *
2719 * Execute all verbs recorded in the command caches to resume.
2720 */
Takashi Iwaib3ac5632007-08-10 17:03:40 +02002721void snd_hda_codec_resume_cache(struct hda_codec *codec)
2722{
Takashi Iwai603c4012008-07-30 15:01:44 +02002723 struct hda_cache_head *buffer = codec->cmd_cache.buf.list;
Takashi Iwaib3ac5632007-08-10 17:03:40 +02002724 int i;
2725
Takashi Iwai603c4012008-07-30 15:01:44 +02002726 for (i = 0; i < codec->cmd_cache.buf.used; i++, buffer++) {
Takashi Iwaib3ac5632007-08-10 17:03:40 +02002727 u32 key = buffer->key;
2728 if (!key)
2729 continue;
2730 snd_hda_codec_write(codec, get_cmd_cache_nid(key), 0,
2731 get_cmd_cache_cmd(key), buffer->val);
2732 }
2733}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002734EXPORT_SYMBOL_HDA(snd_hda_codec_resume_cache);
Takashi Iwaib3ac5632007-08-10 17:03:40 +02002735
2736/**
2737 * snd_hda_sequence_write_cache - sequence writes with caching
2738 * @codec: the HDA codec
2739 * @seq: VERB array to send
2740 *
2741 * Send the commands sequentially from the given array.
2742 * Thte commands are recorded on cache for power-save and resume.
2743 * The array must be terminated with NID=0.
2744 */
2745void snd_hda_sequence_write_cache(struct hda_codec *codec,
2746 const struct hda_verb *seq)
2747{
2748 for (; seq->nid; seq++)
2749 snd_hda_codec_write_cache(codec, seq->nid, 0, seq->verb,
2750 seq->param);
2751}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002752EXPORT_SYMBOL_HDA(snd_hda_sequence_write_cache);
Takashi Iwaicb53c622007-08-10 17:21:45 +02002753#endif /* SND_HDA_NEEDS_RESUME */
Takashi Iwaib3ac5632007-08-10 17:03:40 +02002754
Takashi Iwai54d17402005-11-21 16:33:22 +01002755/*
2756 * set power state of the codec
2757 */
2758static void hda_set_power_state(struct hda_codec *codec, hda_nid_t fg,
2759 unsigned int power_state)
2760{
Takashi Iwaicb53c622007-08-10 17:21:45 +02002761 hda_nid_t nid;
2762 int i;
Takashi Iwai54d17402005-11-21 16:33:22 +01002763
Takashi Iwai05ff7e12009-07-22 12:39:24 +02002764 /* this delay seems necessary to avoid click noise at power-down */
2765 if (power_state == AC_PWRST_D3)
2766 msleep(100);
2767 snd_hda_codec_read(codec, fg, 0, AC_VERB_SET_POWER_STATE,
Takashi Iwai54d17402005-11-21 16:33:22 +01002768 power_state);
Takashi Iwai05ff7e12009-07-22 12:39:24 +02002769 /* partial workaround for "azx_get_response timeout" */
Zhang, Ruidd2b4a72010-02-24 09:38:49 +08002770 if (power_state == AC_PWRST_D0 &&
2771 (codec->vendor_id & 0xffff0000) == 0x14f10000)
Takashi Iwai05ff7e12009-07-22 12:39:24 +02002772 msleep(10);
Takashi Iwai54d17402005-11-21 16:33:22 +01002773
Takashi Iwaicb53c622007-08-10 17:21:45 +02002774 nid = codec->start_nid;
2775 for (i = 0; i < codec->num_nodes; i++, nid++) {
Takashi Iwai7eba5c92007-11-14 14:53:42 +01002776 unsigned int wcaps = get_wcaps(codec, nid);
2777 if (wcaps & AC_WCAP_POWER) {
Takashi Iwaia22d5432009-07-27 12:54:26 +02002778 unsigned int wid_type = get_wcaps_type(wcaps);
Takashi Iwaia3b48c82009-04-21 13:37:29 +02002779 if (power_state == AC_PWRST_D3 &&
2780 wid_type == AC_WID_PIN) {
Takashi Iwai7eba5c92007-11-14 14:53:42 +01002781 unsigned int pincap;
2782 /*
2783 * don't power down the widget if it controls
2784 * eapd and EAPD_BTLENABLE is set.
2785 */
Takashi Iwai14bafe32009-03-23 16:35:39 +01002786 pincap = snd_hda_query_pin_caps(codec, nid);
Takashi Iwai7eba5c92007-11-14 14:53:42 +01002787 if (pincap & AC_PINCAP_EAPD) {
2788 int eapd = snd_hda_codec_read(codec,
2789 nid, 0,
2790 AC_VERB_GET_EAPD_BTLENABLE, 0);
2791 eapd &= 0x02;
Takashi Iwaia3b48c82009-04-21 13:37:29 +02002792 if (eapd)
Takashi Iwai7eba5c92007-11-14 14:53:42 +01002793 continue;
2794 }
Takashi Iwai1194b5b2007-10-10 10:04:26 +02002795 }
Takashi Iwai54d17402005-11-21 16:33:22 +01002796 snd_hda_codec_write(codec, nid, 0,
2797 AC_VERB_SET_POWER_STATE,
2798 power_state);
Takashi Iwai1194b5b2007-10-10 10:04:26 +02002799 }
Takashi Iwai54d17402005-11-21 16:33:22 +01002800 }
2801
Takashi Iwaicb53c622007-08-10 17:21:45 +02002802 if (power_state == AC_PWRST_D0) {
2803 unsigned long end_time;
2804 int state;
Takashi Iwaicb53c622007-08-10 17:21:45 +02002805 /* wait until the codec reachs to D0 */
2806 end_time = jiffies + msecs_to_jiffies(500);
2807 do {
2808 state = snd_hda_codec_read(codec, fg, 0,
2809 AC_VERB_GET_POWER_STATE, 0);
2810 if (state == power_state)
2811 break;
2812 msleep(1);
2813 } while (time_after_eq(end_time, jiffies));
2814 }
Takashi Iwai54d17402005-11-21 16:33:22 +01002815}
2816
Takashi Iwai11aeff02008-07-30 15:01:46 +02002817#ifdef CONFIG_SND_HDA_HWDEP
2818/* execute additional init verbs */
2819static void hda_exec_init_verbs(struct hda_codec *codec)
2820{
2821 if (codec->init_verbs.list)
2822 snd_hda_sequence_write(codec, codec->init_verbs.list);
2823}
2824#else
2825static inline void hda_exec_init_verbs(struct hda_codec *codec) {}
2826#endif
2827
Takashi Iwaicb53c622007-08-10 17:21:45 +02002828#ifdef SND_HDA_NEEDS_RESUME
2829/*
2830 * call suspend and power-down; used both from PM and power-save
2831 */
2832static void hda_call_codec_suspend(struct hda_codec *codec)
2833{
2834 if (codec->patch_ops.suspend)
2835 codec->patch_ops.suspend(codec, PMSG_SUSPEND);
2836 hda_set_power_state(codec,
2837 codec->afg ? codec->afg : codec->mfg,
2838 AC_PWRST_D3);
2839#ifdef CONFIG_SND_HDA_POWER_SAVE
Takashi Iwaia2f63092009-11-11 09:34:25 +01002840 snd_hda_update_power_acct(codec);
Takashi Iwaicb53c622007-08-10 17:21:45 +02002841 cancel_delayed_work(&codec->power_work);
Takashi Iwai95e99fd2007-08-13 15:29:04 +02002842 codec->power_on = 0;
Takashi Iwaia221e282007-08-16 16:35:33 +02002843 codec->power_transition = 0;
Takashi Iwaia2f63092009-11-11 09:34:25 +01002844 codec->power_jiffies = jiffies;
Takashi Iwaicb53c622007-08-10 17:21:45 +02002845#endif
2846}
2847
2848/*
2849 * kick up codec; used both from PM and power-save
2850 */
2851static void hda_call_codec_resume(struct hda_codec *codec)
2852{
2853 hda_set_power_state(codec,
2854 codec->afg ? codec->afg : codec->mfg,
2855 AC_PWRST_D0);
Takashi Iwai3be14142009-02-20 14:11:16 +01002856 restore_pincfgs(codec); /* restore all current pin configs */
Takashi Iwai11aeff02008-07-30 15:01:46 +02002857 hda_exec_init_verbs(codec);
Takashi Iwaicb53c622007-08-10 17:21:45 +02002858 if (codec->patch_ops.resume)
2859 codec->patch_ops.resume(codec);
2860 else {
Takashi Iwai9d99f312007-08-14 15:15:52 +02002861 if (codec->patch_ops.init)
2862 codec->patch_ops.init(codec);
Takashi Iwaicb53c622007-08-10 17:21:45 +02002863 snd_hda_codec_resume_amp(codec);
2864 snd_hda_codec_resume_cache(codec);
2865 }
2866}
2867#endif /* SND_HDA_NEEDS_RESUME */
2868
Takashi Iwai54d17402005-11-21 16:33:22 +01002869
Linus Torvalds1da177e2005-04-16 15:20:36 -07002870/**
2871 * snd_hda_build_controls - build mixer controls
2872 * @bus: the BUS
2873 *
2874 * Creates mixer controls for each codec included in the bus.
2875 *
2876 * Returns 0 if successful, otherwise a negative error code.
2877 */
Takashi Iwai1289e9e2008-11-27 15:47:11 +01002878int /*__devinit*/ snd_hda_build_controls(struct hda_bus *bus)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002879{
Takashi Iwai0ba21762007-04-16 11:29:14 +02002880 struct hda_codec *codec;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002881
Takashi Iwai0ba21762007-04-16 11:29:14 +02002882 list_for_each_entry(codec, &bus->codec_list, list) {
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02002883 int err = snd_hda_codec_build_controls(codec);
Takashi Iwaif93d4612009-03-02 10:44:15 +01002884 if (err < 0) {
2885 printk(KERN_ERR "hda_codec: cannot build controls"
2886 "for #%d (error %d)\n", codec->addr, err);
2887 err = snd_hda_codec_reset(codec);
2888 if (err < 0) {
2889 printk(KERN_ERR
2890 "hda_codec: cannot revert codec\n");
2891 return err;
2892 }
2893 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002894 }
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02002895 return 0;
2896}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002897EXPORT_SYMBOL_HDA(snd_hda_build_controls);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002898
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02002899int snd_hda_codec_build_controls(struct hda_codec *codec)
2900{
2901 int err = 0;
Takashi Iwai11aeff02008-07-30 15:01:46 +02002902 hda_exec_init_verbs(codec);
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02002903 /* continue to initialize... */
2904 if (codec->patch_ops.init)
2905 err = codec->patch_ops.init(codec);
2906 if (!err && codec->patch_ops.build_controls)
2907 err = codec->patch_ops.build_controls(codec);
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02002908 if (err < 0)
2909 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002910 return 0;
2911}
2912
Linus Torvalds1da177e2005-04-16 15:20:36 -07002913/*
2914 * stream formats
2915 */
Takashi Iwaibefdf312005-08-22 13:57:55 +02002916struct hda_rate_tbl {
2917 unsigned int hz;
2918 unsigned int alsa_bits;
2919 unsigned int hda_fmt;
2920};
2921
2922static struct hda_rate_tbl rate_bits[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002923 /* rate in Hz, ALSA rate bitmask, HDA format value */
Nicolas Graziano9d8f53f2005-08-22 13:47:16 +02002924
2925 /* autodetected value used in snd_hda_query_supported_pcm */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002926 { 8000, SNDRV_PCM_RATE_8000, 0x0500 }, /* 1/6 x 48 */
2927 { 11025, SNDRV_PCM_RATE_11025, 0x4300 }, /* 1/4 x 44 */
2928 { 16000, SNDRV_PCM_RATE_16000, 0x0200 }, /* 1/3 x 48 */
2929 { 22050, SNDRV_PCM_RATE_22050, 0x4100 }, /* 1/2 x 44 */
2930 { 32000, SNDRV_PCM_RATE_32000, 0x0a00 }, /* 2/3 x 48 */
2931 { 44100, SNDRV_PCM_RATE_44100, 0x4000 }, /* 44 */
2932 { 48000, SNDRV_PCM_RATE_48000, 0x0000 }, /* 48 */
2933 { 88200, SNDRV_PCM_RATE_88200, 0x4800 }, /* 2 x 44 */
2934 { 96000, SNDRV_PCM_RATE_96000, 0x0800 }, /* 2 x 48 */
2935 { 176400, SNDRV_PCM_RATE_176400, 0x5800 },/* 4 x 44 */
2936 { 192000, SNDRV_PCM_RATE_192000, 0x1800 }, /* 4 x 48 */
Takashi Iwaia961f9f2007-04-12 13:08:09 +02002937#define AC_PAR_PCM_RATE_BITS 11
2938 /* up to bits 10, 384kHZ isn't supported properly */
2939
2940 /* not autodetected value */
2941 { 9600, SNDRV_PCM_RATE_KNOT, 0x0400 }, /* 1/5 x 48 */
Nicolas Graziano9d8f53f2005-08-22 13:47:16 +02002942
Takashi Iwaibefdf312005-08-22 13:57:55 +02002943 { 0 } /* terminator */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002944};
2945
2946/**
2947 * snd_hda_calc_stream_format - calculate format bitset
2948 * @rate: the sample rate
2949 * @channels: the number of channels
2950 * @format: the PCM format (SNDRV_PCM_FORMAT_XXX)
2951 * @maxbps: the max. bps
2952 *
2953 * Calculate the format bitset from the given rate, channels and th PCM format.
2954 *
2955 * Return zero if invalid.
2956 */
2957unsigned int snd_hda_calc_stream_format(unsigned int rate,
2958 unsigned int channels,
2959 unsigned int format,
2960 unsigned int maxbps)
2961{
2962 int i;
2963 unsigned int val = 0;
2964
Takashi Iwaibefdf312005-08-22 13:57:55 +02002965 for (i = 0; rate_bits[i].hz; i++)
2966 if (rate_bits[i].hz == rate) {
2967 val = rate_bits[i].hda_fmt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002968 break;
2969 }
Takashi Iwai0ba21762007-04-16 11:29:14 +02002970 if (!rate_bits[i].hz) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002971 snd_printdd("invalid rate %d\n", rate);
2972 return 0;
2973 }
2974
2975 if (channels == 0 || channels > 8) {
2976 snd_printdd("invalid channels %d\n", channels);
2977 return 0;
2978 }
2979 val |= channels - 1;
2980
2981 switch (snd_pcm_format_width(format)) {
2982 case 8: val |= 0x00; break;
2983 case 16: val |= 0x10; break;
2984 case 20:
2985 case 24:
2986 case 32:
Takashi Iwaib0bb3aa2009-07-03 23:25:37 +02002987 if (maxbps >= 32 || format == SNDRV_PCM_FORMAT_FLOAT_LE)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002988 val |= 0x40;
2989 else if (maxbps >= 24)
2990 val |= 0x30;
2991 else
2992 val |= 0x20;
2993 break;
2994 default:
Takashi Iwai0ba21762007-04-16 11:29:14 +02002995 snd_printdd("invalid format width %d\n",
2996 snd_pcm_format_width(format));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002997 return 0;
2998 }
2999
3000 return val;
3001}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003002EXPORT_SYMBOL_HDA(snd_hda_calc_stream_format);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003003
Takashi Iwai92c7c8a2009-03-24 07:32:14 +01003004static unsigned int get_pcm_param(struct hda_codec *codec, hda_nid_t nid)
3005{
3006 unsigned int val = 0;
3007 if (nid != codec->afg &&
3008 (get_wcaps(codec, nid) & AC_WCAP_FORMAT_OVRD))
3009 val = snd_hda_param_read(codec, nid, AC_PAR_PCM);
3010 if (!val || val == -1)
3011 val = snd_hda_param_read(codec, codec->afg, AC_PAR_PCM);
3012 if (!val || val == -1)
3013 return 0;
3014 return val;
3015}
3016
3017static unsigned int query_pcm_param(struct hda_codec *codec, hda_nid_t nid)
3018{
3019 return query_caps_hash(codec, nid, HDA_HASH_PARPCM_KEY(nid),
3020 get_pcm_param);
3021}
3022
3023static unsigned int get_stream_param(struct hda_codec *codec, hda_nid_t nid)
3024{
3025 unsigned int streams = snd_hda_param_read(codec, nid, AC_PAR_STREAM);
3026 if (!streams || streams == -1)
3027 streams = snd_hda_param_read(codec, codec->afg, AC_PAR_STREAM);
3028 if (!streams || streams == -1)
3029 return 0;
3030 return streams;
3031}
3032
3033static unsigned int query_stream_param(struct hda_codec *codec, hda_nid_t nid)
3034{
3035 return query_caps_hash(codec, nid, HDA_HASH_PARSTR_KEY(nid),
3036 get_stream_param);
3037}
3038
Linus Torvalds1da177e2005-04-16 15:20:36 -07003039/**
3040 * snd_hda_query_supported_pcm - query the supported PCM rates and formats
3041 * @codec: the HDA codec
3042 * @nid: NID to query
3043 * @ratesp: the pointer to store the detected rate bitflags
3044 * @formatsp: the pointer to store the detected formats
3045 * @bpsp: the pointer to store the detected format widths
3046 *
3047 * Queries the supported PCM rates and formats. The NULL @ratesp, @formatsp
3048 * or @bsps argument is ignored.
3049 *
3050 * Returns 0 if successful, otherwise a negative error code.
3051 */
Takashi Iwai986862b2008-11-27 12:40:13 +01003052static int snd_hda_query_supported_pcm(struct hda_codec *codec, hda_nid_t nid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003053 u32 *ratesp, u64 *formatsp, unsigned int *bpsp)
3054{
Jaroslav Kyselaee504712009-03-17 14:30:31 +01003055 unsigned int i, val, wcaps;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003056
Jaroslav Kyselaee504712009-03-17 14:30:31 +01003057 wcaps = get_wcaps(codec, nid);
Takashi Iwai92c7c8a2009-03-24 07:32:14 +01003058 val = query_pcm_param(codec, nid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003059
3060 if (ratesp) {
3061 u32 rates = 0;
Takashi Iwaia961f9f2007-04-12 13:08:09 +02003062 for (i = 0; i < AC_PAR_PCM_RATE_BITS; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003063 if (val & (1 << i))
Takashi Iwaibefdf312005-08-22 13:57:55 +02003064 rates |= rate_bits[i].alsa_bits;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003065 }
Jaroslav Kyselaee504712009-03-17 14:30:31 +01003066 if (rates == 0) {
3067 snd_printk(KERN_ERR "hda_codec: rates == 0 "
3068 "(nid=0x%x, val=0x%x, ovrd=%i)\n",
3069 nid, val,
3070 (wcaps & AC_WCAP_FORMAT_OVRD) ? 1 : 0);
3071 return -EIO;
3072 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003073 *ratesp = rates;
3074 }
3075
3076 if (formatsp || bpsp) {
3077 u64 formats = 0;
Jaroslav Kyselaee504712009-03-17 14:30:31 +01003078 unsigned int streams, bps;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003079
Takashi Iwai92c7c8a2009-03-24 07:32:14 +01003080 streams = query_stream_param(codec, nid);
3081 if (!streams)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003082 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003083
3084 bps = 0;
3085 if (streams & AC_SUPFMT_PCM) {
3086 if (val & AC_SUPPCM_BITS_8) {
3087 formats |= SNDRV_PCM_FMTBIT_U8;
3088 bps = 8;
3089 }
3090 if (val & AC_SUPPCM_BITS_16) {
3091 formats |= SNDRV_PCM_FMTBIT_S16_LE;
3092 bps = 16;
3093 }
3094 if (wcaps & AC_WCAP_DIGITAL) {
3095 if (val & AC_SUPPCM_BITS_32)
3096 formats |= SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_LE;
3097 if (val & (AC_SUPPCM_BITS_20|AC_SUPPCM_BITS_24))
3098 formats |= SNDRV_PCM_FMTBIT_S32_LE;
3099 if (val & AC_SUPPCM_BITS_24)
3100 bps = 24;
3101 else if (val & AC_SUPPCM_BITS_20)
3102 bps = 20;
Takashi Iwai0ba21762007-04-16 11:29:14 +02003103 } else if (val & (AC_SUPPCM_BITS_20|AC_SUPPCM_BITS_24|
3104 AC_SUPPCM_BITS_32)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003105 formats |= SNDRV_PCM_FMTBIT_S32_LE;
3106 if (val & AC_SUPPCM_BITS_32)
3107 bps = 32;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003108 else if (val & AC_SUPPCM_BITS_24)
3109 bps = 24;
Nicolas Graziano33ef7652006-09-19 14:23:14 +02003110 else if (val & AC_SUPPCM_BITS_20)
3111 bps = 20;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003112 }
3113 }
Takashi Iwaib5025c52009-07-01 18:05:27 +02003114 if (streams & AC_SUPFMT_FLOAT32) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003115 formats |= SNDRV_PCM_FMTBIT_FLOAT_LE;
Takashi Iwaib0bb3aa2009-07-03 23:25:37 +02003116 if (!bps)
3117 bps = 32;
Takashi Iwaib5025c52009-07-01 18:05:27 +02003118 }
3119 if (streams == AC_SUPFMT_AC3) {
Takashi Iwai0ba21762007-04-16 11:29:14 +02003120 /* should be exclusive */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003121 /* temporary hack: we have still no proper support
3122 * for the direct AC3 stream...
3123 */
3124 formats |= SNDRV_PCM_FMTBIT_U8;
3125 bps = 8;
3126 }
Jaroslav Kyselaee504712009-03-17 14:30:31 +01003127 if (formats == 0) {
3128 snd_printk(KERN_ERR "hda_codec: formats == 0 "
3129 "(nid=0x%x, val=0x%x, ovrd=%i, "
3130 "streams=0x%x)\n",
3131 nid, val,
3132 (wcaps & AC_WCAP_FORMAT_OVRD) ? 1 : 0,
3133 streams);
3134 return -EIO;
3135 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003136 if (formatsp)
3137 *formatsp = formats;
3138 if (bpsp)
3139 *bpsp = bps;
3140 }
3141
3142 return 0;
3143}
3144
3145/**
Takashi Iwaid5191e52009-11-16 14:58:17 +01003146 * snd_hda_is_supported_format - Check the validity of the format
3147 * @codec: HD-audio codec
3148 * @nid: NID to check
3149 * @format: the HD-audio format value to check
3150 *
3151 * Check whether the given node supports the format value.
Linus Torvalds1da177e2005-04-16 15:20:36 -07003152 *
3153 * Returns 1 if supported, 0 if not.
3154 */
3155int snd_hda_is_supported_format(struct hda_codec *codec, hda_nid_t nid,
3156 unsigned int format)
3157{
3158 int i;
3159 unsigned int val = 0, rate, stream;
3160
Takashi Iwai92c7c8a2009-03-24 07:32:14 +01003161 val = query_pcm_param(codec, nid);
3162 if (!val)
3163 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003164
3165 rate = format & 0xff00;
Takashi Iwaia961f9f2007-04-12 13:08:09 +02003166 for (i = 0; i < AC_PAR_PCM_RATE_BITS; i++)
Takashi Iwaibefdf312005-08-22 13:57:55 +02003167 if (rate_bits[i].hda_fmt == rate) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003168 if (val & (1 << i))
3169 break;
3170 return 0;
3171 }
Takashi Iwaia961f9f2007-04-12 13:08:09 +02003172 if (i >= AC_PAR_PCM_RATE_BITS)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003173 return 0;
3174
Takashi Iwai92c7c8a2009-03-24 07:32:14 +01003175 stream = query_stream_param(codec, nid);
3176 if (!stream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003177 return 0;
3178
3179 if (stream & AC_SUPFMT_PCM) {
3180 switch (format & 0xf0) {
3181 case 0x00:
Takashi Iwai0ba21762007-04-16 11:29:14 +02003182 if (!(val & AC_SUPPCM_BITS_8))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003183 return 0;
3184 break;
3185 case 0x10:
Takashi Iwai0ba21762007-04-16 11:29:14 +02003186 if (!(val & AC_SUPPCM_BITS_16))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003187 return 0;
3188 break;
3189 case 0x20:
Takashi Iwai0ba21762007-04-16 11:29:14 +02003190 if (!(val & AC_SUPPCM_BITS_20))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003191 return 0;
3192 break;
3193 case 0x30:
Takashi Iwai0ba21762007-04-16 11:29:14 +02003194 if (!(val & AC_SUPPCM_BITS_24))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003195 return 0;
3196 break;
3197 case 0x40:
Takashi Iwai0ba21762007-04-16 11:29:14 +02003198 if (!(val & AC_SUPPCM_BITS_32))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003199 return 0;
3200 break;
3201 default:
3202 return 0;
3203 }
3204 } else {
3205 /* FIXME: check for float32 and AC3? */
3206 }
3207
3208 return 1;
3209}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003210EXPORT_SYMBOL_HDA(snd_hda_is_supported_format);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003211
3212/*
3213 * PCM stuff
3214 */
3215static int hda_pcm_default_open_close(struct hda_pcm_stream *hinfo,
3216 struct hda_codec *codec,
Takashi Iwaic8b6bf9b2005-11-17 14:57:47 +01003217 struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003218{
3219 return 0;
3220}
3221
3222static int hda_pcm_default_prepare(struct hda_pcm_stream *hinfo,
3223 struct hda_codec *codec,
3224 unsigned int stream_tag,
3225 unsigned int format,
Takashi Iwaic8b6bf9b2005-11-17 14:57:47 +01003226 struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003227{
3228 snd_hda_codec_setup_stream(codec, hinfo->nid, stream_tag, 0, format);
3229 return 0;
3230}
3231
3232static int hda_pcm_default_cleanup(struct hda_pcm_stream *hinfo,
3233 struct hda_codec *codec,
Takashi Iwaic8b6bf9b2005-11-17 14:57:47 +01003234 struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003235{
Takashi Iwai888afa12008-03-18 09:57:50 +01003236 snd_hda_codec_cleanup_stream(codec, hinfo->nid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003237 return 0;
3238}
3239
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02003240static int set_pcm_default_values(struct hda_codec *codec,
3241 struct hda_pcm_stream *info)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003242{
Jaroslav Kyselaee504712009-03-17 14:30:31 +01003243 int err;
3244
Takashi Iwai0ba21762007-04-16 11:29:14 +02003245 /* query support PCM information from the given NID */
3246 if (info->nid && (!info->rates || !info->formats)) {
Jaroslav Kyselaee504712009-03-17 14:30:31 +01003247 err = snd_hda_query_supported_pcm(codec, info->nid,
Takashi Iwai0ba21762007-04-16 11:29:14 +02003248 info->rates ? NULL : &info->rates,
3249 info->formats ? NULL : &info->formats,
3250 info->maxbps ? NULL : &info->maxbps);
Jaroslav Kyselaee504712009-03-17 14:30:31 +01003251 if (err < 0)
3252 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003253 }
3254 if (info->ops.open == NULL)
3255 info->ops.open = hda_pcm_default_open_close;
3256 if (info->ops.close == NULL)
3257 info->ops.close = hda_pcm_default_open_close;
3258 if (info->ops.prepare == 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.prepare = hda_pcm_default_prepare;
3262 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003263 if (info->ops.cleanup == NULL) {
Takashi Iwaida3cec32008-08-08 17:12:14 +02003264 if (snd_BUG_ON(!info->nid))
3265 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003266 info->ops.cleanup = hda_pcm_default_cleanup;
3267 }
3268 return 0;
3269}
3270
Takashi Iwaid5191e52009-11-16 14:58:17 +01003271/* global */
Jaroslav Kyselae3303232009-11-10 14:53:02 +01003272const char *snd_hda_pcm_type_name[HDA_PCM_NTYPES] = {
3273 "Audio", "SPDIF", "HDMI", "Modem"
3274};
3275
Takashi Iwai176d5332008-07-30 15:01:44 +02003276/*
Takashi Iwai529bd6c2008-11-27 14:17:01 +01003277 * get the empty PCM device number to assign
Takashi Iwaic8936222010-01-28 17:08:53 +01003278 *
3279 * note the max device number is limited by HDA_MAX_PCMS, currently 10
Takashi Iwai529bd6c2008-11-27 14:17:01 +01003280 */
3281static int get_empty_pcm_device(struct hda_bus *bus, int type)
3282{
Wu Fengguangf5d6def2009-10-30 11:38:26 +01003283 /* audio device indices; not linear to keep compatibility */
3284 static int audio_idx[HDA_PCM_NTYPES][5] = {
3285 [HDA_PCM_TYPE_AUDIO] = { 0, 2, 4, 5, -1 },
3286 [HDA_PCM_TYPE_SPDIF] = { 1, -1 },
Wu Fengguang92608ba2009-10-30 11:40:03 +01003287 [HDA_PCM_TYPE_HDMI] = { 3, 7, 8, 9, -1 },
Wu Fengguangf5d6def2009-10-30 11:38:26 +01003288 [HDA_PCM_TYPE_MODEM] = { 6, -1 },
Takashi Iwai529bd6c2008-11-27 14:17:01 +01003289 };
Wu Fengguangf5d6def2009-10-30 11:38:26 +01003290 int i;
Takashi Iwai529bd6c2008-11-27 14:17:01 +01003291
Wu Fengguangf5d6def2009-10-30 11:38:26 +01003292 if (type >= HDA_PCM_NTYPES) {
Takashi Iwai529bd6c2008-11-27 14:17:01 +01003293 snd_printk(KERN_WARNING "Invalid PCM type %d\n", type);
3294 return -EINVAL;
3295 }
Wu Fengguangf5d6def2009-10-30 11:38:26 +01003296
3297 for (i = 0; audio_idx[type][i] >= 0 ; i++)
3298 if (!test_and_set_bit(audio_idx[type][i], bus->pcm_dev_bits))
3299 return audio_idx[type][i];
3300
Jaroslav Kyselae3303232009-11-10 14:53:02 +01003301 snd_printk(KERN_WARNING "Too many %s devices\n", snd_hda_pcm_type_name[type]);
Wu Fengguangf5d6def2009-10-30 11:38:26 +01003302 return -EAGAIN;
Takashi Iwai529bd6c2008-11-27 14:17:01 +01003303}
3304
3305/*
Takashi Iwai176d5332008-07-30 15:01:44 +02003306 * attach a new PCM stream
3307 */
Takashi Iwai529bd6c2008-11-27 14:17:01 +01003308static int snd_hda_attach_pcm(struct hda_codec *codec, struct hda_pcm *pcm)
Takashi Iwai176d5332008-07-30 15:01:44 +02003309{
Takashi Iwai33fa35e2008-11-06 16:50:40 +01003310 struct hda_bus *bus = codec->bus;
Takashi Iwai176d5332008-07-30 15:01:44 +02003311 struct hda_pcm_stream *info;
3312 int stream, err;
3313
Takashi Iwaib91f0802008-11-04 08:43:08 +01003314 if (snd_BUG_ON(!pcm->name))
Takashi Iwai176d5332008-07-30 15:01:44 +02003315 return -EINVAL;
3316 for (stream = 0; stream < 2; stream++) {
3317 info = &pcm->stream[stream];
3318 if (info->substreams) {
3319 err = set_pcm_default_values(codec, info);
3320 if (err < 0)
3321 return err;
3322 }
3323 }
Takashi Iwai33fa35e2008-11-06 16:50:40 +01003324 return bus->ops.attach_pcm(bus, codec, pcm);
Takashi Iwai176d5332008-07-30 15:01:44 +02003325}
3326
Takashi Iwai529bd6c2008-11-27 14:17:01 +01003327/* assign all PCMs of the given codec */
3328int snd_hda_codec_build_pcms(struct hda_codec *codec)
3329{
3330 unsigned int pcm;
3331 int err;
3332
3333 if (!codec->num_pcms) {
3334 if (!codec->patch_ops.build_pcms)
3335 return 0;
3336 err = codec->patch_ops.build_pcms(codec);
Takashi Iwai6e655bf2009-03-02 10:46:03 +01003337 if (err < 0) {
3338 printk(KERN_ERR "hda_codec: cannot build PCMs"
3339 "for #%d (error %d)\n", codec->addr, err);
3340 err = snd_hda_codec_reset(codec);
3341 if (err < 0) {
3342 printk(KERN_ERR
3343 "hda_codec: cannot revert codec\n");
3344 return err;
3345 }
3346 }
Takashi Iwai529bd6c2008-11-27 14:17:01 +01003347 }
3348 for (pcm = 0; pcm < codec->num_pcms; pcm++) {
3349 struct hda_pcm *cpcm = &codec->pcm_info[pcm];
3350 int dev;
3351
3352 if (!cpcm->stream[0].substreams && !cpcm->stream[1].substreams)
Takashi Iwai41b5b012009-01-20 18:21:23 +01003353 continue; /* no substreams assigned */
Takashi Iwai529bd6c2008-11-27 14:17:01 +01003354
3355 if (!cpcm->pcm) {
3356 dev = get_empty_pcm_device(codec->bus, cpcm->pcm_type);
3357 if (dev < 0)
Takashi Iwai6e655bf2009-03-02 10:46:03 +01003358 continue; /* no fatal error */
Takashi Iwai529bd6c2008-11-27 14:17:01 +01003359 cpcm->device = dev;
3360 err = snd_hda_attach_pcm(codec, cpcm);
Takashi Iwai6e655bf2009-03-02 10:46:03 +01003361 if (err < 0) {
3362 printk(KERN_ERR "hda_codec: cannot attach "
3363 "PCM stream %d for codec #%d\n",
3364 dev, codec->addr);
3365 continue; /* no fatal error */
3366 }
Takashi Iwai529bd6c2008-11-27 14:17:01 +01003367 }
3368 }
3369 return 0;
3370}
3371
Linus Torvalds1da177e2005-04-16 15:20:36 -07003372/**
3373 * snd_hda_build_pcms - build PCM information
3374 * @bus: the BUS
3375 *
3376 * Create PCM information for each codec included in the bus.
3377 *
3378 * The build_pcms codec patch is requested to set up codec->num_pcms and
3379 * codec->pcm_info properly. The array is referred by the top-level driver
3380 * to create its PCM instances.
3381 * The allocated codec->pcm_info should be released in codec->patch_ops.free
3382 * callback.
3383 *
3384 * At least, substreams, channels_min and channels_max must be filled for
3385 * each stream. substreams = 0 indicates that the stream doesn't exist.
3386 * When rates and/or formats are zero, the supported values are queried
3387 * from the given nid. The nid is used also by the default ops.prepare
3388 * and ops.cleanup callbacks.
3389 *
3390 * The driver needs to call ops.open in its open callback. Similarly,
3391 * ops.close is supposed to be called in the close callback.
3392 * ops.prepare should be called in the prepare or hw_params callback
3393 * with the proper parameters for set up.
3394 * ops.cleanup should be called in hw_free for clean up of streams.
3395 *
3396 * This function returns 0 if successfull, or a negative error code.
3397 */
Takashi Iwai529bd6c2008-11-27 14:17:01 +01003398int __devinit snd_hda_build_pcms(struct hda_bus *bus)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003399{
Takashi Iwai0ba21762007-04-16 11:29:14 +02003400 struct hda_codec *codec;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003401
Takashi Iwai0ba21762007-04-16 11:29:14 +02003402 list_for_each_entry(codec, &bus->codec_list, list) {
Takashi Iwai529bd6c2008-11-27 14:17:01 +01003403 int err = snd_hda_codec_build_pcms(codec);
3404 if (err < 0)
3405 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003406 }
3407 return 0;
3408}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003409EXPORT_SYMBOL_HDA(snd_hda_build_pcms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003410
Linus Torvalds1da177e2005-04-16 15:20:36 -07003411/**
3412 * snd_hda_check_board_config - compare the current codec with the config table
3413 * @codec: the HDA codec
Takashi Iwaif5fcc132006-11-24 17:07:44 +01003414 * @num_configs: number of config enums
3415 * @models: array of model name strings
Linus Torvalds1da177e2005-04-16 15:20:36 -07003416 * @tbl: configuration table, terminated by null entries
3417 *
3418 * Compares the modelname or PCI subsystem id of the current codec with the
3419 * given configuration table. If a matching entry is found, returns its
3420 * config value (supposed to be 0 or positive).
3421 *
3422 * If no entries are matching, the function returns a negative value.
3423 */
Takashi Iwai12f288b2007-08-02 15:51:59 +02003424int snd_hda_check_board_config(struct hda_codec *codec,
3425 int num_configs, const char **models,
3426 const struct snd_pci_quirk *tbl)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003427{
Takashi Iwaif44ac832008-07-30 15:01:45 +02003428 if (codec->modelname && models) {
Takashi Iwaif5fcc132006-11-24 17:07:44 +01003429 int i;
3430 for (i = 0; i < num_configs; i++) {
3431 if (models[i] &&
Takashi Iwaif44ac832008-07-30 15:01:45 +02003432 !strcmp(codec->modelname, models[i])) {
Takashi Iwaif5fcc132006-11-24 17:07:44 +01003433 snd_printd(KERN_INFO "hda_codec: model '%s' is "
3434 "selected\n", models[i]);
3435 return i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003436 }
3437 }
3438 }
3439
Takashi Iwaif5fcc132006-11-24 17:07:44 +01003440 if (!codec->bus->pci || !tbl)
3441 return -1;
3442
3443 tbl = snd_pci_quirk_lookup(codec->bus->pci, tbl);
3444 if (!tbl)
3445 return -1;
3446 if (tbl->value >= 0 && tbl->value < num_configs) {
Takashi Iwai62cf8722008-05-20 12:15:15 +02003447#ifdef CONFIG_SND_DEBUG_VERBOSE
Takashi Iwaif5fcc132006-11-24 17:07:44 +01003448 char tmp[10];
3449 const char *model = NULL;
3450 if (models)
3451 model = models[tbl->value];
3452 if (!model) {
3453 sprintf(tmp, "#%d", tbl->value);
3454 model = tmp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003455 }
Takashi Iwaif5fcc132006-11-24 17:07:44 +01003456 snd_printdd(KERN_INFO "hda_codec: model '%s' is selected "
3457 "for config %x:%x (%s)\n",
3458 model, tbl->subvendor, tbl->subdevice,
3459 (tbl->name ? tbl->name : "Unknown device"));
3460#endif
3461 return tbl->value;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003462 }
3463 return -1;
3464}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003465EXPORT_SYMBOL_HDA(snd_hda_check_board_config);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003466
3467/**
Mauro Carvalho Chehab2eda3442008-08-11 10:18:39 +02003468 * snd_hda_check_board_codec_sid_config - compare the current codec
3469 subsystem ID with the
3470 config table
3471
3472 This is important for Gateway notebooks with SB450 HDA Audio
3473 where the vendor ID of the PCI device is:
3474 ATI Technologies Inc SB450 HDA Audio [1002:437b]
3475 and the vendor/subvendor are found only at the codec.
3476
3477 * @codec: the HDA codec
3478 * @num_configs: number of config enums
3479 * @models: array of model name strings
3480 * @tbl: configuration table, terminated by null entries
3481 *
3482 * Compares the modelname or PCI subsystem id of the current codec with the
3483 * given configuration table. If a matching entry is found, returns its
3484 * config value (supposed to be 0 or positive).
3485 *
3486 * If no entries are matching, the function returns a negative value.
3487 */
3488int snd_hda_check_board_codec_sid_config(struct hda_codec *codec,
3489 int num_configs, const char **models,
3490 const struct snd_pci_quirk *tbl)
3491{
3492 const struct snd_pci_quirk *q;
3493
3494 /* Search for codec ID */
3495 for (q = tbl; q->subvendor; q++) {
3496 unsigned long vendorid = (q->subdevice) | (q->subvendor << 16);
3497
3498 if (vendorid == codec->subsystem_id)
3499 break;
3500 }
3501
3502 if (!q->subvendor)
3503 return -1;
3504
3505 tbl = q;
3506
3507 if (tbl->value >= 0 && tbl->value < num_configs) {
Takashi Iwaid94ff6b2009-09-02 00:20:21 +02003508#ifdef CONFIG_SND_DEBUG_VERBOSE
Mauro Carvalho Chehab2eda3442008-08-11 10:18:39 +02003509 char tmp[10];
3510 const char *model = NULL;
3511 if (models)
3512 model = models[tbl->value];
3513 if (!model) {
3514 sprintf(tmp, "#%d", tbl->value);
3515 model = tmp;
3516 }
3517 snd_printdd(KERN_INFO "hda_codec: model '%s' is selected "
3518 "for config %x:%x (%s)\n",
3519 model, tbl->subvendor, tbl->subdevice,
3520 (tbl->name ? tbl->name : "Unknown device"));
3521#endif
3522 return tbl->value;
3523 }
3524 return -1;
3525}
3526EXPORT_SYMBOL_HDA(snd_hda_check_board_codec_sid_config);
3527
3528/**
Linus Torvalds1da177e2005-04-16 15:20:36 -07003529 * snd_hda_add_new_ctls - create controls from the array
3530 * @codec: the HDA codec
Takashi Iwaic8b6bf9b2005-11-17 14:57:47 +01003531 * @knew: the array of struct snd_kcontrol_new
Linus Torvalds1da177e2005-04-16 15:20:36 -07003532 *
3533 * This helper function creates and add new controls in the given array.
3534 * The array must be terminated with an empty entry as terminator.
3535 *
3536 * Returns 0 if successful, or a negative error code.
3537 */
Takashi Iwai12f288b2007-08-02 15:51:59 +02003538int snd_hda_add_new_ctls(struct hda_codec *codec, struct snd_kcontrol_new *knew)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003539{
Jaroslav Kysela4d02d1b2009-11-12 10:15:48 +01003540 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003541
3542 for (; knew->name; knew++) {
Takashi Iwai54d17402005-11-21 16:33:22 +01003543 struct snd_kcontrol *kctl;
Jaroslav Kysela5b0cb1d2009-12-08 16:13:32 +01003544 if (knew->iface == -1) /* skip this codec private value */
3545 continue;
Takashi Iwai54d17402005-11-21 16:33:22 +01003546 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;
Jaroslav Kysela3911a4c2009-11-11 13:43:01 +01003549 err = snd_hda_ctl_add(codec, 0, kctl);
Takashi Iwai54d17402005-11-21 16:33:22 +01003550 if (err < 0) {
Takashi Iwai0ba21762007-04-16 11:29:14 +02003551 if (!codec->addr)
Takashi Iwai54d17402005-11-21 16:33:22 +01003552 return err;
3553 kctl = snd_ctl_new1(knew, codec);
Takashi Iwai0ba21762007-04-16 11:29:14 +02003554 if (!kctl)
Takashi Iwai54d17402005-11-21 16:33:22 +01003555 return -ENOMEM;
3556 kctl->id.device = codec->addr;
Jaroslav Kysela3911a4c2009-11-11 13:43:01 +01003557 err = snd_hda_ctl_add(codec, 0, kctl);
Takashi Iwai0ba21762007-04-16 11:29:14 +02003558 if (err < 0)
Takashi Iwai54d17402005-11-21 16:33:22 +01003559 return err;
3560 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003561 }
3562 return 0;
3563}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003564EXPORT_SYMBOL_HDA(snd_hda_add_new_ctls);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003565
Takashi Iwaicb53c622007-08-10 17:21:45 +02003566#ifdef CONFIG_SND_HDA_POWER_SAVE
3567static void hda_set_power_state(struct hda_codec *codec, hda_nid_t fg,
3568 unsigned int power_state);
3569
3570static void hda_power_work(struct work_struct *work)
3571{
3572 struct hda_codec *codec =
3573 container_of(work, struct hda_codec, power_work.work);
Takashi Iwai33fa35e2008-11-06 16:50:40 +01003574 struct hda_bus *bus = codec->bus;
Takashi Iwaicb53c622007-08-10 17:21:45 +02003575
Maxim Levitsky2e492462007-09-03 15:26:57 +02003576 if (!codec->power_on || codec->power_count) {
3577 codec->power_transition = 0;
Takashi Iwaicb53c622007-08-10 17:21:45 +02003578 return;
Maxim Levitsky2e492462007-09-03 15:26:57 +02003579 }
Takashi Iwaicb53c622007-08-10 17:21:45 +02003580
3581 hda_call_codec_suspend(codec);
Takashi Iwai33fa35e2008-11-06 16:50:40 +01003582 if (bus->ops.pm_notify)
3583 bus->ops.pm_notify(bus);
Takashi Iwaicb53c622007-08-10 17:21:45 +02003584}
3585
3586static void hda_keep_power_on(struct hda_codec *codec)
3587{
3588 codec->power_count++;
3589 codec->power_on = 1;
Takashi Iwaia2f63092009-11-11 09:34:25 +01003590 codec->power_jiffies = jiffies;
3591}
3592
Takashi Iwaid5191e52009-11-16 14:58:17 +01003593/* update the power on/off account with the current jiffies */
Takashi Iwaia2f63092009-11-11 09:34:25 +01003594void snd_hda_update_power_acct(struct hda_codec *codec)
3595{
3596 unsigned long delta = jiffies - codec->power_jiffies;
3597 if (codec->power_on)
3598 codec->power_on_acct += delta;
3599 else
3600 codec->power_off_acct += delta;
3601 codec->power_jiffies += delta;
Takashi Iwaicb53c622007-08-10 17:21:45 +02003602}
3603
Takashi Iwaid5191e52009-11-16 14:58:17 +01003604/**
3605 * snd_hda_power_up - Power-up the codec
3606 * @codec: HD-audio codec
3607 *
3608 * Increment the power-up counter and power up the hardware really when
3609 * not turned on yet.
3610 */
Takashi Iwaicb53c622007-08-10 17:21:45 +02003611void snd_hda_power_up(struct hda_codec *codec)
3612{
Takashi Iwai33fa35e2008-11-06 16:50:40 +01003613 struct hda_bus *bus = codec->bus;
3614
Takashi Iwaicb53c622007-08-10 17:21:45 +02003615 codec->power_count++;
Takashi Iwaia221e282007-08-16 16:35:33 +02003616 if (codec->power_on || codec->power_transition)
Takashi Iwaicb53c622007-08-10 17:21:45 +02003617 return;
3618
Takashi Iwaia2f63092009-11-11 09:34:25 +01003619 snd_hda_update_power_acct(codec);
Takashi Iwaicb53c622007-08-10 17:21:45 +02003620 codec->power_on = 1;
Takashi Iwaia2f63092009-11-11 09:34:25 +01003621 codec->power_jiffies = jiffies;
Takashi Iwai33fa35e2008-11-06 16:50:40 +01003622 if (bus->ops.pm_notify)
3623 bus->ops.pm_notify(bus);
Takashi Iwaicb53c622007-08-10 17:21:45 +02003624 hda_call_codec_resume(codec);
3625 cancel_delayed_work(&codec->power_work);
Takashi Iwaia221e282007-08-16 16:35:33 +02003626 codec->power_transition = 0;
Takashi Iwaicb53c622007-08-10 17:21:45 +02003627}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003628EXPORT_SYMBOL_HDA(snd_hda_power_up);
Takashi Iwai1289e9e2008-11-27 15:47:11 +01003629
3630#define power_save(codec) \
3631 ((codec)->bus->power_save ? *(codec)->bus->power_save : 0)
Takashi Iwaicb53c622007-08-10 17:21:45 +02003632
Takashi Iwaid5191e52009-11-16 14:58:17 +01003633/**
3634 * snd_hda_power_down - Power-down the codec
3635 * @codec: HD-audio codec
3636 *
3637 * Decrement the power-up counter and schedules the power-off work if
3638 * the counter rearches to zero.
3639 */
Takashi Iwaicb53c622007-08-10 17:21:45 +02003640void snd_hda_power_down(struct hda_codec *codec)
3641{
3642 --codec->power_count;
Takashi Iwaia221e282007-08-16 16:35:33 +02003643 if (!codec->power_on || codec->power_count || codec->power_transition)
Takashi Iwaicb53c622007-08-10 17:21:45 +02003644 return;
Takashi Iwaifee2fba2008-11-27 12:43:28 +01003645 if (power_save(codec)) {
Takashi Iwaia221e282007-08-16 16:35:33 +02003646 codec->power_transition = 1; /* avoid reentrance */
Takashi Iwaic107b412009-01-13 17:46:37 +01003647 queue_delayed_work(codec->bus->workq, &codec->power_work,
Takashi Iwaifee2fba2008-11-27 12:43:28 +01003648 msecs_to_jiffies(power_save(codec) * 1000));
Takashi Iwaia221e282007-08-16 16:35:33 +02003649 }
Takashi Iwaicb53c622007-08-10 17:21:45 +02003650}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003651EXPORT_SYMBOL_HDA(snd_hda_power_down);
Takashi Iwaicb53c622007-08-10 17:21:45 +02003652
Takashi Iwaid5191e52009-11-16 14:58:17 +01003653/**
3654 * snd_hda_check_amp_list_power - Check the amp list and update the power
3655 * @codec: HD-audio codec
3656 * @check: the object containing an AMP list and the status
3657 * @nid: NID to check / update
3658 *
3659 * Check whether the given NID is in the amp list. If it's in the list,
3660 * check the current AMP status, and update the the power-status according
3661 * to the mute status.
3662 *
3663 * This function is supposed to be set or called from the check_power_status
3664 * patch ops.
3665 */
Takashi Iwaicb53c622007-08-10 17:21:45 +02003666int snd_hda_check_amp_list_power(struct hda_codec *codec,
3667 struct hda_loopback_check *check,
3668 hda_nid_t nid)
3669{
3670 struct hda_amp_list *p;
3671 int ch, v;
3672
3673 if (!check->amplist)
3674 return 0;
3675 for (p = check->amplist; p->nid; p++) {
3676 if (p->nid == nid)
3677 break;
3678 }
3679 if (!p->nid)
3680 return 0; /* nothing changed */
3681
3682 for (p = check->amplist; p->nid; p++) {
3683 for (ch = 0; ch < 2; ch++) {
3684 v = snd_hda_codec_amp_read(codec, p->nid, ch, p->dir,
3685 p->idx);
3686 if (!(v & HDA_AMP_MUTE) && v > 0) {
3687 if (!check->power_on) {
3688 check->power_on = 1;
3689 snd_hda_power_up(codec);
3690 }
3691 return 1;
3692 }
3693 }
3694 }
3695 if (check->power_on) {
3696 check->power_on = 0;
3697 snd_hda_power_down(codec);
3698 }
3699 return 0;
3700}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003701EXPORT_SYMBOL_HDA(snd_hda_check_amp_list_power);
Takashi Iwaicb53c622007-08-10 17:21:45 +02003702#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07003703
Takashi Iwaic8b6bf9b2005-11-17 14:57:47 +01003704/*
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01003705 * Channel mode helper
3706 */
Takashi Iwaid5191e52009-11-16 14:58:17 +01003707
3708/**
3709 * snd_hda_ch_mode_info - Info callback helper for the channel mode enum
3710 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003711int snd_hda_ch_mode_info(struct hda_codec *codec,
3712 struct snd_ctl_elem_info *uinfo,
3713 const struct hda_channel_mode *chmode,
3714 int num_chmodes)
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01003715{
3716 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
3717 uinfo->count = 1;
3718 uinfo->value.enumerated.items = num_chmodes;
3719 if (uinfo->value.enumerated.item >= num_chmodes)
3720 uinfo->value.enumerated.item = num_chmodes - 1;
3721 sprintf(uinfo->value.enumerated.name, "%dch",
3722 chmode[uinfo->value.enumerated.item].channels);
3723 return 0;
3724}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003725EXPORT_SYMBOL_HDA(snd_hda_ch_mode_info);
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01003726
Takashi Iwaid5191e52009-11-16 14:58:17 +01003727/**
3728 * snd_hda_ch_mode_get - Get callback helper for the channel mode enum
3729 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003730int snd_hda_ch_mode_get(struct hda_codec *codec,
3731 struct snd_ctl_elem_value *ucontrol,
3732 const struct hda_channel_mode *chmode,
3733 int num_chmodes,
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01003734 int max_channels)
3735{
3736 int i;
3737
3738 for (i = 0; i < num_chmodes; i++) {
3739 if (max_channels == chmode[i].channels) {
3740 ucontrol->value.enumerated.item[0] = i;
3741 break;
3742 }
3743 }
3744 return 0;
3745}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003746EXPORT_SYMBOL_HDA(snd_hda_ch_mode_get);
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01003747
Takashi Iwaid5191e52009-11-16 14:58:17 +01003748/**
3749 * snd_hda_ch_mode_put - Put callback helper for the channel mode enum
3750 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003751int snd_hda_ch_mode_put(struct hda_codec *codec,
3752 struct snd_ctl_elem_value *ucontrol,
3753 const struct hda_channel_mode *chmode,
3754 int num_chmodes,
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01003755 int *max_channelsp)
3756{
3757 unsigned int mode;
3758
3759 mode = ucontrol->value.enumerated.item[0];
Takashi Iwai68ea7b22007-11-15 15:54:38 +01003760 if (mode >= num_chmodes)
3761 return -EINVAL;
Takashi Iwai82beb8f2007-08-10 17:09:26 +02003762 if (*max_channelsp == chmode[mode].channels)
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01003763 return 0;
3764 /* change the current channel setting */
3765 *max_channelsp = chmode[mode].channels;
3766 if (chmode[mode].sequence)
Takashi Iwai82beb8f2007-08-10 17:09:26 +02003767 snd_hda_sequence_write_cache(codec, chmode[mode].sequence);
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01003768 return 1;
3769}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003770EXPORT_SYMBOL_HDA(snd_hda_ch_mode_put);
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01003771
Linus Torvalds1da177e2005-04-16 15:20:36 -07003772/*
3773 * input MUX helper
3774 */
Takashi Iwaid5191e52009-11-16 14:58:17 +01003775
3776/**
3777 * snd_hda_input_mux_info_info - Info callback helper for the input-mux enum
3778 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003779int snd_hda_input_mux_info(const struct hda_input_mux *imux,
3780 struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003781{
3782 unsigned int index;
3783
3784 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
3785 uinfo->count = 1;
3786 uinfo->value.enumerated.items = imux->num_items;
Takashi Iwai5513b0c2007-10-09 11:58:41 +02003787 if (!imux->num_items)
3788 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003789 index = uinfo->value.enumerated.item;
3790 if (index >= imux->num_items)
3791 index = imux->num_items - 1;
3792 strcpy(uinfo->value.enumerated.name, imux->items[index].label);
3793 return 0;
3794}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003795EXPORT_SYMBOL_HDA(snd_hda_input_mux_info);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003796
Takashi Iwaid5191e52009-11-16 14:58:17 +01003797/**
3798 * snd_hda_input_mux_info_put - Put callback helper for the input-mux enum
3799 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003800int snd_hda_input_mux_put(struct hda_codec *codec,
3801 const struct hda_input_mux *imux,
3802 struct snd_ctl_elem_value *ucontrol,
3803 hda_nid_t nid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003804 unsigned int *cur_val)
3805{
3806 unsigned int idx;
3807
Takashi Iwai5513b0c2007-10-09 11:58:41 +02003808 if (!imux->num_items)
3809 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003810 idx = ucontrol->value.enumerated.item[0];
3811 if (idx >= imux->num_items)
3812 idx = imux->num_items - 1;
Takashi Iwai82beb8f2007-08-10 17:09:26 +02003813 if (*cur_val == idx)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003814 return 0;
Takashi Iwai82beb8f2007-08-10 17:09:26 +02003815 snd_hda_codec_write_cache(codec, nid, 0, AC_VERB_SET_CONNECT_SEL,
3816 imux->items[idx].index);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003817 *cur_val = idx;
3818 return 1;
3819}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003820EXPORT_SYMBOL_HDA(snd_hda_input_mux_put);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003821
3822
3823/*
3824 * Multi-channel / digital-out PCM helper functions
3825 */
3826
Takashi Iwai6b97eb42007-04-05 14:51:48 +02003827/* setup SPDIF output stream */
3828static void setup_dig_out_stream(struct hda_codec *codec, hda_nid_t nid,
3829 unsigned int stream_tag, unsigned int format)
3830{
3831 /* turn off SPDIF once; otherwise the IEC958 bits won't be updated */
Takashi Iwai2f728532008-09-25 16:32:41 +02003832 if (codec->spdif_status_reset && (codec->spdif_ctls & AC_DIG1_ENABLE))
3833 set_dig_out_convert(codec, nid,
3834 codec->spdif_ctls & ~AC_DIG1_ENABLE & 0xff,
3835 -1);
Takashi Iwai6b97eb42007-04-05 14:51:48 +02003836 snd_hda_codec_setup_stream(codec, nid, stream_tag, 0, format);
Takashi Iwai2f728532008-09-25 16:32:41 +02003837 if (codec->slave_dig_outs) {
3838 hda_nid_t *d;
3839 for (d = codec->slave_dig_outs; *d; d++)
3840 snd_hda_codec_setup_stream(codec, *d, stream_tag, 0,
3841 format);
Matthew Ranostayde51ca12008-09-07 14:31:40 -04003842 }
Takashi Iwai2f728532008-09-25 16:32:41 +02003843 /* turn on again (if needed) */
3844 if (codec->spdif_status_reset && (codec->spdif_ctls & AC_DIG1_ENABLE))
3845 set_dig_out_convert(codec, nid,
3846 codec->spdif_ctls & 0xff, -1);
3847}
Matthew Ranostayde51ca12008-09-07 14:31:40 -04003848
Takashi Iwai2f728532008-09-25 16:32:41 +02003849static void cleanup_dig_out_stream(struct hda_codec *codec, hda_nid_t nid)
3850{
3851 snd_hda_codec_cleanup_stream(codec, nid);
3852 if (codec->slave_dig_outs) {
3853 hda_nid_t *d;
3854 for (d = codec->slave_dig_outs; *d; d++)
3855 snd_hda_codec_cleanup_stream(codec, *d);
3856 }
Takashi Iwai6b97eb42007-04-05 14:51:48 +02003857}
3858
Takashi Iwaid5191e52009-11-16 14:58:17 +01003859/**
3860 * snd_hda_bus_reboot_notify - call the reboot notifier of each codec
3861 * @bus: HD-audio bus
3862 */
Takashi Iwaifb8d1a32009-11-10 16:02:29 +01003863void snd_hda_bus_reboot_notify(struct hda_bus *bus)
3864{
3865 struct hda_codec *codec;
3866
3867 if (!bus)
3868 return;
3869 list_for_each_entry(codec, &bus->codec_list, list) {
3870#ifdef CONFIG_SND_HDA_POWER_SAVE
3871 if (!codec->power_on)
3872 continue;
3873#endif
3874 if (codec->patch_ops.reboot_notify)
3875 codec->patch_ops.reboot_notify(codec);
3876 }
3877}
Takashi Iwai8f217a22009-11-10 18:26:12 +01003878EXPORT_SYMBOL_HDA(snd_hda_bus_reboot_notify);
Takashi Iwaifb8d1a32009-11-10 16:02:29 +01003879
Takashi Iwaid5191e52009-11-16 14:58:17 +01003880/**
3881 * snd_hda_multi_out_dig_open - open the digital out in the exclusive mode
Linus Torvalds1da177e2005-04-16 15:20:36 -07003882 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003883int snd_hda_multi_out_dig_open(struct hda_codec *codec,
3884 struct hda_multi_out *mout)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003885{
Ingo Molnar62932df2006-01-16 16:34:20 +01003886 mutex_lock(&codec->spdif_mutex);
Takashi Iwai5930ca42007-04-16 11:23:56 +02003887 if (mout->dig_out_used == HDA_DIG_ANALOG_DUP)
3888 /* already opened as analog dup; reset it once */
Takashi Iwai2f728532008-09-25 16:32:41 +02003889 cleanup_dig_out_stream(codec, mout->dig_out_nid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003890 mout->dig_out_used = HDA_DIG_EXCLUSIVE;
Ingo Molnar62932df2006-01-16 16:34:20 +01003891 mutex_unlock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003892 return 0;
3893}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003894EXPORT_SYMBOL_HDA(snd_hda_multi_out_dig_open);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003895
Takashi Iwaid5191e52009-11-16 14:58:17 +01003896/**
3897 * snd_hda_multi_out_dig_prepare - prepare the digital out stream
3898 */
Takashi Iwai6b97eb42007-04-05 14:51:48 +02003899int snd_hda_multi_out_dig_prepare(struct hda_codec *codec,
3900 struct hda_multi_out *mout,
3901 unsigned int stream_tag,
3902 unsigned int format,
3903 struct snd_pcm_substream *substream)
3904{
3905 mutex_lock(&codec->spdif_mutex);
3906 setup_dig_out_stream(codec, mout->dig_out_nid, stream_tag, format);
3907 mutex_unlock(&codec->spdif_mutex);
3908 return 0;
3909}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003910EXPORT_SYMBOL_HDA(snd_hda_multi_out_dig_prepare);
Takashi Iwai6b97eb42007-04-05 14:51:48 +02003911
Takashi Iwaid5191e52009-11-16 14:58:17 +01003912/**
3913 * snd_hda_multi_out_dig_cleanup - clean-up the digital out stream
3914 */
Takashi Iwai9411e212009-02-13 11:32:28 +01003915int snd_hda_multi_out_dig_cleanup(struct hda_codec *codec,
3916 struct hda_multi_out *mout)
3917{
3918 mutex_lock(&codec->spdif_mutex);
3919 cleanup_dig_out_stream(codec, mout->dig_out_nid);
3920 mutex_unlock(&codec->spdif_mutex);
3921 return 0;
3922}
3923EXPORT_SYMBOL_HDA(snd_hda_multi_out_dig_cleanup);
3924
Takashi Iwaid5191e52009-11-16 14:58:17 +01003925/**
3926 * snd_hda_multi_out_dig_close - release the digital out stream
Linus Torvalds1da177e2005-04-16 15:20:36 -07003927 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003928int snd_hda_multi_out_dig_close(struct hda_codec *codec,
3929 struct hda_multi_out *mout)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003930{
Ingo Molnar62932df2006-01-16 16:34:20 +01003931 mutex_lock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003932 mout->dig_out_used = 0;
Ingo Molnar62932df2006-01-16 16:34:20 +01003933 mutex_unlock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003934 return 0;
3935}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003936EXPORT_SYMBOL_HDA(snd_hda_multi_out_dig_close);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003937
Takashi Iwaid5191e52009-11-16 14:58:17 +01003938/**
3939 * snd_hda_multi_out_analog_open - open analog outputs
3940 *
3941 * Open analog outputs and set up the hw-constraints.
3942 * If the digital outputs can be opened as slave, open the digital
3943 * outputs, too.
Linus Torvalds1da177e2005-04-16 15:20:36 -07003944 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003945int snd_hda_multi_out_analog_open(struct hda_codec *codec,
3946 struct hda_multi_out *mout,
Takashi Iwai9a081602008-02-12 18:37:26 +01003947 struct snd_pcm_substream *substream,
3948 struct hda_pcm_stream *hinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003949{
Takashi Iwai9a081602008-02-12 18:37:26 +01003950 struct snd_pcm_runtime *runtime = substream->runtime;
3951 runtime->hw.channels_max = mout->max_channels;
3952 if (mout->dig_out_nid) {
3953 if (!mout->analog_rates) {
3954 mout->analog_rates = hinfo->rates;
3955 mout->analog_formats = hinfo->formats;
3956 mout->analog_maxbps = hinfo->maxbps;
3957 } else {
3958 runtime->hw.rates = mout->analog_rates;
3959 runtime->hw.formats = mout->analog_formats;
3960 hinfo->maxbps = mout->analog_maxbps;
3961 }
3962 if (!mout->spdif_rates) {
3963 snd_hda_query_supported_pcm(codec, mout->dig_out_nid,
3964 &mout->spdif_rates,
3965 &mout->spdif_formats,
3966 &mout->spdif_maxbps);
3967 }
3968 mutex_lock(&codec->spdif_mutex);
3969 if (mout->share_spdif) {
Takashi Iwai022b4662009-07-03 23:03:30 +02003970 if ((runtime->hw.rates & mout->spdif_rates) &&
3971 (runtime->hw.formats & mout->spdif_formats)) {
3972 runtime->hw.rates &= mout->spdif_rates;
3973 runtime->hw.formats &= mout->spdif_formats;
3974 if (mout->spdif_maxbps < hinfo->maxbps)
3975 hinfo->maxbps = mout->spdif_maxbps;
3976 } else {
3977 mout->share_spdif = 0;
3978 /* FIXME: need notify? */
3979 }
Takashi Iwai9a081602008-02-12 18:37:26 +01003980 }
Frederik Deweerdteaa99852008-04-14 13:11:44 +02003981 mutex_unlock(&codec->spdif_mutex);
Takashi Iwai9a081602008-02-12 18:37:26 +01003982 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003983 return snd_pcm_hw_constraint_step(substream->runtime, 0,
3984 SNDRV_PCM_HW_PARAM_CHANNELS, 2);
3985}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003986EXPORT_SYMBOL_HDA(snd_hda_multi_out_analog_open);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003987
Takashi Iwaid5191e52009-11-16 14:58:17 +01003988/**
3989 * snd_hda_multi_out_analog_prepare - Preapre the analog outputs.
3990 *
3991 * Set up the i/o for analog out.
3992 * When the digital out is available, copy the front out to digital out, too.
Linus Torvalds1da177e2005-04-16 15:20:36 -07003993 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003994int snd_hda_multi_out_analog_prepare(struct hda_codec *codec,
3995 struct hda_multi_out *mout,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003996 unsigned int stream_tag,
3997 unsigned int format,
Takashi Iwaic8b6bf9b2005-11-17 14:57:47 +01003998 struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003999{
4000 hda_nid_t *nids = mout->dac_nids;
4001 int chs = substream->runtime->channels;
4002 int i;
4003
Ingo Molnar62932df2006-01-16 16:34:20 +01004004 mutex_lock(&codec->spdif_mutex);
Takashi Iwai9a081602008-02-12 18:37:26 +01004005 if (mout->dig_out_nid && mout->share_spdif &&
4006 mout->dig_out_used != HDA_DIG_EXCLUSIVE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004007 if (chs == 2 &&
Takashi Iwai0ba21762007-04-16 11:29:14 +02004008 snd_hda_is_supported_format(codec, mout->dig_out_nid,
4009 format) &&
4010 !(codec->spdif_status & IEC958_AES0_NONAUDIO)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004011 mout->dig_out_used = HDA_DIG_ANALOG_DUP;
Takashi Iwai6b97eb42007-04-05 14:51:48 +02004012 setup_dig_out_stream(codec, mout->dig_out_nid,
4013 stream_tag, format);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004014 } else {
4015 mout->dig_out_used = 0;
Takashi Iwai2f728532008-09-25 16:32:41 +02004016 cleanup_dig_out_stream(codec, mout->dig_out_nid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004017 }
4018 }
Ingo Molnar62932df2006-01-16 16:34:20 +01004019 mutex_unlock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004020
4021 /* front */
Takashi Iwai0ba21762007-04-16 11:29:14 +02004022 snd_hda_codec_setup_stream(codec, nids[HDA_FRONT], stream_tag,
4023 0, format);
Takashi Iwaid29240c2007-10-26 12:35:56 +02004024 if (!mout->no_share_stream &&
4025 mout->hp_nid && mout->hp_nid != nids[HDA_FRONT])
Linus Torvalds1da177e2005-04-16 15:20:36 -07004026 /* headphone out will just decode front left/right (stereo) */
Takashi Iwai0ba21762007-04-16 11:29:14 +02004027 snd_hda_codec_setup_stream(codec, mout->hp_nid, stream_tag,
4028 0, format);
Takashi Iwai82bc9552006-03-21 11:24:42 +01004029 /* extra outputs copied from front */
4030 for (i = 0; i < ARRAY_SIZE(mout->extra_out_nid); i++)
Takashi Iwaid29240c2007-10-26 12:35:56 +02004031 if (!mout->no_share_stream && mout->extra_out_nid[i])
Takashi Iwai82bc9552006-03-21 11:24:42 +01004032 snd_hda_codec_setup_stream(codec,
4033 mout->extra_out_nid[i],
4034 stream_tag, 0, format);
4035
Linus Torvalds1da177e2005-04-16 15:20:36 -07004036 /* surrounds */
4037 for (i = 1; i < mout->num_dacs; i++) {
Takashi Iwai4b3acaf2005-06-10 19:48:10 +02004038 if (chs >= (i + 1) * 2) /* independent out */
Takashi Iwai0ba21762007-04-16 11:29:14 +02004039 snd_hda_codec_setup_stream(codec, nids[i], stream_tag,
4040 i * 2, format);
Takashi Iwaid29240c2007-10-26 12:35:56 +02004041 else if (!mout->no_share_stream) /* copy front */
Takashi Iwai0ba21762007-04-16 11:29:14 +02004042 snd_hda_codec_setup_stream(codec, nids[i], stream_tag,
4043 0, format);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004044 }
4045 return 0;
4046}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01004047EXPORT_SYMBOL_HDA(snd_hda_multi_out_analog_prepare);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004048
Takashi Iwaid5191e52009-11-16 14:58:17 +01004049/**
4050 * snd_hda_multi_out_analog_cleanup - clean up the setting for analog out
Linus Torvalds1da177e2005-04-16 15:20:36 -07004051 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02004052int snd_hda_multi_out_analog_cleanup(struct hda_codec *codec,
4053 struct hda_multi_out *mout)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004054{
4055 hda_nid_t *nids = mout->dac_nids;
4056 int i;
4057
4058 for (i = 0; i < mout->num_dacs; i++)
Takashi Iwai888afa12008-03-18 09:57:50 +01004059 snd_hda_codec_cleanup_stream(codec, nids[i]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004060 if (mout->hp_nid)
Takashi Iwai888afa12008-03-18 09:57:50 +01004061 snd_hda_codec_cleanup_stream(codec, mout->hp_nid);
Takashi Iwai82bc9552006-03-21 11:24:42 +01004062 for (i = 0; i < ARRAY_SIZE(mout->extra_out_nid); i++)
4063 if (mout->extra_out_nid[i])
Takashi Iwai888afa12008-03-18 09:57:50 +01004064 snd_hda_codec_cleanup_stream(codec,
4065 mout->extra_out_nid[i]);
Ingo Molnar62932df2006-01-16 16:34:20 +01004066 mutex_lock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004067 if (mout->dig_out_nid && mout->dig_out_used == HDA_DIG_ANALOG_DUP) {
Takashi Iwai2f728532008-09-25 16:32:41 +02004068 cleanup_dig_out_stream(codec, mout->dig_out_nid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004069 mout->dig_out_used = 0;
4070 }
Ingo Molnar62932df2006-01-16 16:34:20 +01004071 mutex_unlock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004072 return 0;
4073}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01004074EXPORT_SYMBOL_HDA(snd_hda_multi_out_analog_cleanup);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004075
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004076/*
Wu Fengguang6b345002008-10-07 14:21:41 +08004077 * Helper for automatic pin configuration
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004078 */
Kailang Yangdf694da2005-12-05 19:42:22 +01004079
Takashi Iwai12f288b2007-08-02 15:51:59 +02004080static int is_in_nid_list(hda_nid_t nid, hda_nid_t *list)
Kailang Yangdf694da2005-12-05 19:42:22 +01004081{
4082 for (; *list; list++)
4083 if (*list == nid)
4084 return 1;
4085 return 0;
4086}
4087
Steve Longerbeam81937d32007-05-08 15:33:03 +02004088
4089/*
4090 * Sort an associated group of pins according to their sequence numbers.
4091 */
4092static void sort_pins_by_sequence(hda_nid_t * pins, short * sequences,
4093 int num_pins)
4094{
4095 int i, j;
4096 short seq;
4097 hda_nid_t nid;
4098
4099 for (i = 0; i < num_pins; i++) {
4100 for (j = i + 1; j < num_pins; j++) {
4101 if (sequences[i] > sequences[j]) {
4102 seq = sequences[i];
4103 sequences[i] = sequences[j];
4104 sequences[j] = seq;
4105 nid = pins[i];
4106 pins[i] = pins[j];
4107 pins[j] = nid;
4108 }
4109 }
4110 }
4111}
4112
4113
Takashi Iwai82bc9552006-03-21 11:24:42 +01004114/*
4115 * Parse all pin widgets and store the useful pin nids to cfg
4116 *
4117 * The number of line-outs or any primary output is stored in line_outs,
4118 * and the corresponding output pins are assigned to line_out_pins[],
4119 * in the order of front, rear, CLFE, side, ...
4120 *
4121 * If more extra outputs (speaker and headphone) are found, the pins are
Takashi Iwaieb06ed82006-09-20 17:10:27 +02004122 * assisnged to hp_pins[] and speaker_pins[], respectively. If no line-out jack
Takashi Iwai82bc9552006-03-21 11:24:42 +01004123 * is detected, one of speaker of HP pins is assigned as the primary
4124 * output, i.e. to line_out_pins[0]. So, line_outs is always positive
4125 * if any analog output exists.
4126 *
4127 * The analog input pins are assigned to input_pins array.
4128 * The digital input/output pins are assigned to dig_in_pin and dig_out_pin,
4129 * respectively.
4130 */
Takashi Iwai12f288b2007-08-02 15:51:59 +02004131int snd_hda_parse_pin_def_config(struct hda_codec *codec,
4132 struct auto_pin_cfg *cfg,
4133 hda_nid_t *ignore_nids)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004134{
Takashi Iwai0ef6ce72008-01-22 15:35:37 +01004135 hda_nid_t nid, end_nid;
Steve Longerbeam81937d32007-05-08 15:33:03 +02004136 short seq, assoc_line_out, assoc_speaker;
4137 short sequences_line_out[ARRAY_SIZE(cfg->line_out_pins)];
4138 short sequences_speaker[ARRAY_SIZE(cfg->speaker_pins)];
Takashi Iwaif889fa92007-10-31 15:49:32 +01004139 short sequences_hp[ARRAY_SIZE(cfg->hp_pins)];
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004140
4141 memset(cfg, 0, sizeof(*cfg));
4142
Steve Longerbeam81937d32007-05-08 15:33:03 +02004143 memset(sequences_line_out, 0, sizeof(sequences_line_out));
4144 memset(sequences_speaker, 0, sizeof(sequences_speaker));
Takashi Iwaif889fa92007-10-31 15:49:32 +01004145 memset(sequences_hp, 0, sizeof(sequences_hp));
Steve Longerbeam81937d32007-05-08 15:33:03 +02004146 assoc_line_out = assoc_speaker = 0;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004147
Takashi Iwai0ef6ce72008-01-22 15:35:37 +01004148 end_nid = codec->start_nid + codec->num_nodes;
4149 for (nid = codec->start_nid; nid < end_nid; nid++) {
Takashi Iwai54d17402005-11-21 16:33:22 +01004150 unsigned int wid_caps = get_wcaps(codec, nid);
Takashi Iwaia22d5432009-07-27 12:54:26 +02004151 unsigned int wid_type = get_wcaps_type(wid_caps);
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004152 unsigned int def_conf;
4153 short assoc, loc;
4154
4155 /* read all default configuration for pin complex */
4156 if (wid_type != AC_WID_PIN)
4157 continue;
Kailang Yangdf694da2005-12-05 19:42:22 +01004158 /* ignore the given nids (e.g. pc-beep returns error) */
4159 if (ignore_nids && is_in_nid_list(nid, ignore_nids))
4160 continue;
4161
Takashi Iwaic17a1ab2009-02-23 09:28:12 +01004162 def_conf = snd_hda_codec_get_pincfg(codec, nid);
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004163 if (get_defcfg_connect(def_conf) == AC_JACK_PORT_NONE)
4164 continue;
4165 loc = get_defcfg_location(def_conf);
4166 switch (get_defcfg_device(def_conf)) {
4167 case AC_JACK_LINE_OUT:
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004168 seq = get_defcfg_sequence(def_conf);
4169 assoc = get_defcfg_association(def_conf);
Matthew Ranostay90da78b2008-01-24 11:48:01 +01004170
4171 if (!(wid_caps & AC_WCAP_STEREO))
4172 if (!cfg->mono_out_pin)
4173 cfg->mono_out_pin = nid;
Takashi Iwai0ba21762007-04-16 11:29:14 +02004174 if (!assoc)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004175 continue;
Takashi Iwai0ba21762007-04-16 11:29:14 +02004176 if (!assoc_line_out)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004177 assoc_line_out = assoc;
4178 else if (assoc_line_out != assoc)
4179 continue;
4180 if (cfg->line_outs >= ARRAY_SIZE(cfg->line_out_pins))
4181 continue;
4182 cfg->line_out_pins[cfg->line_outs] = nid;
Steve Longerbeam81937d32007-05-08 15:33:03 +02004183 sequences_line_out[cfg->line_outs] = seq;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004184 cfg->line_outs++;
4185 break;
Takashi Iwai8d88bc32005-11-17 11:09:23 +01004186 case AC_JACK_SPEAKER:
Steve Longerbeam81937d32007-05-08 15:33:03 +02004187 seq = get_defcfg_sequence(def_conf);
4188 assoc = get_defcfg_association(def_conf);
4189 if (! assoc)
4190 continue;
4191 if (! assoc_speaker)
4192 assoc_speaker = assoc;
4193 else if (assoc_speaker != assoc)
4194 continue;
Takashi Iwai82bc9552006-03-21 11:24:42 +01004195 if (cfg->speaker_outs >= ARRAY_SIZE(cfg->speaker_pins))
4196 continue;
4197 cfg->speaker_pins[cfg->speaker_outs] = nid;
Steve Longerbeam81937d32007-05-08 15:33:03 +02004198 sequences_speaker[cfg->speaker_outs] = seq;
Takashi Iwai82bc9552006-03-21 11:24:42 +01004199 cfg->speaker_outs++;
Takashi Iwai8d88bc32005-11-17 11:09:23 +01004200 break;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004201 case AC_JACK_HP_OUT:
Takashi Iwaif889fa92007-10-31 15:49:32 +01004202 seq = get_defcfg_sequence(def_conf);
4203 assoc = get_defcfg_association(def_conf);
Takashi Iwaieb06ed82006-09-20 17:10:27 +02004204 if (cfg->hp_outs >= ARRAY_SIZE(cfg->hp_pins))
4205 continue;
4206 cfg->hp_pins[cfg->hp_outs] = nid;
Takashi Iwaif889fa92007-10-31 15:49:32 +01004207 sequences_hp[cfg->hp_outs] = (assoc << 4) | seq;
Takashi Iwaieb06ed82006-09-20 17:10:27 +02004208 cfg->hp_outs++;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004209 break;
Takashi Iwai314634b2006-09-21 11:56:18 +02004210 case AC_JACK_MIC_IN: {
4211 int preferred, alt;
4212 if (loc == AC_JACK_LOC_FRONT) {
4213 preferred = AUTO_PIN_FRONT_MIC;
4214 alt = AUTO_PIN_MIC;
4215 } else {
4216 preferred = AUTO_PIN_MIC;
4217 alt = AUTO_PIN_FRONT_MIC;
4218 }
4219 if (!cfg->input_pins[preferred])
4220 cfg->input_pins[preferred] = nid;
4221 else if (!cfg->input_pins[alt])
4222 cfg->input_pins[alt] = nid;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004223 break;
Takashi Iwai314634b2006-09-21 11:56:18 +02004224 }
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004225 case AC_JACK_LINE_IN:
4226 if (loc == AC_JACK_LOC_FRONT)
4227 cfg->input_pins[AUTO_PIN_FRONT_LINE] = nid;
4228 else
4229 cfg->input_pins[AUTO_PIN_LINE] = nid;
4230 break;
4231 case AC_JACK_CD:
4232 cfg->input_pins[AUTO_PIN_CD] = nid;
4233 break;
4234 case AC_JACK_AUX:
4235 cfg->input_pins[AUTO_PIN_AUX] = nid;
4236 break;
4237 case AC_JACK_SPDIF_OUT:
Takashi Iwai1b52ae72009-01-20 17:17:29 +01004238 case AC_JACK_DIG_OTHER_OUT:
Takashi Iwai0852d7a2009-02-11 11:35:15 +01004239 if (cfg->dig_outs >= ARRAY_SIZE(cfg->dig_out_pins))
4240 continue;
4241 cfg->dig_out_pins[cfg->dig_outs] = nid;
4242 cfg->dig_out_type[cfg->dig_outs] =
4243 (loc == AC_JACK_LOC_HDMI) ?
4244 HDA_PCM_TYPE_HDMI : HDA_PCM_TYPE_SPDIF;
4245 cfg->dig_outs++;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004246 break;
4247 case AC_JACK_SPDIF_IN:
Takashi Iwai1b52ae72009-01-20 17:17:29 +01004248 case AC_JACK_DIG_OTHER_IN:
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004249 cfg->dig_in_pin = nid;
Takashi Iwai2297bd62009-01-20 18:24:13 +01004250 if (loc == AC_JACK_LOC_HDMI)
4251 cfg->dig_in_type = HDA_PCM_TYPE_HDMI;
4252 else
4253 cfg->dig_in_type = HDA_PCM_TYPE_SPDIF;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004254 break;
4255 }
4256 }
4257
Takashi Iwai5832fcf2008-02-12 18:30:12 +01004258 /* FIX-UP:
4259 * If no line-out is defined but multiple HPs are found,
4260 * some of them might be the real line-outs.
4261 */
4262 if (!cfg->line_outs && cfg->hp_outs > 1) {
4263 int i = 0;
4264 while (i < cfg->hp_outs) {
4265 /* The real HPs should have the sequence 0x0f */
4266 if ((sequences_hp[i] & 0x0f) == 0x0f) {
4267 i++;
4268 continue;
4269 }
4270 /* Move it to the line-out table */
4271 cfg->line_out_pins[cfg->line_outs] = cfg->hp_pins[i];
4272 sequences_line_out[cfg->line_outs] = sequences_hp[i];
4273 cfg->line_outs++;
4274 cfg->hp_outs--;
4275 memmove(cfg->hp_pins + i, cfg->hp_pins + i + 1,
4276 sizeof(cfg->hp_pins[0]) * (cfg->hp_outs - i));
4277 memmove(sequences_hp + i - 1, sequences_hp + i,
4278 sizeof(sequences_hp[0]) * (cfg->hp_outs - i));
4279 }
4280 }
4281
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004282 /* sort by sequence */
Steve Longerbeam81937d32007-05-08 15:33:03 +02004283 sort_pins_by_sequence(cfg->line_out_pins, sequences_line_out,
4284 cfg->line_outs);
4285 sort_pins_by_sequence(cfg->speaker_pins, sequences_speaker,
4286 cfg->speaker_outs);
Takashi Iwaif889fa92007-10-31 15:49:32 +01004287 sort_pins_by_sequence(cfg->hp_pins, sequences_hp,
4288 cfg->hp_outs);
Steve Longerbeam81937d32007-05-08 15:33:03 +02004289
Takashi Iwaif889fa92007-10-31 15:49:32 +01004290 /* if we have only one mic, make it AUTO_PIN_MIC */
4291 if (!cfg->input_pins[AUTO_PIN_MIC] &&
4292 cfg->input_pins[AUTO_PIN_FRONT_MIC]) {
4293 cfg->input_pins[AUTO_PIN_MIC] =
4294 cfg->input_pins[AUTO_PIN_FRONT_MIC];
4295 cfg->input_pins[AUTO_PIN_FRONT_MIC] = 0;
4296 }
4297 /* ditto for line-in */
4298 if (!cfg->input_pins[AUTO_PIN_LINE] &&
4299 cfg->input_pins[AUTO_PIN_FRONT_LINE]) {
4300 cfg->input_pins[AUTO_PIN_LINE] =
4301 cfg->input_pins[AUTO_PIN_FRONT_LINE];
4302 cfg->input_pins[AUTO_PIN_FRONT_LINE] = 0;
4303 }
4304
Steve Longerbeam81937d32007-05-08 15:33:03 +02004305 /*
4306 * FIX-UP: if no line-outs are detected, try to use speaker or HP pin
4307 * as a primary output
4308 */
4309 if (!cfg->line_outs) {
4310 if (cfg->speaker_outs) {
4311 cfg->line_outs = cfg->speaker_outs;
4312 memcpy(cfg->line_out_pins, cfg->speaker_pins,
4313 sizeof(cfg->speaker_pins));
4314 cfg->speaker_outs = 0;
4315 memset(cfg->speaker_pins, 0, sizeof(cfg->speaker_pins));
4316 cfg->line_out_type = AUTO_PIN_SPEAKER_OUT;
4317 } else if (cfg->hp_outs) {
4318 cfg->line_outs = cfg->hp_outs;
4319 memcpy(cfg->line_out_pins, cfg->hp_pins,
4320 sizeof(cfg->hp_pins));
4321 cfg->hp_outs = 0;
4322 memset(cfg->hp_pins, 0, sizeof(cfg->hp_pins));
4323 cfg->line_out_type = AUTO_PIN_HP_OUT;
4324 }
4325 }
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004326
Takashi Iwaicb8e2f82005-07-29 11:54:32 +02004327 /* Reorder the surround channels
4328 * ALSA sequence is front/surr/clfe/side
4329 * HDA sequence is:
4330 * 4-ch: front/surr => OK as it is
4331 * 6-ch: front/clfe/surr
Takashi Iwai9422db42007-04-20 16:11:43 +02004332 * 8-ch: front/clfe/rear/side|fc
Takashi Iwaicb8e2f82005-07-29 11:54:32 +02004333 */
4334 switch (cfg->line_outs) {
4335 case 3:
Takashi Iwaicb8e2f82005-07-29 11:54:32 +02004336 case 4:
4337 nid = cfg->line_out_pins[1];
Takashi Iwai9422db42007-04-20 16:11:43 +02004338 cfg->line_out_pins[1] = cfg->line_out_pins[2];
Takashi Iwaicb8e2f82005-07-29 11:54:32 +02004339 cfg->line_out_pins[2] = nid;
4340 break;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004341 }
4342
Takashi Iwai82bc9552006-03-21 11:24:42 +01004343 /*
4344 * debug prints of the parsed results
4345 */
4346 snd_printd("autoconfig: line_outs=%d (0x%x/0x%x/0x%x/0x%x/0x%x)\n",
4347 cfg->line_outs, cfg->line_out_pins[0], cfg->line_out_pins[1],
4348 cfg->line_out_pins[2], cfg->line_out_pins[3],
4349 cfg->line_out_pins[4]);
4350 snd_printd(" speaker_outs=%d (0x%x/0x%x/0x%x/0x%x/0x%x)\n",
4351 cfg->speaker_outs, cfg->speaker_pins[0],
4352 cfg->speaker_pins[1], cfg->speaker_pins[2],
4353 cfg->speaker_pins[3], cfg->speaker_pins[4]);
Takashi Iwaieb06ed82006-09-20 17:10:27 +02004354 snd_printd(" hp_outs=%d (0x%x/0x%x/0x%x/0x%x/0x%x)\n",
4355 cfg->hp_outs, cfg->hp_pins[0],
4356 cfg->hp_pins[1], cfg->hp_pins[2],
4357 cfg->hp_pins[3], cfg->hp_pins[4]);
Matthew Ranostay90da78b2008-01-24 11:48:01 +01004358 snd_printd(" mono: mono_out=0x%x\n", cfg->mono_out_pin);
Takashi Iwai0852d7a2009-02-11 11:35:15 +01004359 if (cfg->dig_outs)
4360 snd_printd(" dig-out=0x%x/0x%x\n",
4361 cfg->dig_out_pins[0], cfg->dig_out_pins[1]);
Takashi Iwai82bc9552006-03-21 11:24:42 +01004362 snd_printd(" inputs: mic=0x%x, fmic=0x%x, line=0x%x, fline=0x%x,"
4363 " cd=0x%x, aux=0x%x\n",
4364 cfg->input_pins[AUTO_PIN_MIC],
4365 cfg->input_pins[AUTO_PIN_FRONT_MIC],
4366 cfg->input_pins[AUTO_PIN_LINE],
4367 cfg->input_pins[AUTO_PIN_FRONT_LINE],
4368 cfg->input_pins[AUTO_PIN_CD],
4369 cfg->input_pins[AUTO_PIN_AUX]);
Takashi Iwai32d2c7f2009-02-11 11:33:13 +01004370 if (cfg->dig_in_pin)
Takashi Iwai89ce9e82009-01-20 17:15:57 +01004371 snd_printd(" dig-in=0x%x\n", cfg->dig_in_pin);
Takashi Iwai82bc9552006-03-21 11:24:42 +01004372
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004373 return 0;
4374}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01004375EXPORT_SYMBOL_HDA(snd_hda_parse_pin_def_config);
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004376
Takashi Iwai4a471b72005-12-07 13:56:29 +01004377/* labels for input pins */
4378const char *auto_pin_cfg_labels[AUTO_PIN_LAST] = {
4379 "Mic", "Front Mic", "Line", "Front Line", "CD", "Aux"
4380};
Takashi Iwaiff7a3262008-11-28 15:17:06 +01004381EXPORT_SYMBOL_HDA(auto_pin_cfg_labels);
Takashi Iwai4a471b72005-12-07 13:56:29 +01004382
4383
Linus Torvalds1da177e2005-04-16 15:20:36 -07004384#ifdef CONFIG_PM
4385/*
4386 * power management
4387 */
4388
4389/**
4390 * snd_hda_suspend - suspend the codecs
4391 * @bus: the HDA bus
Linus Torvalds1da177e2005-04-16 15:20:36 -07004392 *
4393 * Returns 0 if successful.
4394 */
Takashi Iwai8dd78332009-06-02 01:16:07 +02004395int snd_hda_suspend(struct hda_bus *bus)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004396{
Takashi Iwai0ba21762007-04-16 11:29:14 +02004397 struct hda_codec *codec;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004398
Takashi Iwai0ba21762007-04-16 11:29:14 +02004399 list_for_each_entry(codec, &bus->codec_list, list) {
Takashi Iwai0b7a2e92007-08-14 15:18:26 +02004400#ifdef CONFIG_SND_HDA_POWER_SAVE
4401 if (!codec->power_on)
4402 continue;
4403#endif
Takashi Iwaicb53c622007-08-10 17:21:45 +02004404 hda_call_codec_suspend(codec);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004405 }
4406 return 0;
4407}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01004408EXPORT_SYMBOL_HDA(snd_hda_suspend);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004409
4410/**
4411 * snd_hda_resume - resume the codecs
4412 * @bus: the HDA bus
Linus Torvalds1da177e2005-04-16 15:20:36 -07004413 *
4414 * Returns 0 if successful.
Takashi Iwaicb53c622007-08-10 17:21:45 +02004415 *
4416 * This fucntion is defined only when POWER_SAVE isn't set.
4417 * In the power-save mode, the codec is resumed dynamically.
Linus Torvalds1da177e2005-04-16 15:20:36 -07004418 */
4419int snd_hda_resume(struct hda_bus *bus)
4420{
Takashi Iwai0ba21762007-04-16 11:29:14 +02004421 struct hda_codec *codec;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004422
Takashi Iwai0ba21762007-04-16 11:29:14 +02004423 list_for_each_entry(codec, &bus->codec_list, list) {
Maxim Levitskyd804ad92007-09-03 15:28:04 +02004424 if (snd_hda_codec_needs_resume(codec))
4425 hda_call_codec_resume(codec);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004426 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004427 return 0;
4428}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01004429EXPORT_SYMBOL_HDA(snd_hda_resume);
Takashi Iwai1289e9e2008-11-27 15:47:11 +01004430#endif /* CONFIG_PM */
Takashi Iwaib2e18592008-07-30 15:01:44 +02004431
4432/*
4433 * generic arrays
4434 */
4435
Takashi Iwaid5191e52009-11-16 14:58:17 +01004436/**
4437 * snd_array_new - get a new element from the given array
4438 * @array: the array object
4439 *
4440 * Get a new element from the given array. If it exceeds the
4441 * pre-allocated array size, re-allocate the array.
4442 *
4443 * Returns NULL if allocation failed.
Takashi Iwaib2e18592008-07-30 15:01:44 +02004444 */
4445void *snd_array_new(struct snd_array *array)
4446{
4447 if (array->used >= array->alloced) {
4448 int num = array->alloced + array->alloc_align;
Takashi Iwaib910d9a2008-11-07 00:26:52 +01004449 void *nlist;
4450 if (snd_BUG_ON(num >= 4096))
4451 return NULL;
4452 nlist = kcalloc(num + 1, array->elem_size, GFP_KERNEL);
Takashi Iwaib2e18592008-07-30 15:01:44 +02004453 if (!nlist)
4454 return NULL;
4455 if (array->list) {
4456 memcpy(nlist, array->list,
4457 array->elem_size * array->alloced);
4458 kfree(array->list);
4459 }
4460 array->list = nlist;
4461 array->alloced = num;
4462 }
Takashi Iwaif43aa022008-11-10 16:24:26 +01004463 return snd_array_elem(array, array->used++);
Takashi Iwaib2e18592008-07-30 15:01:44 +02004464}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01004465EXPORT_SYMBOL_HDA(snd_array_new);
Takashi Iwaib2e18592008-07-30 15:01:44 +02004466
Takashi Iwaid5191e52009-11-16 14:58:17 +01004467/**
4468 * snd_array_free - free the given array elements
4469 * @array: the array object
4470 */
Takashi Iwaib2e18592008-07-30 15:01:44 +02004471void snd_array_free(struct snd_array *array)
4472{
4473 kfree(array->list);
4474 array->used = 0;
4475 array->alloced = 0;
4476 array->list = NULL;
4477}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01004478EXPORT_SYMBOL_HDA(snd_array_free);
Takashi Iwaib2022262008-11-21 21:24:03 +01004479
Takashi Iwaid5191e52009-11-16 14:58:17 +01004480/**
4481 * snd_print_pcm_rates - Print the supported PCM rates to the string buffer
4482 * @pcm: PCM caps bits
4483 * @buf: the string buffer to write
4484 * @buflen: the max buffer length
4485 *
Takashi Iwaib2022262008-11-21 21:24:03 +01004486 * used by hda_proc.c and hda_eld.c
4487 */
4488void snd_print_pcm_rates(int pcm, char *buf, int buflen)
4489{
4490 static unsigned int rates[] = {
4491 8000, 11025, 16000, 22050, 32000, 44100, 48000, 88200,
4492 96000, 176400, 192000, 384000
4493 };
4494 int i, j;
4495
4496 for (i = 0, j = 0; i < ARRAY_SIZE(rates); i++)
4497 if (pcm & (1 << i))
4498 j += snprintf(buf + j, buflen - j, " %d", rates[i]);
4499
4500 buf[j] = '\0'; /* necessary when j == 0 */
4501}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01004502EXPORT_SYMBOL_HDA(snd_print_pcm_rates);
Takashi Iwaib2022262008-11-21 21:24:03 +01004503
Takashi Iwaid5191e52009-11-16 14:58:17 +01004504/**
4505 * snd_print_pcm_bits - Print the supported PCM fmt bits to the string buffer
4506 * @pcm: PCM caps bits
4507 * @buf: the string buffer to write
4508 * @buflen: the max buffer length
4509 *
4510 * used by hda_proc.c and hda_eld.c
4511 */
Takashi Iwaib2022262008-11-21 21:24:03 +01004512void snd_print_pcm_bits(int pcm, char *buf, int buflen)
4513{
4514 static unsigned int bits[] = { 8, 16, 20, 24, 32 };
4515 int i, j;
4516
4517 for (i = 0, j = 0; i < ARRAY_SIZE(bits); i++)
4518 if (pcm & (AC_SUPPCM_BITS_8 << i))
4519 j += snprintf(buf + j, buflen - j, " %d", bits[i]);
4520
4521 buf[j] = '\0'; /* necessary when j == 0 */
4522}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01004523EXPORT_SYMBOL_HDA(snd_print_pcm_bits);
Takashi Iwai1289e9e2008-11-27 15:47:11 +01004524
4525MODULE_DESCRIPTION("HDA codec core");
4526MODULE_LICENSE("GPL");