blob: b8c656c21feb35599af0cba73dcc5a3846a1046b [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"
Takashi Iwai28073142007-07-27 18:58:06 +020033#include <sound/hda_hwdep.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070034
Linus Torvalds1da177e2005-04-16 15:20:36 -070035/*
36 * vendor / preset table
37 */
38
39struct hda_vendor_id {
40 unsigned int id;
41 const char *name;
42};
43
44/* codec vendor labels */
45static struct hda_vendor_id hda_vendor_ids[] = {
Takashi Iwaic8cd1282008-02-13 16:59:29 +010046 { 0x1002, "ATI" },
Takashi Iwaia9226252006-09-17 22:05:54 +020047 { 0x1057, "Motorola" },
Takashi Iwaic8cd1282008-02-13 16:59:29 +010048 { 0x1095, "Silicon Image" },
Takashi Iwai31117b72008-12-16 14:43:21 +010049 { 0x10de, "Nvidia" },
Takashi Iwaic8cd1282008-02-13 16:59:29 +010050 { 0x10ec, "Realtek" },
Takashi Iwai4e01f542009-04-16 08:53:34 +020051 { 0x1102, "Creative" },
Joseph Chanc577b8a2006-11-29 15:29:40 +010052 { 0x1106, "VIA" },
Matthew Ranostay7f168592007-10-18 17:38:17 +020053 { 0x111d, "IDT" },
Takashi Iwaic8cd1282008-02-13 16:59:29 +010054 { 0x11c1, "LSI" },
Takashi Iwai54b903e2005-05-15 14:30:10 +020055 { 0x11d4, "Analog Devices" },
Linus Torvalds1da177e2005-04-16 15:20:36 -070056 { 0x13f6, "C-Media" },
Takashi Iwaia9226252006-09-17 22:05:54 +020057 { 0x14f1, "Conexant" },
Takashi Iwaic8cd1282008-02-13 16:59:29 +010058 { 0x17e8, "Chrontel" },
59 { 0x1854, "LG" },
Mark Brown8199de32008-10-28 14:50:13 +000060 { 0x1aec, "Wolfson Microelectronics" },
Linus Torvalds1da177e2005-04-16 15:20:36 -070061 { 0x434d, "C-Media" },
Takashi Iwai74c61132008-12-18 09:11:33 +010062 { 0x8086, "Intel" },
Matt2f2f4252005-04-13 14:45:30 +020063 { 0x8384, "SigmaTel" },
Linus Torvalds1da177e2005-04-16 15:20:36 -070064 {} /* terminator */
65};
66
Takashi Iwai1289e9e2008-11-27 15:47:11 +010067static DEFINE_MUTEX(preset_mutex);
68static LIST_HEAD(hda_preset_tables);
69
70int snd_hda_add_codec_preset(struct hda_codec_preset_list *preset)
71{
72 mutex_lock(&preset_mutex);
73 list_add_tail(&preset->list, &hda_preset_tables);
74 mutex_unlock(&preset_mutex);
75 return 0;
76}
Takashi Iwaiff7a3262008-11-28 15:17:06 +010077EXPORT_SYMBOL_HDA(snd_hda_add_codec_preset);
Takashi Iwai1289e9e2008-11-27 15:47:11 +010078
79int snd_hda_delete_codec_preset(struct hda_codec_preset_list *preset)
80{
81 mutex_lock(&preset_mutex);
82 list_del(&preset->list);
83 mutex_unlock(&preset_mutex);
84 return 0;
85}
Takashi Iwaiff7a3262008-11-28 15:17:06 +010086EXPORT_SYMBOL_HDA(snd_hda_delete_codec_preset);
Linus Torvalds1da177e2005-04-16 15:20:36 -070087
Takashi Iwaicb53c622007-08-10 17:21:45 +020088#ifdef CONFIG_SND_HDA_POWER_SAVE
89static void hda_power_work(struct work_struct *work);
90static void hda_keep_power_on(struct hda_codec *codec);
91#else
92static inline void hda_keep_power_on(struct hda_codec *codec) {}
93#endif
94
Matthew Ranostay50a9f792008-10-25 01:05:45 -040095const char *snd_hda_get_jack_location(u32 cfg)
96{
97 static char *bases[7] = {
98 "N/A", "Rear", "Front", "Left", "Right", "Top", "Bottom",
99 };
100 static unsigned char specials_idx[] = {
101 0x07, 0x08,
102 0x17, 0x18, 0x19,
103 0x37, 0x38
104 };
105 static char *specials[] = {
106 "Rear Panel", "Drive Bar",
107 "Riser", "HDMI", "ATAPI",
108 "Mobile-In", "Mobile-Out"
109 };
110 int i;
111 cfg = (cfg & AC_DEFCFG_LOCATION) >> AC_DEFCFG_LOCATION_SHIFT;
112 if ((cfg & 0x0f) < 7)
113 return bases[cfg & 0x0f];
114 for (i = 0; i < ARRAY_SIZE(specials_idx); i++) {
115 if (cfg == specials_idx[i])
116 return specials[i];
117 }
118 return "UNKNOWN";
119}
Takashi Iwaiff7a3262008-11-28 15:17:06 +0100120EXPORT_SYMBOL_HDA(snd_hda_get_jack_location);
Matthew Ranostay50a9f792008-10-25 01:05:45 -0400121
122const char *snd_hda_get_jack_connectivity(u32 cfg)
123{
124 static char *jack_locations[4] = { "Ext", "Int", "Sep", "Oth" };
125
126 return jack_locations[(cfg >> (AC_DEFCFG_LOCATION_SHIFT + 4)) & 3];
127}
Takashi Iwaiff7a3262008-11-28 15:17:06 +0100128EXPORT_SYMBOL_HDA(snd_hda_get_jack_connectivity);
Matthew Ranostay50a9f792008-10-25 01:05:45 -0400129
130const char *snd_hda_get_jack_type(u32 cfg)
131{
132 static char *jack_types[16] = {
133 "Line Out", "Speaker", "HP Out", "CD",
134 "SPDIF Out", "Digital Out", "Modem Line", "Modem Hand",
135 "Line In", "Aux", "Mic", "Telephony",
136 "SPDIF In", "Digitial In", "Reserved", "Other"
137 };
138
139 return jack_types[(cfg & AC_DEFCFG_DEVICE)
140 >> AC_DEFCFG_DEVICE_SHIFT];
141}
Takashi Iwaiff7a3262008-11-28 15:17:06 +0100142EXPORT_SYMBOL_HDA(snd_hda_get_jack_type);
Matthew Ranostay50a9f792008-10-25 01:05:45 -0400143
Takashi Iwai33fa35e2008-11-06 16:50:40 +0100144/*
145 * Compose a 32bit command word to be sent to the HD-audio controller
146 */
147static inline unsigned int
148make_codec_cmd(struct hda_codec *codec, hda_nid_t nid, int direct,
149 unsigned int verb, unsigned int parm)
150{
151 u32 val;
152
Takashi Iwai82e1b802009-07-17 12:47:34 +0200153 if ((codec->addr & ~0xf) || (direct & ~1) || (nid & ~0x7f) ||
154 (verb & ~0xfff) || (parm & ~0xffff)) {
Wu Fengguang6430aee2009-07-17 16:49:19 +0800155 printk(KERN_ERR "hda-codec: out of range cmd %x:%x:%x:%x:%x\n",
156 codec->addr, direct, nid, verb, parm);
157 return ~0;
158 }
159
160 val = (u32)codec->addr << 28;
Takashi Iwai33fa35e2008-11-06 16:50:40 +0100161 val |= (u32)direct << 27;
162 val |= (u32)nid << 20;
163 val |= verb << 8;
164 val |= parm;
165 return val;
166}
167
Takashi Iwaiaa2936f2009-05-26 16:07:57 +0200168/*
169 * Send and receive a verb
170 */
171static int codec_exec_verb(struct hda_codec *codec, unsigned int cmd,
172 unsigned int *res)
173{
174 struct hda_bus *bus = codec->bus;
Takashi Iwai8dd78332009-06-02 01:16:07 +0200175 int err;
Takashi Iwaiaa2936f2009-05-26 16:07:57 +0200176
Wu Fengguang6430aee2009-07-17 16:49:19 +0800177 if (cmd == ~0)
178 return -1;
179
Takashi Iwaiaa2936f2009-05-26 16:07:57 +0200180 if (res)
181 *res = -1;
Takashi Iwai8dd78332009-06-02 01:16:07 +0200182 again:
Takashi Iwaiaa2936f2009-05-26 16:07:57 +0200183 snd_hda_power_up(codec);
184 mutex_lock(&bus->cmd_mutex);
Takashi Iwaiaa2936f2009-05-26 16:07:57 +0200185 err = bus->ops.command(bus, cmd);
Takashi Iwai8dd78332009-06-02 01:16:07 +0200186 if (!err && res)
187 *res = bus->ops.get_response(bus);
Takashi Iwaiaa2936f2009-05-26 16:07:57 +0200188 mutex_unlock(&bus->cmd_mutex);
189 snd_hda_power_down(codec);
Takashi Iwai8dd78332009-06-02 01:16:07 +0200190 if (res && *res == -1 && bus->rirb_error) {
191 if (bus->response_reset) {
192 snd_printd("hda_codec: resetting BUS due to "
193 "fatal communication error\n");
194 bus->ops.bus_reset(bus);
195 }
196 goto again;
197 }
198 /* clear reset-flag when the communication gets recovered */
199 if (!err)
200 bus->response_reset = 0;
Takashi Iwaiaa2936f2009-05-26 16:07:57 +0200201 return err;
202}
203
Linus Torvalds1da177e2005-04-16 15:20:36 -0700204/**
205 * snd_hda_codec_read - send a command and get the response
206 * @codec: the HDA codec
207 * @nid: NID to send the command
208 * @direct: direct flag
209 * @verb: the verb to send
210 * @parm: the parameter for the verb
211 *
212 * Send a single command and read the corresponding response.
213 *
214 * Returns the obtained response value, or -1 for an error.
215 */
Takashi Iwai0ba21762007-04-16 11:29:14 +0200216unsigned int snd_hda_codec_read(struct hda_codec *codec, hda_nid_t nid,
217 int direct,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700218 unsigned int verb, unsigned int parm)
219{
Takashi Iwaiaa2936f2009-05-26 16:07:57 +0200220 unsigned cmd = make_codec_cmd(codec, nid, direct, verb, parm);
221 unsigned int res;
222 codec_exec_verb(codec, cmd, &res);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700223 return res;
224}
Takashi Iwaiff7a3262008-11-28 15:17:06 +0100225EXPORT_SYMBOL_HDA(snd_hda_codec_read);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700226
227/**
228 * snd_hda_codec_write - send a single command without waiting for 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 without waiting for response.
236 *
237 * Returns 0 if successful, or a negative error code.
238 */
239int snd_hda_codec_write(struct hda_codec *codec, hda_nid_t nid, int direct,
240 unsigned int verb, unsigned int parm)
241{
Takashi Iwaiaa2936f2009-05-26 16:07:57 +0200242 unsigned int cmd = make_codec_cmd(codec, nid, direct, verb, parm);
Takashi Iwai33fa35e2008-11-06 16:50:40 +0100243 unsigned int res;
Takashi Iwaib20f3b82009-06-02 01:20:22 +0200244 return codec_exec_verb(codec, cmd,
245 codec->bus->sync_write ? &res : NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700246}
Takashi Iwaiff7a3262008-11-28 15:17:06 +0100247EXPORT_SYMBOL_HDA(snd_hda_codec_write);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700248
249/**
250 * snd_hda_sequence_write - sequence writes
251 * @codec: the HDA codec
252 * @seq: VERB array to send
253 *
254 * Send the commands sequentially from the given array.
255 * The array must be terminated with NID=0.
256 */
257void snd_hda_sequence_write(struct hda_codec *codec, const struct hda_verb *seq)
258{
259 for (; seq->nid; seq++)
260 snd_hda_codec_write(codec, seq->nid, 0, seq->verb, seq->param);
261}
Takashi Iwaiff7a3262008-11-28 15:17:06 +0100262EXPORT_SYMBOL_HDA(snd_hda_sequence_write);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700263
264/**
265 * snd_hda_get_sub_nodes - get the range of sub nodes
266 * @codec: the HDA codec
267 * @nid: NID to parse
268 * @start_id: the pointer to store the start NID
269 *
270 * Parse the NID and store the start NID of its sub-nodes.
271 * Returns the number of sub-nodes.
272 */
Takashi Iwai0ba21762007-04-16 11:29:14 +0200273int snd_hda_get_sub_nodes(struct hda_codec *codec, hda_nid_t nid,
274 hda_nid_t *start_id)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700275{
276 unsigned int parm;
277
278 parm = snd_hda_param_read(codec, nid, AC_PAR_NODE_COUNT);
Danny Tholene8a7f132007-09-11 21:41:56 +0200279 if (parm == -1)
280 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700281 *start_id = (parm >> 16) & 0x7fff;
282 return (int)(parm & 0x7fff);
283}
Takashi Iwaiff7a3262008-11-28 15:17:06 +0100284EXPORT_SYMBOL_HDA(snd_hda_get_sub_nodes);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700285
286/**
287 * snd_hda_get_connections - get connection list
288 * @codec: the HDA codec
289 * @nid: NID to parse
290 * @conn_list: connection list array
291 * @max_conns: max. number of connections to store
292 *
293 * Parses the connection list of the given widget and stores the list
294 * of NIDs.
295 *
296 * Returns the number of connections, or a negative error code.
297 */
298int snd_hda_get_connections(struct hda_codec *codec, hda_nid_t nid,
299 hda_nid_t *conn_list, int max_conns)
300{
301 unsigned int parm;
Takashi Iwai54d17402005-11-21 16:33:22 +0100302 int i, conn_len, conns;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700303 unsigned int shift, num_elems, mask;
Takashi Iwai54d17402005-11-21 16:33:22 +0100304 hda_nid_t prev_nid;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700305
Takashi Iwaida3cec32008-08-08 17:12:14 +0200306 if (snd_BUG_ON(!conn_list || max_conns <= 0))
307 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700308
Jaroslav Kysela16a433d2009-07-22 16:20:40 +0200309 if ((get_wcaps(codec, nid) & AC_WCAP_CONN_LIST) == 0) {
310 snd_printk(KERN_WARNING "hda_codec: "
311 "connection list not available for 0x%x\n", nid);
312 return -EINVAL;
313 }
314
Linus Torvalds1da177e2005-04-16 15:20:36 -0700315 parm = snd_hda_param_read(codec, nid, AC_PAR_CONNLIST_LEN);
316 if (parm & AC_CLIST_LONG) {
317 /* long form */
318 shift = 16;
319 num_elems = 2;
320 } else {
321 /* short form */
322 shift = 8;
323 num_elems = 4;
324 }
325 conn_len = parm & AC_CLIST_LENGTH;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700326 mask = (1 << (shift-1)) - 1;
327
Takashi Iwai0ba21762007-04-16 11:29:14 +0200328 if (!conn_len)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700329 return 0; /* no connection */
330
331 if (conn_len == 1) {
332 /* single connection */
Takashi Iwai0ba21762007-04-16 11:29:14 +0200333 parm = snd_hda_codec_read(codec, nid, 0,
334 AC_VERB_GET_CONNECT_LIST, 0);
Takashi Iwai3c6aae42009-07-10 12:52:27 +0200335 if (parm == -1 && codec->bus->rirb_error)
336 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700337 conn_list[0] = parm & mask;
338 return 1;
339 }
340
341 /* multi connection */
342 conns = 0;
Takashi Iwai54d17402005-11-21 16:33:22 +0100343 prev_nid = 0;
344 for (i = 0; i < conn_len; i++) {
345 int range_val;
346 hda_nid_t val, n;
347
Takashi Iwai3c6aae42009-07-10 12:52:27 +0200348 if (i % num_elems == 0) {
Takashi Iwai54d17402005-11-21 16:33:22 +0100349 parm = snd_hda_codec_read(codec, nid, 0,
350 AC_VERB_GET_CONNECT_LIST, i);
Takashi Iwai3c6aae42009-07-10 12:52:27 +0200351 if (parm == -1 && codec->bus->rirb_error)
352 return -EIO;
353 }
Takashi Iwai0ba21762007-04-16 11:29:14 +0200354 range_val = !!(parm & (1 << (shift-1))); /* ranges */
Takashi Iwai54d17402005-11-21 16:33:22 +0100355 val = parm & mask;
Jaroslav Kysela2e9bf242009-07-18 11:48:19 +0200356 if (val == 0) {
357 snd_printk(KERN_WARNING "hda_codec: "
358 "invalid CONNECT_LIST verb %x[%i]:%x\n",
359 nid, i, parm);
360 return 0;
361 }
Takashi Iwai54d17402005-11-21 16:33:22 +0100362 parm >>= shift;
363 if (range_val) {
364 /* ranges between the previous and this one */
Takashi Iwai0ba21762007-04-16 11:29:14 +0200365 if (!prev_nid || prev_nid >= val) {
366 snd_printk(KERN_WARNING "hda_codec: "
367 "invalid dep_range_val %x:%x\n",
368 prev_nid, val);
Takashi Iwai54d17402005-11-21 16:33:22 +0100369 continue;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700370 }
Takashi Iwai54d17402005-11-21 16:33:22 +0100371 for (n = prev_nid + 1; n <= val; n++) {
372 if (conns >= max_conns) {
Takashi Iwai0ba21762007-04-16 11:29:14 +0200373 snd_printk(KERN_ERR
374 "Too many connections\n");
Takashi Iwai54d17402005-11-21 16:33:22 +0100375 return -EINVAL;
376 }
377 conn_list[conns++] = n;
378 }
379 } else {
380 if (conns >= max_conns) {
381 snd_printk(KERN_ERR "Too many connections\n");
382 return -EINVAL;
383 }
384 conn_list[conns++] = val;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700385 }
Takashi Iwai54d17402005-11-21 16:33:22 +0100386 prev_nid = val;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700387 }
388 return conns;
389}
Takashi Iwaiff7a3262008-11-28 15:17:06 +0100390EXPORT_SYMBOL_HDA(snd_hda_get_connections);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700391
392
393/**
394 * snd_hda_queue_unsol_event - add an unsolicited event to queue
395 * @bus: the BUS
396 * @res: unsolicited event (lower 32bit of RIRB entry)
397 * @res_ex: codec addr and flags (upper 32bit or RIRB entry)
398 *
399 * Adds the given event to the queue. The events are processed in
400 * the workqueue asynchronously. Call this function in the interrupt
401 * hanlder when RIRB receives an unsolicited event.
402 *
403 * Returns 0 if successful, or a negative error code.
404 */
405int snd_hda_queue_unsol_event(struct hda_bus *bus, u32 res, u32 res_ex)
406{
407 struct hda_bus_unsolicited *unsol;
408 unsigned int wp;
409
Takashi Iwai0ba21762007-04-16 11:29:14 +0200410 unsol = bus->unsol;
411 if (!unsol)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700412 return 0;
413
414 wp = (unsol->wp + 1) % HDA_UNSOL_QUEUE_SIZE;
415 unsol->wp = wp;
416
417 wp <<= 1;
418 unsol->queue[wp] = res;
419 unsol->queue[wp + 1] = res_ex;
420
Takashi Iwai6acaed32009-01-12 10:09:24 +0100421 queue_work(bus->workq, &unsol->work);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700422
423 return 0;
424}
Takashi Iwaiff7a3262008-11-28 15:17:06 +0100425EXPORT_SYMBOL_HDA(snd_hda_queue_unsol_event);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700426
427/*
Wu Fengguang5c1d1a92008-10-07 14:17:53 +0800428 * process queued unsolicited events
Linus Torvalds1da177e2005-04-16 15:20:36 -0700429 */
David Howellsc4028952006-11-22 14:57:56 +0000430static void process_unsol_events(struct work_struct *work)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700431{
David Howellsc4028952006-11-22 14:57:56 +0000432 struct hda_bus_unsolicited *unsol =
433 container_of(work, struct hda_bus_unsolicited, work);
434 struct hda_bus *bus = unsol->bus;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700435 struct hda_codec *codec;
436 unsigned int rp, caddr, res;
437
438 while (unsol->rp != unsol->wp) {
439 rp = (unsol->rp + 1) % HDA_UNSOL_QUEUE_SIZE;
440 unsol->rp = rp;
441 rp <<= 1;
442 res = unsol->queue[rp];
443 caddr = unsol->queue[rp + 1];
Takashi Iwai0ba21762007-04-16 11:29:14 +0200444 if (!(caddr & (1 << 4))) /* no unsolicited event? */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700445 continue;
446 codec = bus->caddr_tbl[caddr & 0x0f];
447 if (codec && codec->patch_ops.unsol_event)
448 codec->patch_ops.unsol_event(codec, res);
449 }
450}
451
452/*
453 * initialize unsolicited queue
454 */
Takashi Iwai6c1f45e2008-07-30 15:01:45 +0200455static int init_unsol_queue(struct hda_bus *bus)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700456{
457 struct hda_bus_unsolicited *unsol;
458
Takashi Iwai9f146bb2005-11-17 11:07:49 +0100459 if (bus->unsol) /* already initialized */
460 return 0;
461
Takashi Iwaie560d8d2005-09-09 14:21:46 +0200462 unsol = kzalloc(sizeof(*unsol), GFP_KERNEL);
Takashi Iwai0ba21762007-04-16 11:29:14 +0200463 if (!unsol) {
464 snd_printk(KERN_ERR "hda_codec: "
465 "can't allocate unsolicited queue\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700466 return -ENOMEM;
467 }
David Howellsc4028952006-11-22 14:57:56 +0000468 INIT_WORK(&unsol->work, process_unsol_events);
469 unsol->bus = bus;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700470 bus->unsol = unsol;
471 return 0;
472}
473
474/*
475 * destructor
476 */
477static void snd_hda_codec_free(struct hda_codec *codec);
478
479static int snd_hda_bus_free(struct hda_bus *bus)
480{
Takashi Iwai0ba21762007-04-16 11:29:14 +0200481 struct hda_codec *codec, *n;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700482
Takashi Iwai0ba21762007-04-16 11:29:14 +0200483 if (!bus)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700484 return 0;
Takashi Iwai6acaed32009-01-12 10:09:24 +0100485 if (bus->workq)
486 flush_workqueue(bus->workq);
487 if (bus->unsol)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700488 kfree(bus->unsol);
Takashi Iwai0ba21762007-04-16 11:29:14 +0200489 list_for_each_entry_safe(codec, n, &bus->codec_list, list) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700490 snd_hda_codec_free(codec);
491 }
492 if (bus->ops.private_free)
493 bus->ops.private_free(bus);
Takashi Iwai6acaed32009-01-12 10:09:24 +0100494 if (bus->workq)
495 destroy_workqueue(bus->workq);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700496 kfree(bus);
497 return 0;
498}
499
Takashi Iwaic8b6bf92005-11-17 14:57:47 +0100500static int snd_hda_bus_dev_free(struct snd_device *device)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700501{
502 struct hda_bus *bus = device->device_data;
Takashi Iwaib94d35392008-11-21 09:08:06 +0100503 bus->shutdown = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700504 return snd_hda_bus_free(bus);
505}
506
Takashi Iwaid7ffba12008-07-30 15:01:46 +0200507#ifdef CONFIG_SND_HDA_HWDEP
508static int snd_hda_bus_dev_register(struct snd_device *device)
509{
510 struct hda_bus *bus = device->device_data;
511 struct hda_codec *codec;
512 list_for_each_entry(codec, &bus->codec_list, list) {
513 snd_hda_hwdep_add_sysfs(codec);
514 }
515 return 0;
516}
517#else
518#define snd_hda_bus_dev_register NULL
519#endif
520
Linus Torvalds1da177e2005-04-16 15:20:36 -0700521/**
522 * snd_hda_bus_new - create a HDA bus
523 * @card: the card entry
524 * @temp: the template for hda_bus information
525 * @busp: the pointer to store the created bus instance
526 *
527 * Returns 0 if successful, or a negative error code.
528 */
Takashi Iwai1289e9e2008-11-27 15:47:11 +0100529int /*__devinit*/ snd_hda_bus_new(struct snd_card *card,
Takashi Iwai756e2b02007-04-16 11:27:07 +0200530 const struct hda_bus_template *temp,
531 struct hda_bus **busp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700532{
533 struct hda_bus *bus;
534 int err;
Takashi Iwaic8b6bf92005-11-17 14:57:47 +0100535 static struct snd_device_ops dev_ops = {
Takashi Iwaid7ffba12008-07-30 15:01:46 +0200536 .dev_register = snd_hda_bus_dev_register,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700537 .dev_free = snd_hda_bus_dev_free,
538 };
539
Takashi Iwaida3cec32008-08-08 17:12:14 +0200540 if (snd_BUG_ON(!temp))
541 return -EINVAL;
542 if (snd_BUG_ON(!temp->ops.command || !temp->ops.get_response))
543 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700544
545 if (busp)
546 *busp = NULL;
547
Takashi Iwaie560d8d2005-09-09 14:21:46 +0200548 bus = kzalloc(sizeof(*bus), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700549 if (bus == NULL) {
550 snd_printk(KERN_ERR "can't allocate struct hda_bus\n");
551 return -ENOMEM;
552 }
553
554 bus->card = card;
555 bus->private_data = temp->private_data;
556 bus->pci = temp->pci;
557 bus->modelname = temp->modelname;
Takashi Iwaifee2fba2008-11-27 12:43:28 +0100558 bus->power_save = temp->power_save;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700559 bus->ops = temp->ops;
560
Ingo Molnar62932df2006-01-16 16:34:20 +0100561 mutex_init(&bus->cmd_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700562 INIT_LIST_HEAD(&bus->codec_list);
563
Takashi Iwaie8c0ee52009-02-05 07:34:28 +0100564 snprintf(bus->workq_name, sizeof(bus->workq_name),
565 "hd-audio%d", card->number);
566 bus->workq = create_singlethread_workqueue(bus->workq_name);
Takashi Iwai6acaed32009-01-12 10:09:24 +0100567 if (!bus->workq) {
Takashi Iwaie8c0ee52009-02-05 07:34:28 +0100568 snd_printk(KERN_ERR "cannot create workqueue %s\n",
569 bus->workq_name);
Takashi Iwai6acaed32009-01-12 10:09:24 +0100570 kfree(bus);
571 return -ENOMEM;
572 }
573
Takashi Iwai0ba21762007-04-16 11:29:14 +0200574 err = snd_device_new(card, SNDRV_DEV_BUS, bus, &dev_ops);
575 if (err < 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700576 snd_hda_bus_free(bus);
577 return err;
578 }
579 if (busp)
580 *busp = bus;
581 return 0;
582}
Takashi Iwaiff7a3262008-11-28 15:17:06 +0100583EXPORT_SYMBOL_HDA(snd_hda_bus_new);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700584
Takashi Iwai82467612007-07-27 19:15:54 +0200585#ifdef CONFIG_SND_HDA_GENERIC
586#define is_generic_config(codec) \
Takashi Iwaif44ac832008-07-30 15:01:45 +0200587 (codec->modelname && !strcmp(codec->modelname, "generic"))
Takashi Iwai82467612007-07-27 19:15:54 +0200588#else
589#define is_generic_config(codec) 0
590#endif
591
Takashi Iwai645f10c2008-11-28 15:07:37 +0100592#ifdef MODULE
Takashi Iwai1289e9e2008-11-27 15:47:11 +0100593#define HDA_MODREQ_MAX_COUNT 2 /* two request_modules()'s */
594#else
Takashi Iwai645f10c2008-11-28 15:07:37 +0100595#define HDA_MODREQ_MAX_COUNT 0 /* all presets are statically linked */
Takashi Iwai1289e9e2008-11-27 15:47:11 +0100596#endif
597
Linus Torvalds1da177e2005-04-16 15:20:36 -0700598/*
599 * find a matching codec preset
600 */
Takashi Iwai6c1f45e2008-07-30 15:01:45 +0200601static const struct hda_codec_preset *
Takashi Iwai756e2b02007-04-16 11:27:07 +0200602find_codec_preset(struct hda_codec *codec)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700603{
Takashi Iwai1289e9e2008-11-27 15:47:11 +0100604 struct hda_codec_preset_list *tbl;
605 const struct hda_codec_preset *preset;
606 int mod_requested = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700607
Takashi Iwai82467612007-07-27 19:15:54 +0200608 if (is_generic_config(codec))
Takashi Iwaid5ad6302007-03-07 15:55:59 +0100609 return NULL; /* use the generic parser */
610
Takashi Iwai1289e9e2008-11-27 15:47:11 +0100611 again:
612 mutex_lock(&preset_mutex);
613 list_for_each_entry(tbl, &hda_preset_tables, list) {
614 if (!try_module_get(tbl->owner)) {
615 snd_printk(KERN_ERR "hda_codec: cannot module_get\n");
616 continue;
617 }
618 for (preset = tbl->preset; preset->id; preset++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700619 u32 mask = preset->mask;
Marc Boucherca7cfae2008-01-22 15:32:25 +0100620 if (preset->afg && preset->afg != codec->afg)
621 continue;
622 if (preset->mfg && preset->mfg != codec->mfg)
623 continue;
Takashi Iwai0ba21762007-04-16 11:29:14 +0200624 if (!mask)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700625 mask = ~0;
Takashi Iwai9c7f8522006-06-28 15:08:22 +0200626 if (preset->id == (codec->vendor_id & mask) &&
Takashi Iwai0ba21762007-04-16 11:29:14 +0200627 (!preset->rev ||
Takashi Iwai1289e9e2008-11-27 15:47:11 +0100628 preset->rev == codec->revision_id)) {
629 mutex_unlock(&preset_mutex);
630 codec->owner = tbl->owner;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700631 return preset;
Takashi Iwai1289e9e2008-11-27 15:47:11 +0100632 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700633 }
Takashi Iwai1289e9e2008-11-27 15:47:11 +0100634 module_put(tbl->owner);
635 }
636 mutex_unlock(&preset_mutex);
637
638 if (mod_requested < HDA_MODREQ_MAX_COUNT) {
639 char name[32];
640 if (!mod_requested)
641 snprintf(name, sizeof(name), "snd-hda-codec-id:%08x",
642 codec->vendor_id);
643 else
644 snprintf(name, sizeof(name), "snd-hda-codec-id:%04x*",
645 (codec->vendor_id >> 16) & 0xffff);
646 request_module(name);
647 mod_requested++;
648 goto again;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700649 }
650 return NULL;
651}
652
653/*
Takashi Iwaif44ac832008-07-30 15:01:45 +0200654 * get_codec_name - store the codec name
Linus Torvalds1da177e2005-04-16 15:20:36 -0700655 */
Takashi Iwaif44ac832008-07-30 15:01:45 +0200656static int get_codec_name(struct hda_codec *codec)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700657{
658 const struct hda_vendor_id *c;
659 const char *vendor = NULL;
660 u16 vendor_id = codec->vendor_id >> 16;
Takashi Iwai812a2cc2009-05-16 10:00:49 +0200661 char tmp[16];
662
663 if (codec->vendor_name)
664 goto get_chip_name;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700665
666 for (c = hda_vendor_ids; c->id; c++) {
667 if (c->id == vendor_id) {
668 vendor = c->name;
669 break;
670 }
671 }
Takashi Iwai0ba21762007-04-16 11:29:14 +0200672 if (!vendor) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700673 sprintf(tmp, "Generic %04x", vendor_id);
674 vendor = tmp;
675 }
Takashi Iwai812a2cc2009-05-16 10:00:49 +0200676 codec->vendor_name = kstrdup(vendor, GFP_KERNEL);
677 if (!codec->vendor_name)
678 return -ENOMEM;
679
680 get_chip_name:
681 if (codec->chip_name)
682 return 0;
683
Linus Torvalds1da177e2005-04-16 15:20:36 -0700684 if (codec->preset && codec->preset->name)
Takashi Iwai812a2cc2009-05-16 10:00:49 +0200685 codec->chip_name = kstrdup(codec->preset->name, GFP_KERNEL);
686 else {
687 sprintf(tmp, "ID %x", codec->vendor_id & 0xffff);
688 codec->chip_name = kstrdup(tmp, GFP_KERNEL);
689 }
690 if (!codec->chip_name)
Takashi Iwaif44ac832008-07-30 15:01:45 +0200691 return -ENOMEM;
692 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700693}
694
695/*
Sasha Khapyorsky673b6832005-08-11 11:00:16 +0200696 * look for an AFG and MFG nodes
Linus Torvalds1da177e2005-04-16 15:20:36 -0700697 */
Takashi Iwai1289e9e2008-11-27 15:47:11 +0100698static void /*__devinit*/ setup_fg_nodes(struct hda_codec *codec)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700699{
Takashi Iwai93e82ae2009-04-17 18:04:41 +0200700 int i, total_nodes, function_id;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700701 hda_nid_t nid;
702
703 total_nodes = snd_hda_get_sub_nodes(codec, AC_NODE_ROOT, &nid);
704 for (i = 0; i < total_nodes; i++, nid++) {
Takashi Iwai93e82ae2009-04-17 18:04:41 +0200705 function_id = snd_hda_param_read(codec, nid,
Pascal de Bruijn234b4342009-03-23 11:15:59 +0100706 AC_PAR_FUNCTION_TYPE) & 0xff;
Takashi Iwai93e82ae2009-04-17 18:04:41 +0200707 switch (function_id) {
Sasha Khapyorsky673b6832005-08-11 11:00:16 +0200708 case AC_GRP_AUDIO_FUNCTION:
709 codec->afg = nid;
Takashi Iwai93e82ae2009-04-17 18:04:41 +0200710 codec->function_id = function_id;
Sasha Khapyorsky673b6832005-08-11 11:00:16 +0200711 break;
712 case AC_GRP_MODEM_FUNCTION:
713 codec->mfg = nid;
Takashi Iwai93e82ae2009-04-17 18:04:41 +0200714 codec->function_id = function_id;
Sasha Khapyorsky673b6832005-08-11 11:00:16 +0200715 break;
716 default:
717 break;
718 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700719 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700720}
721
722/*
Takashi Iwai54d17402005-11-21 16:33:22 +0100723 * read widget caps for each widget and store in cache
724 */
725static int read_widget_caps(struct hda_codec *codec, hda_nid_t fg_node)
726{
727 int i;
728 hda_nid_t nid;
729
730 codec->num_nodes = snd_hda_get_sub_nodes(codec, fg_node,
731 &codec->start_nid);
732 codec->wcaps = kmalloc(codec->num_nodes * 4, GFP_KERNEL);
Takashi Iwai0ba21762007-04-16 11:29:14 +0200733 if (!codec->wcaps)
Takashi Iwai54d17402005-11-21 16:33:22 +0100734 return -ENOMEM;
735 nid = codec->start_nid;
736 for (i = 0; i < codec->num_nodes; i++, nid++)
737 codec->wcaps[i] = snd_hda_param_read(codec, nid,
738 AC_PAR_AUDIO_WIDGET_CAP);
739 return 0;
740}
741
Takashi Iwai3be14142009-02-20 14:11:16 +0100742/* read all pin default configurations and save codec->init_pins */
743static int read_pin_defaults(struct hda_codec *codec)
744{
745 int i;
746 hda_nid_t nid = codec->start_nid;
747
748 for (i = 0; i < codec->num_nodes; i++, nid++) {
749 struct hda_pincfg *pin;
750 unsigned int wcaps = get_wcaps(codec, nid);
Takashi Iwaia22d5432009-07-27 12:54:26 +0200751 unsigned int wid_type = get_wcaps_type(wcaps);
Takashi Iwai3be14142009-02-20 14:11:16 +0100752 if (wid_type != AC_WID_PIN)
753 continue;
754 pin = snd_array_new(&codec->init_pins);
755 if (!pin)
756 return -ENOMEM;
757 pin->nid = nid;
758 pin->cfg = snd_hda_codec_read(codec, nid, 0,
759 AC_VERB_GET_CONFIG_DEFAULT, 0);
760 }
761 return 0;
762}
763
764/* look up the given pin config list and return the item matching with NID */
765static struct hda_pincfg *look_up_pincfg(struct hda_codec *codec,
766 struct snd_array *array,
767 hda_nid_t nid)
768{
769 int i;
770 for (i = 0; i < array->used; i++) {
771 struct hda_pincfg *pin = snd_array_elem(array, i);
772 if (pin->nid == nid)
773 return pin;
774 }
775 return NULL;
776}
777
778/* write a config value for the given NID */
779static void set_pincfg(struct hda_codec *codec, hda_nid_t nid,
780 unsigned int cfg)
781{
782 int i;
783 for (i = 0; i < 4; i++) {
784 snd_hda_codec_write(codec, nid, 0,
785 AC_VERB_SET_CONFIG_DEFAULT_BYTES_0 + i,
786 cfg & 0xff);
787 cfg >>= 8;
788 }
789}
790
791/* set the current pin config value for the given NID.
792 * the value is cached, and read via snd_hda_codec_get_pincfg()
793 */
794int snd_hda_add_pincfg(struct hda_codec *codec, struct snd_array *list,
795 hda_nid_t nid, unsigned int cfg)
796{
797 struct hda_pincfg *pin;
Takashi Iwai5e7b8e02009-02-23 09:45:59 +0100798 unsigned int oldcfg;
Takashi Iwai3be14142009-02-20 14:11:16 +0100799
Takashi Iwai5e7b8e02009-02-23 09:45:59 +0100800 oldcfg = snd_hda_codec_get_pincfg(codec, nid);
Takashi Iwai3be14142009-02-20 14:11:16 +0100801 pin = look_up_pincfg(codec, list, nid);
802 if (!pin) {
803 pin = snd_array_new(list);
804 if (!pin)
805 return -ENOMEM;
806 pin->nid = nid;
807 }
808 pin->cfg = cfg;
Takashi Iwai5e7b8e02009-02-23 09:45:59 +0100809
810 /* change only when needed; e.g. if the pincfg is already present
811 * in user_pins[], don't write it
812 */
813 cfg = snd_hda_codec_get_pincfg(codec, nid);
814 if (oldcfg != cfg)
815 set_pincfg(codec, nid, cfg);
Takashi Iwai3be14142009-02-20 14:11:16 +0100816 return 0;
817}
818
819int snd_hda_codec_set_pincfg(struct hda_codec *codec,
820 hda_nid_t nid, unsigned int cfg)
821{
Takashi Iwai346ff702009-02-23 09:42:57 +0100822 return snd_hda_add_pincfg(codec, &codec->driver_pins, nid, cfg);
Takashi Iwai3be14142009-02-20 14:11:16 +0100823}
824EXPORT_SYMBOL_HDA(snd_hda_codec_set_pincfg);
825
826/* get the current pin config value of the given pin NID */
827unsigned int snd_hda_codec_get_pincfg(struct hda_codec *codec, hda_nid_t nid)
828{
829 struct hda_pincfg *pin;
830
Takashi Iwai3be14142009-02-20 14:11:16 +0100831#ifdef CONFIG_SND_HDA_HWDEP
Takashi Iwai346ff702009-02-23 09:42:57 +0100832 pin = look_up_pincfg(codec, &codec->user_pins, nid);
Takashi Iwai3be14142009-02-20 14:11:16 +0100833 if (pin)
834 return pin->cfg;
835#endif
Takashi Iwai5e7b8e02009-02-23 09:45:59 +0100836 pin = look_up_pincfg(codec, &codec->driver_pins, nid);
837 if (pin)
838 return pin->cfg;
Takashi Iwai3be14142009-02-20 14:11:16 +0100839 pin = look_up_pincfg(codec, &codec->init_pins, nid);
840 if (pin)
841 return pin->cfg;
842 return 0;
843}
844EXPORT_SYMBOL_HDA(snd_hda_codec_get_pincfg);
845
846/* restore all current pin configs */
847static void restore_pincfgs(struct hda_codec *codec)
848{
849 int i;
850 for (i = 0; i < codec->init_pins.used; i++) {
851 struct hda_pincfg *pin = snd_array_elem(&codec->init_pins, i);
852 set_pincfg(codec, pin->nid,
853 snd_hda_codec_get_pincfg(codec, pin->nid));
854 }
855}
Takashi Iwai54d17402005-11-21 16:33:22 +0100856
Takashi Iwai01751f52007-08-10 16:59:39 +0200857static void init_hda_cache(struct hda_cache_rec *cache,
858 unsigned int record_size);
Takashi Iwai1fcaee62007-08-23 00:01:09 +0200859static void free_hda_cache(struct hda_cache_rec *cache);
Takashi Iwai01751f52007-08-10 16:59:39 +0200860
Takashi Iwai3be14142009-02-20 14:11:16 +0100861/* restore the initial pin cfgs and release all pincfg lists */
862static void restore_init_pincfgs(struct hda_codec *codec)
863{
Takashi Iwai346ff702009-02-23 09:42:57 +0100864 /* first free driver_pins and user_pins, then call restore_pincfg
Takashi Iwai3be14142009-02-20 14:11:16 +0100865 * so that only the values in init_pins are restored
866 */
Takashi Iwai346ff702009-02-23 09:42:57 +0100867 snd_array_free(&codec->driver_pins);
Takashi Iwai3be14142009-02-20 14:11:16 +0100868#ifdef CONFIG_SND_HDA_HWDEP
Takashi Iwai346ff702009-02-23 09:42:57 +0100869 snd_array_free(&codec->user_pins);
Takashi Iwai3be14142009-02-20 14:11:16 +0100870#endif
871 restore_pincfgs(codec);
872 snd_array_free(&codec->init_pins);
873}
874
Takashi Iwai54d17402005-11-21 16:33:22 +0100875/*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700876 * codec destructor
877 */
878static void snd_hda_codec_free(struct hda_codec *codec)
879{
Takashi Iwai0ba21762007-04-16 11:29:14 +0200880 if (!codec)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700881 return;
Takashi Iwai3be14142009-02-20 14:11:16 +0100882 restore_init_pincfgs(codec);
Takashi Iwaicb53c622007-08-10 17:21:45 +0200883#ifdef CONFIG_SND_HDA_POWER_SAVE
884 cancel_delayed_work(&codec->power_work);
Takashi Iwai6acaed32009-01-12 10:09:24 +0100885 flush_workqueue(codec->bus->workq);
Takashi Iwaicb53c622007-08-10 17:21:45 +0200886#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700887 list_del(&codec->list);
Takashi Iwaid13bd412008-07-30 15:01:45 +0200888 snd_array_free(&codec->mixers);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700889 codec->bus->caddr_tbl[codec->addr] = NULL;
890 if (codec->patch_ops.free)
891 codec->patch_ops.free(codec);
Takashi Iwai1289e9e2008-11-27 15:47:11 +0100892 module_put(codec->owner);
Takashi Iwai01751f52007-08-10 16:59:39 +0200893 free_hda_cache(&codec->amp_cache);
Takashi Iwaib3ac5632007-08-10 17:03:40 +0200894 free_hda_cache(&codec->cmd_cache);
Takashi Iwai812a2cc2009-05-16 10:00:49 +0200895 kfree(codec->vendor_name);
896 kfree(codec->chip_name);
Takashi Iwaif44ac832008-07-30 15:01:45 +0200897 kfree(codec->modelname);
Takashi Iwai54d17402005-11-21 16:33:22 +0100898 kfree(codec->wcaps);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700899 kfree(codec);
900}
901
Takashi Iwaibb6ac722009-03-13 09:02:42 +0100902static void hda_set_power_state(struct hda_codec *codec, hda_nid_t fg,
903 unsigned int power_state);
904
Linus Torvalds1da177e2005-04-16 15:20:36 -0700905/**
906 * snd_hda_codec_new - create a HDA codec
907 * @bus: the bus to assign
908 * @codec_addr: the codec address
909 * @codecp: the pointer to store the generated codec
910 *
911 * Returns 0 if successful, or a negative error code.
912 */
Takashi Iwai1289e9e2008-11-27 15:47:11 +0100913int /*__devinit*/ snd_hda_codec_new(struct hda_bus *bus, unsigned int codec_addr,
Takashi Iwaia1e21c92009-06-17 09:33:52 +0200914 struct hda_codec **codecp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700915{
916 struct hda_codec *codec;
Jaroslav Kyselaba443682008-08-13 20:55:32 +0200917 char component[31];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700918 int err;
919
Takashi Iwaida3cec32008-08-08 17:12:14 +0200920 if (snd_BUG_ON(!bus))
921 return -EINVAL;
922 if (snd_BUG_ON(codec_addr > HDA_MAX_CODEC_ADDRESS))
923 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700924
925 if (bus->caddr_tbl[codec_addr]) {
Takashi Iwai0ba21762007-04-16 11:29:14 +0200926 snd_printk(KERN_ERR "hda_codec: "
927 "address 0x%x is already occupied\n", codec_addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700928 return -EBUSY;
929 }
930
Takashi Iwaie560d8d2005-09-09 14:21:46 +0200931 codec = kzalloc(sizeof(*codec), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700932 if (codec == NULL) {
933 snd_printk(KERN_ERR "can't allocate struct hda_codec\n");
934 return -ENOMEM;
935 }
936
937 codec->bus = bus;
938 codec->addr = codec_addr;
Ingo Molnar62932df2006-01-16 16:34:20 +0100939 mutex_init(&codec->spdif_mutex);
Wu Fengguang5a9e02e2009-01-09 16:45:24 +0800940 mutex_init(&codec->control_mutex);
Takashi Iwai01751f52007-08-10 16:59:39 +0200941 init_hda_cache(&codec->amp_cache, sizeof(struct hda_amp_info));
Takashi Iwaib3ac5632007-08-10 17:03:40 +0200942 init_hda_cache(&codec->cmd_cache, sizeof(struct hda_cache_head));
Takashi Iwaid13bd412008-07-30 15:01:45 +0200943 snd_array_init(&codec->mixers, sizeof(struct snd_kcontrol *), 32);
Takashi Iwai3be14142009-02-20 14:11:16 +0100944 snd_array_init(&codec->init_pins, sizeof(struct hda_pincfg), 16);
Takashi Iwai346ff702009-02-23 09:42:57 +0100945 snd_array_init(&codec->driver_pins, sizeof(struct hda_pincfg), 16);
Takashi Iwai6c1f45e2008-07-30 15:01:45 +0200946 if (codec->bus->modelname) {
947 codec->modelname = kstrdup(codec->bus->modelname, GFP_KERNEL);
948 if (!codec->modelname) {
949 snd_hda_codec_free(codec);
950 return -ENODEV;
951 }
952 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700953
Takashi Iwaicb53c622007-08-10 17:21:45 +0200954#ifdef CONFIG_SND_HDA_POWER_SAVE
955 INIT_DELAYED_WORK(&codec->power_work, hda_power_work);
956 /* snd_hda_codec_new() marks the codec as power-up, and leave it as is.
957 * the caller has to power down appropriatley after initialization
958 * phase.
959 */
960 hda_keep_power_on(codec);
961#endif
962
Linus Torvalds1da177e2005-04-16 15:20:36 -0700963 list_add_tail(&codec->list, &bus->codec_list);
964 bus->caddr_tbl[codec_addr] = codec;
965
Takashi Iwai0ba21762007-04-16 11:29:14 +0200966 codec->vendor_id = snd_hda_param_read(codec, AC_NODE_ROOT,
967 AC_PAR_VENDOR_ID);
Takashi Iwai111d3af2006-02-16 18:17:58 +0100968 if (codec->vendor_id == -1)
969 /* read again, hopefully the access method was corrected
970 * in the last read...
971 */
972 codec->vendor_id = snd_hda_param_read(codec, AC_NODE_ROOT,
973 AC_PAR_VENDOR_ID);
Takashi Iwai0ba21762007-04-16 11:29:14 +0200974 codec->subsystem_id = snd_hda_param_read(codec, AC_NODE_ROOT,
975 AC_PAR_SUBSYSTEM_ID);
976 codec->revision_id = snd_hda_param_read(codec, AC_NODE_ROOT,
977 AC_PAR_REV_ID);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700978
Sasha Khapyorsky673b6832005-08-11 11:00:16 +0200979 setup_fg_nodes(codec);
Takashi Iwai0ba21762007-04-16 11:29:14 +0200980 if (!codec->afg && !codec->mfg) {
Sasha Khapyorsky673b6832005-08-11 11:00:16 +0200981 snd_printdd("hda_codec: no AFG or MFG node found\n");
Takashi Iwai3be14142009-02-20 14:11:16 +0100982 err = -ENODEV;
983 goto error;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700984 }
985
Takashi Iwai3be14142009-02-20 14:11:16 +0100986 err = read_widget_caps(codec, codec->afg ? codec->afg : codec->mfg);
987 if (err < 0) {
Takashi Iwai54d17402005-11-21 16:33:22 +0100988 snd_printk(KERN_ERR "hda_codec: cannot malloc\n");
Takashi Iwai3be14142009-02-20 14:11:16 +0100989 goto error;
Takashi Iwai54d17402005-11-21 16:33:22 +0100990 }
Takashi Iwai3be14142009-02-20 14:11:16 +0100991 err = read_pin_defaults(codec);
992 if (err < 0)
993 goto error;
Takashi Iwai54d17402005-11-21 16:33:22 +0100994
Takashi Iwai0ba21762007-04-16 11:29:14 +0200995 if (!codec->subsystem_id) {
Takashi Iwai86284e42005-10-11 15:05:54 +0200996 hda_nid_t nid = codec->afg ? codec->afg : codec->mfg;
Takashi Iwai0ba21762007-04-16 11:29:14 +0200997 codec->subsystem_id =
998 snd_hda_codec_read(codec, nid, 0,
999 AC_VERB_GET_SUBSYSTEM_ID, 0);
Takashi Iwai86284e42005-10-11 15:05:54 +02001000 }
1001
Takashi Iwaibb6ac722009-03-13 09:02:42 +01001002 /* power-up all before initialization */
1003 hda_set_power_state(codec,
1004 codec->afg ? codec->afg : codec->mfg,
1005 AC_PWRST_D0);
1006
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001007 snd_hda_codec_proc_new(codec);
1008
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001009 snd_hda_create_hwdep(codec);
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001010
1011 sprintf(component, "HDA:%08x,%08x,%08x", codec->vendor_id,
1012 codec->subsystem_id, codec->revision_id);
1013 snd_component_add(codec->bus->card, component);
1014
1015 if (codecp)
1016 *codecp = codec;
1017 return 0;
Takashi Iwai3be14142009-02-20 14:11:16 +01001018
1019 error:
1020 snd_hda_codec_free(codec);
1021 return err;
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001022}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001023EXPORT_SYMBOL_HDA(snd_hda_codec_new);
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001024
1025int snd_hda_codec_configure(struct hda_codec *codec)
1026{
1027 int err;
1028
Takashi Iwaid5ad6302007-03-07 15:55:59 +01001029 codec->preset = find_codec_preset(codec);
Takashi Iwai812a2cc2009-05-16 10:00:49 +02001030 if (!codec->vendor_name || !codec->chip_name) {
Takashi Iwaif44ac832008-07-30 15:01:45 +02001031 err = get_codec_name(codec);
1032 if (err < 0)
1033 return err;
1034 }
Takashi Iwai43ea1d42007-04-26 19:12:08 +02001035 /* audio codec should override the mixer name */
Takashi Iwaif44ac832008-07-30 15:01:45 +02001036 if (codec->afg || !*codec->bus->card->mixername)
Takashi Iwai812a2cc2009-05-16 10:00:49 +02001037 snprintf(codec->bus->card->mixername,
1038 sizeof(codec->bus->card->mixername),
1039 "%s %s", codec->vendor_name, codec->chip_name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001040
Takashi Iwai82467612007-07-27 19:15:54 +02001041 if (is_generic_config(codec)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001042 err = snd_hda_parse_generic_codec(codec);
Takashi Iwai82467612007-07-27 19:15:54 +02001043 goto patched;
1044 }
Takashi Iwai82467612007-07-27 19:15:54 +02001045 if (codec->preset && codec->preset->patch) {
1046 err = codec->preset->patch(codec);
1047 goto patched;
1048 }
1049
1050 /* call the default parser */
Takashi Iwai82467612007-07-27 19:15:54 +02001051 err = snd_hda_parse_generic_codec(codec);
Takashi Iwai35a1e0c2007-10-19 08:13:40 +02001052 if (err < 0)
1053 printk(KERN_ERR "hda-codec: No codec parser is available\n");
Takashi Iwai82467612007-07-27 19:15:54 +02001054
1055 patched:
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001056 if (!err && codec->patch_ops.unsol_event)
1057 err = init_unsol_queue(codec->bus);
1058 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001059}
Takashi Iwaia1e21c92009-06-17 09:33:52 +02001060EXPORT_SYMBOL_HDA(snd_hda_codec_configure);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001061
1062/**
1063 * snd_hda_codec_setup_stream - set up the codec for streaming
1064 * @codec: the CODEC to set up
1065 * @nid: the NID to set up
1066 * @stream_tag: stream tag to pass, it's between 0x1 and 0xf.
1067 * @channel_id: channel id to pass, zero based.
1068 * @format: stream format.
1069 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02001070void snd_hda_codec_setup_stream(struct hda_codec *codec, hda_nid_t nid,
1071 u32 stream_tag,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001072 int channel_id, int format)
1073{
Takashi Iwai0ba21762007-04-16 11:29:14 +02001074 if (!nid)
Takashi Iwaid21b37e2005-04-20 13:45:55 +02001075 return;
1076
Takashi Iwai0ba21762007-04-16 11:29:14 +02001077 snd_printdd("hda_codec_setup_stream: "
1078 "NID=0x%x, stream=0x%x, channel=%d, format=0x%x\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07001079 nid, stream_tag, channel_id, format);
1080 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CHANNEL_STREAMID,
1081 (stream_tag << 4) | channel_id);
1082 msleep(1);
1083 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_STREAM_FORMAT, format);
1084}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001085EXPORT_SYMBOL_HDA(snd_hda_codec_setup_stream);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001086
Takashi Iwai888afa12008-03-18 09:57:50 +01001087void snd_hda_codec_cleanup_stream(struct hda_codec *codec, hda_nid_t nid)
1088{
1089 if (!nid)
1090 return;
1091
1092 snd_printdd("hda_codec_cleanup_stream: NID=0x%x\n", nid);
1093 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CHANNEL_STREAMID, 0);
1094#if 0 /* keep the format */
1095 msleep(1);
1096 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_STREAM_FORMAT, 0);
1097#endif
1098}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001099EXPORT_SYMBOL_HDA(snd_hda_codec_cleanup_stream);
Takashi Iwai888afa12008-03-18 09:57:50 +01001100
Linus Torvalds1da177e2005-04-16 15:20:36 -07001101/*
1102 * amp access functions
1103 */
1104
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001105/* FIXME: more better hash key? */
1106#define HDA_HASH_KEY(nid,dir,idx) (u32)((nid) + ((idx) << 16) + ((dir) << 24))
Takashi Iwai1327a322009-03-23 13:07:47 +01001107#define HDA_HASH_PINCAP_KEY(nid) (u32)((nid) + (0x02 << 24))
Takashi Iwai92c7c8a2009-03-24 07:32:14 +01001108#define HDA_HASH_PARPCM_KEY(nid) (u32)((nid) + (0x03 << 24))
1109#define HDA_HASH_PARSTR_KEY(nid) (u32)((nid) + (0x04 << 24))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001110#define INFO_AMP_CAPS (1<<0)
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001111#define INFO_AMP_VOL(ch) (1 << (1 + (ch)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001112
1113/* initialize the hash table */
Takashi Iwai1289e9e2008-11-27 15:47:11 +01001114static void /*__devinit*/ init_hda_cache(struct hda_cache_rec *cache,
Takashi Iwai01751f52007-08-10 16:59:39 +02001115 unsigned int record_size)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001116{
Takashi Iwai01751f52007-08-10 16:59:39 +02001117 memset(cache, 0, sizeof(*cache));
1118 memset(cache->hash, 0xff, sizeof(cache->hash));
Takashi Iwai603c4012008-07-30 15:01:44 +02001119 snd_array_init(&cache->buf, record_size, 64);
Takashi Iwai01751f52007-08-10 16:59:39 +02001120}
1121
Takashi Iwai1fcaee62007-08-23 00:01:09 +02001122static void free_hda_cache(struct hda_cache_rec *cache)
Takashi Iwai01751f52007-08-10 16:59:39 +02001123{
Takashi Iwai603c4012008-07-30 15:01:44 +02001124 snd_array_free(&cache->buf);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001125}
1126
1127/* query the hash. allocate an entry if not found. */
Takashi Iwai01751f52007-08-10 16:59:39 +02001128static struct hda_cache_head *get_alloc_hash(struct hda_cache_rec *cache,
1129 u32 key)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001130{
Takashi Iwai01751f52007-08-10 16:59:39 +02001131 u16 idx = key % (u16)ARRAY_SIZE(cache->hash);
1132 u16 cur = cache->hash[idx];
1133 struct hda_cache_head *info;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001134
1135 while (cur != 0xffff) {
Takashi Iwaif43aa022008-11-10 16:24:26 +01001136 info = snd_array_elem(&cache->buf, cur);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001137 if (info->key == key)
1138 return info;
1139 cur = info->next;
1140 }
1141
1142 /* add a new hash entry */
Takashi Iwai603c4012008-07-30 15:01:44 +02001143 info = snd_array_new(&cache->buf);
Takashi Iwaic2174292008-11-07 00:23:30 +01001144 if (!info)
1145 return NULL;
Takashi Iwaif43aa022008-11-10 16:24:26 +01001146 cur = snd_array_index(&cache->buf, info);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001147 info->key = key;
Takashi Iwai01751f52007-08-10 16:59:39 +02001148 info->val = 0;
1149 info->next = cache->hash[idx];
1150 cache->hash[idx] = cur;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001151
1152 return info;
1153}
1154
Takashi Iwai01751f52007-08-10 16:59:39 +02001155/* query and allocate an amp hash entry */
1156static inline struct hda_amp_info *
1157get_alloc_amp_hash(struct hda_codec *codec, u32 key)
1158{
1159 return (struct hda_amp_info *)get_alloc_hash(&codec->amp_cache, key);
1160}
1161
Linus Torvalds1da177e2005-04-16 15:20:36 -07001162/*
1163 * query AMP capabilities for the given widget and direction
1164 */
Matthew Ranostay09a99952008-01-24 11:49:21 +01001165u32 query_amp_caps(struct hda_codec *codec, hda_nid_t nid, int direction)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001166{
Takashi Iwai0ba21762007-04-16 11:29:14 +02001167 struct hda_amp_info *info;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001168
Takashi Iwai0ba21762007-04-16 11:29:14 +02001169 info = get_alloc_amp_hash(codec, HDA_HASH_KEY(nid, direction, 0));
1170 if (!info)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001171 return 0;
Takashi Iwai01751f52007-08-10 16:59:39 +02001172 if (!(info->head.val & INFO_AMP_CAPS)) {
Takashi Iwai0ba21762007-04-16 11:29:14 +02001173 if (!(get_wcaps(codec, nid) & AC_WCAP_AMP_OVRD))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001174 nid = codec->afg;
Takashi Iwai0ba21762007-04-16 11:29:14 +02001175 info->amp_caps = snd_hda_param_read(codec, nid,
1176 direction == HDA_OUTPUT ?
1177 AC_PAR_AMP_OUT_CAP :
1178 AC_PAR_AMP_IN_CAP);
Takashi Iwaib75e53f2007-05-10 16:56:09 +02001179 if (info->amp_caps)
Takashi Iwai01751f52007-08-10 16:59:39 +02001180 info->head.val |= INFO_AMP_CAPS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001181 }
1182 return info->amp_caps;
1183}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001184EXPORT_SYMBOL_HDA(query_amp_caps);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001185
Takashi Iwai897cc182007-05-29 19:01:37 +02001186int snd_hda_override_amp_caps(struct hda_codec *codec, hda_nid_t nid, int dir,
1187 unsigned int caps)
1188{
1189 struct hda_amp_info *info;
1190
1191 info = get_alloc_amp_hash(codec, HDA_HASH_KEY(nid, dir, 0));
1192 if (!info)
1193 return -EINVAL;
1194 info->amp_caps = caps;
Takashi Iwai01751f52007-08-10 16:59:39 +02001195 info->head.val |= INFO_AMP_CAPS;
Takashi Iwai897cc182007-05-29 19:01:37 +02001196 return 0;
1197}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001198EXPORT_SYMBOL_HDA(snd_hda_override_amp_caps);
Takashi Iwai897cc182007-05-29 19:01:37 +02001199
Takashi Iwai92c7c8a2009-03-24 07:32:14 +01001200static unsigned int
1201query_caps_hash(struct hda_codec *codec, hda_nid_t nid, u32 key,
1202 unsigned int (*func)(struct hda_codec *, hda_nid_t))
Takashi Iwai1327a322009-03-23 13:07:47 +01001203{
1204 struct hda_amp_info *info;
1205
Takashi Iwai92c7c8a2009-03-24 07:32:14 +01001206 info = get_alloc_amp_hash(codec, key);
Takashi Iwai1327a322009-03-23 13:07:47 +01001207 if (!info)
1208 return 0;
1209 if (!info->head.val) {
Takashi Iwai1327a322009-03-23 13:07:47 +01001210 info->head.val |= INFO_AMP_CAPS;
Takashi Iwai92c7c8a2009-03-24 07:32:14 +01001211 info->amp_caps = func(codec, nid);
Takashi Iwai1327a322009-03-23 13:07:47 +01001212 }
1213 return info->amp_caps;
1214}
Takashi Iwai92c7c8a2009-03-24 07:32:14 +01001215
1216static unsigned int read_pin_cap(struct hda_codec *codec, hda_nid_t nid)
1217{
1218 return snd_hda_param_read(codec, nid, AC_PAR_PIN_CAP);
1219}
1220
1221u32 snd_hda_query_pin_caps(struct hda_codec *codec, hda_nid_t nid)
1222{
1223 return query_caps_hash(codec, nid, HDA_HASH_PINCAP_KEY(nid),
1224 read_pin_cap);
1225}
Takashi Iwai1327a322009-03-23 13:07:47 +01001226EXPORT_SYMBOL_HDA(snd_hda_query_pin_caps);
1227
Linus Torvalds1da177e2005-04-16 15:20:36 -07001228/*
1229 * read the current volume to info
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001230 * if the cache exists, read the cache value.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001231 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02001232static unsigned int get_vol_mute(struct hda_codec *codec,
1233 struct hda_amp_info *info, hda_nid_t nid,
1234 int ch, int direction, int index)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001235{
1236 u32 val, parm;
1237
Takashi Iwai01751f52007-08-10 16:59:39 +02001238 if (info->head.val & INFO_AMP_VOL(ch))
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001239 return info->vol[ch];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001240
1241 parm = ch ? AC_AMP_GET_RIGHT : AC_AMP_GET_LEFT;
1242 parm |= direction == HDA_OUTPUT ? AC_AMP_GET_OUTPUT : AC_AMP_GET_INPUT;
1243 parm |= index;
Takashi Iwai0ba21762007-04-16 11:29:14 +02001244 val = snd_hda_codec_read(codec, nid, 0,
1245 AC_VERB_GET_AMP_GAIN_MUTE, parm);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001246 info->vol[ch] = val & 0xff;
Takashi Iwai01751f52007-08-10 16:59:39 +02001247 info->head.val |= INFO_AMP_VOL(ch);
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001248 return info->vol[ch];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001249}
1250
1251/*
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001252 * write the current volume in info to the h/w and update the cache
Linus Torvalds1da177e2005-04-16 15:20:36 -07001253 */
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001254static void put_vol_mute(struct hda_codec *codec, struct hda_amp_info *info,
Takashi Iwai0ba21762007-04-16 11:29:14 +02001255 hda_nid_t nid, int ch, int direction, int index,
1256 int val)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001257{
1258 u32 parm;
1259
1260 parm = ch ? AC_AMP_SET_RIGHT : AC_AMP_SET_LEFT;
1261 parm |= direction == HDA_OUTPUT ? AC_AMP_SET_OUTPUT : AC_AMP_SET_INPUT;
1262 parm |= index << AC_AMP_SET_INDEX_SHIFT;
1263 parm |= val;
1264 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, parm);
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001265 info->vol[ch] = val;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001266}
1267
1268/*
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001269 * read AMP value. The volume is between 0 to 0x7f, 0x80 = mute bit.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001270 */
Takashi Iwai834be882006-03-01 14:16:17 +01001271int snd_hda_codec_amp_read(struct hda_codec *codec, hda_nid_t nid, int ch,
1272 int direction, int index)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001273{
Takashi Iwai0ba21762007-04-16 11:29:14 +02001274 struct hda_amp_info *info;
1275 info = get_alloc_amp_hash(codec, HDA_HASH_KEY(nid, direction, index));
1276 if (!info)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001277 return 0;
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001278 return get_vol_mute(codec, info, nid, ch, direction, index);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001279}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001280EXPORT_SYMBOL_HDA(snd_hda_codec_amp_read);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001281
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001282/*
1283 * update the AMP value, mask = bit mask to set, val = the value
1284 */
Takashi Iwai834be882006-03-01 14:16:17 +01001285int snd_hda_codec_amp_update(struct hda_codec *codec, hda_nid_t nid, int ch,
1286 int direction, int idx, int mask, int val)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001287{
Takashi Iwai0ba21762007-04-16 11:29:14 +02001288 struct hda_amp_info *info;
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001289
Takashi Iwai0ba21762007-04-16 11:29:14 +02001290 info = get_alloc_amp_hash(codec, HDA_HASH_KEY(nid, direction, idx));
1291 if (!info)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001292 return 0;
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001293 val &= mask;
1294 val |= get_vol_mute(codec, info, nid, ch, direction, idx) & ~mask;
Takashi Iwai82beb8f2007-08-10 17:09:26 +02001295 if (info->vol[ch] == val)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001296 return 0;
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001297 put_vol_mute(codec, info, nid, ch, direction, idx, val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001298 return 1;
1299}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001300EXPORT_SYMBOL_HDA(snd_hda_codec_amp_update);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001301
Takashi Iwai47fd8302007-08-10 17:11:07 +02001302/*
1303 * update the AMP stereo with the same mask and value
1304 */
1305int snd_hda_codec_amp_stereo(struct hda_codec *codec, hda_nid_t nid,
1306 int direction, int idx, int mask, int val)
1307{
1308 int ch, ret = 0;
1309 for (ch = 0; ch < 2; ch++)
1310 ret |= snd_hda_codec_amp_update(codec, nid, ch, direction,
1311 idx, mask, val);
1312 return ret;
1313}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001314EXPORT_SYMBOL_HDA(snd_hda_codec_amp_stereo);
Takashi Iwai47fd8302007-08-10 17:11:07 +02001315
Takashi Iwaicb53c622007-08-10 17:21:45 +02001316#ifdef SND_HDA_NEEDS_RESUME
Takashi Iwaib3ac5632007-08-10 17:03:40 +02001317/* resume the all amp commands from the cache */
1318void snd_hda_codec_resume_amp(struct hda_codec *codec)
1319{
Takashi Iwai603c4012008-07-30 15:01:44 +02001320 struct hda_amp_info *buffer = codec->amp_cache.buf.list;
Takashi Iwaib3ac5632007-08-10 17:03:40 +02001321 int i;
1322
Takashi Iwai603c4012008-07-30 15:01:44 +02001323 for (i = 0; i < codec->amp_cache.buf.used; i++, buffer++) {
Takashi Iwaib3ac5632007-08-10 17:03:40 +02001324 u32 key = buffer->head.key;
1325 hda_nid_t nid;
1326 unsigned int idx, dir, ch;
1327 if (!key)
1328 continue;
1329 nid = key & 0xff;
1330 idx = (key >> 16) & 0xff;
1331 dir = (key >> 24) & 0xff;
1332 for (ch = 0; ch < 2; ch++) {
1333 if (!(buffer->head.val & INFO_AMP_VOL(ch)))
1334 continue;
1335 put_vol_mute(codec, buffer, nid, ch, dir, idx,
1336 buffer->vol[ch]);
1337 }
1338 }
1339}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001340EXPORT_SYMBOL_HDA(snd_hda_codec_resume_amp);
Takashi Iwaicb53c622007-08-10 17:21:45 +02001341#endif /* SND_HDA_NEEDS_RESUME */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001342
Linus Torvalds1da177e2005-04-16 15:20:36 -07001343/* volume */
Takashi Iwai0ba21762007-04-16 11:29:14 +02001344int snd_hda_mixer_amp_volume_info(struct snd_kcontrol *kcontrol,
1345 struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001346{
1347 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1348 u16 nid = get_amp_nid(kcontrol);
1349 u8 chs = get_amp_channels(kcontrol);
1350 int dir = get_amp_direction(kcontrol);
Takashi Iwai29fdbec2009-01-20 13:07:55 +01001351 unsigned int ofs = get_amp_offset(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001352 u32 caps;
1353
1354 caps = query_amp_caps(codec, nid, dir);
Takashi Iwai0ba21762007-04-16 11:29:14 +02001355 /* num steps */
1356 caps = (caps & AC_AMPCAP_NUM_STEPS) >> AC_AMPCAP_NUM_STEPS_SHIFT;
1357 if (!caps) {
1358 printk(KERN_WARNING "hda_codec: "
Takashi Iwai9c8f2ab2008-01-11 16:12:23 +01001359 "num_steps = 0 for NID=0x%x (ctl = %s)\n", nid,
1360 kcontrol->id.name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001361 return -EINVAL;
1362 }
Takashi Iwai29fdbec2009-01-20 13:07:55 +01001363 if (ofs < caps)
1364 caps -= ofs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001365 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
1366 uinfo->count = chs == 3 ? 2 : 1;
1367 uinfo->value.integer.min = 0;
1368 uinfo->value.integer.max = caps;
1369 return 0;
1370}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001371EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_volume_info);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001372
Takashi Iwai29fdbec2009-01-20 13:07:55 +01001373
1374static inline unsigned int
1375read_amp_value(struct hda_codec *codec, hda_nid_t nid,
1376 int ch, int dir, int idx, unsigned int ofs)
1377{
1378 unsigned int val;
1379 val = snd_hda_codec_amp_read(codec, nid, ch, dir, idx);
1380 val &= HDA_AMP_VOLMASK;
1381 if (val >= ofs)
1382 val -= ofs;
1383 else
1384 val = 0;
1385 return val;
1386}
1387
1388static inline int
1389update_amp_value(struct hda_codec *codec, hda_nid_t nid,
1390 int ch, int dir, int idx, unsigned int ofs,
1391 unsigned int val)
1392{
1393 if (val > 0)
1394 val += ofs;
1395 return snd_hda_codec_amp_update(codec, nid, ch, dir, idx,
1396 HDA_AMP_VOLMASK, val);
1397}
1398
Takashi Iwai0ba21762007-04-16 11:29:14 +02001399int snd_hda_mixer_amp_volume_get(struct snd_kcontrol *kcontrol,
1400 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001401{
1402 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1403 hda_nid_t nid = get_amp_nid(kcontrol);
1404 int chs = get_amp_channels(kcontrol);
1405 int dir = get_amp_direction(kcontrol);
1406 int idx = get_amp_index(kcontrol);
Takashi Iwai29fdbec2009-01-20 13:07:55 +01001407 unsigned int ofs = get_amp_offset(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001408 long *valp = ucontrol->value.integer.value;
1409
1410 if (chs & 1)
Takashi Iwai29fdbec2009-01-20 13:07:55 +01001411 *valp++ = read_amp_value(codec, nid, 0, dir, idx, ofs);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001412 if (chs & 2)
Takashi Iwai29fdbec2009-01-20 13:07:55 +01001413 *valp = read_amp_value(codec, nid, 1, dir, idx, ofs);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001414 return 0;
1415}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001416EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_volume_get);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001417
Takashi Iwai0ba21762007-04-16 11:29:14 +02001418int snd_hda_mixer_amp_volume_put(struct snd_kcontrol *kcontrol,
1419 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001420{
1421 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1422 hda_nid_t nid = get_amp_nid(kcontrol);
1423 int chs = get_amp_channels(kcontrol);
1424 int dir = get_amp_direction(kcontrol);
1425 int idx = get_amp_index(kcontrol);
Takashi Iwai29fdbec2009-01-20 13:07:55 +01001426 unsigned int ofs = get_amp_offset(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001427 long *valp = ucontrol->value.integer.value;
1428 int change = 0;
1429
Takashi Iwaicb53c622007-08-10 17:21:45 +02001430 snd_hda_power_up(codec);
Nicolas Grazianob9f5a892005-07-29 12:17:20 +02001431 if (chs & 1) {
Takashi Iwai29fdbec2009-01-20 13:07:55 +01001432 change = update_amp_value(codec, nid, 0, dir, idx, ofs, *valp);
Nicolas Grazianob9f5a892005-07-29 12:17:20 +02001433 valp++;
1434 }
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001435 if (chs & 2)
Takashi Iwai29fdbec2009-01-20 13:07:55 +01001436 change |= update_amp_value(codec, nid, 1, dir, idx, ofs, *valp);
Takashi Iwaicb53c622007-08-10 17:21:45 +02001437 snd_hda_power_down(codec);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001438 return change;
1439}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001440EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_volume_put);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001441
Jaroslav Kysela302e9c52006-07-05 17:39:49 +02001442int snd_hda_mixer_amp_tlv(struct snd_kcontrol *kcontrol, int op_flag,
1443 unsigned int size, unsigned int __user *_tlv)
1444{
1445 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1446 hda_nid_t nid = get_amp_nid(kcontrol);
1447 int dir = get_amp_direction(kcontrol);
Takashi Iwai29fdbec2009-01-20 13:07:55 +01001448 unsigned int ofs = get_amp_offset(kcontrol);
Jaroslav Kysela302e9c52006-07-05 17:39:49 +02001449 u32 caps, val1, val2;
1450
1451 if (size < 4 * sizeof(unsigned int))
1452 return -ENOMEM;
1453 caps = query_amp_caps(codec, nid, dir);
Takashi Iwai0ba21762007-04-16 11:29:14 +02001454 val2 = (caps & AC_AMPCAP_STEP_SIZE) >> AC_AMPCAP_STEP_SIZE_SHIFT;
1455 val2 = (val2 + 1) * 25;
Jaroslav Kysela302e9c52006-07-05 17:39:49 +02001456 val1 = -((caps & AC_AMPCAP_OFFSET) >> AC_AMPCAP_OFFSET_SHIFT);
Takashi Iwai29fdbec2009-01-20 13:07:55 +01001457 val1 += ofs;
Jaroslav Kysela302e9c52006-07-05 17:39:49 +02001458 val1 = ((int)val1) * ((int)val2);
Jaroslav Kysela302e9c52006-07-05 17:39:49 +02001459 if (put_user(SNDRV_CTL_TLVT_DB_SCALE, _tlv))
1460 return -EFAULT;
1461 if (put_user(2 * sizeof(unsigned int), _tlv + 1))
1462 return -EFAULT;
1463 if (put_user(val1, _tlv + 2))
1464 return -EFAULT;
1465 if (put_user(val2, _tlv + 3))
1466 return -EFAULT;
1467 return 0;
1468}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001469EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_tlv);
Jaroslav Kysela302e9c52006-07-05 17:39:49 +02001470
Takashi Iwai2134ea42008-01-10 16:53:55 +01001471/*
1472 * set (static) TLV for virtual master volume; recalculated as max 0dB
1473 */
1474void snd_hda_set_vmaster_tlv(struct hda_codec *codec, hda_nid_t nid, int dir,
1475 unsigned int *tlv)
1476{
1477 u32 caps;
1478 int nums, step;
1479
1480 caps = query_amp_caps(codec, nid, dir);
1481 nums = (caps & AC_AMPCAP_NUM_STEPS) >> AC_AMPCAP_NUM_STEPS_SHIFT;
1482 step = (caps & AC_AMPCAP_STEP_SIZE) >> AC_AMPCAP_STEP_SIZE_SHIFT;
1483 step = (step + 1) * 25;
1484 tlv[0] = SNDRV_CTL_TLVT_DB_SCALE;
1485 tlv[1] = 2 * sizeof(unsigned int);
1486 tlv[2] = -nums * step;
1487 tlv[3] = step;
1488}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001489EXPORT_SYMBOL_HDA(snd_hda_set_vmaster_tlv);
Takashi Iwai2134ea42008-01-10 16:53:55 +01001490
1491/* find a mixer control element with the given name */
Takashi Iwai09f99702008-02-04 12:31:13 +01001492static struct snd_kcontrol *
1493_snd_hda_find_mixer_ctl(struct hda_codec *codec,
1494 const char *name, int idx)
Takashi Iwai2134ea42008-01-10 16:53:55 +01001495{
1496 struct snd_ctl_elem_id id;
1497 memset(&id, 0, sizeof(id));
1498 id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
Takashi Iwai09f99702008-02-04 12:31:13 +01001499 id.index = idx;
Takashi Iwai18cb7102009-04-16 10:22:24 +02001500 if (snd_BUG_ON(strlen(name) >= sizeof(id.name)))
1501 return NULL;
Takashi Iwai2134ea42008-01-10 16:53:55 +01001502 strcpy(id.name, name);
1503 return snd_ctl_find_id(codec->bus->card, &id);
1504}
1505
Takashi Iwai09f99702008-02-04 12:31:13 +01001506struct snd_kcontrol *snd_hda_find_mixer_ctl(struct hda_codec *codec,
1507 const char *name)
1508{
1509 return _snd_hda_find_mixer_ctl(codec, name, 0);
1510}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001511EXPORT_SYMBOL_HDA(snd_hda_find_mixer_ctl);
Takashi Iwai09f99702008-02-04 12:31:13 +01001512
Takashi Iwaid13bd412008-07-30 15:01:45 +02001513/* Add a control element and assign to the codec */
1514int snd_hda_ctl_add(struct hda_codec *codec, struct snd_kcontrol *kctl)
1515{
1516 int err;
1517 struct snd_kcontrol **knewp;
1518
1519 err = snd_ctl_add(codec->bus->card, kctl);
1520 if (err < 0)
1521 return err;
1522 knewp = snd_array_new(&codec->mixers);
1523 if (!knewp)
1524 return -ENOMEM;
1525 *knewp = kctl;
1526 return 0;
1527}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001528EXPORT_SYMBOL_HDA(snd_hda_ctl_add);
Takashi Iwaid13bd412008-07-30 15:01:45 +02001529
1530/* Clear all controls assigned to the given codec */
1531void snd_hda_ctls_clear(struct hda_codec *codec)
1532{
1533 int i;
1534 struct snd_kcontrol **kctls = codec->mixers.list;
1535 for (i = 0; i < codec->mixers.used; i++)
1536 snd_ctl_remove(codec->bus->card, kctls[i]);
1537 snd_array_free(&codec->mixers);
1538}
1539
Takashi Iwaia65d6292009-02-23 16:57:04 +01001540/* pseudo device locking
1541 * toggle card->shutdown to allow/disallow the device access (as a hack)
1542 */
1543static int hda_lock_devices(struct snd_card *card)
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001544{
Takashi Iwaia65d6292009-02-23 16:57:04 +01001545 spin_lock(&card->files_lock);
1546 if (card->shutdown) {
1547 spin_unlock(&card->files_lock);
1548 return -EINVAL;
1549 }
1550 card->shutdown = 1;
1551 spin_unlock(&card->files_lock);
1552 return 0;
1553}
1554
1555static void hda_unlock_devices(struct snd_card *card)
1556{
1557 spin_lock(&card->files_lock);
1558 card->shutdown = 0;
1559 spin_unlock(&card->files_lock);
1560}
1561
1562int snd_hda_codec_reset(struct hda_codec *codec)
1563{
1564 struct snd_card *card = codec->bus->card;
1565 int i, pcm;
1566
1567 if (hda_lock_devices(card) < 0)
1568 return -EBUSY;
1569 /* check whether the codec isn't used by any mixer or PCM streams */
1570 if (!list_empty(&card->ctl_files)) {
1571 hda_unlock_devices(card);
1572 return -EBUSY;
1573 }
1574 for (pcm = 0; pcm < codec->num_pcms; pcm++) {
1575 struct hda_pcm *cpcm = &codec->pcm_info[pcm];
1576 if (!cpcm->pcm)
1577 continue;
1578 if (cpcm->pcm->streams[0].substream_opened ||
1579 cpcm->pcm->streams[1].substream_opened) {
1580 hda_unlock_devices(card);
1581 return -EBUSY;
1582 }
1583 }
1584
1585 /* OK, let it free */
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001586
1587#ifdef CONFIG_SND_HDA_POWER_SAVE
1588 cancel_delayed_work(&codec->power_work);
Takashi Iwai6acaed32009-01-12 10:09:24 +01001589 flush_workqueue(codec->bus->workq);
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001590#endif
1591 snd_hda_ctls_clear(codec);
1592 /* relase PCMs */
1593 for (i = 0; i < codec->num_pcms; i++) {
Takashi Iwai529bd6c2008-11-27 14:17:01 +01001594 if (codec->pcm_info[i].pcm) {
Takashi Iwaia65d6292009-02-23 16:57:04 +01001595 snd_device_free(card, codec->pcm_info[i].pcm);
Takashi Iwai529bd6c2008-11-27 14:17:01 +01001596 clear_bit(codec->pcm_info[i].device,
1597 codec->bus->pcm_dev_bits);
1598 }
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001599 }
1600 if (codec->patch_ops.free)
1601 codec->patch_ops.free(codec);
Takashi Iwai56d17712008-11-28 14:36:23 +01001602 codec->proc_widget_hook = NULL;
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001603 codec->spec = NULL;
1604 free_hda_cache(&codec->amp_cache);
1605 free_hda_cache(&codec->cmd_cache);
Takashi Iwai827057f2008-12-19 10:12:02 +01001606 init_hda_cache(&codec->amp_cache, sizeof(struct hda_amp_info));
1607 init_hda_cache(&codec->cmd_cache, sizeof(struct hda_cache_head));
Takashi Iwai346ff702009-02-23 09:42:57 +01001608 /* free only driver_pins so that init_pins + user_pins are restored */
1609 snd_array_free(&codec->driver_pins);
Takashi Iwai3be14142009-02-20 14:11:16 +01001610 restore_pincfgs(codec);
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001611 codec->num_pcms = 0;
1612 codec->pcm_info = NULL;
1613 codec->preset = NULL;
Takashi Iwaid1f1af22009-03-02 10:35:29 +01001614 memset(&codec->patch_ops, 0, sizeof(codec->patch_ops));
1615 codec->slave_dig_outs = NULL;
1616 codec->spdif_status_reset = 0;
Takashi Iwai1289e9e2008-11-27 15:47:11 +01001617 module_put(codec->owner);
1618 codec->owner = NULL;
Takashi Iwaia65d6292009-02-23 16:57:04 +01001619
1620 /* allow device access again */
1621 hda_unlock_devices(card);
1622 return 0;
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001623}
1624
Takashi Iwai2134ea42008-01-10 16:53:55 +01001625/* create a virtual master control and add slaves */
1626int snd_hda_add_vmaster(struct hda_codec *codec, char *name,
1627 unsigned int *tlv, const char **slaves)
1628{
1629 struct snd_kcontrol *kctl;
1630 const char **s;
1631 int err;
1632
Takashi Iwai2f085542008-02-22 18:43:50 +01001633 for (s = slaves; *s && !snd_hda_find_mixer_ctl(codec, *s); s++)
1634 ;
1635 if (!*s) {
1636 snd_printdd("No slave found for %s\n", name);
1637 return 0;
1638 }
Takashi Iwai2134ea42008-01-10 16:53:55 +01001639 kctl = snd_ctl_make_virtual_master(name, tlv);
1640 if (!kctl)
1641 return -ENOMEM;
Takashi Iwaid13bd412008-07-30 15:01:45 +02001642 err = snd_hda_ctl_add(codec, kctl);
Takashi Iwai2134ea42008-01-10 16:53:55 +01001643 if (err < 0)
1644 return err;
1645
1646 for (s = slaves; *s; s++) {
1647 struct snd_kcontrol *sctl;
Takashi Iwai7a411ee2009-03-06 10:08:14 +01001648 int i = 0;
1649 for (;;) {
1650 sctl = _snd_hda_find_mixer_ctl(codec, *s, i);
1651 if (!sctl) {
1652 if (!i)
1653 snd_printdd("Cannot find slave %s, "
1654 "skipped\n", *s);
1655 break;
1656 }
1657 err = snd_ctl_add_slave(kctl, sctl);
1658 if (err < 0)
1659 return err;
1660 i++;
Takashi Iwai2134ea42008-01-10 16:53:55 +01001661 }
Takashi Iwai2134ea42008-01-10 16:53:55 +01001662 }
1663 return 0;
1664}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001665EXPORT_SYMBOL_HDA(snd_hda_add_vmaster);
Takashi Iwai2134ea42008-01-10 16:53:55 +01001666
Linus Torvalds1da177e2005-04-16 15:20:36 -07001667/* switch */
Takashi Iwai0ba21762007-04-16 11:29:14 +02001668int snd_hda_mixer_amp_switch_info(struct snd_kcontrol *kcontrol,
1669 struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001670{
1671 int chs = get_amp_channels(kcontrol);
1672
1673 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
1674 uinfo->count = chs == 3 ? 2 : 1;
1675 uinfo->value.integer.min = 0;
1676 uinfo->value.integer.max = 1;
1677 return 0;
1678}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001679EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_switch_info);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001680
Takashi Iwai0ba21762007-04-16 11:29:14 +02001681int snd_hda_mixer_amp_switch_get(struct snd_kcontrol *kcontrol,
1682 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001683{
1684 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1685 hda_nid_t nid = get_amp_nid(kcontrol);
1686 int chs = get_amp_channels(kcontrol);
1687 int dir = get_amp_direction(kcontrol);
1688 int idx = get_amp_index(kcontrol);
1689 long *valp = ucontrol->value.integer.value;
1690
1691 if (chs & 1)
Takashi Iwai0ba21762007-04-16 11:29:14 +02001692 *valp++ = (snd_hda_codec_amp_read(codec, nid, 0, dir, idx) &
Takashi Iwai47fd8302007-08-10 17:11:07 +02001693 HDA_AMP_MUTE) ? 0 : 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001694 if (chs & 2)
Takashi Iwai0ba21762007-04-16 11:29:14 +02001695 *valp = (snd_hda_codec_amp_read(codec, nid, 1, dir, idx) &
Takashi Iwai47fd8302007-08-10 17:11:07 +02001696 HDA_AMP_MUTE) ? 0 : 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001697 return 0;
1698}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001699EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_switch_get);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001700
Takashi Iwai0ba21762007-04-16 11:29:14 +02001701int snd_hda_mixer_amp_switch_put(struct snd_kcontrol *kcontrol,
1702 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001703{
1704 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1705 hda_nid_t nid = get_amp_nid(kcontrol);
1706 int chs = get_amp_channels(kcontrol);
1707 int dir = get_amp_direction(kcontrol);
1708 int idx = get_amp_index(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001709 long *valp = ucontrol->value.integer.value;
1710 int change = 0;
1711
Takashi Iwaicb53c622007-08-10 17:21:45 +02001712 snd_hda_power_up(codec);
Nicolas Grazianob9f5a892005-07-29 12:17:20 +02001713 if (chs & 1) {
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001714 change = snd_hda_codec_amp_update(codec, nid, 0, dir, idx,
Takashi Iwai47fd8302007-08-10 17:11:07 +02001715 HDA_AMP_MUTE,
1716 *valp ? 0 : HDA_AMP_MUTE);
Nicolas Grazianob9f5a892005-07-29 12:17:20 +02001717 valp++;
1718 }
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001719 if (chs & 2)
1720 change |= snd_hda_codec_amp_update(codec, nid, 1, dir, idx,
Takashi Iwai47fd8302007-08-10 17:11:07 +02001721 HDA_AMP_MUTE,
1722 *valp ? 0 : HDA_AMP_MUTE);
Takashi Iwaicb53c622007-08-10 17:21:45 +02001723#ifdef CONFIG_SND_HDA_POWER_SAVE
1724 if (codec->patch_ops.check_power_status)
1725 codec->patch_ops.check_power_status(codec, nid);
1726#endif
1727 snd_hda_power_down(codec);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001728 return change;
1729}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001730EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_switch_put);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001731
1732/*
Takashi Iwai985be542005-11-02 18:26:49 +01001733 * bound volume controls
1734 *
1735 * bind multiple volumes (# indices, from 0)
1736 */
1737
1738#define AMP_VAL_IDX_SHIFT 19
1739#define AMP_VAL_IDX_MASK (0x0f<<19)
1740
Takashi Iwai0ba21762007-04-16 11:29:14 +02001741int snd_hda_mixer_bind_switch_get(struct snd_kcontrol *kcontrol,
1742 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai985be542005-11-02 18:26:49 +01001743{
1744 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1745 unsigned long pval;
1746 int err;
1747
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001748 mutex_lock(&codec->control_mutex);
Takashi Iwai985be542005-11-02 18:26:49 +01001749 pval = kcontrol->private_value;
1750 kcontrol->private_value = pval & ~AMP_VAL_IDX_MASK; /* index 0 */
1751 err = snd_hda_mixer_amp_switch_get(kcontrol, ucontrol);
1752 kcontrol->private_value = pval;
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001753 mutex_unlock(&codec->control_mutex);
Takashi Iwai985be542005-11-02 18:26:49 +01001754 return err;
1755}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001756EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_switch_get);
Takashi Iwai985be542005-11-02 18:26:49 +01001757
Takashi Iwai0ba21762007-04-16 11:29:14 +02001758int snd_hda_mixer_bind_switch_put(struct snd_kcontrol *kcontrol,
1759 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai985be542005-11-02 18:26:49 +01001760{
1761 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1762 unsigned long pval;
1763 int i, indices, err = 0, change = 0;
1764
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001765 mutex_lock(&codec->control_mutex);
Takashi Iwai985be542005-11-02 18:26:49 +01001766 pval = kcontrol->private_value;
1767 indices = (pval & AMP_VAL_IDX_MASK) >> AMP_VAL_IDX_SHIFT;
1768 for (i = 0; i < indices; i++) {
Takashi Iwai0ba21762007-04-16 11:29:14 +02001769 kcontrol->private_value = (pval & ~AMP_VAL_IDX_MASK) |
1770 (i << AMP_VAL_IDX_SHIFT);
Takashi Iwai985be542005-11-02 18:26:49 +01001771 err = snd_hda_mixer_amp_switch_put(kcontrol, ucontrol);
1772 if (err < 0)
1773 break;
1774 change |= err;
1775 }
1776 kcontrol->private_value = pval;
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001777 mutex_unlock(&codec->control_mutex);
Takashi Iwai985be542005-11-02 18:26:49 +01001778 return err < 0 ? err : change;
1779}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001780EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_switch_put);
Takashi Iwai985be542005-11-02 18:26:49 +01001781
1782/*
Takashi Iwai532d5382007-07-27 19:02:40 +02001783 * generic bound volume/swtich controls
1784 */
1785int snd_hda_mixer_bind_ctls_info(struct snd_kcontrol *kcontrol,
1786 struct snd_ctl_elem_info *uinfo)
1787{
1788 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1789 struct hda_bind_ctls *c;
1790 int err;
1791
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001792 mutex_lock(&codec->control_mutex);
Serge A. Suchkov14c65f92008-02-22 18:43:16 +01001793 c = (struct hda_bind_ctls *)kcontrol->private_value;
Takashi Iwai532d5382007-07-27 19:02:40 +02001794 kcontrol->private_value = *c->values;
1795 err = c->ops->info(kcontrol, uinfo);
1796 kcontrol->private_value = (long)c;
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001797 mutex_unlock(&codec->control_mutex);
Takashi Iwai532d5382007-07-27 19:02:40 +02001798 return err;
1799}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001800EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_ctls_info);
Takashi Iwai532d5382007-07-27 19:02:40 +02001801
1802int snd_hda_mixer_bind_ctls_get(struct snd_kcontrol *kcontrol,
1803 struct snd_ctl_elem_value *ucontrol)
1804{
1805 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1806 struct hda_bind_ctls *c;
1807 int err;
1808
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001809 mutex_lock(&codec->control_mutex);
Serge A. Suchkov14c65f92008-02-22 18:43:16 +01001810 c = (struct hda_bind_ctls *)kcontrol->private_value;
Takashi Iwai532d5382007-07-27 19:02:40 +02001811 kcontrol->private_value = *c->values;
1812 err = c->ops->get(kcontrol, ucontrol);
1813 kcontrol->private_value = (long)c;
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001814 mutex_unlock(&codec->control_mutex);
Takashi Iwai532d5382007-07-27 19:02:40 +02001815 return err;
1816}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001817EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_ctls_get);
Takashi Iwai532d5382007-07-27 19:02:40 +02001818
1819int snd_hda_mixer_bind_ctls_put(struct snd_kcontrol *kcontrol,
1820 struct snd_ctl_elem_value *ucontrol)
1821{
1822 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1823 struct hda_bind_ctls *c;
1824 unsigned long *vals;
1825 int err = 0, change = 0;
1826
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001827 mutex_lock(&codec->control_mutex);
Serge A. Suchkov14c65f92008-02-22 18:43:16 +01001828 c = (struct hda_bind_ctls *)kcontrol->private_value;
Takashi Iwai532d5382007-07-27 19:02:40 +02001829 for (vals = c->values; *vals; vals++) {
1830 kcontrol->private_value = *vals;
1831 err = c->ops->put(kcontrol, ucontrol);
1832 if (err < 0)
1833 break;
1834 change |= err;
1835 }
1836 kcontrol->private_value = (long)c;
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001837 mutex_unlock(&codec->control_mutex);
Takashi Iwai532d5382007-07-27 19:02:40 +02001838 return err < 0 ? err : change;
1839}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001840EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_ctls_put);
Takashi Iwai532d5382007-07-27 19:02:40 +02001841
1842int snd_hda_mixer_bind_tlv(struct snd_kcontrol *kcontrol, int op_flag,
1843 unsigned int size, unsigned int __user *tlv)
1844{
1845 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1846 struct hda_bind_ctls *c;
1847 int err;
1848
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001849 mutex_lock(&codec->control_mutex);
Serge A. Suchkov14c65f92008-02-22 18:43:16 +01001850 c = (struct hda_bind_ctls *)kcontrol->private_value;
Takashi Iwai532d5382007-07-27 19:02:40 +02001851 kcontrol->private_value = *c->values;
1852 err = c->ops->tlv(kcontrol, op_flag, size, tlv);
1853 kcontrol->private_value = (long)c;
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001854 mutex_unlock(&codec->control_mutex);
Takashi Iwai532d5382007-07-27 19:02:40 +02001855 return err;
1856}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001857EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_tlv);
Takashi Iwai532d5382007-07-27 19:02:40 +02001858
1859struct hda_ctl_ops snd_hda_bind_vol = {
1860 .info = snd_hda_mixer_amp_volume_info,
1861 .get = snd_hda_mixer_amp_volume_get,
1862 .put = snd_hda_mixer_amp_volume_put,
1863 .tlv = snd_hda_mixer_amp_tlv
1864};
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001865EXPORT_SYMBOL_HDA(snd_hda_bind_vol);
Takashi Iwai532d5382007-07-27 19:02:40 +02001866
1867struct hda_ctl_ops snd_hda_bind_sw = {
1868 .info = snd_hda_mixer_amp_switch_info,
1869 .get = snd_hda_mixer_amp_switch_get,
1870 .put = snd_hda_mixer_amp_switch_put,
1871 .tlv = snd_hda_mixer_amp_tlv
1872};
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001873EXPORT_SYMBOL_HDA(snd_hda_bind_sw);
Takashi Iwai532d5382007-07-27 19:02:40 +02001874
1875/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07001876 * SPDIF out controls
1877 */
1878
Takashi Iwai0ba21762007-04-16 11:29:14 +02001879static int snd_hda_spdif_mask_info(struct snd_kcontrol *kcontrol,
1880 struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001881{
1882 uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
1883 uinfo->count = 1;
1884 return 0;
1885}
1886
Takashi Iwai0ba21762007-04-16 11:29:14 +02001887static int snd_hda_spdif_cmask_get(struct snd_kcontrol *kcontrol,
1888 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001889{
1890 ucontrol->value.iec958.status[0] = IEC958_AES0_PROFESSIONAL |
1891 IEC958_AES0_NONAUDIO |
1892 IEC958_AES0_CON_EMPHASIS_5015 |
1893 IEC958_AES0_CON_NOT_COPYRIGHT;
1894 ucontrol->value.iec958.status[1] = IEC958_AES1_CON_CATEGORY |
1895 IEC958_AES1_CON_ORIGINAL;
1896 return 0;
1897}
1898
Takashi Iwai0ba21762007-04-16 11:29:14 +02001899static int snd_hda_spdif_pmask_get(struct snd_kcontrol *kcontrol,
1900 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001901{
1902 ucontrol->value.iec958.status[0] = IEC958_AES0_PROFESSIONAL |
1903 IEC958_AES0_NONAUDIO |
1904 IEC958_AES0_PRO_EMPHASIS_5015;
1905 return 0;
1906}
1907
Takashi Iwai0ba21762007-04-16 11:29:14 +02001908static int snd_hda_spdif_default_get(struct snd_kcontrol *kcontrol,
1909 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001910{
1911 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1912
1913 ucontrol->value.iec958.status[0] = codec->spdif_status & 0xff;
1914 ucontrol->value.iec958.status[1] = (codec->spdif_status >> 8) & 0xff;
1915 ucontrol->value.iec958.status[2] = (codec->spdif_status >> 16) & 0xff;
1916 ucontrol->value.iec958.status[3] = (codec->spdif_status >> 24) & 0xff;
1917
1918 return 0;
1919}
1920
1921/* convert from SPDIF status bits to HDA SPDIF bits
1922 * bit 0 (DigEn) is always set zero (to be filled later)
1923 */
1924static unsigned short convert_from_spdif_status(unsigned int sbits)
1925{
1926 unsigned short val = 0;
1927
1928 if (sbits & IEC958_AES0_PROFESSIONAL)
Takashi Iwai0ba21762007-04-16 11:29:14 +02001929 val |= AC_DIG1_PROFESSIONAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001930 if (sbits & IEC958_AES0_NONAUDIO)
Takashi Iwai0ba21762007-04-16 11:29:14 +02001931 val |= AC_DIG1_NONAUDIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001932 if (sbits & IEC958_AES0_PROFESSIONAL) {
Takashi Iwai0ba21762007-04-16 11:29:14 +02001933 if ((sbits & IEC958_AES0_PRO_EMPHASIS) ==
1934 IEC958_AES0_PRO_EMPHASIS_5015)
1935 val |= AC_DIG1_EMPHASIS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001936 } else {
Takashi Iwai0ba21762007-04-16 11:29:14 +02001937 if ((sbits & IEC958_AES0_CON_EMPHASIS) ==
1938 IEC958_AES0_CON_EMPHASIS_5015)
1939 val |= AC_DIG1_EMPHASIS;
1940 if (!(sbits & IEC958_AES0_CON_NOT_COPYRIGHT))
1941 val |= AC_DIG1_COPYRIGHT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001942 if (sbits & (IEC958_AES1_CON_ORIGINAL << 8))
Takashi Iwai0ba21762007-04-16 11:29:14 +02001943 val |= AC_DIG1_LEVEL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001944 val |= sbits & (IEC958_AES1_CON_CATEGORY << 8);
1945 }
1946 return val;
1947}
1948
1949/* convert to SPDIF status bits from HDA SPDIF bits
1950 */
1951static unsigned int convert_to_spdif_status(unsigned short val)
1952{
1953 unsigned int sbits = 0;
1954
Takashi Iwai0ba21762007-04-16 11:29:14 +02001955 if (val & AC_DIG1_NONAUDIO)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001956 sbits |= IEC958_AES0_NONAUDIO;
Takashi Iwai0ba21762007-04-16 11:29:14 +02001957 if (val & AC_DIG1_PROFESSIONAL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001958 sbits |= IEC958_AES0_PROFESSIONAL;
1959 if (sbits & IEC958_AES0_PROFESSIONAL) {
Takashi Iwai0ba21762007-04-16 11:29:14 +02001960 if (sbits & AC_DIG1_EMPHASIS)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001961 sbits |= IEC958_AES0_PRO_EMPHASIS_5015;
1962 } else {
Takashi Iwai0ba21762007-04-16 11:29:14 +02001963 if (val & AC_DIG1_EMPHASIS)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001964 sbits |= IEC958_AES0_CON_EMPHASIS_5015;
Takashi Iwai0ba21762007-04-16 11:29:14 +02001965 if (!(val & AC_DIG1_COPYRIGHT))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001966 sbits |= IEC958_AES0_CON_NOT_COPYRIGHT;
Takashi Iwai0ba21762007-04-16 11:29:14 +02001967 if (val & AC_DIG1_LEVEL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001968 sbits |= (IEC958_AES1_CON_ORIGINAL << 8);
1969 sbits |= val & (0x7f << 8);
1970 }
1971 return sbits;
1972}
1973
Takashi Iwai2f728532008-09-25 16:32:41 +02001974/* set digital convert verbs both for the given NID and its slaves */
1975static void set_dig_out(struct hda_codec *codec, hda_nid_t nid,
1976 int verb, int val)
1977{
1978 hda_nid_t *d;
1979
Takashi Iwai9e976972008-11-25 08:17:20 +01001980 snd_hda_codec_write_cache(codec, nid, 0, verb, val);
Takashi Iwai2f728532008-09-25 16:32:41 +02001981 d = codec->slave_dig_outs;
1982 if (!d)
1983 return;
1984 for (; *d; d++)
Takashi Iwai9e976972008-11-25 08:17:20 +01001985 snd_hda_codec_write_cache(codec, *d, 0, verb, val);
Takashi Iwai2f728532008-09-25 16:32:41 +02001986}
1987
1988static inline void set_dig_out_convert(struct hda_codec *codec, hda_nid_t nid,
1989 int dig1, int dig2)
1990{
1991 if (dig1 != -1)
1992 set_dig_out(codec, nid, AC_VERB_SET_DIGI_CONVERT_1, dig1);
1993 if (dig2 != -1)
1994 set_dig_out(codec, nid, AC_VERB_SET_DIGI_CONVERT_2, dig2);
1995}
1996
Takashi Iwai0ba21762007-04-16 11:29:14 +02001997static int snd_hda_spdif_default_put(struct snd_kcontrol *kcontrol,
1998 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001999{
2000 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2001 hda_nid_t nid = kcontrol->private_value;
2002 unsigned short val;
2003 int change;
2004
Ingo Molnar62932df2006-01-16 16:34:20 +01002005 mutex_lock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002006 codec->spdif_status = ucontrol->value.iec958.status[0] |
2007 ((unsigned int)ucontrol->value.iec958.status[1] << 8) |
2008 ((unsigned int)ucontrol->value.iec958.status[2] << 16) |
2009 ((unsigned int)ucontrol->value.iec958.status[3] << 24);
2010 val = convert_from_spdif_status(codec->spdif_status);
2011 val |= codec->spdif_ctls & 1;
2012 change = codec->spdif_ctls != val;
2013 codec->spdif_ctls = val;
2014
Takashi Iwai2f728532008-09-25 16:32:41 +02002015 if (change)
2016 set_dig_out_convert(codec, nid, val & 0xff, (val >> 8) & 0xff);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002017
Ingo Molnar62932df2006-01-16 16:34:20 +01002018 mutex_unlock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002019 return change;
2020}
2021
Takashi Iwaia5ce8892007-07-23 15:42:26 +02002022#define snd_hda_spdif_out_switch_info snd_ctl_boolean_mono_info
Linus Torvalds1da177e2005-04-16 15:20:36 -07002023
Takashi Iwai0ba21762007-04-16 11:29:14 +02002024static int snd_hda_spdif_out_switch_get(struct snd_kcontrol *kcontrol,
2025 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002026{
2027 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2028
Takashi Iwai0ba21762007-04-16 11:29:14 +02002029 ucontrol->value.integer.value[0] = codec->spdif_ctls & AC_DIG1_ENABLE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002030 return 0;
2031}
2032
Takashi Iwai0ba21762007-04-16 11:29:14 +02002033static int snd_hda_spdif_out_switch_put(struct snd_kcontrol *kcontrol,
2034 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002035{
2036 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2037 hda_nid_t nid = kcontrol->private_value;
2038 unsigned short val;
2039 int change;
2040
Ingo Molnar62932df2006-01-16 16:34:20 +01002041 mutex_lock(&codec->spdif_mutex);
Takashi Iwai0ba21762007-04-16 11:29:14 +02002042 val = codec->spdif_ctls & ~AC_DIG1_ENABLE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002043 if (ucontrol->value.integer.value[0])
Takashi Iwai0ba21762007-04-16 11:29:14 +02002044 val |= AC_DIG1_ENABLE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002045 change = codec->spdif_ctls != val;
Takashi Iwai82beb8f2007-08-10 17:09:26 +02002046 if (change) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002047 codec->spdif_ctls = val;
Takashi Iwai2f728532008-09-25 16:32:41 +02002048 set_dig_out_convert(codec, nid, val & 0xff, -1);
Takashi Iwai0ba21762007-04-16 11:29:14 +02002049 /* unmute amp switch (if any) */
2050 if ((get_wcaps(codec, nid) & AC_WCAP_OUT_AMP) &&
Takashi Iwai47fd8302007-08-10 17:11:07 +02002051 (val & AC_DIG1_ENABLE))
2052 snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0,
2053 HDA_AMP_MUTE, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002054 }
Ingo Molnar62932df2006-01-16 16:34:20 +01002055 mutex_unlock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002056 return change;
2057}
2058
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01002059static struct snd_kcontrol_new dig_mixes[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002060 {
2061 .access = SNDRV_CTL_ELEM_ACCESS_READ,
2062 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2063 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,CON_MASK),
2064 .info = snd_hda_spdif_mask_info,
2065 .get = snd_hda_spdif_cmask_get,
2066 },
2067 {
2068 .access = SNDRV_CTL_ELEM_ACCESS_READ,
2069 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2070 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,PRO_MASK),
2071 .info = snd_hda_spdif_mask_info,
2072 .get = snd_hda_spdif_pmask_get,
2073 },
2074 {
2075 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2076 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT),
2077 .info = snd_hda_spdif_mask_info,
2078 .get = snd_hda_spdif_default_get,
2079 .put = snd_hda_spdif_default_put,
2080 },
2081 {
2082 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2083 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,SWITCH),
2084 .info = snd_hda_spdif_out_switch_info,
2085 .get = snd_hda_spdif_out_switch_get,
2086 .put = snd_hda_spdif_out_switch_put,
2087 },
2088 { } /* end */
2089};
2090
Takashi Iwai09f99702008-02-04 12:31:13 +01002091#define SPDIF_MAX_IDX 4 /* 4 instances should be enough to probe */
2092
Linus Torvalds1da177e2005-04-16 15:20:36 -07002093/**
2094 * snd_hda_create_spdif_out_ctls - create Output SPDIF-related controls
2095 * @codec: the HDA codec
2096 * @nid: audio out widget NID
2097 *
2098 * Creates controls related with the SPDIF output.
2099 * Called from each patch supporting the SPDIF out.
2100 *
2101 * Returns 0 if successful, or a negative error code.
2102 */
Takashi Iwai12f288b2007-08-02 15:51:59 +02002103int snd_hda_create_spdif_out_ctls(struct hda_codec *codec, hda_nid_t nid)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002104{
2105 int err;
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01002106 struct snd_kcontrol *kctl;
2107 struct snd_kcontrol_new *dig_mix;
Takashi Iwai09f99702008-02-04 12:31:13 +01002108 int idx;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002109
Takashi Iwai09f99702008-02-04 12:31:13 +01002110 for (idx = 0; idx < SPDIF_MAX_IDX; idx++) {
2111 if (!_snd_hda_find_mixer_ctl(codec, "IEC958 Playback Switch",
2112 idx))
2113 break;
2114 }
2115 if (idx >= SPDIF_MAX_IDX) {
2116 printk(KERN_ERR "hda_codec: too many IEC958 outputs\n");
2117 return -EBUSY;
2118 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002119 for (dig_mix = dig_mixes; dig_mix->name; dig_mix++) {
2120 kctl = snd_ctl_new1(dig_mix, codec);
Takashi Iwaib91f0802008-11-04 08:43:08 +01002121 if (!kctl)
2122 return -ENOMEM;
Takashi Iwai09f99702008-02-04 12:31:13 +01002123 kctl->id.index = idx;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002124 kctl->private_value = nid;
Takashi Iwaid13bd412008-07-30 15:01:45 +02002125 err = snd_hda_ctl_add(codec, kctl);
Takashi Iwai0ba21762007-04-16 11:29:14 +02002126 if (err < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002127 return err;
2128 }
Takashi Iwai0ba21762007-04-16 11:29:14 +02002129 codec->spdif_ctls =
Andrew Paprocki3982d172007-12-19 12:13:44 +01002130 snd_hda_codec_read(codec, nid, 0,
2131 AC_VERB_GET_DIGI_CONVERT_1, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002132 codec->spdif_status = convert_to_spdif_status(codec->spdif_ctls);
2133 return 0;
2134}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002135EXPORT_SYMBOL_HDA(snd_hda_create_spdif_out_ctls);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002136
2137/*
Takashi Iwai9a081602008-02-12 18:37:26 +01002138 * SPDIF sharing with analog output
2139 */
2140static int spdif_share_sw_get(struct snd_kcontrol *kcontrol,
2141 struct snd_ctl_elem_value *ucontrol)
2142{
2143 struct hda_multi_out *mout = snd_kcontrol_chip(kcontrol);
2144 ucontrol->value.integer.value[0] = mout->share_spdif;
2145 return 0;
2146}
2147
2148static int spdif_share_sw_put(struct snd_kcontrol *kcontrol,
2149 struct snd_ctl_elem_value *ucontrol)
2150{
2151 struct hda_multi_out *mout = snd_kcontrol_chip(kcontrol);
2152 mout->share_spdif = !!ucontrol->value.integer.value[0];
2153 return 0;
2154}
2155
2156static struct snd_kcontrol_new spdif_share_sw = {
2157 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2158 .name = "IEC958 Default PCM Playback Switch",
2159 .info = snd_ctl_boolean_mono_info,
2160 .get = spdif_share_sw_get,
2161 .put = spdif_share_sw_put,
2162};
2163
2164int snd_hda_create_spdif_share_sw(struct hda_codec *codec,
2165 struct hda_multi_out *mout)
2166{
2167 if (!mout->dig_out_nid)
2168 return 0;
2169 /* ATTENTION: here mout is passed as private_data, instead of codec */
Takashi Iwaid13bd412008-07-30 15:01:45 +02002170 return snd_hda_ctl_add(codec,
Takashi Iwai9a081602008-02-12 18:37:26 +01002171 snd_ctl_new1(&spdif_share_sw, mout));
2172}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002173EXPORT_SYMBOL_HDA(snd_hda_create_spdif_share_sw);
Takashi Iwai9a081602008-02-12 18:37:26 +01002174
2175/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002176 * SPDIF input
2177 */
2178
2179#define snd_hda_spdif_in_switch_info snd_hda_spdif_out_switch_info
2180
Takashi Iwai0ba21762007-04-16 11:29:14 +02002181static int snd_hda_spdif_in_switch_get(struct snd_kcontrol *kcontrol,
2182 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002183{
2184 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2185
2186 ucontrol->value.integer.value[0] = codec->spdif_in_enable;
2187 return 0;
2188}
2189
Takashi Iwai0ba21762007-04-16 11:29:14 +02002190static int snd_hda_spdif_in_switch_put(struct snd_kcontrol *kcontrol,
2191 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002192{
2193 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2194 hda_nid_t nid = kcontrol->private_value;
2195 unsigned int val = !!ucontrol->value.integer.value[0];
2196 int change;
2197
Ingo Molnar62932df2006-01-16 16:34:20 +01002198 mutex_lock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002199 change = codec->spdif_in_enable != val;
Takashi Iwai82beb8f2007-08-10 17:09:26 +02002200 if (change) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002201 codec->spdif_in_enable = val;
Takashi Iwai82beb8f2007-08-10 17:09:26 +02002202 snd_hda_codec_write_cache(codec, nid, 0,
2203 AC_VERB_SET_DIGI_CONVERT_1, val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002204 }
Ingo Molnar62932df2006-01-16 16:34:20 +01002205 mutex_unlock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002206 return change;
2207}
2208
Takashi Iwai0ba21762007-04-16 11:29:14 +02002209static int snd_hda_spdif_in_status_get(struct snd_kcontrol *kcontrol,
2210 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002211{
2212 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2213 hda_nid_t nid = kcontrol->private_value;
2214 unsigned short val;
2215 unsigned int sbits;
2216
Andrew Paprocki3982d172007-12-19 12:13:44 +01002217 val = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_DIGI_CONVERT_1, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002218 sbits = convert_to_spdif_status(val);
2219 ucontrol->value.iec958.status[0] = sbits;
2220 ucontrol->value.iec958.status[1] = sbits >> 8;
2221 ucontrol->value.iec958.status[2] = sbits >> 16;
2222 ucontrol->value.iec958.status[3] = sbits >> 24;
2223 return 0;
2224}
2225
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01002226static struct snd_kcontrol_new dig_in_ctls[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002227 {
2228 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2229 .name = SNDRV_CTL_NAME_IEC958("",CAPTURE,SWITCH),
2230 .info = snd_hda_spdif_in_switch_info,
2231 .get = snd_hda_spdif_in_switch_get,
2232 .put = snd_hda_spdif_in_switch_put,
2233 },
2234 {
2235 .access = SNDRV_CTL_ELEM_ACCESS_READ,
2236 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2237 .name = SNDRV_CTL_NAME_IEC958("",CAPTURE,DEFAULT),
2238 .info = snd_hda_spdif_mask_info,
2239 .get = snd_hda_spdif_in_status_get,
2240 },
2241 { } /* end */
2242};
2243
2244/**
2245 * snd_hda_create_spdif_in_ctls - create Input SPDIF-related controls
2246 * @codec: the HDA codec
2247 * @nid: audio in widget NID
2248 *
2249 * Creates controls related with the SPDIF input.
2250 * Called from each patch supporting the SPDIF in.
2251 *
2252 * Returns 0 if successful, or a negative error code.
2253 */
Takashi Iwai12f288b2007-08-02 15:51:59 +02002254int snd_hda_create_spdif_in_ctls(struct hda_codec *codec, hda_nid_t nid)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002255{
2256 int err;
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01002257 struct snd_kcontrol *kctl;
2258 struct snd_kcontrol_new *dig_mix;
Takashi Iwai09f99702008-02-04 12:31:13 +01002259 int idx;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002260
Takashi Iwai09f99702008-02-04 12:31:13 +01002261 for (idx = 0; idx < SPDIF_MAX_IDX; idx++) {
2262 if (!_snd_hda_find_mixer_ctl(codec, "IEC958 Capture Switch",
2263 idx))
2264 break;
2265 }
2266 if (idx >= SPDIF_MAX_IDX) {
2267 printk(KERN_ERR "hda_codec: too many IEC958 inputs\n");
2268 return -EBUSY;
2269 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002270 for (dig_mix = dig_in_ctls; dig_mix->name; dig_mix++) {
2271 kctl = snd_ctl_new1(dig_mix, codec);
Takashi Iwaic8dcdf82009-02-06 16:21:20 +01002272 if (!kctl)
2273 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002274 kctl->private_value = nid;
Takashi Iwaid13bd412008-07-30 15:01:45 +02002275 err = snd_hda_ctl_add(codec, kctl);
Takashi Iwai0ba21762007-04-16 11:29:14 +02002276 if (err < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002277 return err;
2278 }
Takashi Iwai0ba21762007-04-16 11:29:14 +02002279 codec->spdif_in_enable =
Andrew Paprocki3982d172007-12-19 12:13:44 +01002280 snd_hda_codec_read(codec, nid, 0,
2281 AC_VERB_GET_DIGI_CONVERT_1, 0) &
Takashi Iwai0ba21762007-04-16 11:29:14 +02002282 AC_DIG1_ENABLE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002283 return 0;
2284}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002285EXPORT_SYMBOL_HDA(snd_hda_create_spdif_in_ctls);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002286
Takashi Iwaicb53c622007-08-10 17:21:45 +02002287#ifdef SND_HDA_NEEDS_RESUME
Takashi Iwai82beb8f2007-08-10 17:09:26 +02002288/*
2289 * command cache
2290 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002291
Takashi Iwaib3ac5632007-08-10 17:03:40 +02002292/* build a 32bit cache key with the widget id and the command parameter */
2293#define build_cmd_cache_key(nid, verb) ((verb << 8) | nid)
2294#define get_cmd_cache_nid(key) ((key) & 0xff)
2295#define get_cmd_cache_cmd(key) (((key) >> 8) & 0xffff)
2296
2297/**
2298 * snd_hda_codec_write_cache - send a single command with caching
2299 * @codec: the HDA codec
2300 * @nid: NID to send the command
2301 * @direct: direct flag
2302 * @verb: the verb to send
2303 * @parm: the parameter for the verb
2304 *
2305 * Send a single command without waiting for response.
2306 *
2307 * Returns 0 if successful, or a negative error code.
2308 */
2309int snd_hda_codec_write_cache(struct hda_codec *codec, hda_nid_t nid,
2310 int direct, unsigned int verb, unsigned int parm)
2311{
Takashi Iwaiaa2936f2009-05-26 16:07:57 +02002312 int err = snd_hda_codec_write(codec, nid, direct, verb, parm);
2313 struct hda_cache_head *c;
2314 u32 key;
Takashi Iwai33fa35e2008-11-06 16:50:40 +01002315
Takashi Iwaiaa2936f2009-05-26 16:07:57 +02002316 if (err < 0)
2317 return err;
2318 /* parm may contain the verb stuff for get/set amp */
2319 verb = verb | (parm >> 8);
2320 parm &= 0xff;
2321 key = build_cmd_cache_key(nid, verb);
2322 mutex_lock(&codec->bus->cmd_mutex);
2323 c = get_alloc_hash(&codec->cmd_cache, key);
2324 if (c)
2325 c->val = parm;
2326 mutex_unlock(&codec->bus->cmd_mutex);
2327 return 0;
Takashi Iwaib3ac5632007-08-10 17:03:40 +02002328}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002329EXPORT_SYMBOL_HDA(snd_hda_codec_write_cache);
Takashi Iwaib3ac5632007-08-10 17:03:40 +02002330
2331/* resume the all commands from the cache */
2332void snd_hda_codec_resume_cache(struct hda_codec *codec)
2333{
Takashi Iwai603c4012008-07-30 15:01:44 +02002334 struct hda_cache_head *buffer = codec->cmd_cache.buf.list;
Takashi Iwaib3ac5632007-08-10 17:03:40 +02002335 int i;
2336
Takashi Iwai603c4012008-07-30 15:01:44 +02002337 for (i = 0; i < codec->cmd_cache.buf.used; i++, buffer++) {
Takashi Iwaib3ac5632007-08-10 17:03:40 +02002338 u32 key = buffer->key;
2339 if (!key)
2340 continue;
2341 snd_hda_codec_write(codec, get_cmd_cache_nid(key), 0,
2342 get_cmd_cache_cmd(key), buffer->val);
2343 }
2344}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002345EXPORT_SYMBOL_HDA(snd_hda_codec_resume_cache);
Takashi Iwaib3ac5632007-08-10 17:03:40 +02002346
2347/**
2348 * snd_hda_sequence_write_cache - sequence writes with caching
2349 * @codec: the HDA codec
2350 * @seq: VERB array to send
2351 *
2352 * Send the commands sequentially from the given array.
2353 * Thte commands are recorded on cache for power-save and resume.
2354 * The array must be terminated with NID=0.
2355 */
2356void snd_hda_sequence_write_cache(struct hda_codec *codec,
2357 const struct hda_verb *seq)
2358{
2359 for (; seq->nid; seq++)
2360 snd_hda_codec_write_cache(codec, seq->nid, 0, seq->verb,
2361 seq->param);
2362}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002363EXPORT_SYMBOL_HDA(snd_hda_sequence_write_cache);
Takashi Iwaicb53c622007-08-10 17:21:45 +02002364#endif /* SND_HDA_NEEDS_RESUME */
Takashi Iwaib3ac5632007-08-10 17:03:40 +02002365
Takashi Iwai54d17402005-11-21 16:33:22 +01002366/*
2367 * set power state of the codec
2368 */
2369static void hda_set_power_state(struct hda_codec *codec, hda_nid_t fg,
2370 unsigned int power_state)
2371{
Takashi Iwaicb53c622007-08-10 17:21:45 +02002372 hda_nid_t nid;
2373 int i;
Takashi Iwai54d17402005-11-21 16:33:22 +01002374
Takashi Iwai05ff7e12009-07-22 12:39:24 +02002375 /* this delay seems necessary to avoid click noise at power-down */
2376 if (power_state == AC_PWRST_D3)
2377 msleep(100);
2378 snd_hda_codec_read(codec, fg, 0, AC_VERB_SET_POWER_STATE,
Takashi Iwai54d17402005-11-21 16:33:22 +01002379 power_state);
Takashi Iwai05ff7e12009-07-22 12:39:24 +02002380 /* partial workaround for "azx_get_response timeout" */
2381 if (power_state == AC_PWRST_D0)
2382 msleep(10);
Takashi Iwai54d17402005-11-21 16:33:22 +01002383
Takashi Iwaicb53c622007-08-10 17:21:45 +02002384 nid = codec->start_nid;
2385 for (i = 0; i < codec->num_nodes; i++, nid++) {
Takashi Iwai7eba5c92007-11-14 14:53:42 +01002386 unsigned int wcaps = get_wcaps(codec, nid);
2387 if (wcaps & AC_WCAP_POWER) {
Takashi Iwaia22d5432009-07-27 12:54:26 +02002388 unsigned int wid_type = get_wcaps_type(wcaps);
Takashi Iwaia3b48c82009-04-21 13:37:29 +02002389 if (power_state == AC_PWRST_D3 &&
2390 wid_type == AC_WID_PIN) {
Takashi Iwai7eba5c92007-11-14 14:53:42 +01002391 unsigned int pincap;
2392 /*
2393 * don't power down the widget if it controls
2394 * eapd and EAPD_BTLENABLE is set.
2395 */
Takashi Iwai14bafe32009-03-23 16:35:39 +01002396 pincap = snd_hda_query_pin_caps(codec, nid);
Takashi Iwai7eba5c92007-11-14 14:53:42 +01002397 if (pincap & AC_PINCAP_EAPD) {
2398 int eapd = snd_hda_codec_read(codec,
2399 nid, 0,
2400 AC_VERB_GET_EAPD_BTLENABLE, 0);
2401 eapd &= 0x02;
Takashi Iwaia3b48c82009-04-21 13:37:29 +02002402 if (eapd)
Takashi Iwai7eba5c92007-11-14 14:53:42 +01002403 continue;
2404 }
Takashi Iwai1194b5b2007-10-10 10:04:26 +02002405 }
Takashi Iwai54d17402005-11-21 16:33:22 +01002406 snd_hda_codec_write(codec, nid, 0,
2407 AC_VERB_SET_POWER_STATE,
2408 power_state);
Takashi Iwai1194b5b2007-10-10 10:04:26 +02002409 }
Takashi Iwai54d17402005-11-21 16:33:22 +01002410 }
2411
Takashi Iwaicb53c622007-08-10 17:21:45 +02002412 if (power_state == AC_PWRST_D0) {
2413 unsigned long end_time;
2414 int state;
Takashi Iwai54d17402005-11-21 16:33:22 +01002415 msleep(10);
Takashi Iwaicb53c622007-08-10 17:21:45 +02002416 /* wait until the codec reachs to D0 */
2417 end_time = jiffies + msecs_to_jiffies(500);
2418 do {
2419 state = snd_hda_codec_read(codec, fg, 0,
2420 AC_VERB_GET_POWER_STATE, 0);
2421 if (state == power_state)
2422 break;
2423 msleep(1);
2424 } while (time_after_eq(end_time, jiffies));
2425 }
Takashi Iwai54d17402005-11-21 16:33:22 +01002426}
2427
Takashi Iwai11aeff02008-07-30 15:01:46 +02002428#ifdef CONFIG_SND_HDA_HWDEP
2429/* execute additional init verbs */
2430static void hda_exec_init_verbs(struct hda_codec *codec)
2431{
2432 if (codec->init_verbs.list)
2433 snd_hda_sequence_write(codec, codec->init_verbs.list);
2434}
2435#else
2436static inline void hda_exec_init_verbs(struct hda_codec *codec) {}
2437#endif
2438
Takashi Iwaicb53c622007-08-10 17:21:45 +02002439#ifdef SND_HDA_NEEDS_RESUME
2440/*
2441 * call suspend and power-down; used both from PM and power-save
2442 */
2443static void hda_call_codec_suspend(struct hda_codec *codec)
2444{
2445 if (codec->patch_ops.suspend)
2446 codec->patch_ops.suspend(codec, PMSG_SUSPEND);
2447 hda_set_power_state(codec,
2448 codec->afg ? codec->afg : codec->mfg,
2449 AC_PWRST_D3);
2450#ifdef CONFIG_SND_HDA_POWER_SAVE
2451 cancel_delayed_work(&codec->power_work);
Takashi Iwai95e99fd2007-08-13 15:29:04 +02002452 codec->power_on = 0;
Takashi Iwaia221e282007-08-16 16:35:33 +02002453 codec->power_transition = 0;
Takashi Iwaicb53c622007-08-10 17:21:45 +02002454#endif
2455}
2456
2457/*
2458 * kick up codec; used both from PM and power-save
2459 */
2460static void hda_call_codec_resume(struct hda_codec *codec)
2461{
2462 hda_set_power_state(codec,
2463 codec->afg ? codec->afg : codec->mfg,
2464 AC_PWRST_D0);
Takashi Iwai3be14142009-02-20 14:11:16 +01002465 restore_pincfgs(codec); /* restore all current pin configs */
Takashi Iwai11aeff02008-07-30 15:01:46 +02002466 hda_exec_init_verbs(codec);
Takashi Iwaicb53c622007-08-10 17:21:45 +02002467 if (codec->patch_ops.resume)
2468 codec->patch_ops.resume(codec);
2469 else {
Takashi Iwai9d99f312007-08-14 15:15:52 +02002470 if (codec->patch_ops.init)
2471 codec->patch_ops.init(codec);
Takashi Iwaicb53c622007-08-10 17:21:45 +02002472 snd_hda_codec_resume_amp(codec);
2473 snd_hda_codec_resume_cache(codec);
2474 }
2475}
2476#endif /* SND_HDA_NEEDS_RESUME */
2477
Takashi Iwai54d17402005-11-21 16:33:22 +01002478
Linus Torvalds1da177e2005-04-16 15:20:36 -07002479/**
2480 * snd_hda_build_controls - build mixer controls
2481 * @bus: the BUS
2482 *
2483 * Creates mixer controls for each codec included in the bus.
2484 *
2485 * Returns 0 if successful, otherwise a negative error code.
2486 */
Takashi Iwai1289e9e2008-11-27 15:47:11 +01002487int /*__devinit*/ snd_hda_build_controls(struct hda_bus *bus)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002488{
Takashi Iwai0ba21762007-04-16 11:29:14 +02002489 struct hda_codec *codec;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002490
Takashi Iwai0ba21762007-04-16 11:29:14 +02002491 list_for_each_entry(codec, &bus->codec_list, list) {
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02002492 int err = snd_hda_codec_build_controls(codec);
Takashi Iwaif93d4612009-03-02 10:44:15 +01002493 if (err < 0) {
2494 printk(KERN_ERR "hda_codec: cannot build controls"
2495 "for #%d (error %d)\n", codec->addr, err);
2496 err = snd_hda_codec_reset(codec);
2497 if (err < 0) {
2498 printk(KERN_ERR
2499 "hda_codec: cannot revert codec\n");
2500 return err;
2501 }
2502 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002503 }
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02002504 return 0;
2505}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002506EXPORT_SYMBOL_HDA(snd_hda_build_controls);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002507
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02002508int snd_hda_codec_build_controls(struct hda_codec *codec)
2509{
2510 int err = 0;
Takashi Iwai11aeff02008-07-30 15:01:46 +02002511 hda_exec_init_verbs(codec);
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02002512 /* continue to initialize... */
2513 if (codec->patch_ops.init)
2514 err = codec->patch_ops.init(codec);
2515 if (!err && codec->patch_ops.build_controls)
2516 err = codec->patch_ops.build_controls(codec);
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02002517 if (err < 0)
2518 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002519 return 0;
2520}
2521
Linus Torvalds1da177e2005-04-16 15:20:36 -07002522/*
2523 * stream formats
2524 */
Takashi Iwaibefdf312005-08-22 13:57:55 +02002525struct hda_rate_tbl {
2526 unsigned int hz;
2527 unsigned int alsa_bits;
2528 unsigned int hda_fmt;
2529};
2530
2531static struct hda_rate_tbl rate_bits[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002532 /* rate in Hz, ALSA rate bitmask, HDA format value */
Nicolas Graziano9d8f53f2005-08-22 13:47:16 +02002533
2534 /* autodetected value used in snd_hda_query_supported_pcm */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002535 { 8000, SNDRV_PCM_RATE_8000, 0x0500 }, /* 1/6 x 48 */
2536 { 11025, SNDRV_PCM_RATE_11025, 0x4300 }, /* 1/4 x 44 */
2537 { 16000, SNDRV_PCM_RATE_16000, 0x0200 }, /* 1/3 x 48 */
2538 { 22050, SNDRV_PCM_RATE_22050, 0x4100 }, /* 1/2 x 44 */
2539 { 32000, SNDRV_PCM_RATE_32000, 0x0a00 }, /* 2/3 x 48 */
2540 { 44100, SNDRV_PCM_RATE_44100, 0x4000 }, /* 44 */
2541 { 48000, SNDRV_PCM_RATE_48000, 0x0000 }, /* 48 */
2542 { 88200, SNDRV_PCM_RATE_88200, 0x4800 }, /* 2 x 44 */
2543 { 96000, SNDRV_PCM_RATE_96000, 0x0800 }, /* 2 x 48 */
2544 { 176400, SNDRV_PCM_RATE_176400, 0x5800 },/* 4 x 44 */
2545 { 192000, SNDRV_PCM_RATE_192000, 0x1800 }, /* 4 x 48 */
Takashi Iwaia961f9f2007-04-12 13:08:09 +02002546#define AC_PAR_PCM_RATE_BITS 11
2547 /* up to bits 10, 384kHZ isn't supported properly */
2548
2549 /* not autodetected value */
2550 { 9600, SNDRV_PCM_RATE_KNOT, 0x0400 }, /* 1/5 x 48 */
Nicolas Graziano9d8f53f2005-08-22 13:47:16 +02002551
Takashi Iwaibefdf312005-08-22 13:57:55 +02002552 { 0 } /* terminator */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002553};
2554
2555/**
2556 * snd_hda_calc_stream_format - calculate format bitset
2557 * @rate: the sample rate
2558 * @channels: the number of channels
2559 * @format: the PCM format (SNDRV_PCM_FORMAT_XXX)
2560 * @maxbps: the max. bps
2561 *
2562 * Calculate the format bitset from the given rate, channels and th PCM format.
2563 *
2564 * Return zero if invalid.
2565 */
2566unsigned int snd_hda_calc_stream_format(unsigned int rate,
2567 unsigned int channels,
2568 unsigned int format,
2569 unsigned int maxbps)
2570{
2571 int i;
2572 unsigned int val = 0;
2573
Takashi Iwaibefdf312005-08-22 13:57:55 +02002574 for (i = 0; rate_bits[i].hz; i++)
2575 if (rate_bits[i].hz == rate) {
2576 val = rate_bits[i].hda_fmt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002577 break;
2578 }
Takashi Iwai0ba21762007-04-16 11:29:14 +02002579 if (!rate_bits[i].hz) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002580 snd_printdd("invalid rate %d\n", rate);
2581 return 0;
2582 }
2583
2584 if (channels == 0 || channels > 8) {
2585 snd_printdd("invalid channels %d\n", channels);
2586 return 0;
2587 }
2588 val |= channels - 1;
2589
2590 switch (snd_pcm_format_width(format)) {
2591 case 8: val |= 0x00; break;
2592 case 16: val |= 0x10; break;
2593 case 20:
2594 case 24:
2595 case 32:
Takashi Iwaib0bb3aa2009-07-03 23:25:37 +02002596 if (maxbps >= 32 || format == SNDRV_PCM_FORMAT_FLOAT_LE)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002597 val |= 0x40;
2598 else if (maxbps >= 24)
2599 val |= 0x30;
2600 else
2601 val |= 0x20;
2602 break;
2603 default:
Takashi Iwai0ba21762007-04-16 11:29:14 +02002604 snd_printdd("invalid format width %d\n",
2605 snd_pcm_format_width(format));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002606 return 0;
2607 }
2608
2609 return val;
2610}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002611EXPORT_SYMBOL_HDA(snd_hda_calc_stream_format);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002612
Takashi Iwai92c7c8a2009-03-24 07:32:14 +01002613static unsigned int get_pcm_param(struct hda_codec *codec, hda_nid_t nid)
2614{
2615 unsigned int val = 0;
2616 if (nid != codec->afg &&
2617 (get_wcaps(codec, nid) & AC_WCAP_FORMAT_OVRD))
2618 val = snd_hda_param_read(codec, nid, AC_PAR_PCM);
2619 if (!val || val == -1)
2620 val = snd_hda_param_read(codec, codec->afg, AC_PAR_PCM);
2621 if (!val || val == -1)
2622 return 0;
2623 return val;
2624}
2625
2626static unsigned int query_pcm_param(struct hda_codec *codec, hda_nid_t nid)
2627{
2628 return query_caps_hash(codec, nid, HDA_HASH_PARPCM_KEY(nid),
2629 get_pcm_param);
2630}
2631
2632static unsigned int get_stream_param(struct hda_codec *codec, hda_nid_t nid)
2633{
2634 unsigned int streams = snd_hda_param_read(codec, nid, AC_PAR_STREAM);
2635 if (!streams || streams == -1)
2636 streams = snd_hda_param_read(codec, codec->afg, AC_PAR_STREAM);
2637 if (!streams || streams == -1)
2638 return 0;
2639 return streams;
2640}
2641
2642static unsigned int query_stream_param(struct hda_codec *codec, hda_nid_t nid)
2643{
2644 return query_caps_hash(codec, nid, HDA_HASH_PARSTR_KEY(nid),
2645 get_stream_param);
2646}
2647
Linus Torvalds1da177e2005-04-16 15:20:36 -07002648/**
2649 * snd_hda_query_supported_pcm - query the supported PCM rates and formats
2650 * @codec: the HDA codec
2651 * @nid: NID to query
2652 * @ratesp: the pointer to store the detected rate bitflags
2653 * @formatsp: the pointer to store the detected formats
2654 * @bpsp: the pointer to store the detected format widths
2655 *
2656 * Queries the supported PCM rates and formats. The NULL @ratesp, @formatsp
2657 * or @bsps argument is ignored.
2658 *
2659 * Returns 0 if successful, otherwise a negative error code.
2660 */
Takashi Iwai986862bd2008-11-27 12:40:13 +01002661static int snd_hda_query_supported_pcm(struct hda_codec *codec, hda_nid_t nid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002662 u32 *ratesp, u64 *formatsp, unsigned int *bpsp)
2663{
Jaroslav Kyselaee504712009-03-17 14:30:31 +01002664 unsigned int i, val, wcaps;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002665
Jaroslav Kyselaee504712009-03-17 14:30:31 +01002666 wcaps = get_wcaps(codec, nid);
Takashi Iwai92c7c8a2009-03-24 07:32:14 +01002667 val = query_pcm_param(codec, nid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002668
2669 if (ratesp) {
2670 u32 rates = 0;
Takashi Iwaia961f9f2007-04-12 13:08:09 +02002671 for (i = 0; i < AC_PAR_PCM_RATE_BITS; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002672 if (val & (1 << i))
Takashi Iwaibefdf312005-08-22 13:57:55 +02002673 rates |= rate_bits[i].alsa_bits;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002674 }
Jaroslav Kyselaee504712009-03-17 14:30:31 +01002675 if (rates == 0) {
2676 snd_printk(KERN_ERR "hda_codec: rates == 0 "
2677 "(nid=0x%x, val=0x%x, ovrd=%i)\n",
2678 nid, val,
2679 (wcaps & AC_WCAP_FORMAT_OVRD) ? 1 : 0);
2680 return -EIO;
2681 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002682 *ratesp = rates;
2683 }
2684
2685 if (formatsp || bpsp) {
2686 u64 formats = 0;
Jaroslav Kyselaee504712009-03-17 14:30:31 +01002687 unsigned int streams, bps;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002688
Takashi Iwai92c7c8a2009-03-24 07:32:14 +01002689 streams = query_stream_param(codec, nid);
2690 if (!streams)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002691 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002692
2693 bps = 0;
2694 if (streams & AC_SUPFMT_PCM) {
2695 if (val & AC_SUPPCM_BITS_8) {
2696 formats |= SNDRV_PCM_FMTBIT_U8;
2697 bps = 8;
2698 }
2699 if (val & AC_SUPPCM_BITS_16) {
2700 formats |= SNDRV_PCM_FMTBIT_S16_LE;
2701 bps = 16;
2702 }
2703 if (wcaps & AC_WCAP_DIGITAL) {
2704 if (val & AC_SUPPCM_BITS_32)
2705 formats |= SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_LE;
2706 if (val & (AC_SUPPCM_BITS_20|AC_SUPPCM_BITS_24))
2707 formats |= SNDRV_PCM_FMTBIT_S32_LE;
2708 if (val & AC_SUPPCM_BITS_24)
2709 bps = 24;
2710 else if (val & AC_SUPPCM_BITS_20)
2711 bps = 20;
Takashi Iwai0ba21762007-04-16 11:29:14 +02002712 } else if (val & (AC_SUPPCM_BITS_20|AC_SUPPCM_BITS_24|
2713 AC_SUPPCM_BITS_32)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002714 formats |= SNDRV_PCM_FMTBIT_S32_LE;
2715 if (val & AC_SUPPCM_BITS_32)
2716 bps = 32;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002717 else if (val & AC_SUPPCM_BITS_24)
2718 bps = 24;
Nicolas Graziano33ef76512006-09-19 14:23:14 +02002719 else if (val & AC_SUPPCM_BITS_20)
2720 bps = 20;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002721 }
2722 }
Takashi Iwaib5025c52009-07-01 18:05:27 +02002723 if (streams & AC_SUPFMT_FLOAT32) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002724 formats |= SNDRV_PCM_FMTBIT_FLOAT_LE;
Takashi Iwaib0bb3aa2009-07-03 23:25:37 +02002725 if (!bps)
2726 bps = 32;
Takashi Iwaib5025c52009-07-01 18:05:27 +02002727 }
2728 if (streams == AC_SUPFMT_AC3) {
Takashi Iwai0ba21762007-04-16 11:29:14 +02002729 /* should be exclusive */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002730 /* temporary hack: we have still no proper support
2731 * for the direct AC3 stream...
2732 */
2733 formats |= SNDRV_PCM_FMTBIT_U8;
2734 bps = 8;
2735 }
Jaroslav Kyselaee504712009-03-17 14:30:31 +01002736 if (formats == 0) {
2737 snd_printk(KERN_ERR "hda_codec: formats == 0 "
2738 "(nid=0x%x, val=0x%x, ovrd=%i, "
2739 "streams=0x%x)\n",
2740 nid, val,
2741 (wcaps & AC_WCAP_FORMAT_OVRD) ? 1 : 0,
2742 streams);
2743 return -EIO;
2744 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002745 if (formatsp)
2746 *formatsp = formats;
2747 if (bpsp)
2748 *bpsp = bps;
2749 }
2750
2751 return 0;
2752}
2753
2754/**
Takashi Iwai0ba21762007-04-16 11:29:14 +02002755 * snd_hda_is_supported_format - check whether the given node supports
2756 * the format val
Linus Torvalds1da177e2005-04-16 15:20:36 -07002757 *
2758 * Returns 1 if supported, 0 if not.
2759 */
2760int snd_hda_is_supported_format(struct hda_codec *codec, hda_nid_t nid,
2761 unsigned int format)
2762{
2763 int i;
2764 unsigned int val = 0, rate, stream;
2765
Takashi Iwai92c7c8a2009-03-24 07:32:14 +01002766 val = query_pcm_param(codec, nid);
2767 if (!val)
2768 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002769
2770 rate = format & 0xff00;
Takashi Iwaia961f9f2007-04-12 13:08:09 +02002771 for (i = 0; i < AC_PAR_PCM_RATE_BITS; i++)
Takashi Iwaibefdf312005-08-22 13:57:55 +02002772 if (rate_bits[i].hda_fmt == rate) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002773 if (val & (1 << i))
2774 break;
2775 return 0;
2776 }
Takashi Iwaia961f9f2007-04-12 13:08:09 +02002777 if (i >= AC_PAR_PCM_RATE_BITS)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002778 return 0;
2779
Takashi Iwai92c7c8a2009-03-24 07:32:14 +01002780 stream = query_stream_param(codec, nid);
2781 if (!stream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002782 return 0;
2783
2784 if (stream & AC_SUPFMT_PCM) {
2785 switch (format & 0xf0) {
2786 case 0x00:
Takashi Iwai0ba21762007-04-16 11:29:14 +02002787 if (!(val & AC_SUPPCM_BITS_8))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002788 return 0;
2789 break;
2790 case 0x10:
Takashi Iwai0ba21762007-04-16 11:29:14 +02002791 if (!(val & AC_SUPPCM_BITS_16))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002792 return 0;
2793 break;
2794 case 0x20:
Takashi Iwai0ba21762007-04-16 11:29:14 +02002795 if (!(val & AC_SUPPCM_BITS_20))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002796 return 0;
2797 break;
2798 case 0x30:
Takashi Iwai0ba21762007-04-16 11:29:14 +02002799 if (!(val & AC_SUPPCM_BITS_24))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002800 return 0;
2801 break;
2802 case 0x40:
Takashi Iwai0ba21762007-04-16 11:29:14 +02002803 if (!(val & AC_SUPPCM_BITS_32))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002804 return 0;
2805 break;
2806 default:
2807 return 0;
2808 }
2809 } else {
2810 /* FIXME: check for float32 and AC3? */
2811 }
2812
2813 return 1;
2814}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002815EXPORT_SYMBOL_HDA(snd_hda_is_supported_format);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002816
2817/*
2818 * PCM stuff
2819 */
2820static int hda_pcm_default_open_close(struct hda_pcm_stream *hinfo,
2821 struct hda_codec *codec,
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01002822 struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002823{
2824 return 0;
2825}
2826
2827static int hda_pcm_default_prepare(struct hda_pcm_stream *hinfo,
2828 struct hda_codec *codec,
2829 unsigned int stream_tag,
2830 unsigned int format,
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01002831 struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002832{
2833 snd_hda_codec_setup_stream(codec, hinfo->nid, stream_tag, 0, format);
2834 return 0;
2835}
2836
2837static int hda_pcm_default_cleanup(struct hda_pcm_stream *hinfo,
2838 struct hda_codec *codec,
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01002839 struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002840{
Takashi Iwai888afa12008-03-18 09:57:50 +01002841 snd_hda_codec_cleanup_stream(codec, hinfo->nid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002842 return 0;
2843}
2844
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02002845static int set_pcm_default_values(struct hda_codec *codec,
2846 struct hda_pcm_stream *info)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002847{
Jaroslav Kyselaee504712009-03-17 14:30:31 +01002848 int err;
2849
Takashi Iwai0ba21762007-04-16 11:29:14 +02002850 /* query support PCM information from the given NID */
2851 if (info->nid && (!info->rates || !info->formats)) {
Jaroslav Kyselaee504712009-03-17 14:30:31 +01002852 err = snd_hda_query_supported_pcm(codec, info->nid,
Takashi Iwai0ba21762007-04-16 11:29:14 +02002853 info->rates ? NULL : &info->rates,
2854 info->formats ? NULL : &info->formats,
2855 info->maxbps ? NULL : &info->maxbps);
Jaroslav Kyselaee504712009-03-17 14:30:31 +01002856 if (err < 0)
2857 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002858 }
2859 if (info->ops.open == NULL)
2860 info->ops.open = hda_pcm_default_open_close;
2861 if (info->ops.close == NULL)
2862 info->ops.close = hda_pcm_default_open_close;
2863 if (info->ops.prepare == NULL) {
Takashi Iwaida3cec32008-08-08 17:12:14 +02002864 if (snd_BUG_ON(!info->nid))
2865 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002866 info->ops.prepare = hda_pcm_default_prepare;
2867 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002868 if (info->ops.cleanup == NULL) {
Takashi Iwaida3cec32008-08-08 17:12:14 +02002869 if (snd_BUG_ON(!info->nid))
2870 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002871 info->ops.cleanup = hda_pcm_default_cleanup;
2872 }
2873 return 0;
2874}
2875
Takashi Iwai176d5332008-07-30 15:01:44 +02002876/*
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002877 * get the empty PCM device number to assign
2878 */
2879static int get_empty_pcm_device(struct hda_bus *bus, int type)
2880{
2881 static const char *dev_name[HDA_PCM_NTYPES] = {
2882 "Audio", "SPDIF", "HDMI", "Modem"
2883 };
2884 /* starting device index for each PCM type */
2885 static int dev_idx[HDA_PCM_NTYPES] = {
2886 [HDA_PCM_TYPE_AUDIO] = 0,
2887 [HDA_PCM_TYPE_SPDIF] = 1,
2888 [HDA_PCM_TYPE_HDMI] = 3,
2889 [HDA_PCM_TYPE_MODEM] = 6
2890 };
2891 /* normal audio device indices; not linear to keep compatibility */
2892 static int audio_idx[4] = { 0, 2, 4, 5 };
2893 int i, dev;
2894
2895 switch (type) {
2896 case HDA_PCM_TYPE_AUDIO:
2897 for (i = 0; i < ARRAY_SIZE(audio_idx); i++) {
2898 dev = audio_idx[i];
2899 if (!test_bit(dev, bus->pcm_dev_bits))
Takashi Iwai82ad39f2009-03-03 15:00:35 +01002900 goto ok;
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002901 }
Takashi Iwai82ad39f2009-03-03 15:00:35 +01002902 snd_printk(KERN_WARNING "Too many audio devices\n");
2903 return -EAGAIN;
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002904 case HDA_PCM_TYPE_SPDIF:
2905 case HDA_PCM_TYPE_HDMI:
2906 case HDA_PCM_TYPE_MODEM:
2907 dev = dev_idx[type];
2908 if (test_bit(dev, bus->pcm_dev_bits)) {
2909 snd_printk(KERN_WARNING "%s already defined\n",
2910 dev_name[type]);
2911 return -EAGAIN;
2912 }
2913 break;
2914 default:
2915 snd_printk(KERN_WARNING "Invalid PCM type %d\n", type);
2916 return -EINVAL;
2917 }
Takashi Iwai82ad39f2009-03-03 15:00:35 +01002918 ok:
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002919 set_bit(dev, bus->pcm_dev_bits);
2920 return dev;
2921}
2922
2923/*
Takashi Iwai176d5332008-07-30 15:01:44 +02002924 * attach a new PCM stream
2925 */
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002926static int snd_hda_attach_pcm(struct hda_codec *codec, struct hda_pcm *pcm)
Takashi Iwai176d5332008-07-30 15:01:44 +02002927{
Takashi Iwai33fa35e2008-11-06 16:50:40 +01002928 struct hda_bus *bus = codec->bus;
Takashi Iwai176d5332008-07-30 15:01:44 +02002929 struct hda_pcm_stream *info;
2930 int stream, err;
2931
Takashi Iwaib91f0802008-11-04 08:43:08 +01002932 if (snd_BUG_ON(!pcm->name))
Takashi Iwai176d5332008-07-30 15:01:44 +02002933 return -EINVAL;
2934 for (stream = 0; stream < 2; stream++) {
2935 info = &pcm->stream[stream];
2936 if (info->substreams) {
2937 err = set_pcm_default_values(codec, info);
2938 if (err < 0)
2939 return err;
2940 }
2941 }
Takashi Iwai33fa35e2008-11-06 16:50:40 +01002942 return bus->ops.attach_pcm(bus, codec, pcm);
Takashi Iwai176d5332008-07-30 15:01:44 +02002943}
2944
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002945/* assign all PCMs of the given codec */
2946int snd_hda_codec_build_pcms(struct hda_codec *codec)
2947{
2948 unsigned int pcm;
2949 int err;
2950
2951 if (!codec->num_pcms) {
2952 if (!codec->patch_ops.build_pcms)
2953 return 0;
2954 err = codec->patch_ops.build_pcms(codec);
Takashi Iwai6e655bf2009-03-02 10:46:03 +01002955 if (err < 0) {
2956 printk(KERN_ERR "hda_codec: cannot build PCMs"
2957 "for #%d (error %d)\n", codec->addr, err);
2958 err = snd_hda_codec_reset(codec);
2959 if (err < 0) {
2960 printk(KERN_ERR
2961 "hda_codec: cannot revert codec\n");
2962 return err;
2963 }
2964 }
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002965 }
2966 for (pcm = 0; pcm < codec->num_pcms; pcm++) {
2967 struct hda_pcm *cpcm = &codec->pcm_info[pcm];
2968 int dev;
2969
2970 if (!cpcm->stream[0].substreams && !cpcm->stream[1].substreams)
Takashi Iwai41b5b012009-01-20 18:21:23 +01002971 continue; /* no substreams assigned */
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002972
2973 if (!cpcm->pcm) {
2974 dev = get_empty_pcm_device(codec->bus, cpcm->pcm_type);
2975 if (dev < 0)
Takashi Iwai6e655bf2009-03-02 10:46:03 +01002976 continue; /* no fatal error */
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002977 cpcm->device = dev;
2978 err = snd_hda_attach_pcm(codec, cpcm);
Takashi Iwai6e655bf2009-03-02 10:46:03 +01002979 if (err < 0) {
2980 printk(KERN_ERR "hda_codec: cannot attach "
2981 "PCM stream %d for codec #%d\n",
2982 dev, codec->addr);
2983 continue; /* no fatal error */
2984 }
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002985 }
2986 }
2987 return 0;
2988}
2989
Linus Torvalds1da177e2005-04-16 15:20:36 -07002990/**
2991 * snd_hda_build_pcms - build PCM information
2992 * @bus: the BUS
2993 *
2994 * Create PCM information for each codec included in the bus.
2995 *
2996 * The build_pcms codec patch is requested to set up codec->num_pcms and
2997 * codec->pcm_info properly. The array is referred by the top-level driver
2998 * to create its PCM instances.
2999 * The allocated codec->pcm_info should be released in codec->patch_ops.free
3000 * callback.
3001 *
3002 * At least, substreams, channels_min and channels_max must be filled for
3003 * each stream. substreams = 0 indicates that the stream doesn't exist.
3004 * When rates and/or formats are zero, the supported values are queried
3005 * from the given nid. The nid is used also by the default ops.prepare
3006 * and ops.cleanup callbacks.
3007 *
3008 * The driver needs to call ops.open in its open callback. Similarly,
3009 * ops.close is supposed to be called in the close callback.
3010 * ops.prepare should be called in the prepare or hw_params callback
3011 * with the proper parameters for set up.
3012 * ops.cleanup should be called in hw_free for clean up of streams.
3013 *
3014 * This function returns 0 if successfull, or a negative error code.
3015 */
Takashi Iwai529bd6c2008-11-27 14:17:01 +01003016int __devinit snd_hda_build_pcms(struct hda_bus *bus)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003017{
Takashi Iwai0ba21762007-04-16 11:29:14 +02003018 struct hda_codec *codec;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003019
Takashi Iwai0ba21762007-04-16 11:29:14 +02003020 list_for_each_entry(codec, &bus->codec_list, list) {
Takashi Iwai529bd6c2008-11-27 14:17:01 +01003021 int err = snd_hda_codec_build_pcms(codec);
3022 if (err < 0)
3023 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003024 }
3025 return 0;
3026}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003027EXPORT_SYMBOL_HDA(snd_hda_build_pcms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003028
Linus Torvalds1da177e2005-04-16 15:20:36 -07003029/**
3030 * snd_hda_check_board_config - compare the current codec with the config table
3031 * @codec: the HDA codec
Takashi Iwaif5fcc132006-11-24 17:07:44 +01003032 * @num_configs: number of config enums
3033 * @models: array of model name strings
Linus Torvalds1da177e2005-04-16 15:20:36 -07003034 * @tbl: configuration table, terminated by null entries
3035 *
3036 * Compares the modelname or PCI subsystem id of the current codec with the
3037 * given configuration table. If a matching entry is found, returns its
3038 * config value (supposed to be 0 or positive).
3039 *
3040 * If no entries are matching, the function returns a negative value.
3041 */
Takashi Iwai12f288b2007-08-02 15:51:59 +02003042int snd_hda_check_board_config(struct hda_codec *codec,
3043 int num_configs, const char **models,
3044 const struct snd_pci_quirk *tbl)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003045{
Takashi Iwaif44ac832008-07-30 15:01:45 +02003046 if (codec->modelname && models) {
Takashi Iwaif5fcc132006-11-24 17:07:44 +01003047 int i;
3048 for (i = 0; i < num_configs; i++) {
3049 if (models[i] &&
Takashi Iwaif44ac832008-07-30 15:01:45 +02003050 !strcmp(codec->modelname, models[i])) {
Takashi Iwaif5fcc132006-11-24 17:07:44 +01003051 snd_printd(KERN_INFO "hda_codec: model '%s' is "
3052 "selected\n", models[i]);
3053 return i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003054 }
3055 }
3056 }
3057
Takashi Iwaif5fcc132006-11-24 17:07:44 +01003058 if (!codec->bus->pci || !tbl)
3059 return -1;
3060
3061 tbl = snd_pci_quirk_lookup(codec->bus->pci, tbl);
3062 if (!tbl)
3063 return -1;
3064 if (tbl->value >= 0 && tbl->value < num_configs) {
Takashi Iwai62cf8722008-05-20 12:15:15 +02003065#ifdef CONFIG_SND_DEBUG_VERBOSE
Takashi Iwaif5fcc132006-11-24 17:07:44 +01003066 char tmp[10];
3067 const char *model = NULL;
3068 if (models)
3069 model = models[tbl->value];
3070 if (!model) {
3071 sprintf(tmp, "#%d", tbl->value);
3072 model = tmp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003073 }
Takashi Iwaif5fcc132006-11-24 17:07:44 +01003074 snd_printdd(KERN_INFO "hda_codec: model '%s' is selected "
3075 "for config %x:%x (%s)\n",
3076 model, tbl->subvendor, tbl->subdevice,
3077 (tbl->name ? tbl->name : "Unknown device"));
3078#endif
3079 return tbl->value;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003080 }
3081 return -1;
3082}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003083EXPORT_SYMBOL_HDA(snd_hda_check_board_config);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003084
3085/**
Mauro Carvalho Chehab2eda3442008-08-11 10:18:39 +02003086 * snd_hda_check_board_codec_sid_config - compare the current codec
3087 subsystem ID with the
3088 config table
3089
3090 This is important for Gateway notebooks with SB450 HDA Audio
3091 where the vendor ID of the PCI device is:
3092 ATI Technologies Inc SB450 HDA Audio [1002:437b]
3093 and the vendor/subvendor are found only at the codec.
3094
3095 * @codec: the HDA codec
3096 * @num_configs: number of config enums
3097 * @models: array of model name strings
3098 * @tbl: configuration table, terminated by null entries
3099 *
3100 * Compares the modelname or PCI subsystem id of the current codec with the
3101 * given configuration table. If a matching entry is found, returns its
3102 * config value (supposed to be 0 or positive).
3103 *
3104 * If no entries are matching, the function returns a negative value.
3105 */
3106int snd_hda_check_board_codec_sid_config(struct hda_codec *codec,
3107 int num_configs, const char **models,
3108 const struct snd_pci_quirk *tbl)
3109{
3110 const struct snd_pci_quirk *q;
3111
3112 /* Search for codec ID */
3113 for (q = tbl; q->subvendor; q++) {
3114 unsigned long vendorid = (q->subdevice) | (q->subvendor << 16);
3115
3116 if (vendorid == codec->subsystem_id)
3117 break;
3118 }
3119
3120 if (!q->subvendor)
3121 return -1;
3122
3123 tbl = q;
3124
3125 if (tbl->value >= 0 && tbl->value < num_configs) {
3126#ifdef CONFIG_SND_DEBUG_DETECT
3127 char tmp[10];
3128 const char *model = NULL;
3129 if (models)
3130 model = models[tbl->value];
3131 if (!model) {
3132 sprintf(tmp, "#%d", tbl->value);
3133 model = tmp;
3134 }
3135 snd_printdd(KERN_INFO "hda_codec: model '%s' is selected "
3136 "for config %x:%x (%s)\n",
3137 model, tbl->subvendor, tbl->subdevice,
3138 (tbl->name ? tbl->name : "Unknown device"));
3139#endif
3140 return tbl->value;
3141 }
3142 return -1;
3143}
3144EXPORT_SYMBOL_HDA(snd_hda_check_board_codec_sid_config);
3145
3146/**
Linus Torvalds1da177e2005-04-16 15:20:36 -07003147 * snd_hda_add_new_ctls - create controls from the array
3148 * @codec: the HDA codec
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01003149 * @knew: the array of struct snd_kcontrol_new
Linus Torvalds1da177e2005-04-16 15:20:36 -07003150 *
3151 * This helper function creates and add new controls in the given array.
3152 * The array must be terminated with an empty entry as terminator.
3153 *
3154 * Returns 0 if successful, or a negative error code.
3155 */
Takashi Iwai12f288b2007-08-02 15:51:59 +02003156int snd_hda_add_new_ctls(struct hda_codec *codec, struct snd_kcontrol_new *knew)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003157{
Takashi Iwaicb53c622007-08-10 17:21:45 +02003158 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003159
3160 for (; knew->name; knew++) {
Takashi Iwai54d17402005-11-21 16:33:22 +01003161 struct snd_kcontrol *kctl;
3162 kctl = snd_ctl_new1(knew, codec);
Takashi Iwai0ba21762007-04-16 11:29:14 +02003163 if (!kctl)
Takashi Iwai54d17402005-11-21 16:33:22 +01003164 return -ENOMEM;
Takashi Iwaid13bd412008-07-30 15:01:45 +02003165 err = snd_hda_ctl_add(codec, kctl);
Takashi Iwai54d17402005-11-21 16:33:22 +01003166 if (err < 0) {
Takashi Iwai0ba21762007-04-16 11:29:14 +02003167 if (!codec->addr)
Takashi Iwai54d17402005-11-21 16:33:22 +01003168 return err;
3169 kctl = snd_ctl_new1(knew, codec);
Takashi Iwai0ba21762007-04-16 11:29:14 +02003170 if (!kctl)
Takashi Iwai54d17402005-11-21 16:33:22 +01003171 return -ENOMEM;
3172 kctl->id.device = codec->addr;
Takashi Iwaid13bd412008-07-30 15:01:45 +02003173 err = snd_hda_ctl_add(codec, kctl);
Takashi Iwai0ba21762007-04-16 11:29:14 +02003174 if (err < 0)
Takashi Iwai54d17402005-11-21 16:33:22 +01003175 return err;
3176 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003177 }
3178 return 0;
3179}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003180EXPORT_SYMBOL_HDA(snd_hda_add_new_ctls);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003181
Takashi Iwaicb53c622007-08-10 17:21:45 +02003182#ifdef CONFIG_SND_HDA_POWER_SAVE
3183static void hda_set_power_state(struct hda_codec *codec, hda_nid_t fg,
3184 unsigned int power_state);
3185
3186static void hda_power_work(struct work_struct *work)
3187{
3188 struct hda_codec *codec =
3189 container_of(work, struct hda_codec, power_work.work);
Takashi Iwai33fa35e2008-11-06 16:50:40 +01003190 struct hda_bus *bus = codec->bus;
Takashi Iwaicb53c622007-08-10 17:21:45 +02003191
Maxim Levitsky2e492462007-09-03 15:26:57 +02003192 if (!codec->power_on || codec->power_count) {
3193 codec->power_transition = 0;
Takashi Iwaicb53c622007-08-10 17:21:45 +02003194 return;
Maxim Levitsky2e492462007-09-03 15:26:57 +02003195 }
Takashi Iwaicb53c622007-08-10 17:21:45 +02003196
3197 hda_call_codec_suspend(codec);
Takashi Iwai33fa35e2008-11-06 16:50:40 +01003198 if (bus->ops.pm_notify)
3199 bus->ops.pm_notify(bus);
Takashi Iwaicb53c622007-08-10 17:21:45 +02003200}
3201
3202static void hda_keep_power_on(struct hda_codec *codec)
3203{
3204 codec->power_count++;
3205 codec->power_on = 1;
3206}
3207
3208void snd_hda_power_up(struct hda_codec *codec)
3209{
Takashi Iwai33fa35e2008-11-06 16:50:40 +01003210 struct hda_bus *bus = codec->bus;
3211
Takashi Iwaicb53c622007-08-10 17:21:45 +02003212 codec->power_count++;
Takashi Iwaia221e282007-08-16 16:35:33 +02003213 if (codec->power_on || codec->power_transition)
Takashi Iwaicb53c622007-08-10 17:21:45 +02003214 return;
3215
3216 codec->power_on = 1;
Takashi Iwai33fa35e2008-11-06 16:50:40 +01003217 if (bus->ops.pm_notify)
3218 bus->ops.pm_notify(bus);
Takashi Iwaicb53c622007-08-10 17:21:45 +02003219 hda_call_codec_resume(codec);
3220 cancel_delayed_work(&codec->power_work);
Takashi Iwaia221e282007-08-16 16:35:33 +02003221 codec->power_transition = 0;
Takashi Iwaicb53c622007-08-10 17:21:45 +02003222}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003223EXPORT_SYMBOL_HDA(snd_hda_power_up);
Takashi Iwai1289e9e2008-11-27 15:47:11 +01003224
3225#define power_save(codec) \
3226 ((codec)->bus->power_save ? *(codec)->bus->power_save : 0)
Takashi Iwaicb53c622007-08-10 17:21:45 +02003227
Takashi Iwaifee2fba2008-11-27 12:43:28 +01003228#define power_save(codec) \
3229 ((codec)->bus->power_save ? *(codec)->bus->power_save : 0)
3230
Takashi Iwaicb53c622007-08-10 17:21:45 +02003231void snd_hda_power_down(struct hda_codec *codec)
3232{
3233 --codec->power_count;
Takashi Iwaia221e282007-08-16 16:35:33 +02003234 if (!codec->power_on || codec->power_count || codec->power_transition)
Takashi Iwaicb53c622007-08-10 17:21:45 +02003235 return;
Takashi Iwaifee2fba2008-11-27 12:43:28 +01003236 if (power_save(codec)) {
Takashi Iwaia221e282007-08-16 16:35:33 +02003237 codec->power_transition = 1; /* avoid reentrance */
Takashi Iwaic107b412009-01-13 17:46:37 +01003238 queue_delayed_work(codec->bus->workq, &codec->power_work,
Takashi Iwaifee2fba2008-11-27 12:43:28 +01003239 msecs_to_jiffies(power_save(codec) * 1000));
Takashi Iwaia221e282007-08-16 16:35:33 +02003240 }
Takashi Iwaicb53c622007-08-10 17:21:45 +02003241}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003242EXPORT_SYMBOL_HDA(snd_hda_power_down);
Takashi Iwaicb53c622007-08-10 17:21:45 +02003243
3244int snd_hda_check_amp_list_power(struct hda_codec *codec,
3245 struct hda_loopback_check *check,
3246 hda_nid_t nid)
3247{
3248 struct hda_amp_list *p;
3249 int ch, v;
3250
3251 if (!check->amplist)
3252 return 0;
3253 for (p = check->amplist; p->nid; p++) {
3254 if (p->nid == nid)
3255 break;
3256 }
3257 if (!p->nid)
3258 return 0; /* nothing changed */
3259
3260 for (p = check->amplist; p->nid; p++) {
3261 for (ch = 0; ch < 2; ch++) {
3262 v = snd_hda_codec_amp_read(codec, p->nid, ch, p->dir,
3263 p->idx);
3264 if (!(v & HDA_AMP_MUTE) && v > 0) {
3265 if (!check->power_on) {
3266 check->power_on = 1;
3267 snd_hda_power_up(codec);
3268 }
3269 return 1;
3270 }
3271 }
3272 }
3273 if (check->power_on) {
3274 check->power_on = 0;
3275 snd_hda_power_down(codec);
3276 }
3277 return 0;
3278}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003279EXPORT_SYMBOL_HDA(snd_hda_check_amp_list_power);
Takashi Iwaicb53c622007-08-10 17:21:45 +02003280#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07003281
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01003282/*
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01003283 * Channel mode helper
3284 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003285int snd_hda_ch_mode_info(struct hda_codec *codec,
3286 struct snd_ctl_elem_info *uinfo,
3287 const struct hda_channel_mode *chmode,
3288 int num_chmodes)
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01003289{
3290 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
3291 uinfo->count = 1;
3292 uinfo->value.enumerated.items = num_chmodes;
3293 if (uinfo->value.enumerated.item >= num_chmodes)
3294 uinfo->value.enumerated.item = num_chmodes - 1;
3295 sprintf(uinfo->value.enumerated.name, "%dch",
3296 chmode[uinfo->value.enumerated.item].channels);
3297 return 0;
3298}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003299EXPORT_SYMBOL_HDA(snd_hda_ch_mode_info);
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01003300
Takashi Iwai0ba21762007-04-16 11:29:14 +02003301int snd_hda_ch_mode_get(struct hda_codec *codec,
3302 struct snd_ctl_elem_value *ucontrol,
3303 const struct hda_channel_mode *chmode,
3304 int num_chmodes,
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01003305 int max_channels)
3306{
3307 int i;
3308
3309 for (i = 0; i < num_chmodes; i++) {
3310 if (max_channels == chmode[i].channels) {
3311 ucontrol->value.enumerated.item[0] = i;
3312 break;
3313 }
3314 }
3315 return 0;
3316}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003317EXPORT_SYMBOL_HDA(snd_hda_ch_mode_get);
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01003318
Takashi Iwai0ba21762007-04-16 11:29:14 +02003319int snd_hda_ch_mode_put(struct hda_codec *codec,
3320 struct snd_ctl_elem_value *ucontrol,
3321 const struct hda_channel_mode *chmode,
3322 int num_chmodes,
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01003323 int *max_channelsp)
3324{
3325 unsigned int mode;
3326
3327 mode = ucontrol->value.enumerated.item[0];
Takashi Iwai68ea7b22007-11-15 15:54:38 +01003328 if (mode >= num_chmodes)
3329 return -EINVAL;
Takashi Iwai82beb8f2007-08-10 17:09:26 +02003330 if (*max_channelsp == chmode[mode].channels)
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01003331 return 0;
3332 /* change the current channel setting */
3333 *max_channelsp = chmode[mode].channels;
3334 if (chmode[mode].sequence)
Takashi Iwai82beb8f2007-08-10 17:09:26 +02003335 snd_hda_sequence_write_cache(codec, chmode[mode].sequence);
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01003336 return 1;
3337}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003338EXPORT_SYMBOL_HDA(snd_hda_ch_mode_put);
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01003339
Linus Torvalds1da177e2005-04-16 15:20:36 -07003340/*
3341 * input MUX helper
3342 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003343int snd_hda_input_mux_info(const struct hda_input_mux *imux,
3344 struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003345{
3346 unsigned int index;
3347
3348 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
3349 uinfo->count = 1;
3350 uinfo->value.enumerated.items = imux->num_items;
Takashi Iwai5513b0c2007-10-09 11:58:41 +02003351 if (!imux->num_items)
3352 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003353 index = uinfo->value.enumerated.item;
3354 if (index >= imux->num_items)
3355 index = imux->num_items - 1;
3356 strcpy(uinfo->value.enumerated.name, imux->items[index].label);
3357 return 0;
3358}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003359EXPORT_SYMBOL_HDA(snd_hda_input_mux_info);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003360
Takashi Iwai0ba21762007-04-16 11:29:14 +02003361int snd_hda_input_mux_put(struct hda_codec *codec,
3362 const struct hda_input_mux *imux,
3363 struct snd_ctl_elem_value *ucontrol,
3364 hda_nid_t nid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003365 unsigned int *cur_val)
3366{
3367 unsigned int idx;
3368
Takashi Iwai5513b0c2007-10-09 11:58:41 +02003369 if (!imux->num_items)
3370 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003371 idx = ucontrol->value.enumerated.item[0];
3372 if (idx >= imux->num_items)
3373 idx = imux->num_items - 1;
Takashi Iwai82beb8f2007-08-10 17:09:26 +02003374 if (*cur_val == idx)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003375 return 0;
Takashi Iwai82beb8f2007-08-10 17:09:26 +02003376 snd_hda_codec_write_cache(codec, nid, 0, AC_VERB_SET_CONNECT_SEL,
3377 imux->items[idx].index);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003378 *cur_val = idx;
3379 return 1;
3380}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003381EXPORT_SYMBOL_HDA(snd_hda_input_mux_put);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003382
3383
3384/*
3385 * Multi-channel / digital-out PCM helper functions
3386 */
3387
Takashi Iwai6b97eb42007-04-05 14:51:48 +02003388/* setup SPDIF output stream */
3389static void setup_dig_out_stream(struct hda_codec *codec, hda_nid_t nid,
3390 unsigned int stream_tag, unsigned int format)
3391{
3392 /* turn off SPDIF once; otherwise the IEC958 bits won't be updated */
Takashi Iwai2f728532008-09-25 16:32:41 +02003393 if (codec->spdif_status_reset && (codec->spdif_ctls & AC_DIG1_ENABLE))
3394 set_dig_out_convert(codec, nid,
3395 codec->spdif_ctls & ~AC_DIG1_ENABLE & 0xff,
3396 -1);
Takashi Iwai6b97eb42007-04-05 14:51:48 +02003397 snd_hda_codec_setup_stream(codec, nid, stream_tag, 0, format);
Takashi Iwai2f728532008-09-25 16:32:41 +02003398 if (codec->slave_dig_outs) {
3399 hda_nid_t *d;
3400 for (d = codec->slave_dig_outs; *d; d++)
3401 snd_hda_codec_setup_stream(codec, *d, stream_tag, 0,
3402 format);
Matthew Ranostayde51ca12008-09-07 14:31:40 -04003403 }
Takashi Iwai2f728532008-09-25 16:32:41 +02003404 /* turn on again (if needed) */
3405 if (codec->spdif_status_reset && (codec->spdif_ctls & AC_DIG1_ENABLE))
3406 set_dig_out_convert(codec, nid,
3407 codec->spdif_ctls & 0xff, -1);
3408}
Matthew Ranostayde51ca12008-09-07 14:31:40 -04003409
Takashi Iwai2f728532008-09-25 16:32:41 +02003410static void cleanup_dig_out_stream(struct hda_codec *codec, hda_nid_t nid)
3411{
3412 snd_hda_codec_cleanup_stream(codec, nid);
3413 if (codec->slave_dig_outs) {
3414 hda_nid_t *d;
3415 for (d = codec->slave_dig_outs; *d; d++)
3416 snd_hda_codec_cleanup_stream(codec, *d);
3417 }
Takashi Iwai6b97eb42007-04-05 14:51:48 +02003418}
3419
Linus Torvalds1da177e2005-04-16 15:20:36 -07003420/*
3421 * open the digital out in the exclusive mode
3422 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003423int snd_hda_multi_out_dig_open(struct hda_codec *codec,
3424 struct hda_multi_out *mout)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003425{
Ingo Molnar62932df2006-01-16 16:34:20 +01003426 mutex_lock(&codec->spdif_mutex);
Takashi Iwai5930ca42007-04-16 11:23:56 +02003427 if (mout->dig_out_used == HDA_DIG_ANALOG_DUP)
3428 /* already opened as analog dup; reset it once */
Takashi Iwai2f728532008-09-25 16:32:41 +02003429 cleanup_dig_out_stream(codec, mout->dig_out_nid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003430 mout->dig_out_used = HDA_DIG_EXCLUSIVE;
Ingo Molnar62932df2006-01-16 16:34:20 +01003431 mutex_unlock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003432 return 0;
3433}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003434EXPORT_SYMBOL_HDA(snd_hda_multi_out_dig_open);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003435
Takashi Iwai6b97eb42007-04-05 14:51:48 +02003436int snd_hda_multi_out_dig_prepare(struct hda_codec *codec,
3437 struct hda_multi_out *mout,
3438 unsigned int stream_tag,
3439 unsigned int format,
3440 struct snd_pcm_substream *substream)
3441{
3442 mutex_lock(&codec->spdif_mutex);
3443 setup_dig_out_stream(codec, mout->dig_out_nid, stream_tag, format);
3444 mutex_unlock(&codec->spdif_mutex);
3445 return 0;
3446}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003447EXPORT_SYMBOL_HDA(snd_hda_multi_out_dig_prepare);
Takashi Iwai6b97eb42007-04-05 14:51:48 +02003448
Takashi Iwai9411e212009-02-13 11:32:28 +01003449int snd_hda_multi_out_dig_cleanup(struct hda_codec *codec,
3450 struct hda_multi_out *mout)
3451{
3452 mutex_lock(&codec->spdif_mutex);
3453 cleanup_dig_out_stream(codec, mout->dig_out_nid);
3454 mutex_unlock(&codec->spdif_mutex);
3455 return 0;
3456}
3457EXPORT_SYMBOL_HDA(snd_hda_multi_out_dig_cleanup);
3458
Linus Torvalds1da177e2005-04-16 15:20:36 -07003459/*
3460 * release the digital out
3461 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003462int snd_hda_multi_out_dig_close(struct hda_codec *codec,
3463 struct hda_multi_out *mout)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003464{
Ingo Molnar62932df2006-01-16 16:34:20 +01003465 mutex_lock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003466 mout->dig_out_used = 0;
Ingo Molnar62932df2006-01-16 16:34:20 +01003467 mutex_unlock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003468 return 0;
3469}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003470EXPORT_SYMBOL_HDA(snd_hda_multi_out_dig_close);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003471
3472/*
3473 * set up more restrictions for analog out
3474 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003475int snd_hda_multi_out_analog_open(struct hda_codec *codec,
3476 struct hda_multi_out *mout,
Takashi Iwai9a081602008-02-12 18:37:26 +01003477 struct snd_pcm_substream *substream,
3478 struct hda_pcm_stream *hinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003479{
Takashi Iwai9a081602008-02-12 18:37:26 +01003480 struct snd_pcm_runtime *runtime = substream->runtime;
3481 runtime->hw.channels_max = mout->max_channels;
3482 if (mout->dig_out_nid) {
3483 if (!mout->analog_rates) {
3484 mout->analog_rates = hinfo->rates;
3485 mout->analog_formats = hinfo->formats;
3486 mout->analog_maxbps = hinfo->maxbps;
3487 } else {
3488 runtime->hw.rates = mout->analog_rates;
3489 runtime->hw.formats = mout->analog_formats;
3490 hinfo->maxbps = mout->analog_maxbps;
3491 }
3492 if (!mout->spdif_rates) {
3493 snd_hda_query_supported_pcm(codec, mout->dig_out_nid,
3494 &mout->spdif_rates,
3495 &mout->spdif_formats,
3496 &mout->spdif_maxbps);
3497 }
3498 mutex_lock(&codec->spdif_mutex);
3499 if (mout->share_spdif) {
Takashi Iwai022b4662009-07-03 23:03:30 +02003500 if ((runtime->hw.rates & mout->spdif_rates) &&
3501 (runtime->hw.formats & mout->spdif_formats)) {
3502 runtime->hw.rates &= mout->spdif_rates;
3503 runtime->hw.formats &= mout->spdif_formats;
3504 if (mout->spdif_maxbps < hinfo->maxbps)
3505 hinfo->maxbps = mout->spdif_maxbps;
3506 } else {
3507 mout->share_spdif = 0;
3508 /* FIXME: need notify? */
3509 }
Takashi Iwai9a081602008-02-12 18:37:26 +01003510 }
Frederik Deweerdteaa99852008-04-14 13:11:44 +02003511 mutex_unlock(&codec->spdif_mutex);
Takashi Iwai9a081602008-02-12 18:37:26 +01003512 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003513 return snd_pcm_hw_constraint_step(substream->runtime, 0,
3514 SNDRV_PCM_HW_PARAM_CHANNELS, 2);
3515}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003516EXPORT_SYMBOL_HDA(snd_hda_multi_out_analog_open);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003517
3518/*
3519 * set up the i/o for analog out
3520 * when the digital out is available, copy the front out to digital out, too.
3521 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003522int snd_hda_multi_out_analog_prepare(struct hda_codec *codec,
3523 struct hda_multi_out *mout,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003524 unsigned int stream_tag,
3525 unsigned int format,
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01003526 struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003527{
3528 hda_nid_t *nids = mout->dac_nids;
3529 int chs = substream->runtime->channels;
3530 int i;
3531
Ingo Molnar62932df2006-01-16 16:34:20 +01003532 mutex_lock(&codec->spdif_mutex);
Takashi Iwai9a081602008-02-12 18:37:26 +01003533 if (mout->dig_out_nid && mout->share_spdif &&
3534 mout->dig_out_used != HDA_DIG_EXCLUSIVE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003535 if (chs == 2 &&
Takashi Iwai0ba21762007-04-16 11:29:14 +02003536 snd_hda_is_supported_format(codec, mout->dig_out_nid,
3537 format) &&
3538 !(codec->spdif_status & IEC958_AES0_NONAUDIO)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003539 mout->dig_out_used = HDA_DIG_ANALOG_DUP;
Takashi Iwai6b97eb42007-04-05 14:51:48 +02003540 setup_dig_out_stream(codec, mout->dig_out_nid,
3541 stream_tag, format);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003542 } else {
3543 mout->dig_out_used = 0;
Takashi Iwai2f728532008-09-25 16:32:41 +02003544 cleanup_dig_out_stream(codec, mout->dig_out_nid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003545 }
3546 }
Ingo Molnar62932df2006-01-16 16:34:20 +01003547 mutex_unlock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003548
3549 /* front */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003550 snd_hda_codec_setup_stream(codec, nids[HDA_FRONT], stream_tag,
3551 0, format);
Takashi Iwaid29240c2007-10-26 12:35:56 +02003552 if (!mout->no_share_stream &&
3553 mout->hp_nid && mout->hp_nid != nids[HDA_FRONT])
Linus Torvalds1da177e2005-04-16 15:20:36 -07003554 /* headphone out will just decode front left/right (stereo) */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003555 snd_hda_codec_setup_stream(codec, mout->hp_nid, stream_tag,
3556 0, format);
Takashi Iwai82bc9552006-03-21 11:24:42 +01003557 /* extra outputs copied from front */
3558 for (i = 0; i < ARRAY_SIZE(mout->extra_out_nid); i++)
Takashi Iwaid29240c2007-10-26 12:35:56 +02003559 if (!mout->no_share_stream && mout->extra_out_nid[i])
Takashi Iwai82bc9552006-03-21 11:24:42 +01003560 snd_hda_codec_setup_stream(codec,
3561 mout->extra_out_nid[i],
3562 stream_tag, 0, format);
3563
Linus Torvalds1da177e2005-04-16 15:20:36 -07003564 /* surrounds */
3565 for (i = 1; i < mout->num_dacs; i++) {
Takashi Iwai4b3acaf2005-06-10 19:48:10 +02003566 if (chs >= (i + 1) * 2) /* independent out */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003567 snd_hda_codec_setup_stream(codec, nids[i], stream_tag,
3568 i * 2, format);
Takashi Iwaid29240c2007-10-26 12:35:56 +02003569 else if (!mout->no_share_stream) /* copy front */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003570 snd_hda_codec_setup_stream(codec, nids[i], stream_tag,
3571 0, format);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003572 }
3573 return 0;
3574}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003575EXPORT_SYMBOL_HDA(snd_hda_multi_out_analog_prepare);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003576
3577/*
3578 * clean up the setting for analog out
3579 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003580int snd_hda_multi_out_analog_cleanup(struct hda_codec *codec,
3581 struct hda_multi_out *mout)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003582{
3583 hda_nid_t *nids = mout->dac_nids;
3584 int i;
3585
3586 for (i = 0; i < mout->num_dacs; i++)
Takashi Iwai888afa12008-03-18 09:57:50 +01003587 snd_hda_codec_cleanup_stream(codec, nids[i]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003588 if (mout->hp_nid)
Takashi Iwai888afa12008-03-18 09:57:50 +01003589 snd_hda_codec_cleanup_stream(codec, mout->hp_nid);
Takashi Iwai82bc9552006-03-21 11:24:42 +01003590 for (i = 0; i < ARRAY_SIZE(mout->extra_out_nid); i++)
3591 if (mout->extra_out_nid[i])
Takashi Iwai888afa12008-03-18 09:57:50 +01003592 snd_hda_codec_cleanup_stream(codec,
3593 mout->extra_out_nid[i]);
Ingo Molnar62932df2006-01-16 16:34:20 +01003594 mutex_lock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003595 if (mout->dig_out_nid && mout->dig_out_used == HDA_DIG_ANALOG_DUP) {
Takashi Iwai2f728532008-09-25 16:32:41 +02003596 cleanup_dig_out_stream(codec, mout->dig_out_nid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003597 mout->dig_out_used = 0;
3598 }
Ingo Molnar62932df2006-01-16 16:34:20 +01003599 mutex_unlock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003600 return 0;
3601}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003602EXPORT_SYMBOL_HDA(snd_hda_multi_out_analog_cleanup);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003603
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003604/*
Wu Fengguang6b345002008-10-07 14:21:41 +08003605 * Helper for automatic pin configuration
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003606 */
Kailang Yangdf694da2005-12-05 19:42:22 +01003607
Takashi Iwai12f288b2007-08-02 15:51:59 +02003608static int is_in_nid_list(hda_nid_t nid, hda_nid_t *list)
Kailang Yangdf694da2005-12-05 19:42:22 +01003609{
3610 for (; *list; list++)
3611 if (*list == nid)
3612 return 1;
3613 return 0;
3614}
3615
Steve Longerbeam81937d32007-05-08 15:33:03 +02003616
3617/*
3618 * Sort an associated group of pins according to their sequence numbers.
3619 */
3620static void sort_pins_by_sequence(hda_nid_t * pins, short * sequences,
3621 int num_pins)
3622{
3623 int i, j;
3624 short seq;
3625 hda_nid_t nid;
3626
3627 for (i = 0; i < num_pins; i++) {
3628 for (j = i + 1; j < num_pins; j++) {
3629 if (sequences[i] > sequences[j]) {
3630 seq = sequences[i];
3631 sequences[i] = sequences[j];
3632 sequences[j] = seq;
3633 nid = pins[i];
3634 pins[i] = pins[j];
3635 pins[j] = nid;
3636 }
3637 }
3638 }
3639}
3640
3641
Takashi Iwai82bc9552006-03-21 11:24:42 +01003642/*
3643 * Parse all pin widgets and store the useful pin nids to cfg
3644 *
3645 * The number of line-outs or any primary output is stored in line_outs,
3646 * and the corresponding output pins are assigned to line_out_pins[],
3647 * in the order of front, rear, CLFE, side, ...
3648 *
3649 * If more extra outputs (speaker and headphone) are found, the pins are
Takashi Iwaieb06ed82006-09-20 17:10:27 +02003650 * assisnged to hp_pins[] and speaker_pins[], respectively. If no line-out jack
Takashi Iwai82bc9552006-03-21 11:24:42 +01003651 * is detected, one of speaker of HP pins is assigned as the primary
3652 * output, i.e. to line_out_pins[0]. So, line_outs is always positive
3653 * if any analog output exists.
3654 *
3655 * The analog input pins are assigned to input_pins array.
3656 * The digital input/output pins are assigned to dig_in_pin and dig_out_pin,
3657 * respectively.
3658 */
Takashi Iwai12f288b2007-08-02 15:51:59 +02003659int snd_hda_parse_pin_def_config(struct hda_codec *codec,
3660 struct auto_pin_cfg *cfg,
3661 hda_nid_t *ignore_nids)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003662{
Takashi Iwai0ef6ce72008-01-22 15:35:37 +01003663 hda_nid_t nid, end_nid;
Steve Longerbeam81937d32007-05-08 15:33:03 +02003664 short seq, assoc_line_out, assoc_speaker;
3665 short sequences_line_out[ARRAY_SIZE(cfg->line_out_pins)];
3666 short sequences_speaker[ARRAY_SIZE(cfg->speaker_pins)];
Takashi Iwaif889fa92007-10-31 15:49:32 +01003667 short sequences_hp[ARRAY_SIZE(cfg->hp_pins)];
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003668
3669 memset(cfg, 0, sizeof(*cfg));
3670
Steve Longerbeam81937d32007-05-08 15:33:03 +02003671 memset(sequences_line_out, 0, sizeof(sequences_line_out));
3672 memset(sequences_speaker, 0, sizeof(sequences_speaker));
Takashi Iwaif889fa92007-10-31 15:49:32 +01003673 memset(sequences_hp, 0, sizeof(sequences_hp));
Steve Longerbeam81937d32007-05-08 15:33:03 +02003674 assoc_line_out = assoc_speaker = 0;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003675
Takashi Iwai0ef6ce72008-01-22 15:35:37 +01003676 end_nid = codec->start_nid + codec->num_nodes;
3677 for (nid = codec->start_nid; nid < end_nid; nid++) {
Takashi Iwai54d17402005-11-21 16:33:22 +01003678 unsigned int wid_caps = get_wcaps(codec, nid);
Takashi Iwaia22d5432009-07-27 12:54:26 +02003679 unsigned int wid_type = get_wcaps_type(wid_caps);
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003680 unsigned int def_conf;
3681 short assoc, loc;
3682
3683 /* read all default configuration for pin complex */
3684 if (wid_type != AC_WID_PIN)
3685 continue;
Kailang Yangdf694da2005-12-05 19:42:22 +01003686 /* ignore the given nids (e.g. pc-beep returns error) */
3687 if (ignore_nids && is_in_nid_list(nid, ignore_nids))
3688 continue;
3689
Takashi Iwaic17a1ab2009-02-23 09:28:12 +01003690 def_conf = snd_hda_codec_get_pincfg(codec, nid);
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003691 if (get_defcfg_connect(def_conf) == AC_JACK_PORT_NONE)
3692 continue;
3693 loc = get_defcfg_location(def_conf);
3694 switch (get_defcfg_device(def_conf)) {
3695 case AC_JACK_LINE_OUT:
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003696 seq = get_defcfg_sequence(def_conf);
3697 assoc = get_defcfg_association(def_conf);
Matthew Ranostay90da78b2008-01-24 11:48:01 +01003698
3699 if (!(wid_caps & AC_WCAP_STEREO))
3700 if (!cfg->mono_out_pin)
3701 cfg->mono_out_pin = nid;
Takashi Iwai0ba21762007-04-16 11:29:14 +02003702 if (!assoc)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003703 continue;
Takashi Iwai0ba21762007-04-16 11:29:14 +02003704 if (!assoc_line_out)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003705 assoc_line_out = assoc;
3706 else if (assoc_line_out != assoc)
3707 continue;
3708 if (cfg->line_outs >= ARRAY_SIZE(cfg->line_out_pins))
3709 continue;
3710 cfg->line_out_pins[cfg->line_outs] = nid;
Steve Longerbeam81937d32007-05-08 15:33:03 +02003711 sequences_line_out[cfg->line_outs] = seq;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003712 cfg->line_outs++;
3713 break;
Takashi Iwai8d88bc32005-11-17 11:09:23 +01003714 case AC_JACK_SPEAKER:
Steve Longerbeam81937d32007-05-08 15:33:03 +02003715 seq = get_defcfg_sequence(def_conf);
3716 assoc = get_defcfg_association(def_conf);
3717 if (! assoc)
3718 continue;
3719 if (! assoc_speaker)
3720 assoc_speaker = assoc;
3721 else if (assoc_speaker != assoc)
3722 continue;
Takashi Iwai82bc9552006-03-21 11:24:42 +01003723 if (cfg->speaker_outs >= ARRAY_SIZE(cfg->speaker_pins))
3724 continue;
3725 cfg->speaker_pins[cfg->speaker_outs] = nid;
Steve Longerbeam81937d32007-05-08 15:33:03 +02003726 sequences_speaker[cfg->speaker_outs] = seq;
Takashi Iwai82bc9552006-03-21 11:24:42 +01003727 cfg->speaker_outs++;
Takashi Iwai8d88bc32005-11-17 11:09:23 +01003728 break;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003729 case AC_JACK_HP_OUT:
Takashi Iwaif889fa92007-10-31 15:49:32 +01003730 seq = get_defcfg_sequence(def_conf);
3731 assoc = get_defcfg_association(def_conf);
Takashi Iwaieb06ed82006-09-20 17:10:27 +02003732 if (cfg->hp_outs >= ARRAY_SIZE(cfg->hp_pins))
3733 continue;
3734 cfg->hp_pins[cfg->hp_outs] = nid;
Takashi Iwaif889fa92007-10-31 15:49:32 +01003735 sequences_hp[cfg->hp_outs] = (assoc << 4) | seq;
Takashi Iwaieb06ed82006-09-20 17:10:27 +02003736 cfg->hp_outs++;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003737 break;
Takashi Iwai314634b2006-09-21 11:56:18 +02003738 case AC_JACK_MIC_IN: {
3739 int preferred, alt;
3740 if (loc == AC_JACK_LOC_FRONT) {
3741 preferred = AUTO_PIN_FRONT_MIC;
3742 alt = AUTO_PIN_MIC;
3743 } else {
3744 preferred = AUTO_PIN_MIC;
3745 alt = AUTO_PIN_FRONT_MIC;
3746 }
3747 if (!cfg->input_pins[preferred])
3748 cfg->input_pins[preferred] = nid;
3749 else if (!cfg->input_pins[alt])
3750 cfg->input_pins[alt] = nid;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003751 break;
Takashi Iwai314634b2006-09-21 11:56:18 +02003752 }
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003753 case AC_JACK_LINE_IN:
3754 if (loc == AC_JACK_LOC_FRONT)
3755 cfg->input_pins[AUTO_PIN_FRONT_LINE] = nid;
3756 else
3757 cfg->input_pins[AUTO_PIN_LINE] = nid;
3758 break;
3759 case AC_JACK_CD:
3760 cfg->input_pins[AUTO_PIN_CD] = nid;
3761 break;
3762 case AC_JACK_AUX:
3763 cfg->input_pins[AUTO_PIN_AUX] = nid;
3764 break;
3765 case AC_JACK_SPDIF_OUT:
Takashi Iwai1b52ae72009-01-20 17:17:29 +01003766 case AC_JACK_DIG_OTHER_OUT:
Takashi Iwai0852d7a2009-02-11 11:35:15 +01003767 if (cfg->dig_outs >= ARRAY_SIZE(cfg->dig_out_pins))
3768 continue;
3769 cfg->dig_out_pins[cfg->dig_outs] = nid;
3770 cfg->dig_out_type[cfg->dig_outs] =
3771 (loc == AC_JACK_LOC_HDMI) ?
3772 HDA_PCM_TYPE_HDMI : HDA_PCM_TYPE_SPDIF;
3773 cfg->dig_outs++;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003774 break;
3775 case AC_JACK_SPDIF_IN:
Takashi Iwai1b52ae72009-01-20 17:17:29 +01003776 case AC_JACK_DIG_OTHER_IN:
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003777 cfg->dig_in_pin = nid;
Takashi Iwai2297bd62009-01-20 18:24:13 +01003778 if (loc == AC_JACK_LOC_HDMI)
3779 cfg->dig_in_type = HDA_PCM_TYPE_HDMI;
3780 else
3781 cfg->dig_in_type = HDA_PCM_TYPE_SPDIF;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003782 break;
3783 }
3784 }
3785
Takashi Iwai5832fcf2008-02-12 18:30:12 +01003786 /* FIX-UP:
3787 * If no line-out is defined but multiple HPs are found,
3788 * some of them might be the real line-outs.
3789 */
3790 if (!cfg->line_outs && cfg->hp_outs > 1) {
3791 int i = 0;
3792 while (i < cfg->hp_outs) {
3793 /* The real HPs should have the sequence 0x0f */
3794 if ((sequences_hp[i] & 0x0f) == 0x0f) {
3795 i++;
3796 continue;
3797 }
3798 /* Move it to the line-out table */
3799 cfg->line_out_pins[cfg->line_outs] = cfg->hp_pins[i];
3800 sequences_line_out[cfg->line_outs] = sequences_hp[i];
3801 cfg->line_outs++;
3802 cfg->hp_outs--;
3803 memmove(cfg->hp_pins + i, cfg->hp_pins + i + 1,
3804 sizeof(cfg->hp_pins[0]) * (cfg->hp_outs - i));
3805 memmove(sequences_hp + i - 1, sequences_hp + i,
3806 sizeof(sequences_hp[0]) * (cfg->hp_outs - i));
3807 }
3808 }
3809
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003810 /* sort by sequence */
Steve Longerbeam81937d32007-05-08 15:33:03 +02003811 sort_pins_by_sequence(cfg->line_out_pins, sequences_line_out,
3812 cfg->line_outs);
3813 sort_pins_by_sequence(cfg->speaker_pins, sequences_speaker,
3814 cfg->speaker_outs);
Takashi Iwaif889fa92007-10-31 15:49:32 +01003815 sort_pins_by_sequence(cfg->hp_pins, sequences_hp,
3816 cfg->hp_outs);
Steve Longerbeam81937d32007-05-08 15:33:03 +02003817
Takashi Iwaif889fa92007-10-31 15:49:32 +01003818 /* if we have only one mic, make it AUTO_PIN_MIC */
3819 if (!cfg->input_pins[AUTO_PIN_MIC] &&
3820 cfg->input_pins[AUTO_PIN_FRONT_MIC]) {
3821 cfg->input_pins[AUTO_PIN_MIC] =
3822 cfg->input_pins[AUTO_PIN_FRONT_MIC];
3823 cfg->input_pins[AUTO_PIN_FRONT_MIC] = 0;
3824 }
3825 /* ditto for line-in */
3826 if (!cfg->input_pins[AUTO_PIN_LINE] &&
3827 cfg->input_pins[AUTO_PIN_FRONT_LINE]) {
3828 cfg->input_pins[AUTO_PIN_LINE] =
3829 cfg->input_pins[AUTO_PIN_FRONT_LINE];
3830 cfg->input_pins[AUTO_PIN_FRONT_LINE] = 0;
3831 }
3832
Steve Longerbeam81937d32007-05-08 15:33:03 +02003833 /*
3834 * FIX-UP: if no line-outs are detected, try to use speaker or HP pin
3835 * as a primary output
3836 */
3837 if (!cfg->line_outs) {
3838 if (cfg->speaker_outs) {
3839 cfg->line_outs = cfg->speaker_outs;
3840 memcpy(cfg->line_out_pins, cfg->speaker_pins,
3841 sizeof(cfg->speaker_pins));
3842 cfg->speaker_outs = 0;
3843 memset(cfg->speaker_pins, 0, sizeof(cfg->speaker_pins));
3844 cfg->line_out_type = AUTO_PIN_SPEAKER_OUT;
3845 } else if (cfg->hp_outs) {
3846 cfg->line_outs = cfg->hp_outs;
3847 memcpy(cfg->line_out_pins, cfg->hp_pins,
3848 sizeof(cfg->hp_pins));
3849 cfg->hp_outs = 0;
3850 memset(cfg->hp_pins, 0, sizeof(cfg->hp_pins));
3851 cfg->line_out_type = AUTO_PIN_HP_OUT;
3852 }
3853 }
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003854
Takashi Iwaicb8e2f82005-07-29 11:54:32 +02003855 /* Reorder the surround channels
3856 * ALSA sequence is front/surr/clfe/side
3857 * HDA sequence is:
3858 * 4-ch: front/surr => OK as it is
3859 * 6-ch: front/clfe/surr
Takashi Iwai9422db42007-04-20 16:11:43 +02003860 * 8-ch: front/clfe/rear/side|fc
Takashi Iwaicb8e2f82005-07-29 11:54:32 +02003861 */
3862 switch (cfg->line_outs) {
3863 case 3:
Takashi Iwaicb8e2f82005-07-29 11:54:32 +02003864 case 4:
3865 nid = cfg->line_out_pins[1];
Takashi Iwai9422db42007-04-20 16:11:43 +02003866 cfg->line_out_pins[1] = cfg->line_out_pins[2];
Takashi Iwaicb8e2f82005-07-29 11:54:32 +02003867 cfg->line_out_pins[2] = nid;
3868 break;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003869 }
3870
Takashi Iwai82bc9552006-03-21 11:24:42 +01003871 /*
3872 * debug prints of the parsed results
3873 */
3874 snd_printd("autoconfig: line_outs=%d (0x%x/0x%x/0x%x/0x%x/0x%x)\n",
3875 cfg->line_outs, cfg->line_out_pins[0], cfg->line_out_pins[1],
3876 cfg->line_out_pins[2], cfg->line_out_pins[3],
3877 cfg->line_out_pins[4]);
3878 snd_printd(" speaker_outs=%d (0x%x/0x%x/0x%x/0x%x/0x%x)\n",
3879 cfg->speaker_outs, cfg->speaker_pins[0],
3880 cfg->speaker_pins[1], cfg->speaker_pins[2],
3881 cfg->speaker_pins[3], cfg->speaker_pins[4]);
Takashi Iwaieb06ed82006-09-20 17:10:27 +02003882 snd_printd(" hp_outs=%d (0x%x/0x%x/0x%x/0x%x/0x%x)\n",
3883 cfg->hp_outs, cfg->hp_pins[0],
3884 cfg->hp_pins[1], cfg->hp_pins[2],
3885 cfg->hp_pins[3], cfg->hp_pins[4]);
Matthew Ranostay90da78b2008-01-24 11:48:01 +01003886 snd_printd(" mono: mono_out=0x%x\n", cfg->mono_out_pin);
Takashi Iwai0852d7a2009-02-11 11:35:15 +01003887 if (cfg->dig_outs)
3888 snd_printd(" dig-out=0x%x/0x%x\n",
3889 cfg->dig_out_pins[0], cfg->dig_out_pins[1]);
Takashi Iwai82bc9552006-03-21 11:24:42 +01003890 snd_printd(" inputs: mic=0x%x, fmic=0x%x, line=0x%x, fline=0x%x,"
3891 " cd=0x%x, aux=0x%x\n",
3892 cfg->input_pins[AUTO_PIN_MIC],
3893 cfg->input_pins[AUTO_PIN_FRONT_MIC],
3894 cfg->input_pins[AUTO_PIN_LINE],
3895 cfg->input_pins[AUTO_PIN_FRONT_LINE],
3896 cfg->input_pins[AUTO_PIN_CD],
3897 cfg->input_pins[AUTO_PIN_AUX]);
Takashi Iwai32d2c7f2009-02-11 11:33:13 +01003898 if (cfg->dig_in_pin)
Takashi Iwai89ce9e82009-01-20 17:15:57 +01003899 snd_printd(" dig-in=0x%x\n", cfg->dig_in_pin);
Takashi Iwai82bc9552006-03-21 11:24:42 +01003900
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003901 return 0;
3902}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003903EXPORT_SYMBOL_HDA(snd_hda_parse_pin_def_config);
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003904
Takashi Iwai4a471b72005-12-07 13:56:29 +01003905/* labels for input pins */
3906const char *auto_pin_cfg_labels[AUTO_PIN_LAST] = {
3907 "Mic", "Front Mic", "Line", "Front Line", "CD", "Aux"
3908};
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003909EXPORT_SYMBOL_HDA(auto_pin_cfg_labels);
Takashi Iwai4a471b72005-12-07 13:56:29 +01003910
3911
Linus Torvalds1da177e2005-04-16 15:20:36 -07003912#ifdef CONFIG_PM
3913/*
3914 * power management
3915 */
3916
3917/**
3918 * snd_hda_suspend - suspend the codecs
3919 * @bus: the HDA bus
Linus Torvalds1da177e2005-04-16 15:20:36 -07003920 *
3921 * Returns 0 if successful.
3922 */
Takashi Iwai8dd78332009-06-02 01:16:07 +02003923int snd_hda_suspend(struct hda_bus *bus)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003924{
Takashi Iwai0ba21762007-04-16 11:29:14 +02003925 struct hda_codec *codec;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003926
Takashi Iwai0ba21762007-04-16 11:29:14 +02003927 list_for_each_entry(codec, &bus->codec_list, list) {
Takashi Iwai0b7a2e92007-08-14 15:18:26 +02003928#ifdef CONFIG_SND_HDA_POWER_SAVE
3929 if (!codec->power_on)
3930 continue;
3931#endif
Takashi Iwaicb53c622007-08-10 17:21:45 +02003932 hda_call_codec_suspend(codec);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003933 }
3934 return 0;
3935}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003936EXPORT_SYMBOL_HDA(snd_hda_suspend);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003937
3938/**
3939 * snd_hda_resume - resume the codecs
3940 * @bus: the HDA bus
Linus Torvalds1da177e2005-04-16 15:20:36 -07003941 *
3942 * Returns 0 if successful.
Takashi Iwaicb53c622007-08-10 17:21:45 +02003943 *
3944 * This fucntion is defined only when POWER_SAVE isn't set.
3945 * In the power-save mode, the codec is resumed dynamically.
Linus Torvalds1da177e2005-04-16 15:20:36 -07003946 */
3947int snd_hda_resume(struct hda_bus *bus)
3948{
Takashi Iwai0ba21762007-04-16 11:29:14 +02003949 struct hda_codec *codec;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003950
Takashi Iwai0ba21762007-04-16 11:29:14 +02003951 list_for_each_entry(codec, &bus->codec_list, list) {
Maxim Levitskyd804ad92007-09-03 15:28:04 +02003952 if (snd_hda_codec_needs_resume(codec))
3953 hda_call_codec_resume(codec);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003954 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003955 return 0;
3956}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003957EXPORT_SYMBOL_HDA(snd_hda_resume);
Takashi Iwai1289e9e2008-11-27 15:47:11 +01003958#endif /* CONFIG_PM */
Takashi Iwaib2e18592008-07-30 15:01:44 +02003959
3960/*
3961 * generic arrays
3962 */
3963
3964/* get a new element from the given array
3965 * if it exceeds the pre-allocated array size, re-allocate the array
3966 */
3967void *snd_array_new(struct snd_array *array)
3968{
3969 if (array->used >= array->alloced) {
3970 int num = array->alloced + array->alloc_align;
Takashi Iwaib910d9a2008-11-07 00:26:52 +01003971 void *nlist;
3972 if (snd_BUG_ON(num >= 4096))
3973 return NULL;
3974 nlist = kcalloc(num + 1, array->elem_size, GFP_KERNEL);
Takashi Iwaib2e18592008-07-30 15:01:44 +02003975 if (!nlist)
3976 return NULL;
3977 if (array->list) {
3978 memcpy(nlist, array->list,
3979 array->elem_size * array->alloced);
3980 kfree(array->list);
3981 }
3982 array->list = nlist;
3983 array->alloced = num;
3984 }
Takashi Iwaif43aa022008-11-10 16:24:26 +01003985 return snd_array_elem(array, array->used++);
Takashi Iwaib2e18592008-07-30 15:01:44 +02003986}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003987EXPORT_SYMBOL_HDA(snd_array_new);
Takashi Iwaib2e18592008-07-30 15:01:44 +02003988
3989/* free the given array elements */
3990void snd_array_free(struct snd_array *array)
3991{
3992 kfree(array->list);
3993 array->used = 0;
3994 array->alloced = 0;
3995 array->list = NULL;
3996}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003997EXPORT_SYMBOL_HDA(snd_array_free);
Takashi Iwaib2022262008-11-21 21:24:03 +01003998
3999/*
4000 * used by hda_proc.c and hda_eld.c
4001 */
4002void snd_print_pcm_rates(int pcm, char *buf, int buflen)
4003{
4004 static unsigned int rates[] = {
4005 8000, 11025, 16000, 22050, 32000, 44100, 48000, 88200,
4006 96000, 176400, 192000, 384000
4007 };
4008 int i, j;
4009
4010 for (i = 0, j = 0; i < ARRAY_SIZE(rates); i++)
4011 if (pcm & (1 << i))
4012 j += snprintf(buf + j, buflen - j, " %d", rates[i]);
4013
4014 buf[j] = '\0'; /* necessary when j == 0 */
4015}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01004016EXPORT_SYMBOL_HDA(snd_print_pcm_rates);
Takashi Iwaib2022262008-11-21 21:24:03 +01004017
4018void snd_print_pcm_bits(int pcm, char *buf, int buflen)
4019{
4020 static unsigned int bits[] = { 8, 16, 20, 24, 32 };
4021 int i, j;
4022
4023 for (i = 0, j = 0; i < ARRAY_SIZE(bits); i++)
4024 if (pcm & (AC_SUPPCM_BITS_8 << i))
4025 j += snprintf(buf + j, buflen - j, " %d", bits[i]);
4026
4027 buf[j] = '\0'; /* necessary when j == 0 */
4028}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01004029EXPORT_SYMBOL_HDA(snd_print_pcm_bits);
Takashi Iwai1289e9e2008-11-27 15:47:11 +01004030
4031MODULE_DESCRIPTION("HDA codec core");
4032MODULE_LICENSE("GPL");