blob: 3a603cde8cc4b7d2fa023d144805d01cd65045bd [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 Iwai1ba7a7c2009-07-27 12:56:26 +0200304 unsigned int wcaps;
Takashi Iwai54d17402005-11-21 16:33:22 +0100305 hda_nid_t prev_nid;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700306
Takashi Iwaida3cec32008-08-08 17:12:14 +0200307 if (snd_BUG_ON(!conn_list || max_conns <= 0))
308 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700309
Takashi Iwai1ba7a7c2009-07-27 12:56:26 +0200310 wcaps = get_wcaps(codec, nid);
311 if (!(wcaps & AC_WCAP_CONN_LIST) &&
312 get_wcaps_type(wcaps) != AC_WID_VOL_KNB) {
Jaroslav Kysela16a433d2009-07-22 16:20:40 +0200313 snd_printk(KERN_WARNING "hda_codec: "
314 "connection list not available for 0x%x\n", nid);
315 return -EINVAL;
316 }
317
Linus Torvalds1da177e2005-04-16 15:20:36 -0700318 parm = snd_hda_param_read(codec, nid, AC_PAR_CONNLIST_LEN);
319 if (parm & AC_CLIST_LONG) {
320 /* long form */
321 shift = 16;
322 num_elems = 2;
323 } else {
324 /* short form */
325 shift = 8;
326 num_elems = 4;
327 }
328 conn_len = parm & AC_CLIST_LENGTH;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700329 mask = (1 << (shift-1)) - 1;
330
Takashi Iwai0ba21762007-04-16 11:29:14 +0200331 if (!conn_len)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700332 return 0; /* no connection */
333
334 if (conn_len == 1) {
335 /* single connection */
Takashi Iwai0ba21762007-04-16 11:29:14 +0200336 parm = snd_hda_codec_read(codec, nid, 0,
337 AC_VERB_GET_CONNECT_LIST, 0);
Takashi Iwai3c6aae42009-07-10 12:52:27 +0200338 if (parm == -1 && codec->bus->rirb_error)
339 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700340 conn_list[0] = parm & mask;
341 return 1;
342 }
343
344 /* multi connection */
345 conns = 0;
Takashi Iwai54d17402005-11-21 16:33:22 +0100346 prev_nid = 0;
347 for (i = 0; i < conn_len; i++) {
348 int range_val;
349 hda_nid_t val, n;
350
Takashi Iwai3c6aae42009-07-10 12:52:27 +0200351 if (i % num_elems == 0) {
Takashi Iwai54d17402005-11-21 16:33:22 +0100352 parm = snd_hda_codec_read(codec, nid, 0,
353 AC_VERB_GET_CONNECT_LIST, i);
Takashi Iwai3c6aae42009-07-10 12:52:27 +0200354 if (parm == -1 && codec->bus->rirb_error)
355 return -EIO;
356 }
Takashi Iwai0ba21762007-04-16 11:29:14 +0200357 range_val = !!(parm & (1 << (shift-1))); /* ranges */
Takashi Iwai54d17402005-11-21 16:33:22 +0100358 val = parm & mask;
Jaroslav Kysela2e9bf242009-07-18 11:48:19 +0200359 if (val == 0) {
360 snd_printk(KERN_WARNING "hda_codec: "
361 "invalid CONNECT_LIST verb %x[%i]:%x\n",
362 nid, i, parm);
363 return 0;
364 }
Takashi Iwai54d17402005-11-21 16:33:22 +0100365 parm >>= shift;
366 if (range_val) {
367 /* ranges between the previous and this one */
Takashi Iwai0ba21762007-04-16 11:29:14 +0200368 if (!prev_nid || prev_nid >= val) {
369 snd_printk(KERN_WARNING "hda_codec: "
370 "invalid dep_range_val %x:%x\n",
371 prev_nid, val);
Takashi Iwai54d17402005-11-21 16:33:22 +0100372 continue;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700373 }
Takashi Iwai54d17402005-11-21 16:33:22 +0100374 for (n = prev_nid + 1; n <= val; n++) {
375 if (conns >= max_conns) {
Takashi Iwai0ba21762007-04-16 11:29:14 +0200376 snd_printk(KERN_ERR
377 "Too many connections\n");
Takashi Iwai54d17402005-11-21 16:33:22 +0100378 return -EINVAL;
379 }
380 conn_list[conns++] = n;
381 }
382 } else {
383 if (conns >= max_conns) {
384 snd_printk(KERN_ERR "Too many connections\n");
385 return -EINVAL;
386 }
387 conn_list[conns++] = val;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700388 }
Takashi Iwai54d17402005-11-21 16:33:22 +0100389 prev_nid = val;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700390 }
391 return conns;
392}
Takashi Iwaiff7a3262008-11-28 15:17:06 +0100393EXPORT_SYMBOL_HDA(snd_hda_get_connections);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700394
395
396/**
397 * snd_hda_queue_unsol_event - add an unsolicited event to queue
398 * @bus: the BUS
399 * @res: unsolicited event (lower 32bit of RIRB entry)
400 * @res_ex: codec addr and flags (upper 32bit or RIRB entry)
401 *
402 * Adds the given event to the queue. The events are processed in
403 * the workqueue asynchronously. Call this function in the interrupt
404 * hanlder when RIRB receives an unsolicited event.
405 *
406 * Returns 0 if successful, or a negative error code.
407 */
408int snd_hda_queue_unsol_event(struct hda_bus *bus, u32 res, u32 res_ex)
409{
410 struct hda_bus_unsolicited *unsol;
411 unsigned int wp;
412
Takashi Iwai0ba21762007-04-16 11:29:14 +0200413 unsol = bus->unsol;
414 if (!unsol)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700415 return 0;
416
417 wp = (unsol->wp + 1) % HDA_UNSOL_QUEUE_SIZE;
418 unsol->wp = wp;
419
420 wp <<= 1;
421 unsol->queue[wp] = res;
422 unsol->queue[wp + 1] = res_ex;
423
Takashi Iwai6acaed32009-01-12 10:09:24 +0100424 queue_work(bus->workq, &unsol->work);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700425
426 return 0;
427}
Takashi Iwaiff7a3262008-11-28 15:17:06 +0100428EXPORT_SYMBOL_HDA(snd_hda_queue_unsol_event);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700429
430/*
Wu Fengguang5c1d1a92008-10-07 14:17:53 +0800431 * process queued unsolicited events
Linus Torvalds1da177e2005-04-16 15:20:36 -0700432 */
David Howellsc4028952006-11-22 14:57:56 +0000433static void process_unsol_events(struct work_struct *work)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700434{
David Howellsc4028952006-11-22 14:57:56 +0000435 struct hda_bus_unsolicited *unsol =
436 container_of(work, struct hda_bus_unsolicited, work);
437 struct hda_bus *bus = unsol->bus;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700438 struct hda_codec *codec;
439 unsigned int rp, caddr, res;
440
441 while (unsol->rp != unsol->wp) {
442 rp = (unsol->rp + 1) % HDA_UNSOL_QUEUE_SIZE;
443 unsol->rp = rp;
444 rp <<= 1;
445 res = unsol->queue[rp];
446 caddr = unsol->queue[rp + 1];
Takashi Iwai0ba21762007-04-16 11:29:14 +0200447 if (!(caddr & (1 << 4))) /* no unsolicited event? */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700448 continue;
449 codec = bus->caddr_tbl[caddr & 0x0f];
450 if (codec && codec->patch_ops.unsol_event)
451 codec->patch_ops.unsol_event(codec, res);
452 }
453}
454
455/*
456 * initialize unsolicited queue
457 */
Takashi Iwai6c1f45e2008-07-30 15:01:45 +0200458static int init_unsol_queue(struct hda_bus *bus)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700459{
460 struct hda_bus_unsolicited *unsol;
461
Takashi Iwai9f146bb2005-11-17 11:07:49 +0100462 if (bus->unsol) /* already initialized */
463 return 0;
464
Takashi Iwaie560d8d2005-09-09 14:21:46 +0200465 unsol = kzalloc(sizeof(*unsol), GFP_KERNEL);
Takashi Iwai0ba21762007-04-16 11:29:14 +0200466 if (!unsol) {
467 snd_printk(KERN_ERR "hda_codec: "
468 "can't allocate unsolicited queue\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700469 return -ENOMEM;
470 }
David Howellsc4028952006-11-22 14:57:56 +0000471 INIT_WORK(&unsol->work, process_unsol_events);
472 unsol->bus = bus;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700473 bus->unsol = unsol;
474 return 0;
475}
476
477/*
478 * destructor
479 */
480static void snd_hda_codec_free(struct hda_codec *codec);
481
482static int snd_hda_bus_free(struct hda_bus *bus)
483{
Takashi Iwai0ba21762007-04-16 11:29:14 +0200484 struct hda_codec *codec, *n;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700485
Takashi Iwai0ba21762007-04-16 11:29:14 +0200486 if (!bus)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700487 return 0;
Takashi Iwai6acaed32009-01-12 10:09:24 +0100488 if (bus->workq)
489 flush_workqueue(bus->workq);
490 if (bus->unsol)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700491 kfree(bus->unsol);
Takashi Iwai0ba21762007-04-16 11:29:14 +0200492 list_for_each_entry_safe(codec, n, &bus->codec_list, list) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700493 snd_hda_codec_free(codec);
494 }
495 if (bus->ops.private_free)
496 bus->ops.private_free(bus);
Takashi Iwai6acaed32009-01-12 10:09:24 +0100497 if (bus->workq)
498 destroy_workqueue(bus->workq);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700499 kfree(bus);
500 return 0;
501}
502
Takashi Iwaic8b6bf92005-11-17 14:57:47 +0100503static int snd_hda_bus_dev_free(struct snd_device *device)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700504{
505 struct hda_bus *bus = device->device_data;
Takashi Iwaib94d35392008-11-21 09:08:06 +0100506 bus->shutdown = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700507 return snd_hda_bus_free(bus);
508}
509
Takashi Iwaid7ffba12008-07-30 15:01:46 +0200510#ifdef CONFIG_SND_HDA_HWDEP
511static int snd_hda_bus_dev_register(struct snd_device *device)
512{
513 struct hda_bus *bus = device->device_data;
514 struct hda_codec *codec;
515 list_for_each_entry(codec, &bus->codec_list, list) {
516 snd_hda_hwdep_add_sysfs(codec);
517 }
518 return 0;
519}
520#else
521#define snd_hda_bus_dev_register NULL
522#endif
523
Linus Torvalds1da177e2005-04-16 15:20:36 -0700524/**
525 * snd_hda_bus_new - create a HDA bus
526 * @card: the card entry
527 * @temp: the template for hda_bus information
528 * @busp: the pointer to store the created bus instance
529 *
530 * Returns 0 if successful, or a negative error code.
531 */
Takashi Iwai1289e9e2008-11-27 15:47:11 +0100532int /*__devinit*/ snd_hda_bus_new(struct snd_card *card,
Takashi Iwai756e2b02007-04-16 11:27:07 +0200533 const struct hda_bus_template *temp,
534 struct hda_bus **busp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700535{
536 struct hda_bus *bus;
537 int err;
Takashi Iwaic8b6bf92005-11-17 14:57:47 +0100538 static struct snd_device_ops dev_ops = {
Takashi Iwaid7ffba12008-07-30 15:01:46 +0200539 .dev_register = snd_hda_bus_dev_register,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700540 .dev_free = snd_hda_bus_dev_free,
541 };
542
Takashi Iwaida3cec32008-08-08 17:12:14 +0200543 if (snd_BUG_ON(!temp))
544 return -EINVAL;
545 if (snd_BUG_ON(!temp->ops.command || !temp->ops.get_response))
546 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700547
548 if (busp)
549 *busp = NULL;
550
Takashi Iwaie560d8d2005-09-09 14:21:46 +0200551 bus = kzalloc(sizeof(*bus), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700552 if (bus == NULL) {
553 snd_printk(KERN_ERR "can't allocate struct hda_bus\n");
554 return -ENOMEM;
555 }
556
557 bus->card = card;
558 bus->private_data = temp->private_data;
559 bus->pci = temp->pci;
560 bus->modelname = temp->modelname;
Takashi Iwaifee2fba2008-11-27 12:43:28 +0100561 bus->power_save = temp->power_save;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700562 bus->ops = temp->ops;
563
Ingo Molnar62932df2006-01-16 16:34:20 +0100564 mutex_init(&bus->cmd_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700565 INIT_LIST_HEAD(&bus->codec_list);
566
Takashi Iwaie8c0ee52009-02-05 07:34:28 +0100567 snprintf(bus->workq_name, sizeof(bus->workq_name),
568 "hd-audio%d", card->number);
569 bus->workq = create_singlethread_workqueue(bus->workq_name);
Takashi Iwai6acaed32009-01-12 10:09:24 +0100570 if (!bus->workq) {
Takashi Iwaie8c0ee52009-02-05 07:34:28 +0100571 snd_printk(KERN_ERR "cannot create workqueue %s\n",
572 bus->workq_name);
Takashi Iwai6acaed32009-01-12 10:09:24 +0100573 kfree(bus);
574 return -ENOMEM;
575 }
576
Takashi Iwai0ba21762007-04-16 11:29:14 +0200577 err = snd_device_new(card, SNDRV_DEV_BUS, bus, &dev_ops);
578 if (err < 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700579 snd_hda_bus_free(bus);
580 return err;
581 }
582 if (busp)
583 *busp = bus;
584 return 0;
585}
Takashi Iwaiff7a3262008-11-28 15:17:06 +0100586EXPORT_SYMBOL_HDA(snd_hda_bus_new);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700587
Takashi Iwai82467612007-07-27 19:15:54 +0200588#ifdef CONFIG_SND_HDA_GENERIC
589#define is_generic_config(codec) \
Takashi Iwaif44ac832008-07-30 15:01:45 +0200590 (codec->modelname && !strcmp(codec->modelname, "generic"))
Takashi Iwai82467612007-07-27 19:15:54 +0200591#else
592#define is_generic_config(codec) 0
593#endif
594
Takashi Iwai645f10c2008-11-28 15:07:37 +0100595#ifdef MODULE
Takashi Iwai1289e9e2008-11-27 15:47:11 +0100596#define HDA_MODREQ_MAX_COUNT 2 /* two request_modules()'s */
597#else
Takashi Iwai645f10c2008-11-28 15:07:37 +0100598#define HDA_MODREQ_MAX_COUNT 0 /* all presets are statically linked */
Takashi Iwai1289e9e2008-11-27 15:47:11 +0100599#endif
600
Linus Torvalds1da177e2005-04-16 15:20:36 -0700601/*
602 * find a matching codec preset
603 */
Takashi Iwai6c1f45e2008-07-30 15:01:45 +0200604static const struct hda_codec_preset *
Takashi Iwai756e2b02007-04-16 11:27:07 +0200605find_codec_preset(struct hda_codec *codec)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700606{
Takashi Iwai1289e9e2008-11-27 15:47:11 +0100607 struct hda_codec_preset_list *tbl;
608 const struct hda_codec_preset *preset;
609 int mod_requested = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700610
Takashi Iwai82467612007-07-27 19:15:54 +0200611 if (is_generic_config(codec))
Takashi Iwaid5ad6302007-03-07 15:55:59 +0100612 return NULL; /* use the generic parser */
613
Takashi Iwai1289e9e2008-11-27 15:47:11 +0100614 again:
615 mutex_lock(&preset_mutex);
616 list_for_each_entry(tbl, &hda_preset_tables, list) {
617 if (!try_module_get(tbl->owner)) {
618 snd_printk(KERN_ERR "hda_codec: cannot module_get\n");
619 continue;
620 }
621 for (preset = tbl->preset; preset->id; preset++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700622 u32 mask = preset->mask;
Marc Boucherca7cfae2008-01-22 15:32:25 +0100623 if (preset->afg && preset->afg != codec->afg)
624 continue;
625 if (preset->mfg && preset->mfg != codec->mfg)
626 continue;
Takashi Iwai0ba21762007-04-16 11:29:14 +0200627 if (!mask)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700628 mask = ~0;
Takashi Iwai9c7f8522006-06-28 15:08:22 +0200629 if (preset->id == (codec->vendor_id & mask) &&
Takashi Iwai0ba21762007-04-16 11:29:14 +0200630 (!preset->rev ||
Takashi Iwai1289e9e2008-11-27 15:47:11 +0100631 preset->rev == codec->revision_id)) {
632 mutex_unlock(&preset_mutex);
633 codec->owner = tbl->owner;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700634 return preset;
Takashi Iwai1289e9e2008-11-27 15:47:11 +0100635 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700636 }
Takashi Iwai1289e9e2008-11-27 15:47:11 +0100637 module_put(tbl->owner);
638 }
639 mutex_unlock(&preset_mutex);
640
641 if (mod_requested < HDA_MODREQ_MAX_COUNT) {
642 char name[32];
643 if (!mod_requested)
644 snprintf(name, sizeof(name), "snd-hda-codec-id:%08x",
645 codec->vendor_id);
646 else
647 snprintf(name, sizeof(name), "snd-hda-codec-id:%04x*",
648 (codec->vendor_id >> 16) & 0xffff);
649 request_module(name);
650 mod_requested++;
651 goto again;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700652 }
653 return NULL;
654}
655
656/*
Takashi Iwaif44ac832008-07-30 15:01:45 +0200657 * get_codec_name - store the codec name
Linus Torvalds1da177e2005-04-16 15:20:36 -0700658 */
Takashi Iwaif44ac832008-07-30 15:01:45 +0200659static int get_codec_name(struct hda_codec *codec)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700660{
661 const struct hda_vendor_id *c;
662 const char *vendor = NULL;
663 u16 vendor_id = codec->vendor_id >> 16;
Takashi Iwai812a2cc2009-05-16 10:00:49 +0200664 char tmp[16];
665
666 if (codec->vendor_name)
667 goto get_chip_name;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700668
669 for (c = hda_vendor_ids; c->id; c++) {
670 if (c->id == vendor_id) {
671 vendor = c->name;
672 break;
673 }
674 }
Takashi Iwai0ba21762007-04-16 11:29:14 +0200675 if (!vendor) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700676 sprintf(tmp, "Generic %04x", vendor_id);
677 vendor = tmp;
678 }
Takashi Iwai812a2cc2009-05-16 10:00:49 +0200679 codec->vendor_name = kstrdup(vendor, GFP_KERNEL);
680 if (!codec->vendor_name)
681 return -ENOMEM;
682
683 get_chip_name:
684 if (codec->chip_name)
685 return 0;
686
Linus Torvalds1da177e2005-04-16 15:20:36 -0700687 if (codec->preset && codec->preset->name)
Takashi Iwai812a2cc2009-05-16 10:00:49 +0200688 codec->chip_name = kstrdup(codec->preset->name, GFP_KERNEL);
689 else {
690 sprintf(tmp, "ID %x", codec->vendor_id & 0xffff);
691 codec->chip_name = kstrdup(tmp, GFP_KERNEL);
692 }
693 if (!codec->chip_name)
Takashi Iwaif44ac832008-07-30 15:01:45 +0200694 return -ENOMEM;
695 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700696}
697
698/*
Sasha Khapyorsky673b6832005-08-11 11:00:16 +0200699 * look for an AFG and MFG nodes
Linus Torvalds1da177e2005-04-16 15:20:36 -0700700 */
Takashi Iwai1289e9e2008-11-27 15:47:11 +0100701static void /*__devinit*/ setup_fg_nodes(struct hda_codec *codec)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700702{
Takashi Iwai93e82ae2009-04-17 18:04:41 +0200703 int i, total_nodes, function_id;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700704 hda_nid_t nid;
705
706 total_nodes = snd_hda_get_sub_nodes(codec, AC_NODE_ROOT, &nid);
707 for (i = 0; i < total_nodes; i++, nid++) {
Takashi Iwai93e82ae2009-04-17 18:04:41 +0200708 function_id = snd_hda_param_read(codec, nid,
Pascal de Bruijn234b4342009-03-23 11:15:59 +0100709 AC_PAR_FUNCTION_TYPE) & 0xff;
Takashi Iwai93e82ae2009-04-17 18:04:41 +0200710 switch (function_id) {
Sasha Khapyorsky673b6832005-08-11 11:00:16 +0200711 case AC_GRP_AUDIO_FUNCTION:
712 codec->afg = nid;
Takashi Iwai93e82ae2009-04-17 18:04:41 +0200713 codec->function_id = function_id;
Sasha Khapyorsky673b6832005-08-11 11:00:16 +0200714 break;
715 case AC_GRP_MODEM_FUNCTION:
716 codec->mfg = nid;
Takashi Iwai93e82ae2009-04-17 18:04:41 +0200717 codec->function_id = function_id;
Sasha Khapyorsky673b6832005-08-11 11:00:16 +0200718 break;
719 default:
720 break;
721 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700722 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700723}
724
725/*
Takashi Iwai54d17402005-11-21 16:33:22 +0100726 * read widget caps for each widget and store in cache
727 */
728static int read_widget_caps(struct hda_codec *codec, hda_nid_t fg_node)
729{
730 int i;
731 hda_nid_t nid;
732
733 codec->num_nodes = snd_hda_get_sub_nodes(codec, fg_node,
734 &codec->start_nid);
735 codec->wcaps = kmalloc(codec->num_nodes * 4, GFP_KERNEL);
Takashi Iwai0ba21762007-04-16 11:29:14 +0200736 if (!codec->wcaps)
Takashi Iwai54d17402005-11-21 16:33:22 +0100737 return -ENOMEM;
738 nid = codec->start_nid;
739 for (i = 0; i < codec->num_nodes; i++, nid++)
740 codec->wcaps[i] = snd_hda_param_read(codec, nid,
741 AC_PAR_AUDIO_WIDGET_CAP);
742 return 0;
743}
744
Takashi Iwai3be14142009-02-20 14:11:16 +0100745/* read all pin default configurations and save codec->init_pins */
746static int read_pin_defaults(struct hda_codec *codec)
747{
748 int i;
749 hda_nid_t nid = codec->start_nid;
750
751 for (i = 0; i < codec->num_nodes; i++, nid++) {
752 struct hda_pincfg *pin;
753 unsigned int wcaps = get_wcaps(codec, nid);
Takashi Iwaia22d5432009-07-27 12:54:26 +0200754 unsigned int wid_type = get_wcaps_type(wcaps);
Takashi Iwai3be14142009-02-20 14:11:16 +0100755 if (wid_type != AC_WID_PIN)
756 continue;
757 pin = snd_array_new(&codec->init_pins);
758 if (!pin)
759 return -ENOMEM;
760 pin->nid = nid;
761 pin->cfg = snd_hda_codec_read(codec, nid, 0,
762 AC_VERB_GET_CONFIG_DEFAULT, 0);
763 }
764 return 0;
765}
766
767/* look up the given pin config list and return the item matching with NID */
768static struct hda_pincfg *look_up_pincfg(struct hda_codec *codec,
769 struct snd_array *array,
770 hda_nid_t nid)
771{
772 int i;
773 for (i = 0; i < array->used; i++) {
774 struct hda_pincfg *pin = snd_array_elem(array, i);
775 if (pin->nid == nid)
776 return pin;
777 }
778 return NULL;
779}
780
781/* write a config value for the given NID */
782static void set_pincfg(struct hda_codec *codec, hda_nid_t nid,
783 unsigned int cfg)
784{
785 int i;
786 for (i = 0; i < 4; i++) {
787 snd_hda_codec_write(codec, nid, 0,
788 AC_VERB_SET_CONFIG_DEFAULT_BYTES_0 + i,
789 cfg & 0xff);
790 cfg >>= 8;
791 }
792}
793
794/* set the current pin config value for the given NID.
795 * the value is cached, and read via snd_hda_codec_get_pincfg()
796 */
797int snd_hda_add_pincfg(struct hda_codec *codec, struct snd_array *list,
798 hda_nid_t nid, unsigned int cfg)
799{
800 struct hda_pincfg *pin;
Takashi Iwai5e7b8e02009-02-23 09:45:59 +0100801 unsigned int oldcfg;
Takashi Iwai3be14142009-02-20 14:11:16 +0100802
Takashi Iwai5e7b8e02009-02-23 09:45:59 +0100803 oldcfg = snd_hda_codec_get_pincfg(codec, nid);
Takashi Iwai3be14142009-02-20 14:11:16 +0100804 pin = look_up_pincfg(codec, list, nid);
805 if (!pin) {
806 pin = snd_array_new(list);
807 if (!pin)
808 return -ENOMEM;
809 pin->nid = nid;
810 }
811 pin->cfg = cfg;
Takashi Iwai5e7b8e02009-02-23 09:45:59 +0100812
813 /* change only when needed; e.g. if the pincfg is already present
814 * in user_pins[], don't write it
815 */
816 cfg = snd_hda_codec_get_pincfg(codec, nid);
817 if (oldcfg != cfg)
818 set_pincfg(codec, nid, cfg);
Takashi Iwai3be14142009-02-20 14:11:16 +0100819 return 0;
820}
821
822int snd_hda_codec_set_pincfg(struct hda_codec *codec,
823 hda_nid_t nid, unsigned int cfg)
824{
Takashi Iwai346ff702009-02-23 09:42:57 +0100825 return snd_hda_add_pincfg(codec, &codec->driver_pins, nid, cfg);
Takashi Iwai3be14142009-02-20 14:11:16 +0100826}
827EXPORT_SYMBOL_HDA(snd_hda_codec_set_pincfg);
828
829/* get the current pin config value of the given pin NID */
830unsigned int snd_hda_codec_get_pincfg(struct hda_codec *codec, hda_nid_t nid)
831{
832 struct hda_pincfg *pin;
833
Takashi Iwai3be14142009-02-20 14:11:16 +0100834#ifdef CONFIG_SND_HDA_HWDEP
Takashi Iwai346ff702009-02-23 09:42:57 +0100835 pin = look_up_pincfg(codec, &codec->user_pins, nid);
Takashi Iwai3be14142009-02-20 14:11:16 +0100836 if (pin)
837 return pin->cfg;
838#endif
Takashi Iwai5e7b8e02009-02-23 09:45:59 +0100839 pin = look_up_pincfg(codec, &codec->driver_pins, nid);
840 if (pin)
841 return pin->cfg;
Takashi Iwai3be14142009-02-20 14:11:16 +0100842 pin = look_up_pincfg(codec, &codec->init_pins, nid);
843 if (pin)
844 return pin->cfg;
845 return 0;
846}
847EXPORT_SYMBOL_HDA(snd_hda_codec_get_pincfg);
848
849/* restore all current pin configs */
850static void restore_pincfgs(struct hda_codec *codec)
851{
852 int i;
853 for (i = 0; i < codec->init_pins.used; i++) {
854 struct hda_pincfg *pin = snd_array_elem(&codec->init_pins, i);
855 set_pincfg(codec, pin->nid,
856 snd_hda_codec_get_pincfg(codec, pin->nid));
857 }
858}
Takashi Iwai54d17402005-11-21 16:33:22 +0100859
Takashi Iwai01751f52007-08-10 16:59:39 +0200860static void init_hda_cache(struct hda_cache_rec *cache,
861 unsigned int record_size);
Takashi Iwai1fcaee62007-08-23 00:01:09 +0200862static void free_hda_cache(struct hda_cache_rec *cache);
Takashi Iwai01751f52007-08-10 16:59:39 +0200863
Takashi Iwai3be14142009-02-20 14:11:16 +0100864/* restore the initial pin cfgs and release all pincfg lists */
865static void restore_init_pincfgs(struct hda_codec *codec)
866{
Takashi Iwai346ff702009-02-23 09:42:57 +0100867 /* first free driver_pins and user_pins, then call restore_pincfg
Takashi Iwai3be14142009-02-20 14:11:16 +0100868 * so that only the values in init_pins are restored
869 */
Takashi Iwai346ff702009-02-23 09:42:57 +0100870 snd_array_free(&codec->driver_pins);
Takashi Iwai3be14142009-02-20 14:11:16 +0100871#ifdef CONFIG_SND_HDA_HWDEP
Takashi Iwai346ff702009-02-23 09:42:57 +0100872 snd_array_free(&codec->user_pins);
Takashi Iwai3be14142009-02-20 14:11:16 +0100873#endif
874 restore_pincfgs(codec);
875 snd_array_free(&codec->init_pins);
876}
877
Takashi Iwai54d17402005-11-21 16:33:22 +0100878/*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700879 * codec destructor
880 */
881static void snd_hda_codec_free(struct hda_codec *codec)
882{
Takashi Iwai0ba21762007-04-16 11:29:14 +0200883 if (!codec)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700884 return;
Takashi Iwai3be14142009-02-20 14:11:16 +0100885 restore_init_pincfgs(codec);
Takashi Iwaicb53c622007-08-10 17:21:45 +0200886#ifdef CONFIG_SND_HDA_POWER_SAVE
887 cancel_delayed_work(&codec->power_work);
Takashi Iwai6acaed32009-01-12 10:09:24 +0100888 flush_workqueue(codec->bus->workq);
Takashi Iwaicb53c622007-08-10 17:21:45 +0200889#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700890 list_del(&codec->list);
Takashi Iwaid13bd412008-07-30 15:01:45 +0200891 snd_array_free(&codec->mixers);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700892 codec->bus->caddr_tbl[codec->addr] = NULL;
893 if (codec->patch_ops.free)
894 codec->patch_ops.free(codec);
Takashi Iwai1289e9e2008-11-27 15:47:11 +0100895 module_put(codec->owner);
Takashi Iwai01751f52007-08-10 16:59:39 +0200896 free_hda_cache(&codec->amp_cache);
Takashi Iwaib3ac5632007-08-10 17:03:40 +0200897 free_hda_cache(&codec->cmd_cache);
Takashi Iwai812a2cc2009-05-16 10:00:49 +0200898 kfree(codec->vendor_name);
899 kfree(codec->chip_name);
Takashi Iwaif44ac832008-07-30 15:01:45 +0200900 kfree(codec->modelname);
Takashi Iwai54d17402005-11-21 16:33:22 +0100901 kfree(codec->wcaps);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700902 kfree(codec);
903}
904
Takashi Iwaibb6ac722009-03-13 09:02:42 +0100905static void hda_set_power_state(struct hda_codec *codec, hda_nid_t fg,
906 unsigned int power_state);
907
Linus Torvalds1da177e2005-04-16 15:20:36 -0700908/**
909 * snd_hda_codec_new - create a HDA codec
910 * @bus: the bus to assign
911 * @codec_addr: the codec address
912 * @codecp: the pointer to store the generated codec
913 *
914 * Returns 0 if successful, or a negative error code.
915 */
Takashi Iwai1289e9e2008-11-27 15:47:11 +0100916int /*__devinit*/ snd_hda_codec_new(struct hda_bus *bus, unsigned int codec_addr,
Takashi Iwaia1e21c92009-06-17 09:33:52 +0200917 struct hda_codec **codecp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700918{
919 struct hda_codec *codec;
Jaroslav Kyselaba443682008-08-13 20:55:32 +0200920 char component[31];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700921 int err;
922
Takashi Iwaida3cec32008-08-08 17:12:14 +0200923 if (snd_BUG_ON(!bus))
924 return -EINVAL;
925 if (snd_BUG_ON(codec_addr > HDA_MAX_CODEC_ADDRESS))
926 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700927
928 if (bus->caddr_tbl[codec_addr]) {
Takashi Iwai0ba21762007-04-16 11:29:14 +0200929 snd_printk(KERN_ERR "hda_codec: "
930 "address 0x%x is already occupied\n", codec_addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700931 return -EBUSY;
932 }
933
Takashi Iwaie560d8d2005-09-09 14:21:46 +0200934 codec = kzalloc(sizeof(*codec), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700935 if (codec == NULL) {
936 snd_printk(KERN_ERR "can't allocate struct hda_codec\n");
937 return -ENOMEM;
938 }
939
940 codec->bus = bus;
941 codec->addr = codec_addr;
Ingo Molnar62932df2006-01-16 16:34:20 +0100942 mutex_init(&codec->spdif_mutex);
Wu Fengguang5a9e02e2009-01-09 16:45:24 +0800943 mutex_init(&codec->control_mutex);
Takashi Iwai01751f52007-08-10 16:59:39 +0200944 init_hda_cache(&codec->amp_cache, sizeof(struct hda_amp_info));
Takashi Iwaib3ac5632007-08-10 17:03:40 +0200945 init_hda_cache(&codec->cmd_cache, sizeof(struct hda_cache_head));
Takashi Iwaid13bd412008-07-30 15:01:45 +0200946 snd_array_init(&codec->mixers, sizeof(struct snd_kcontrol *), 32);
Takashi Iwai3be14142009-02-20 14:11:16 +0100947 snd_array_init(&codec->init_pins, sizeof(struct hda_pincfg), 16);
Takashi Iwai346ff702009-02-23 09:42:57 +0100948 snd_array_init(&codec->driver_pins, sizeof(struct hda_pincfg), 16);
Takashi Iwai6c1f45e2008-07-30 15:01:45 +0200949 if (codec->bus->modelname) {
950 codec->modelname = kstrdup(codec->bus->modelname, GFP_KERNEL);
951 if (!codec->modelname) {
952 snd_hda_codec_free(codec);
953 return -ENODEV;
954 }
955 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700956
Takashi Iwaicb53c622007-08-10 17:21:45 +0200957#ifdef CONFIG_SND_HDA_POWER_SAVE
958 INIT_DELAYED_WORK(&codec->power_work, hda_power_work);
959 /* snd_hda_codec_new() marks the codec as power-up, and leave it as is.
960 * the caller has to power down appropriatley after initialization
961 * phase.
962 */
963 hda_keep_power_on(codec);
964#endif
965
Linus Torvalds1da177e2005-04-16 15:20:36 -0700966 list_add_tail(&codec->list, &bus->codec_list);
967 bus->caddr_tbl[codec_addr] = codec;
968
Takashi Iwai0ba21762007-04-16 11:29:14 +0200969 codec->vendor_id = snd_hda_param_read(codec, AC_NODE_ROOT,
970 AC_PAR_VENDOR_ID);
Takashi Iwai111d3af2006-02-16 18:17:58 +0100971 if (codec->vendor_id == -1)
972 /* read again, hopefully the access method was corrected
973 * in the last read...
974 */
975 codec->vendor_id = snd_hda_param_read(codec, AC_NODE_ROOT,
976 AC_PAR_VENDOR_ID);
Takashi Iwai0ba21762007-04-16 11:29:14 +0200977 codec->subsystem_id = snd_hda_param_read(codec, AC_NODE_ROOT,
978 AC_PAR_SUBSYSTEM_ID);
979 codec->revision_id = snd_hda_param_read(codec, AC_NODE_ROOT,
980 AC_PAR_REV_ID);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700981
Sasha Khapyorsky673b6832005-08-11 11:00:16 +0200982 setup_fg_nodes(codec);
Takashi Iwai0ba21762007-04-16 11:29:14 +0200983 if (!codec->afg && !codec->mfg) {
Sasha Khapyorsky673b6832005-08-11 11:00:16 +0200984 snd_printdd("hda_codec: no AFG or MFG node found\n");
Takashi Iwai3be14142009-02-20 14:11:16 +0100985 err = -ENODEV;
986 goto error;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700987 }
988
Takashi Iwai3be14142009-02-20 14:11:16 +0100989 err = read_widget_caps(codec, codec->afg ? codec->afg : codec->mfg);
990 if (err < 0) {
Takashi Iwai54d17402005-11-21 16:33:22 +0100991 snd_printk(KERN_ERR "hda_codec: cannot malloc\n");
Takashi Iwai3be14142009-02-20 14:11:16 +0100992 goto error;
Takashi Iwai54d17402005-11-21 16:33:22 +0100993 }
Takashi Iwai3be14142009-02-20 14:11:16 +0100994 err = read_pin_defaults(codec);
995 if (err < 0)
996 goto error;
Takashi Iwai54d17402005-11-21 16:33:22 +0100997
Takashi Iwai0ba21762007-04-16 11:29:14 +0200998 if (!codec->subsystem_id) {
Takashi Iwai86284e42005-10-11 15:05:54 +0200999 hda_nid_t nid = codec->afg ? codec->afg : codec->mfg;
Takashi Iwai0ba21762007-04-16 11:29:14 +02001000 codec->subsystem_id =
1001 snd_hda_codec_read(codec, nid, 0,
1002 AC_VERB_GET_SUBSYSTEM_ID, 0);
Takashi Iwai86284e42005-10-11 15:05:54 +02001003 }
1004
Takashi Iwaibb6ac722009-03-13 09:02:42 +01001005 /* power-up all before initialization */
1006 hda_set_power_state(codec,
1007 codec->afg ? codec->afg : codec->mfg,
1008 AC_PWRST_D0);
1009
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001010 snd_hda_codec_proc_new(codec);
1011
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001012 snd_hda_create_hwdep(codec);
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001013
1014 sprintf(component, "HDA:%08x,%08x,%08x", codec->vendor_id,
1015 codec->subsystem_id, codec->revision_id);
1016 snd_component_add(codec->bus->card, component);
1017
1018 if (codecp)
1019 *codecp = codec;
1020 return 0;
Takashi Iwai3be14142009-02-20 14:11:16 +01001021
1022 error:
1023 snd_hda_codec_free(codec);
1024 return err;
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001025}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001026EXPORT_SYMBOL_HDA(snd_hda_codec_new);
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001027
1028int snd_hda_codec_configure(struct hda_codec *codec)
1029{
1030 int err;
1031
Takashi Iwaid5ad6302007-03-07 15:55:59 +01001032 codec->preset = find_codec_preset(codec);
Takashi Iwai812a2cc2009-05-16 10:00:49 +02001033 if (!codec->vendor_name || !codec->chip_name) {
Takashi Iwaif44ac832008-07-30 15:01:45 +02001034 err = get_codec_name(codec);
1035 if (err < 0)
1036 return err;
1037 }
Takashi Iwai43ea1d42007-04-26 19:12:08 +02001038 /* audio codec should override the mixer name */
Takashi Iwaif44ac832008-07-30 15:01:45 +02001039 if (codec->afg || !*codec->bus->card->mixername)
Takashi Iwai812a2cc2009-05-16 10:00:49 +02001040 snprintf(codec->bus->card->mixername,
1041 sizeof(codec->bus->card->mixername),
1042 "%s %s", codec->vendor_name, codec->chip_name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001043
Takashi Iwai82467612007-07-27 19:15:54 +02001044 if (is_generic_config(codec)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001045 err = snd_hda_parse_generic_codec(codec);
Takashi Iwai82467612007-07-27 19:15:54 +02001046 goto patched;
1047 }
Takashi Iwai82467612007-07-27 19:15:54 +02001048 if (codec->preset && codec->preset->patch) {
1049 err = codec->preset->patch(codec);
1050 goto patched;
1051 }
1052
1053 /* call the default parser */
Takashi Iwai82467612007-07-27 19:15:54 +02001054 err = snd_hda_parse_generic_codec(codec);
Takashi Iwai35a1e0c2007-10-19 08:13:40 +02001055 if (err < 0)
1056 printk(KERN_ERR "hda-codec: No codec parser is available\n");
Takashi Iwai82467612007-07-27 19:15:54 +02001057
1058 patched:
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001059 if (!err && codec->patch_ops.unsol_event)
1060 err = init_unsol_queue(codec->bus);
1061 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001062}
Takashi Iwaia1e21c92009-06-17 09:33:52 +02001063EXPORT_SYMBOL_HDA(snd_hda_codec_configure);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001064
1065/**
1066 * snd_hda_codec_setup_stream - set up the codec for streaming
1067 * @codec: the CODEC to set up
1068 * @nid: the NID to set up
1069 * @stream_tag: stream tag to pass, it's between 0x1 and 0xf.
1070 * @channel_id: channel id to pass, zero based.
1071 * @format: stream format.
1072 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02001073void snd_hda_codec_setup_stream(struct hda_codec *codec, hda_nid_t nid,
1074 u32 stream_tag,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001075 int channel_id, int format)
1076{
Takashi Iwai0ba21762007-04-16 11:29:14 +02001077 if (!nid)
Takashi Iwaid21b37e2005-04-20 13:45:55 +02001078 return;
1079
Takashi Iwai0ba21762007-04-16 11:29:14 +02001080 snd_printdd("hda_codec_setup_stream: "
1081 "NID=0x%x, stream=0x%x, channel=%d, format=0x%x\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07001082 nid, stream_tag, channel_id, format);
1083 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CHANNEL_STREAMID,
1084 (stream_tag << 4) | channel_id);
1085 msleep(1);
1086 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_STREAM_FORMAT, format);
1087}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001088EXPORT_SYMBOL_HDA(snd_hda_codec_setup_stream);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001089
Takashi Iwai888afa12008-03-18 09:57:50 +01001090void snd_hda_codec_cleanup_stream(struct hda_codec *codec, hda_nid_t nid)
1091{
1092 if (!nid)
1093 return;
1094
1095 snd_printdd("hda_codec_cleanup_stream: NID=0x%x\n", nid);
1096 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CHANNEL_STREAMID, 0);
1097#if 0 /* keep the format */
1098 msleep(1);
1099 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_STREAM_FORMAT, 0);
1100#endif
1101}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001102EXPORT_SYMBOL_HDA(snd_hda_codec_cleanup_stream);
Takashi Iwai888afa12008-03-18 09:57:50 +01001103
Linus Torvalds1da177e2005-04-16 15:20:36 -07001104/*
1105 * amp access functions
1106 */
1107
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001108/* FIXME: more better hash key? */
1109#define HDA_HASH_KEY(nid,dir,idx) (u32)((nid) + ((idx) << 16) + ((dir) << 24))
Takashi Iwai1327a322009-03-23 13:07:47 +01001110#define HDA_HASH_PINCAP_KEY(nid) (u32)((nid) + (0x02 << 24))
Takashi Iwai92c7c8a2009-03-24 07:32:14 +01001111#define HDA_HASH_PARPCM_KEY(nid) (u32)((nid) + (0x03 << 24))
1112#define HDA_HASH_PARSTR_KEY(nid) (u32)((nid) + (0x04 << 24))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001113#define INFO_AMP_CAPS (1<<0)
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001114#define INFO_AMP_VOL(ch) (1 << (1 + (ch)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001115
1116/* initialize the hash table */
Takashi Iwai1289e9e2008-11-27 15:47:11 +01001117static void /*__devinit*/ init_hda_cache(struct hda_cache_rec *cache,
Takashi Iwai01751f52007-08-10 16:59:39 +02001118 unsigned int record_size)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001119{
Takashi Iwai01751f52007-08-10 16:59:39 +02001120 memset(cache, 0, sizeof(*cache));
1121 memset(cache->hash, 0xff, sizeof(cache->hash));
Takashi Iwai603c4012008-07-30 15:01:44 +02001122 snd_array_init(&cache->buf, record_size, 64);
Takashi Iwai01751f52007-08-10 16:59:39 +02001123}
1124
Takashi Iwai1fcaee62007-08-23 00:01:09 +02001125static void free_hda_cache(struct hda_cache_rec *cache)
Takashi Iwai01751f52007-08-10 16:59:39 +02001126{
Takashi Iwai603c4012008-07-30 15:01:44 +02001127 snd_array_free(&cache->buf);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001128}
1129
1130/* query the hash. allocate an entry if not found. */
Takashi Iwai01751f52007-08-10 16:59:39 +02001131static struct hda_cache_head *get_alloc_hash(struct hda_cache_rec *cache,
1132 u32 key)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001133{
Takashi Iwai01751f52007-08-10 16:59:39 +02001134 u16 idx = key % (u16)ARRAY_SIZE(cache->hash);
1135 u16 cur = cache->hash[idx];
1136 struct hda_cache_head *info;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001137
1138 while (cur != 0xffff) {
Takashi Iwaif43aa022008-11-10 16:24:26 +01001139 info = snd_array_elem(&cache->buf, cur);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001140 if (info->key == key)
1141 return info;
1142 cur = info->next;
1143 }
1144
1145 /* add a new hash entry */
Takashi Iwai603c4012008-07-30 15:01:44 +02001146 info = snd_array_new(&cache->buf);
Takashi Iwaic2174292008-11-07 00:23:30 +01001147 if (!info)
1148 return NULL;
Takashi Iwaif43aa022008-11-10 16:24:26 +01001149 cur = snd_array_index(&cache->buf, info);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001150 info->key = key;
Takashi Iwai01751f52007-08-10 16:59:39 +02001151 info->val = 0;
1152 info->next = cache->hash[idx];
1153 cache->hash[idx] = cur;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001154
1155 return info;
1156}
1157
Takashi Iwai01751f52007-08-10 16:59:39 +02001158/* query and allocate an amp hash entry */
1159static inline struct hda_amp_info *
1160get_alloc_amp_hash(struct hda_codec *codec, u32 key)
1161{
1162 return (struct hda_amp_info *)get_alloc_hash(&codec->amp_cache, key);
1163}
1164
Linus Torvalds1da177e2005-04-16 15:20:36 -07001165/*
1166 * query AMP capabilities for the given widget and direction
1167 */
Matthew Ranostay09a99952008-01-24 11:49:21 +01001168u32 query_amp_caps(struct hda_codec *codec, hda_nid_t nid, int direction)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001169{
Takashi Iwai0ba21762007-04-16 11:29:14 +02001170 struct hda_amp_info *info;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001171
Takashi Iwai0ba21762007-04-16 11:29:14 +02001172 info = get_alloc_amp_hash(codec, HDA_HASH_KEY(nid, direction, 0));
1173 if (!info)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001174 return 0;
Takashi Iwai01751f52007-08-10 16:59:39 +02001175 if (!(info->head.val & INFO_AMP_CAPS)) {
Takashi Iwai0ba21762007-04-16 11:29:14 +02001176 if (!(get_wcaps(codec, nid) & AC_WCAP_AMP_OVRD))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001177 nid = codec->afg;
Takashi Iwai0ba21762007-04-16 11:29:14 +02001178 info->amp_caps = snd_hda_param_read(codec, nid,
1179 direction == HDA_OUTPUT ?
1180 AC_PAR_AMP_OUT_CAP :
1181 AC_PAR_AMP_IN_CAP);
Takashi Iwaib75e53f2007-05-10 16:56:09 +02001182 if (info->amp_caps)
Takashi Iwai01751f52007-08-10 16:59:39 +02001183 info->head.val |= INFO_AMP_CAPS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001184 }
1185 return info->amp_caps;
1186}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001187EXPORT_SYMBOL_HDA(query_amp_caps);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001188
Takashi Iwai897cc182007-05-29 19:01:37 +02001189int snd_hda_override_amp_caps(struct hda_codec *codec, hda_nid_t nid, int dir,
1190 unsigned int caps)
1191{
1192 struct hda_amp_info *info;
1193
1194 info = get_alloc_amp_hash(codec, HDA_HASH_KEY(nid, dir, 0));
1195 if (!info)
1196 return -EINVAL;
1197 info->amp_caps = caps;
Takashi Iwai01751f52007-08-10 16:59:39 +02001198 info->head.val |= INFO_AMP_CAPS;
Takashi Iwai897cc182007-05-29 19:01:37 +02001199 return 0;
1200}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001201EXPORT_SYMBOL_HDA(snd_hda_override_amp_caps);
Takashi Iwai897cc182007-05-29 19:01:37 +02001202
Takashi Iwai92c7c8a2009-03-24 07:32:14 +01001203static unsigned int
1204query_caps_hash(struct hda_codec *codec, hda_nid_t nid, u32 key,
1205 unsigned int (*func)(struct hda_codec *, hda_nid_t))
Takashi Iwai1327a322009-03-23 13:07:47 +01001206{
1207 struct hda_amp_info *info;
1208
Takashi Iwai92c7c8a2009-03-24 07:32:14 +01001209 info = get_alloc_amp_hash(codec, key);
Takashi Iwai1327a322009-03-23 13:07:47 +01001210 if (!info)
1211 return 0;
1212 if (!info->head.val) {
Takashi Iwai1327a322009-03-23 13:07:47 +01001213 info->head.val |= INFO_AMP_CAPS;
Takashi Iwai92c7c8a2009-03-24 07:32:14 +01001214 info->amp_caps = func(codec, nid);
Takashi Iwai1327a322009-03-23 13:07:47 +01001215 }
1216 return info->amp_caps;
1217}
Takashi Iwai92c7c8a2009-03-24 07:32:14 +01001218
1219static unsigned int read_pin_cap(struct hda_codec *codec, hda_nid_t nid)
1220{
1221 return snd_hda_param_read(codec, nid, AC_PAR_PIN_CAP);
1222}
1223
1224u32 snd_hda_query_pin_caps(struct hda_codec *codec, hda_nid_t nid)
1225{
1226 return query_caps_hash(codec, nid, HDA_HASH_PINCAP_KEY(nid),
1227 read_pin_cap);
1228}
Takashi Iwai1327a322009-03-23 13:07:47 +01001229EXPORT_SYMBOL_HDA(snd_hda_query_pin_caps);
1230
Linus Torvalds1da177e2005-04-16 15:20:36 -07001231/*
1232 * read the current volume to info
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001233 * if the cache exists, read the cache value.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001234 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02001235static unsigned int get_vol_mute(struct hda_codec *codec,
1236 struct hda_amp_info *info, hda_nid_t nid,
1237 int ch, int direction, int index)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001238{
1239 u32 val, parm;
1240
Takashi Iwai01751f52007-08-10 16:59:39 +02001241 if (info->head.val & INFO_AMP_VOL(ch))
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001242 return info->vol[ch];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001243
1244 parm = ch ? AC_AMP_GET_RIGHT : AC_AMP_GET_LEFT;
1245 parm |= direction == HDA_OUTPUT ? AC_AMP_GET_OUTPUT : AC_AMP_GET_INPUT;
1246 parm |= index;
Takashi Iwai0ba21762007-04-16 11:29:14 +02001247 val = snd_hda_codec_read(codec, nid, 0,
1248 AC_VERB_GET_AMP_GAIN_MUTE, parm);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001249 info->vol[ch] = val & 0xff;
Takashi Iwai01751f52007-08-10 16:59:39 +02001250 info->head.val |= INFO_AMP_VOL(ch);
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001251 return info->vol[ch];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001252}
1253
1254/*
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001255 * write the current volume in info to the h/w and update the cache
Linus Torvalds1da177e2005-04-16 15:20:36 -07001256 */
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001257static void put_vol_mute(struct hda_codec *codec, struct hda_amp_info *info,
Takashi Iwai0ba21762007-04-16 11:29:14 +02001258 hda_nid_t nid, int ch, int direction, int index,
1259 int val)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001260{
1261 u32 parm;
1262
1263 parm = ch ? AC_AMP_SET_RIGHT : AC_AMP_SET_LEFT;
1264 parm |= direction == HDA_OUTPUT ? AC_AMP_SET_OUTPUT : AC_AMP_SET_INPUT;
1265 parm |= index << AC_AMP_SET_INDEX_SHIFT;
1266 parm |= val;
1267 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, parm);
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001268 info->vol[ch] = val;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001269}
1270
1271/*
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001272 * read AMP value. The volume is between 0 to 0x7f, 0x80 = mute bit.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001273 */
Takashi Iwai834be882006-03-01 14:16:17 +01001274int snd_hda_codec_amp_read(struct hda_codec *codec, hda_nid_t nid, int ch,
1275 int direction, int index)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001276{
Takashi Iwai0ba21762007-04-16 11:29:14 +02001277 struct hda_amp_info *info;
1278 info = get_alloc_amp_hash(codec, HDA_HASH_KEY(nid, direction, index));
1279 if (!info)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001280 return 0;
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001281 return get_vol_mute(codec, info, nid, ch, direction, index);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001282}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001283EXPORT_SYMBOL_HDA(snd_hda_codec_amp_read);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001284
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001285/*
1286 * update the AMP value, mask = bit mask to set, val = the value
1287 */
Takashi Iwai834be882006-03-01 14:16:17 +01001288int snd_hda_codec_amp_update(struct hda_codec *codec, hda_nid_t nid, int ch,
1289 int direction, int idx, int mask, int val)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001290{
Takashi Iwai0ba21762007-04-16 11:29:14 +02001291 struct hda_amp_info *info;
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001292
Takashi Iwai0ba21762007-04-16 11:29:14 +02001293 info = get_alloc_amp_hash(codec, HDA_HASH_KEY(nid, direction, idx));
1294 if (!info)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001295 return 0;
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001296 val &= mask;
1297 val |= get_vol_mute(codec, info, nid, ch, direction, idx) & ~mask;
Takashi Iwai82beb8f2007-08-10 17:09:26 +02001298 if (info->vol[ch] == val)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001299 return 0;
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001300 put_vol_mute(codec, info, nid, ch, direction, idx, val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001301 return 1;
1302}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001303EXPORT_SYMBOL_HDA(snd_hda_codec_amp_update);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001304
Takashi Iwai47fd8302007-08-10 17:11:07 +02001305/*
1306 * update the AMP stereo with the same mask and value
1307 */
1308int snd_hda_codec_amp_stereo(struct hda_codec *codec, hda_nid_t nid,
1309 int direction, int idx, int mask, int val)
1310{
1311 int ch, ret = 0;
1312 for (ch = 0; ch < 2; ch++)
1313 ret |= snd_hda_codec_amp_update(codec, nid, ch, direction,
1314 idx, mask, val);
1315 return ret;
1316}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001317EXPORT_SYMBOL_HDA(snd_hda_codec_amp_stereo);
Takashi Iwai47fd8302007-08-10 17:11:07 +02001318
Takashi Iwaicb53c622007-08-10 17:21:45 +02001319#ifdef SND_HDA_NEEDS_RESUME
Takashi Iwaib3ac5632007-08-10 17:03:40 +02001320/* resume the all amp commands from the cache */
1321void snd_hda_codec_resume_amp(struct hda_codec *codec)
1322{
Takashi Iwai603c4012008-07-30 15:01:44 +02001323 struct hda_amp_info *buffer = codec->amp_cache.buf.list;
Takashi Iwaib3ac5632007-08-10 17:03:40 +02001324 int i;
1325
Takashi Iwai603c4012008-07-30 15:01:44 +02001326 for (i = 0; i < codec->amp_cache.buf.used; i++, buffer++) {
Takashi Iwaib3ac5632007-08-10 17:03:40 +02001327 u32 key = buffer->head.key;
1328 hda_nid_t nid;
1329 unsigned int idx, dir, ch;
1330 if (!key)
1331 continue;
1332 nid = key & 0xff;
1333 idx = (key >> 16) & 0xff;
1334 dir = (key >> 24) & 0xff;
1335 for (ch = 0; ch < 2; ch++) {
1336 if (!(buffer->head.val & INFO_AMP_VOL(ch)))
1337 continue;
1338 put_vol_mute(codec, buffer, nid, ch, dir, idx,
1339 buffer->vol[ch]);
1340 }
1341 }
1342}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001343EXPORT_SYMBOL_HDA(snd_hda_codec_resume_amp);
Takashi Iwaicb53c622007-08-10 17:21:45 +02001344#endif /* SND_HDA_NEEDS_RESUME */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001345
Linus Torvalds1da177e2005-04-16 15:20:36 -07001346/* volume */
Takashi Iwai0ba21762007-04-16 11:29:14 +02001347int snd_hda_mixer_amp_volume_info(struct snd_kcontrol *kcontrol,
1348 struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001349{
1350 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1351 u16 nid = get_amp_nid(kcontrol);
1352 u8 chs = get_amp_channels(kcontrol);
1353 int dir = get_amp_direction(kcontrol);
Takashi Iwai29fdbec2009-01-20 13:07:55 +01001354 unsigned int ofs = get_amp_offset(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001355 u32 caps;
1356
1357 caps = query_amp_caps(codec, nid, dir);
Takashi Iwai0ba21762007-04-16 11:29:14 +02001358 /* num steps */
1359 caps = (caps & AC_AMPCAP_NUM_STEPS) >> AC_AMPCAP_NUM_STEPS_SHIFT;
1360 if (!caps) {
1361 printk(KERN_WARNING "hda_codec: "
Takashi Iwai9c8f2ab2008-01-11 16:12:23 +01001362 "num_steps = 0 for NID=0x%x (ctl = %s)\n", nid,
1363 kcontrol->id.name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001364 return -EINVAL;
1365 }
Takashi Iwai29fdbec2009-01-20 13:07:55 +01001366 if (ofs < caps)
1367 caps -= ofs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001368 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
1369 uinfo->count = chs == 3 ? 2 : 1;
1370 uinfo->value.integer.min = 0;
1371 uinfo->value.integer.max = caps;
1372 return 0;
1373}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001374EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_volume_info);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001375
Takashi Iwai29fdbec2009-01-20 13:07:55 +01001376
1377static inline unsigned int
1378read_amp_value(struct hda_codec *codec, hda_nid_t nid,
1379 int ch, int dir, int idx, unsigned int ofs)
1380{
1381 unsigned int val;
1382 val = snd_hda_codec_amp_read(codec, nid, ch, dir, idx);
1383 val &= HDA_AMP_VOLMASK;
1384 if (val >= ofs)
1385 val -= ofs;
1386 else
1387 val = 0;
1388 return val;
1389}
1390
1391static inline int
1392update_amp_value(struct hda_codec *codec, hda_nid_t nid,
1393 int ch, int dir, int idx, unsigned int ofs,
1394 unsigned int val)
1395{
1396 if (val > 0)
1397 val += ofs;
1398 return snd_hda_codec_amp_update(codec, nid, ch, dir, idx,
1399 HDA_AMP_VOLMASK, val);
1400}
1401
Takashi Iwai0ba21762007-04-16 11:29:14 +02001402int snd_hda_mixer_amp_volume_get(struct snd_kcontrol *kcontrol,
1403 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001404{
1405 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1406 hda_nid_t nid = get_amp_nid(kcontrol);
1407 int chs = get_amp_channels(kcontrol);
1408 int dir = get_amp_direction(kcontrol);
1409 int idx = get_amp_index(kcontrol);
Takashi Iwai29fdbec2009-01-20 13:07:55 +01001410 unsigned int ofs = get_amp_offset(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001411 long *valp = ucontrol->value.integer.value;
1412
1413 if (chs & 1)
Takashi Iwai29fdbec2009-01-20 13:07:55 +01001414 *valp++ = read_amp_value(codec, nid, 0, dir, idx, ofs);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001415 if (chs & 2)
Takashi Iwai29fdbec2009-01-20 13:07:55 +01001416 *valp = read_amp_value(codec, nid, 1, dir, idx, ofs);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001417 return 0;
1418}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001419EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_volume_get);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001420
Takashi Iwai0ba21762007-04-16 11:29:14 +02001421int snd_hda_mixer_amp_volume_put(struct snd_kcontrol *kcontrol,
1422 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001423{
1424 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1425 hda_nid_t nid = get_amp_nid(kcontrol);
1426 int chs = get_amp_channels(kcontrol);
1427 int dir = get_amp_direction(kcontrol);
1428 int idx = get_amp_index(kcontrol);
Takashi Iwai29fdbec2009-01-20 13:07:55 +01001429 unsigned int ofs = get_amp_offset(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001430 long *valp = ucontrol->value.integer.value;
1431 int change = 0;
1432
Takashi Iwaicb53c622007-08-10 17:21:45 +02001433 snd_hda_power_up(codec);
Nicolas Grazianob9f5a892005-07-29 12:17:20 +02001434 if (chs & 1) {
Takashi Iwai29fdbec2009-01-20 13:07:55 +01001435 change = update_amp_value(codec, nid, 0, dir, idx, ofs, *valp);
Nicolas Grazianob9f5a892005-07-29 12:17:20 +02001436 valp++;
1437 }
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001438 if (chs & 2)
Takashi Iwai29fdbec2009-01-20 13:07:55 +01001439 change |= update_amp_value(codec, nid, 1, dir, idx, ofs, *valp);
Takashi Iwaicb53c622007-08-10 17:21:45 +02001440 snd_hda_power_down(codec);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001441 return change;
1442}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001443EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_volume_put);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001444
Jaroslav Kysela302e9c52006-07-05 17:39:49 +02001445int snd_hda_mixer_amp_tlv(struct snd_kcontrol *kcontrol, int op_flag,
1446 unsigned int size, unsigned int __user *_tlv)
1447{
1448 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1449 hda_nid_t nid = get_amp_nid(kcontrol);
1450 int dir = get_amp_direction(kcontrol);
Takashi Iwai29fdbec2009-01-20 13:07:55 +01001451 unsigned int ofs = get_amp_offset(kcontrol);
Jaroslav Kysela302e9c52006-07-05 17:39:49 +02001452 u32 caps, val1, val2;
1453
1454 if (size < 4 * sizeof(unsigned int))
1455 return -ENOMEM;
1456 caps = query_amp_caps(codec, nid, dir);
Takashi Iwai0ba21762007-04-16 11:29:14 +02001457 val2 = (caps & AC_AMPCAP_STEP_SIZE) >> AC_AMPCAP_STEP_SIZE_SHIFT;
1458 val2 = (val2 + 1) * 25;
Jaroslav Kysela302e9c52006-07-05 17:39:49 +02001459 val1 = -((caps & AC_AMPCAP_OFFSET) >> AC_AMPCAP_OFFSET_SHIFT);
Takashi Iwai29fdbec2009-01-20 13:07:55 +01001460 val1 += ofs;
Jaroslav Kysela302e9c52006-07-05 17:39:49 +02001461 val1 = ((int)val1) * ((int)val2);
Jaroslav Kysela302e9c52006-07-05 17:39:49 +02001462 if (put_user(SNDRV_CTL_TLVT_DB_SCALE, _tlv))
1463 return -EFAULT;
1464 if (put_user(2 * sizeof(unsigned int), _tlv + 1))
1465 return -EFAULT;
1466 if (put_user(val1, _tlv + 2))
1467 return -EFAULT;
1468 if (put_user(val2, _tlv + 3))
1469 return -EFAULT;
1470 return 0;
1471}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001472EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_tlv);
Jaroslav Kysela302e9c52006-07-05 17:39:49 +02001473
Takashi Iwai2134ea42008-01-10 16:53:55 +01001474/*
1475 * set (static) TLV for virtual master volume; recalculated as max 0dB
1476 */
1477void snd_hda_set_vmaster_tlv(struct hda_codec *codec, hda_nid_t nid, int dir,
1478 unsigned int *tlv)
1479{
1480 u32 caps;
1481 int nums, step;
1482
1483 caps = query_amp_caps(codec, nid, dir);
1484 nums = (caps & AC_AMPCAP_NUM_STEPS) >> AC_AMPCAP_NUM_STEPS_SHIFT;
1485 step = (caps & AC_AMPCAP_STEP_SIZE) >> AC_AMPCAP_STEP_SIZE_SHIFT;
1486 step = (step + 1) * 25;
1487 tlv[0] = SNDRV_CTL_TLVT_DB_SCALE;
1488 tlv[1] = 2 * sizeof(unsigned int);
1489 tlv[2] = -nums * step;
1490 tlv[3] = step;
1491}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001492EXPORT_SYMBOL_HDA(snd_hda_set_vmaster_tlv);
Takashi Iwai2134ea42008-01-10 16:53:55 +01001493
1494/* find a mixer control element with the given name */
Takashi Iwai09f99702008-02-04 12:31:13 +01001495static struct snd_kcontrol *
1496_snd_hda_find_mixer_ctl(struct hda_codec *codec,
1497 const char *name, int idx)
Takashi Iwai2134ea42008-01-10 16:53:55 +01001498{
1499 struct snd_ctl_elem_id id;
1500 memset(&id, 0, sizeof(id));
1501 id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
Takashi Iwai09f99702008-02-04 12:31:13 +01001502 id.index = idx;
Takashi Iwai18cb7102009-04-16 10:22:24 +02001503 if (snd_BUG_ON(strlen(name) >= sizeof(id.name)))
1504 return NULL;
Takashi Iwai2134ea42008-01-10 16:53:55 +01001505 strcpy(id.name, name);
1506 return snd_ctl_find_id(codec->bus->card, &id);
1507}
1508
Takashi Iwai09f99702008-02-04 12:31:13 +01001509struct snd_kcontrol *snd_hda_find_mixer_ctl(struct hda_codec *codec,
1510 const char *name)
1511{
1512 return _snd_hda_find_mixer_ctl(codec, name, 0);
1513}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001514EXPORT_SYMBOL_HDA(snd_hda_find_mixer_ctl);
Takashi Iwai09f99702008-02-04 12:31:13 +01001515
Takashi Iwaid13bd412008-07-30 15:01:45 +02001516/* Add a control element and assign to the codec */
1517int snd_hda_ctl_add(struct hda_codec *codec, struct snd_kcontrol *kctl)
1518{
1519 int err;
1520 struct snd_kcontrol **knewp;
1521
1522 err = snd_ctl_add(codec->bus->card, kctl);
1523 if (err < 0)
1524 return err;
1525 knewp = snd_array_new(&codec->mixers);
1526 if (!knewp)
1527 return -ENOMEM;
1528 *knewp = kctl;
1529 return 0;
1530}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001531EXPORT_SYMBOL_HDA(snd_hda_ctl_add);
Takashi Iwaid13bd412008-07-30 15:01:45 +02001532
1533/* Clear all controls assigned to the given codec */
1534void snd_hda_ctls_clear(struct hda_codec *codec)
1535{
1536 int i;
1537 struct snd_kcontrol **kctls = codec->mixers.list;
1538 for (i = 0; i < codec->mixers.used; i++)
1539 snd_ctl_remove(codec->bus->card, kctls[i]);
1540 snd_array_free(&codec->mixers);
1541}
1542
Takashi Iwaia65d6292009-02-23 16:57:04 +01001543/* pseudo device locking
1544 * toggle card->shutdown to allow/disallow the device access (as a hack)
1545 */
1546static int hda_lock_devices(struct snd_card *card)
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001547{
Takashi Iwaia65d6292009-02-23 16:57:04 +01001548 spin_lock(&card->files_lock);
1549 if (card->shutdown) {
1550 spin_unlock(&card->files_lock);
1551 return -EINVAL;
1552 }
1553 card->shutdown = 1;
1554 spin_unlock(&card->files_lock);
1555 return 0;
1556}
1557
1558static void hda_unlock_devices(struct snd_card *card)
1559{
1560 spin_lock(&card->files_lock);
1561 card->shutdown = 0;
1562 spin_unlock(&card->files_lock);
1563}
1564
1565int snd_hda_codec_reset(struct hda_codec *codec)
1566{
1567 struct snd_card *card = codec->bus->card;
1568 int i, pcm;
1569
1570 if (hda_lock_devices(card) < 0)
1571 return -EBUSY;
1572 /* check whether the codec isn't used by any mixer or PCM streams */
1573 if (!list_empty(&card->ctl_files)) {
1574 hda_unlock_devices(card);
1575 return -EBUSY;
1576 }
1577 for (pcm = 0; pcm < codec->num_pcms; pcm++) {
1578 struct hda_pcm *cpcm = &codec->pcm_info[pcm];
1579 if (!cpcm->pcm)
1580 continue;
1581 if (cpcm->pcm->streams[0].substream_opened ||
1582 cpcm->pcm->streams[1].substream_opened) {
1583 hda_unlock_devices(card);
1584 return -EBUSY;
1585 }
1586 }
1587
1588 /* OK, let it free */
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001589
1590#ifdef CONFIG_SND_HDA_POWER_SAVE
1591 cancel_delayed_work(&codec->power_work);
Takashi Iwai6acaed32009-01-12 10:09:24 +01001592 flush_workqueue(codec->bus->workq);
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001593#endif
1594 snd_hda_ctls_clear(codec);
1595 /* relase PCMs */
1596 for (i = 0; i < codec->num_pcms; i++) {
Takashi Iwai529bd6c2008-11-27 14:17:01 +01001597 if (codec->pcm_info[i].pcm) {
Takashi Iwaia65d6292009-02-23 16:57:04 +01001598 snd_device_free(card, codec->pcm_info[i].pcm);
Takashi Iwai529bd6c2008-11-27 14:17:01 +01001599 clear_bit(codec->pcm_info[i].device,
1600 codec->bus->pcm_dev_bits);
1601 }
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001602 }
1603 if (codec->patch_ops.free)
1604 codec->patch_ops.free(codec);
Takashi Iwai56d17712008-11-28 14:36:23 +01001605 codec->proc_widget_hook = NULL;
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001606 codec->spec = NULL;
1607 free_hda_cache(&codec->amp_cache);
1608 free_hda_cache(&codec->cmd_cache);
Takashi Iwai827057f2008-12-19 10:12:02 +01001609 init_hda_cache(&codec->amp_cache, sizeof(struct hda_amp_info));
1610 init_hda_cache(&codec->cmd_cache, sizeof(struct hda_cache_head));
Takashi Iwai346ff702009-02-23 09:42:57 +01001611 /* free only driver_pins so that init_pins + user_pins are restored */
1612 snd_array_free(&codec->driver_pins);
Takashi Iwai3be14142009-02-20 14:11:16 +01001613 restore_pincfgs(codec);
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001614 codec->num_pcms = 0;
1615 codec->pcm_info = NULL;
1616 codec->preset = NULL;
Takashi Iwaid1f1af22009-03-02 10:35:29 +01001617 memset(&codec->patch_ops, 0, sizeof(codec->patch_ops));
1618 codec->slave_dig_outs = NULL;
1619 codec->spdif_status_reset = 0;
Takashi Iwai1289e9e2008-11-27 15:47:11 +01001620 module_put(codec->owner);
1621 codec->owner = NULL;
Takashi Iwaia65d6292009-02-23 16:57:04 +01001622
1623 /* allow device access again */
1624 hda_unlock_devices(card);
1625 return 0;
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001626}
1627
Takashi Iwai2134ea42008-01-10 16:53:55 +01001628/* create a virtual master control and add slaves */
1629int snd_hda_add_vmaster(struct hda_codec *codec, char *name,
1630 unsigned int *tlv, const char **slaves)
1631{
1632 struct snd_kcontrol *kctl;
1633 const char **s;
1634 int err;
1635
Takashi Iwai2f085542008-02-22 18:43:50 +01001636 for (s = slaves; *s && !snd_hda_find_mixer_ctl(codec, *s); s++)
1637 ;
1638 if (!*s) {
1639 snd_printdd("No slave found for %s\n", name);
1640 return 0;
1641 }
Takashi Iwai2134ea42008-01-10 16:53:55 +01001642 kctl = snd_ctl_make_virtual_master(name, tlv);
1643 if (!kctl)
1644 return -ENOMEM;
Takashi Iwaid13bd412008-07-30 15:01:45 +02001645 err = snd_hda_ctl_add(codec, kctl);
Takashi Iwai2134ea42008-01-10 16:53:55 +01001646 if (err < 0)
1647 return err;
1648
1649 for (s = slaves; *s; s++) {
1650 struct snd_kcontrol *sctl;
Takashi Iwai7a411ee2009-03-06 10:08:14 +01001651 int i = 0;
1652 for (;;) {
1653 sctl = _snd_hda_find_mixer_ctl(codec, *s, i);
1654 if (!sctl) {
1655 if (!i)
1656 snd_printdd("Cannot find slave %s, "
1657 "skipped\n", *s);
1658 break;
1659 }
1660 err = snd_ctl_add_slave(kctl, sctl);
1661 if (err < 0)
1662 return err;
1663 i++;
Takashi Iwai2134ea42008-01-10 16:53:55 +01001664 }
Takashi Iwai2134ea42008-01-10 16:53:55 +01001665 }
1666 return 0;
1667}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001668EXPORT_SYMBOL_HDA(snd_hda_add_vmaster);
Takashi Iwai2134ea42008-01-10 16:53:55 +01001669
Linus Torvalds1da177e2005-04-16 15:20:36 -07001670/* switch */
Takashi Iwai0ba21762007-04-16 11:29:14 +02001671int snd_hda_mixer_amp_switch_info(struct snd_kcontrol *kcontrol,
1672 struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001673{
1674 int chs = get_amp_channels(kcontrol);
1675
1676 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
1677 uinfo->count = chs == 3 ? 2 : 1;
1678 uinfo->value.integer.min = 0;
1679 uinfo->value.integer.max = 1;
1680 return 0;
1681}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001682EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_switch_info);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001683
Takashi Iwai0ba21762007-04-16 11:29:14 +02001684int snd_hda_mixer_amp_switch_get(struct snd_kcontrol *kcontrol,
1685 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001686{
1687 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1688 hda_nid_t nid = get_amp_nid(kcontrol);
1689 int chs = get_amp_channels(kcontrol);
1690 int dir = get_amp_direction(kcontrol);
1691 int idx = get_amp_index(kcontrol);
1692 long *valp = ucontrol->value.integer.value;
1693
1694 if (chs & 1)
Takashi Iwai0ba21762007-04-16 11:29:14 +02001695 *valp++ = (snd_hda_codec_amp_read(codec, nid, 0, dir, idx) &
Takashi Iwai47fd8302007-08-10 17:11:07 +02001696 HDA_AMP_MUTE) ? 0 : 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001697 if (chs & 2)
Takashi Iwai0ba21762007-04-16 11:29:14 +02001698 *valp = (snd_hda_codec_amp_read(codec, nid, 1, dir, idx) &
Takashi Iwai47fd8302007-08-10 17:11:07 +02001699 HDA_AMP_MUTE) ? 0 : 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001700 return 0;
1701}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001702EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_switch_get);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001703
Takashi Iwai0ba21762007-04-16 11:29:14 +02001704int snd_hda_mixer_amp_switch_put(struct snd_kcontrol *kcontrol,
1705 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001706{
1707 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1708 hda_nid_t nid = get_amp_nid(kcontrol);
1709 int chs = get_amp_channels(kcontrol);
1710 int dir = get_amp_direction(kcontrol);
1711 int idx = get_amp_index(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001712 long *valp = ucontrol->value.integer.value;
1713 int change = 0;
1714
Takashi Iwaicb53c622007-08-10 17:21:45 +02001715 snd_hda_power_up(codec);
Nicolas Grazianob9f5a892005-07-29 12:17:20 +02001716 if (chs & 1) {
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001717 change = snd_hda_codec_amp_update(codec, nid, 0, dir, idx,
Takashi Iwai47fd8302007-08-10 17:11:07 +02001718 HDA_AMP_MUTE,
1719 *valp ? 0 : HDA_AMP_MUTE);
Nicolas Grazianob9f5a892005-07-29 12:17:20 +02001720 valp++;
1721 }
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001722 if (chs & 2)
1723 change |= snd_hda_codec_amp_update(codec, nid, 1, dir, idx,
Takashi Iwai47fd8302007-08-10 17:11:07 +02001724 HDA_AMP_MUTE,
1725 *valp ? 0 : HDA_AMP_MUTE);
Takashi Iwaicb53c622007-08-10 17:21:45 +02001726#ifdef CONFIG_SND_HDA_POWER_SAVE
1727 if (codec->patch_ops.check_power_status)
1728 codec->patch_ops.check_power_status(codec, nid);
1729#endif
1730 snd_hda_power_down(codec);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001731 return change;
1732}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001733EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_switch_put);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001734
1735/*
Takashi Iwai985be542005-11-02 18:26:49 +01001736 * bound volume controls
1737 *
1738 * bind multiple volumes (# indices, from 0)
1739 */
1740
1741#define AMP_VAL_IDX_SHIFT 19
1742#define AMP_VAL_IDX_MASK (0x0f<<19)
1743
Takashi Iwai0ba21762007-04-16 11:29:14 +02001744int snd_hda_mixer_bind_switch_get(struct snd_kcontrol *kcontrol,
1745 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai985be542005-11-02 18:26:49 +01001746{
1747 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1748 unsigned long pval;
1749 int err;
1750
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001751 mutex_lock(&codec->control_mutex);
Takashi Iwai985be542005-11-02 18:26:49 +01001752 pval = kcontrol->private_value;
1753 kcontrol->private_value = pval & ~AMP_VAL_IDX_MASK; /* index 0 */
1754 err = snd_hda_mixer_amp_switch_get(kcontrol, ucontrol);
1755 kcontrol->private_value = pval;
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001756 mutex_unlock(&codec->control_mutex);
Takashi Iwai985be542005-11-02 18:26:49 +01001757 return err;
1758}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001759EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_switch_get);
Takashi Iwai985be542005-11-02 18:26:49 +01001760
Takashi Iwai0ba21762007-04-16 11:29:14 +02001761int snd_hda_mixer_bind_switch_put(struct snd_kcontrol *kcontrol,
1762 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai985be542005-11-02 18:26:49 +01001763{
1764 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1765 unsigned long pval;
1766 int i, indices, err = 0, change = 0;
1767
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001768 mutex_lock(&codec->control_mutex);
Takashi Iwai985be542005-11-02 18:26:49 +01001769 pval = kcontrol->private_value;
1770 indices = (pval & AMP_VAL_IDX_MASK) >> AMP_VAL_IDX_SHIFT;
1771 for (i = 0; i < indices; i++) {
Takashi Iwai0ba21762007-04-16 11:29:14 +02001772 kcontrol->private_value = (pval & ~AMP_VAL_IDX_MASK) |
1773 (i << AMP_VAL_IDX_SHIFT);
Takashi Iwai985be542005-11-02 18:26:49 +01001774 err = snd_hda_mixer_amp_switch_put(kcontrol, ucontrol);
1775 if (err < 0)
1776 break;
1777 change |= err;
1778 }
1779 kcontrol->private_value = pval;
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001780 mutex_unlock(&codec->control_mutex);
Takashi Iwai985be542005-11-02 18:26:49 +01001781 return err < 0 ? err : change;
1782}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001783EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_switch_put);
Takashi Iwai985be542005-11-02 18:26:49 +01001784
1785/*
Takashi Iwai532d5382007-07-27 19:02:40 +02001786 * generic bound volume/swtich controls
1787 */
1788int snd_hda_mixer_bind_ctls_info(struct snd_kcontrol *kcontrol,
1789 struct snd_ctl_elem_info *uinfo)
1790{
1791 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1792 struct hda_bind_ctls *c;
1793 int err;
1794
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001795 mutex_lock(&codec->control_mutex);
Serge A. Suchkov14c65f92008-02-22 18:43:16 +01001796 c = (struct hda_bind_ctls *)kcontrol->private_value;
Takashi Iwai532d5382007-07-27 19:02:40 +02001797 kcontrol->private_value = *c->values;
1798 err = c->ops->info(kcontrol, uinfo);
1799 kcontrol->private_value = (long)c;
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001800 mutex_unlock(&codec->control_mutex);
Takashi Iwai532d5382007-07-27 19:02:40 +02001801 return err;
1802}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001803EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_ctls_info);
Takashi Iwai532d5382007-07-27 19:02:40 +02001804
1805int snd_hda_mixer_bind_ctls_get(struct snd_kcontrol *kcontrol,
1806 struct snd_ctl_elem_value *ucontrol)
1807{
1808 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1809 struct hda_bind_ctls *c;
1810 int err;
1811
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001812 mutex_lock(&codec->control_mutex);
Serge A. Suchkov14c65f92008-02-22 18:43:16 +01001813 c = (struct hda_bind_ctls *)kcontrol->private_value;
Takashi Iwai532d5382007-07-27 19:02:40 +02001814 kcontrol->private_value = *c->values;
1815 err = c->ops->get(kcontrol, ucontrol);
1816 kcontrol->private_value = (long)c;
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001817 mutex_unlock(&codec->control_mutex);
Takashi Iwai532d5382007-07-27 19:02:40 +02001818 return err;
1819}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001820EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_ctls_get);
Takashi Iwai532d5382007-07-27 19:02:40 +02001821
1822int snd_hda_mixer_bind_ctls_put(struct snd_kcontrol *kcontrol,
1823 struct snd_ctl_elem_value *ucontrol)
1824{
1825 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1826 struct hda_bind_ctls *c;
1827 unsigned long *vals;
1828 int err = 0, change = 0;
1829
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001830 mutex_lock(&codec->control_mutex);
Serge A. Suchkov14c65f92008-02-22 18:43:16 +01001831 c = (struct hda_bind_ctls *)kcontrol->private_value;
Takashi Iwai532d5382007-07-27 19:02:40 +02001832 for (vals = c->values; *vals; vals++) {
1833 kcontrol->private_value = *vals;
1834 err = c->ops->put(kcontrol, ucontrol);
1835 if (err < 0)
1836 break;
1837 change |= err;
1838 }
1839 kcontrol->private_value = (long)c;
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001840 mutex_unlock(&codec->control_mutex);
Takashi Iwai532d5382007-07-27 19:02:40 +02001841 return err < 0 ? err : change;
1842}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001843EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_ctls_put);
Takashi Iwai532d5382007-07-27 19:02:40 +02001844
1845int snd_hda_mixer_bind_tlv(struct snd_kcontrol *kcontrol, int op_flag,
1846 unsigned int size, unsigned int __user *tlv)
1847{
1848 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1849 struct hda_bind_ctls *c;
1850 int err;
1851
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001852 mutex_lock(&codec->control_mutex);
Serge A. Suchkov14c65f92008-02-22 18:43:16 +01001853 c = (struct hda_bind_ctls *)kcontrol->private_value;
Takashi Iwai532d5382007-07-27 19:02:40 +02001854 kcontrol->private_value = *c->values;
1855 err = c->ops->tlv(kcontrol, op_flag, size, tlv);
1856 kcontrol->private_value = (long)c;
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001857 mutex_unlock(&codec->control_mutex);
Takashi Iwai532d5382007-07-27 19:02:40 +02001858 return err;
1859}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001860EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_tlv);
Takashi Iwai532d5382007-07-27 19:02:40 +02001861
1862struct hda_ctl_ops snd_hda_bind_vol = {
1863 .info = snd_hda_mixer_amp_volume_info,
1864 .get = snd_hda_mixer_amp_volume_get,
1865 .put = snd_hda_mixer_amp_volume_put,
1866 .tlv = snd_hda_mixer_amp_tlv
1867};
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001868EXPORT_SYMBOL_HDA(snd_hda_bind_vol);
Takashi Iwai532d5382007-07-27 19:02:40 +02001869
1870struct hda_ctl_ops snd_hda_bind_sw = {
1871 .info = snd_hda_mixer_amp_switch_info,
1872 .get = snd_hda_mixer_amp_switch_get,
1873 .put = snd_hda_mixer_amp_switch_put,
1874 .tlv = snd_hda_mixer_amp_tlv
1875};
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001876EXPORT_SYMBOL_HDA(snd_hda_bind_sw);
Takashi Iwai532d5382007-07-27 19:02:40 +02001877
1878/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07001879 * SPDIF out controls
1880 */
1881
Takashi Iwai0ba21762007-04-16 11:29:14 +02001882static int snd_hda_spdif_mask_info(struct snd_kcontrol *kcontrol,
1883 struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001884{
1885 uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
1886 uinfo->count = 1;
1887 return 0;
1888}
1889
Takashi Iwai0ba21762007-04-16 11:29:14 +02001890static int snd_hda_spdif_cmask_get(struct snd_kcontrol *kcontrol,
1891 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001892{
1893 ucontrol->value.iec958.status[0] = IEC958_AES0_PROFESSIONAL |
1894 IEC958_AES0_NONAUDIO |
1895 IEC958_AES0_CON_EMPHASIS_5015 |
1896 IEC958_AES0_CON_NOT_COPYRIGHT;
1897 ucontrol->value.iec958.status[1] = IEC958_AES1_CON_CATEGORY |
1898 IEC958_AES1_CON_ORIGINAL;
1899 return 0;
1900}
1901
Takashi Iwai0ba21762007-04-16 11:29:14 +02001902static int snd_hda_spdif_pmask_get(struct snd_kcontrol *kcontrol,
1903 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001904{
1905 ucontrol->value.iec958.status[0] = IEC958_AES0_PROFESSIONAL |
1906 IEC958_AES0_NONAUDIO |
1907 IEC958_AES0_PRO_EMPHASIS_5015;
1908 return 0;
1909}
1910
Takashi Iwai0ba21762007-04-16 11:29:14 +02001911static int snd_hda_spdif_default_get(struct snd_kcontrol *kcontrol,
1912 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001913{
1914 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1915
1916 ucontrol->value.iec958.status[0] = codec->spdif_status & 0xff;
1917 ucontrol->value.iec958.status[1] = (codec->spdif_status >> 8) & 0xff;
1918 ucontrol->value.iec958.status[2] = (codec->spdif_status >> 16) & 0xff;
1919 ucontrol->value.iec958.status[3] = (codec->spdif_status >> 24) & 0xff;
1920
1921 return 0;
1922}
1923
1924/* convert from SPDIF status bits to HDA SPDIF bits
1925 * bit 0 (DigEn) is always set zero (to be filled later)
1926 */
1927static unsigned short convert_from_spdif_status(unsigned int sbits)
1928{
1929 unsigned short val = 0;
1930
1931 if (sbits & IEC958_AES0_PROFESSIONAL)
Takashi Iwai0ba21762007-04-16 11:29:14 +02001932 val |= AC_DIG1_PROFESSIONAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001933 if (sbits & IEC958_AES0_NONAUDIO)
Takashi Iwai0ba21762007-04-16 11:29:14 +02001934 val |= AC_DIG1_NONAUDIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001935 if (sbits & IEC958_AES0_PROFESSIONAL) {
Takashi Iwai0ba21762007-04-16 11:29:14 +02001936 if ((sbits & IEC958_AES0_PRO_EMPHASIS) ==
1937 IEC958_AES0_PRO_EMPHASIS_5015)
1938 val |= AC_DIG1_EMPHASIS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001939 } else {
Takashi Iwai0ba21762007-04-16 11:29:14 +02001940 if ((sbits & IEC958_AES0_CON_EMPHASIS) ==
1941 IEC958_AES0_CON_EMPHASIS_5015)
1942 val |= AC_DIG1_EMPHASIS;
1943 if (!(sbits & IEC958_AES0_CON_NOT_COPYRIGHT))
1944 val |= AC_DIG1_COPYRIGHT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001945 if (sbits & (IEC958_AES1_CON_ORIGINAL << 8))
Takashi Iwai0ba21762007-04-16 11:29:14 +02001946 val |= AC_DIG1_LEVEL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001947 val |= sbits & (IEC958_AES1_CON_CATEGORY << 8);
1948 }
1949 return val;
1950}
1951
1952/* convert to SPDIF status bits from HDA SPDIF bits
1953 */
1954static unsigned int convert_to_spdif_status(unsigned short val)
1955{
1956 unsigned int sbits = 0;
1957
Takashi Iwai0ba21762007-04-16 11:29:14 +02001958 if (val & AC_DIG1_NONAUDIO)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001959 sbits |= IEC958_AES0_NONAUDIO;
Takashi Iwai0ba21762007-04-16 11:29:14 +02001960 if (val & AC_DIG1_PROFESSIONAL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001961 sbits |= IEC958_AES0_PROFESSIONAL;
1962 if (sbits & IEC958_AES0_PROFESSIONAL) {
Takashi Iwai0ba21762007-04-16 11:29:14 +02001963 if (sbits & AC_DIG1_EMPHASIS)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001964 sbits |= IEC958_AES0_PRO_EMPHASIS_5015;
1965 } else {
Takashi Iwai0ba21762007-04-16 11:29:14 +02001966 if (val & AC_DIG1_EMPHASIS)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001967 sbits |= IEC958_AES0_CON_EMPHASIS_5015;
Takashi Iwai0ba21762007-04-16 11:29:14 +02001968 if (!(val & AC_DIG1_COPYRIGHT))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001969 sbits |= IEC958_AES0_CON_NOT_COPYRIGHT;
Takashi Iwai0ba21762007-04-16 11:29:14 +02001970 if (val & AC_DIG1_LEVEL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001971 sbits |= (IEC958_AES1_CON_ORIGINAL << 8);
1972 sbits |= val & (0x7f << 8);
1973 }
1974 return sbits;
1975}
1976
Takashi Iwai2f728532008-09-25 16:32:41 +02001977/* set digital convert verbs both for the given NID and its slaves */
1978static void set_dig_out(struct hda_codec *codec, hda_nid_t nid,
1979 int verb, int val)
1980{
1981 hda_nid_t *d;
1982
Takashi Iwai9e976972008-11-25 08:17:20 +01001983 snd_hda_codec_write_cache(codec, nid, 0, verb, val);
Takashi Iwai2f728532008-09-25 16:32:41 +02001984 d = codec->slave_dig_outs;
1985 if (!d)
1986 return;
1987 for (; *d; d++)
Takashi Iwai9e976972008-11-25 08:17:20 +01001988 snd_hda_codec_write_cache(codec, *d, 0, verb, val);
Takashi Iwai2f728532008-09-25 16:32:41 +02001989}
1990
1991static inline void set_dig_out_convert(struct hda_codec *codec, hda_nid_t nid,
1992 int dig1, int dig2)
1993{
1994 if (dig1 != -1)
1995 set_dig_out(codec, nid, AC_VERB_SET_DIGI_CONVERT_1, dig1);
1996 if (dig2 != -1)
1997 set_dig_out(codec, nid, AC_VERB_SET_DIGI_CONVERT_2, dig2);
1998}
1999
Takashi Iwai0ba21762007-04-16 11:29:14 +02002000static int snd_hda_spdif_default_put(struct snd_kcontrol *kcontrol,
2001 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002002{
2003 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2004 hda_nid_t nid = kcontrol->private_value;
2005 unsigned short val;
2006 int change;
2007
Ingo Molnar62932df2006-01-16 16:34:20 +01002008 mutex_lock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002009 codec->spdif_status = ucontrol->value.iec958.status[0] |
2010 ((unsigned int)ucontrol->value.iec958.status[1] << 8) |
2011 ((unsigned int)ucontrol->value.iec958.status[2] << 16) |
2012 ((unsigned int)ucontrol->value.iec958.status[3] << 24);
2013 val = convert_from_spdif_status(codec->spdif_status);
2014 val |= codec->spdif_ctls & 1;
2015 change = codec->spdif_ctls != val;
2016 codec->spdif_ctls = val;
2017
Takashi Iwai2f728532008-09-25 16:32:41 +02002018 if (change)
2019 set_dig_out_convert(codec, nid, val & 0xff, (val >> 8) & 0xff);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002020
Ingo Molnar62932df2006-01-16 16:34:20 +01002021 mutex_unlock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002022 return change;
2023}
2024
Takashi Iwaia5ce8892007-07-23 15:42:26 +02002025#define snd_hda_spdif_out_switch_info snd_ctl_boolean_mono_info
Linus Torvalds1da177e2005-04-16 15:20:36 -07002026
Takashi Iwai0ba21762007-04-16 11:29:14 +02002027static int snd_hda_spdif_out_switch_get(struct snd_kcontrol *kcontrol,
2028 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002029{
2030 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2031
Takashi Iwai0ba21762007-04-16 11:29:14 +02002032 ucontrol->value.integer.value[0] = codec->spdif_ctls & AC_DIG1_ENABLE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002033 return 0;
2034}
2035
Takashi Iwai0ba21762007-04-16 11:29:14 +02002036static int snd_hda_spdif_out_switch_put(struct snd_kcontrol *kcontrol,
2037 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002038{
2039 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2040 hda_nid_t nid = kcontrol->private_value;
2041 unsigned short val;
2042 int change;
2043
Ingo Molnar62932df2006-01-16 16:34:20 +01002044 mutex_lock(&codec->spdif_mutex);
Takashi Iwai0ba21762007-04-16 11:29:14 +02002045 val = codec->spdif_ctls & ~AC_DIG1_ENABLE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002046 if (ucontrol->value.integer.value[0])
Takashi Iwai0ba21762007-04-16 11:29:14 +02002047 val |= AC_DIG1_ENABLE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002048 change = codec->spdif_ctls != val;
Takashi Iwai82beb8f2007-08-10 17:09:26 +02002049 if (change) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002050 codec->spdif_ctls = val;
Takashi Iwai2f728532008-09-25 16:32:41 +02002051 set_dig_out_convert(codec, nid, val & 0xff, -1);
Takashi Iwai0ba21762007-04-16 11:29:14 +02002052 /* unmute amp switch (if any) */
2053 if ((get_wcaps(codec, nid) & AC_WCAP_OUT_AMP) &&
Takashi Iwai47fd8302007-08-10 17:11:07 +02002054 (val & AC_DIG1_ENABLE))
2055 snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0,
2056 HDA_AMP_MUTE, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002057 }
Ingo Molnar62932df2006-01-16 16:34:20 +01002058 mutex_unlock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002059 return change;
2060}
2061
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01002062static struct snd_kcontrol_new dig_mixes[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002063 {
2064 .access = SNDRV_CTL_ELEM_ACCESS_READ,
2065 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2066 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,CON_MASK),
2067 .info = snd_hda_spdif_mask_info,
2068 .get = snd_hda_spdif_cmask_get,
2069 },
2070 {
2071 .access = SNDRV_CTL_ELEM_ACCESS_READ,
2072 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2073 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,PRO_MASK),
2074 .info = snd_hda_spdif_mask_info,
2075 .get = snd_hda_spdif_pmask_get,
2076 },
2077 {
2078 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2079 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT),
2080 .info = snd_hda_spdif_mask_info,
2081 .get = snd_hda_spdif_default_get,
2082 .put = snd_hda_spdif_default_put,
2083 },
2084 {
2085 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2086 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,SWITCH),
2087 .info = snd_hda_spdif_out_switch_info,
2088 .get = snd_hda_spdif_out_switch_get,
2089 .put = snd_hda_spdif_out_switch_put,
2090 },
2091 { } /* end */
2092};
2093
Takashi Iwai09f99702008-02-04 12:31:13 +01002094#define SPDIF_MAX_IDX 4 /* 4 instances should be enough to probe */
2095
Linus Torvalds1da177e2005-04-16 15:20:36 -07002096/**
2097 * snd_hda_create_spdif_out_ctls - create Output SPDIF-related controls
2098 * @codec: the HDA codec
2099 * @nid: audio out widget NID
2100 *
2101 * Creates controls related with the SPDIF output.
2102 * Called from each patch supporting the SPDIF out.
2103 *
2104 * Returns 0 if successful, or a negative error code.
2105 */
Takashi Iwai12f288b2007-08-02 15:51:59 +02002106int snd_hda_create_spdif_out_ctls(struct hda_codec *codec, hda_nid_t nid)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002107{
2108 int err;
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01002109 struct snd_kcontrol *kctl;
2110 struct snd_kcontrol_new *dig_mix;
Takashi Iwai09f99702008-02-04 12:31:13 +01002111 int idx;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002112
Takashi Iwai09f99702008-02-04 12:31:13 +01002113 for (idx = 0; idx < SPDIF_MAX_IDX; idx++) {
2114 if (!_snd_hda_find_mixer_ctl(codec, "IEC958 Playback Switch",
2115 idx))
2116 break;
2117 }
2118 if (idx >= SPDIF_MAX_IDX) {
2119 printk(KERN_ERR "hda_codec: too many IEC958 outputs\n");
2120 return -EBUSY;
2121 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002122 for (dig_mix = dig_mixes; dig_mix->name; dig_mix++) {
2123 kctl = snd_ctl_new1(dig_mix, codec);
Takashi Iwaib91f0802008-11-04 08:43:08 +01002124 if (!kctl)
2125 return -ENOMEM;
Takashi Iwai09f99702008-02-04 12:31:13 +01002126 kctl->id.index = idx;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002127 kctl->private_value = nid;
Takashi Iwaid13bd412008-07-30 15:01:45 +02002128 err = snd_hda_ctl_add(codec, kctl);
Takashi Iwai0ba21762007-04-16 11:29:14 +02002129 if (err < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002130 return err;
2131 }
Takashi Iwai0ba21762007-04-16 11:29:14 +02002132 codec->spdif_ctls =
Andrew Paprocki3982d172007-12-19 12:13:44 +01002133 snd_hda_codec_read(codec, nid, 0,
2134 AC_VERB_GET_DIGI_CONVERT_1, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002135 codec->spdif_status = convert_to_spdif_status(codec->spdif_ctls);
2136 return 0;
2137}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002138EXPORT_SYMBOL_HDA(snd_hda_create_spdif_out_ctls);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002139
2140/*
Takashi Iwai9a081602008-02-12 18:37:26 +01002141 * SPDIF sharing with analog output
2142 */
2143static int spdif_share_sw_get(struct snd_kcontrol *kcontrol,
2144 struct snd_ctl_elem_value *ucontrol)
2145{
2146 struct hda_multi_out *mout = snd_kcontrol_chip(kcontrol);
2147 ucontrol->value.integer.value[0] = mout->share_spdif;
2148 return 0;
2149}
2150
2151static int spdif_share_sw_put(struct snd_kcontrol *kcontrol,
2152 struct snd_ctl_elem_value *ucontrol)
2153{
2154 struct hda_multi_out *mout = snd_kcontrol_chip(kcontrol);
2155 mout->share_spdif = !!ucontrol->value.integer.value[0];
2156 return 0;
2157}
2158
2159static struct snd_kcontrol_new spdif_share_sw = {
2160 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2161 .name = "IEC958 Default PCM Playback Switch",
2162 .info = snd_ctl_boolean_mono_info,
2163 .get = spdif_share_sw_get,
2164 .put = spdif_share_sw_put,
2165};
2166
2167int snd_hda_create_spdif_share_sw(struct hda_codec *codec,
2168 struct hda_multi_out *mout)
2169{
2170 if (!mout->dig_out_nid)
2171 return 0;
2172 /* ATTENTION: here mout is passed as private_data, instead of codec */
Takashi Iwaid13bd412008-07-30 15:01:45 +02002173 return snd_hda_ctl_add(codec,
Takashi Iwai9a081602008-02-12 18:37:26 +01002174 snd_ctl_new1(&spdif_share_sw, mout));
2175}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002176EXPORT_SYMBOL_HDA(snd_hda_create_spdif_share_sw);
Takashi Iwai9a081602008-02-12 18:37:26 +01002177
2178/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002179 * SPDIF input
2180 */
2181
2182#define snd_hda_spdif_in_switch_info snd_hda_spdif_out_switch_info
2183
Takashi Iwai0ba21762007-04-16 11:29:14 +02002184static int snd_hda_spdif_in_switch_get(struct snd_kcontrol *kcontrol,
2185 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002186{
2187 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2188
2189 ucontrol->value.integer.value[0] = codec->spdif_in_enable;
2190 return 0;
2191}
2192
Takashi Iwai0ba21762007-04-16 11:29:14 +02002193static int snd_hda_spdif_in_switch_put(struct snd_kcontrol *kcontrol,
2194 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002195{
2196 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2197 hda_nid_t nid = kcontrol->private_value;
2198 unsigned int val = !!ucontrol->value.integer.value[0];
2199 int change;
2200
Ingo Molnar62932df2006-01-16 16:34:20 +01002201 mutex_lock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002202 change = codec->spdif_in_enable != val;
Takashi Iwai82beb8f2007-08-10 17:09:26 +02002203 if (change) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002204 codec->spdif_in_enable = val;
Takashi Iwai82beb8f2007-08-10 17:09:26 +02002205 snd_hda_codec_write_cache(codec, nid, 0,
2206 AC_VERB_SET_DIGI_CONVERT_1, val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002207 }
Ingo Molnar62932df2006-01-16 16:34:20 +01002208 mutex_unlock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002209 return change;
2210}
2211
Takashi Iwai0ba21762007-04-16 11:29:14 +02002212static int snd_hda_spdif_in_status_get(struct snd_kcontrol *kcontrol,
2213 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002214{
2215 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2216 hda_nid_t nid = kcontrol->private_value;
2217 unsigned short val;
2218 unsigned int sbits;
2219
Andrew Paprocki3982d172007-12-19 12:13:44 +01002220 val = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_DIGI_CONVERT_1, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002221 sbits = convert_to_spdif_status(val);
2222 ucontrol->value.iec958.status[0] = sbits;
2223 ucontrol->value.iec958.status[1] = sbits >> 8;
2224 ucontrol->value.iec958.status[2] = sbits >> 16;
2225 ucontrol->value.iec958.status[3] = sbits >> 24;
2226 return 0;
2227}
2228
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01002229static struct snd_kcontrol_new dig_in_ctls[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002230 {
2231 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2232 .name = SNDRV_CTL_NAME_IEC958("",CAPTURE,SWITCH),
2233 .info = snd_hda_spdif_in_switch_info,
2234 .get = snd_hda_spdif_in_switch_get,
2235 .put = snd_hda_spdif_in_switch_put,
2236 },
2237 {
2238 .access = SNDRV_CTL_ELEM_ACCESS_READ,
2239 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2240 .name = SNDRV_CTL_NAME_IEC958("",CAPTURE,DEFAULT),
2241 .info = snd_hda_spdif_mask_info,
2242 .get = snd_hda_spdif_in_status_get,
2243 },
2244 { } /* end */
2245};
2246
2247/**
2248 * snd_hda_create_spdif_in_ctls - create Input SPDIF-related controls
2249 * @codec: the HDA codec
2250 * @nid: audio in widget NID
2251 *
2252 * Creates controls related with the SPDIF input.
2253 * Called from each patch supporting the SPDIF in.
2254 *
2255 * Returns 0 if successful, or a negative error code.
2256 */
Takashi Iwai12f288b2007-08-02 15:51:59 +02002257int snd_hda_create_spdif_in_ctls(struct hda_codec *codec, hda_nid_t nid)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002258{
2259 int err;
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01002260 struct snd_kcontrol *kctl;
2261 struct snd_kcontrol_new *dig_mix;
Takashi Iwai09f99702008-02-04 12:31:13 +01002262 int idx;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002263
Takashi Iwai09f99702008-02-04 12:31:13 +01002264 for (idx = 0; idx < SPDIF_MAX_IDX; idx++) {
2265 if (!_snd_hda_find_mixer_ctl(codec, "IEC958 Capture Switch",
2266 idx))
2267 break;
2268 }
2269 if (idx >= SPDIF_MAX_IDX) {
2270 printk(KERN_ERR "hda_codec: too many IEC958 inputs\n");
2271 return -EBUSY;
2272 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002273 for (dig_mix = dig_in_ctls; dig_mix->name; dig_mix++) {
2274 kctl = snd_ctl_new1(dig_mix, codec);
Takashi Iwaic8dcdf82009-02-06 16:21:20 +01002275 if (!kctl)
2276 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002277 kctl->private_value = nid;
Takashi Iwaid13bd412008-07-30 15:01:45 +02002278 err = snd_hda_ctl_add(codec, kctl);
Takashi Iwai0ba21762007-04-16 11:29:14 +02002279 if (err < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002280 return err;
2281 }
Takashi Iwai0ba21762007-04-16 11:29:14 +02002282 codec->spdif_in_enable =
Andrew Paprocki3982d172007-12-19 12:13:44 +01002283 snd_hda_codec_read(codec, nid, 0,
2284 AC_VERB_GET_DIGI_CONVERT_1, 0) &
Takashi Iwai0ba21762007-04-16 11:29:14 +02002285 AC_DIG1_ENABLE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002286 return 0;
2287}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002288EXPORT_SYMBOL_HDA(snd_hda_create_spdif_in_ctls);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002289
Takashi Iwaicb53c622007-08-10 17:21:45 +02002290#ifdef SND_HDA_NEEDS_RESUME
Takashi Iwai82beb8f2007-08-10 17:09:26 +02002291/*
2292 * command cache
2293 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002294
Takashi Iwaib3ac5632007-08-10 17:03:40 +02002295/* build a 32bit cache key with the widget id and the command parameter */
2296#define build_cmd_cache_key(nid, verb) ((verb << 8) | nid)
2297#define get_cmd_cache_nid(key) ((key) & 0xff)
2298#define get_cmd_cache_cmd(key) (((key) >> 8) & 0xffff)
2299
2300/**
2301 * snd_hda_codec_write_cache - send a single command with caching
2302 * @codec: the HDA codec
2303 * @nid: NID to send the command
2304 * @direct: direct flag
2305 * @verb: the verb to send
2306 * @parm: the parameter for the verb
2307 *
2308 * Send a single command without waiting for response.
2309 *
2310 * Returns 0 if successful, or a negative error code.
2311 */
2312int snd_hda_codec_write_cache(struct hda_codec *codec, hda_nid_t nid,
2313 int direct, unsigned int verb, unsigned int parm)
2314{
Takashi Iwaiaa2936f2009-05-26 16:07:57 +02002315 int err = snd_hda_codec_write(codec, nid, direct, verb, parm);
2316 struct hda_cache_head *c;
2317 u32 key;
Takashi Iwai33fa35e2008-11-06 16:50:40 +01002318
Takashi Iwaiaa2936f2009-05-26 16:07:57 +02002319 if (err < 0)
2320 return err;
2321 /* parm may contain the verb stuff for get/set amp */
2322 verb = verb | (parm >> 8);
2323 parm &= 0xff;
2324 key = build_cmd_cache_key(nid, verb);
2325 mutex_lock(&codec->bus->cmd_mutex);
2326 c = get_alloc_hash(&codec->cmd_cache, key);
2327 if (c)
2328 c->val = parm;
2329 mutex_unlock(&codec->bus->cmd_mutex);
2330 return 0;
Takashi Iwaib3ac5632007-08-10 17:03:40 +02002331}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002332EXPORT_SYMBOL_HDA(snd_hda_codec_write_cache);
Takashi Iwaib3ac5632007-08-10 17:03:40 +02002333
2334/* resume the all commands from the cache */
2335void snd_hda_codec_resume_cache(struct hda_codec *codec)
2336{
Takashi Iwai603c4012008-07-30 15:01:44 +02002337 struct hda_cache_head *buffer = codec->cmd_cache.buf.list;
Takashi Iwaib3ac5632007-08-10 17:03:40 +02002338 int i;
2339
Takashi Iwai603c4012008-07-30 15:01:44 +02002340 for (i = 0; i < codec->cmd_cache.buf.used; i++, buffer++) {
Takashi Iwaib3ac5632007-08-10 17:03:40 +02002341 u32 key = buffer->key;
2342 if (!key)
2343 continue;
2344 snd_hda_codec_write(codec, get_cmd_cache_nid(key), 0,
2345 get_cmd_cache_cmd(key), buffer->val);
2346 }
2347}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002348EXPORT_SYMBOL_HDA(snd_hda_codec_resume_cache);
Takashi Iwaib3ac5632007-08-10 17:03:40 +02002349
2350/**
2351 * snd_hda_sequence_write_cache - sequence writes with caching
2352 * @codec: the HDA codec
2353 * @seq: VERB array to send
2354 *
2355 * Send the commands sequentially from the given array.
2356 * Thte commands are recorded on cache for power-save and resume.
2357 * The array must be terminated with NID=0.
2358 */
2359void snd_hda_sequence_write_cache(struct hda_codec *codec,
2360 const struct hda_verb *seq)
2361{
2362 for (; seq->nid; seq++)
2363 snd_hda_codec_write_cache(codec, seq->nid, 0, seq->verb,
2364 seq->param);
2365}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002366EXPORT_SYMBOL_HDA(snd_hda_sequence_write_cache);
Takashi Iwaicb53c622007-08-10 17:21:45 +02002367#endif /* SND_HDA_NEEDS_RESUME */
Takashi Iwaib3ac5632007-08-10 17:03:40 +02002368
Takashi Iwai54d17402005-11-21 16:33:22 +01002369/*
2370 * set power state of the codec
2371 */
2372static void hda_set_power_state(struct hda_codec *codec, hda_nid_t fg,
2373 unsigned int power_state)
2374{
Takashi Iwaicb53c622007-08-10 17:21:45 +02002375 hda_nid_t nid;
2376 int i;
Takashi Iwai54d17402005-11-21 16:33:22 +01002377
Takashi Iwai05ff7e12009-07-22 12:39:24 +02002378 /* this delay seems necessary to avoid click noise at power-down */
2379 if (power_state == AC_PWRST_D3)
2380 msleep(100);
2381 snd_hda_codec_read(codec, fg, 0, AC_VERB_SET_POWER_STATE,
Takashi Iwai54d17402005-11-21 16:33:22 +01002382 power_state);
Takashi Iwai05ff7e12009-07-22 12:39:24 +02002383 /* partial workaround for "azx_get_response timeout" */
2384 if (power_state == AC_PWRST_D0)
2385 msleep(10);
Takashi Iwai54d17402005-11-21 16:33:22 +01002386
Takashi Iwaicb53c622007-08-10 17:21:45 +02002387 nid = codec->start_nid;
2388 for (i = 0; i < codec->num_nodes; i++, nid++) {
Takashi Iwai7eba5c92007-11-14 14:53:42 +01002389 unsigned int wcaps = get_wcaps(codec, nid);
2390 if (wcaps & AC_WCAP_POWER) {
Takashi Iwaia22d5432009-07-27 12:54:26 +02002391 unsigned int wid_type = get_wcaps_type(wcaps);
Takashi Iwaia3b48c82009-04-21 13:37:29 +02002392 if (power_state == AC_PWRST_D3 &&
2393 wid_type == AC_WID_PIN) {
Takashi Iwai7eba5c92007-11-14 14:53:42 +01002394 unsigned int pincap;
2395 /*
2396 * don't power down the widget if it controls
2397 * eapd and EAPD_BTLENABLE is set.
2398 */
Takashi Iwai14bafe32009-03-23 16:35:39 +01002399 pincap = snd_hda_query_pin_caps(codec, nid);
Takashi Iwai7eba5c92007-11-14 14:53:42 +01002400 if (pincap & AC_PINCAP_EAPD) {
2401 int eapd = snd_hda_codec_read(codec,
2402 nid, 0,
2403 AC_VERB_GET_EAPD_BTLENABLE, 0);
2404 eapd &= 0x02;
Takashi Iwaia3b48c82009-04-21 13:37:29 +02002405 if (eapd)
Takashi Iwai7eba5c92007-11-14 14:53:42 +01002406 continue;
2407 }
Takashi Iwai1194b5b2007-10-10 10:04:26 +02002408 }
Takashi Iwai54d17402005-11-21 16:33:22 +01002409 snd_hda_codec_write(codec, nid, 0,
2410 AC_VERB_SET_POWER_STATE,
2411 power_state);
Takashi Iwai1194b5b2007-10-10 10:04:26 +02002412 }
Takashi Iwai54d17402005-11-21 16:33:22 +01002413 }
2414
Takashi Iwaicb53c622007-08-10 17:21:45 +02002415 if (power_state == AC_PWRST_D0) {
2416 unsigned long end_time;
2417 int state;
Takashi Iwai54d17402005-11-21 16:33:22 +01002418 msleep(10);
Takashi Iwaicb53c622007-08-10 17:21:45 +02002419 /* wait until the codec reachs to D0 */
2420 end_time = jiffies + msecs_to_jiffies(500);
2421 do {
2422 state = snd_hda_codec_read(codec, fg, 0,
2423 AC_VERB_GET_POWER_STATE, 0);
2424 if (state == power_state)
2425 break;
2426 msleep(1);
2427 } while (time_after_eq(end_time, jiffies));
2428 }
Takashi Iwai54d17402005-11-21 16:33:22 +01002429}
2430
Takashi Iwai11aeff02008-07-30 15:01:46 +02002431#ifdef CONFIG_SND_HDA_HWDEP
2432/* execute additional init verbs */
2433static void hda_exec_init_verbs(struct hda_codec *codec)
2434{
2435 if (codec->init_verbs.list)
2436 snd_hda_sequence_write(codec, codec->init_verbs.list);
2437}
2438#else
2439static inline void hda_exec_init_verbs(struct hda_codec *codec) {}
2440#endif
2441
Takashi Iwaicb53c622007-08-10 17:21:45 +02002442#ifdef SND_HDA_NEEDS_RESUME
2443/*
2444 * call suspend and power-down; used both from PM and power-save
2445 */
2446static void hda_call_codec_suspend(struct hda_codec *codec)
2447{
2448 if (codec->patch_ops.suspend)
2449 codec->patch_ops.suspend(codec, PMSG_SUSPEND);
2450 hda_set_power_state(codec,
2451 codec->afg ? codec->afg : codec->mfg,
2452 AC_PWRST_D3);
2453#ifdef CONFIG_SND_HDA_POWER_SAVE
2454 cancel_delayed_work(&codec->power_work);
Takashi Iwai95e99fd2007-08-13 15:29:04 +02002455 codec->power_on = 0;
Takashi Iwaia221e282007-08-16 16:35:33 +02002456 codec->power_transition = 0;
Takashi Iwaicb53c622007-08-10 17:21:45 +02002457#endif
2458}
2459
2460/*
2461 * kick up codec; used both from PM and power-save
2462 */
2463static void hda_call_codec_resume(struct hda_codec *codec)
2464{
2465 hda_set_power_state(codec,
2466 codec->afg ? codec->afg : codec->mfg,
2467 AC_PWRST_D0);
Takashi Iwai3be14142009-02-20 14:11:16 +01002468 restore_pincfgs(codec); /* restore all current pin configs */
Takashi Iwai11aeff02008-07-30 15:01:46 +02002469 hda_exec_init_verbs(codec);
Takashi Iwaicb53c622007-08-10 17:21:45 +02002470 if (codec->patch_ops.resume)
2471 codec->patch_ops.resume(codec);
2472 else {
Takashi Iwai9d99f312007-08-14 15:15:52 +02002473 if (codec->patch_ops.init)
2474 codec->patch_ops.init(codec);
Takashi Iwaicb53c622007-08-10 17:21:45 +02002475 snd_hda_codec_resume_amp(codec);
2476 snd_hda_codec_resume_cache(codec);
2477 }
2478}
2479#endif /* SND_HDA_NEEDS_RESUME */
2480
Takashi Iwai54d17402005-11-21 16:33:22 +01002481
Linus Torvalds1da177e2005-04-16 15:20:36 -07002482/**
2483 * snd_hda_build_controls - build mixer controls
2484 * @bus: the BUS
2485 *
2486 * Creates mixer controls for each codec included in the bus.
2487 *
2488 * Returns 0 if successful, otherwise a negative error code.
2489 */
Takashi Iwai1289e9e2008-11-27 15:47:11 +01002490int /*__devinit*/ snd_hda_build_controls(struct hda_bus *bus)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002491{
Takashi Iwai0ba21762007-04-16 11:29:14 +02002492 struct hda_codec *codec;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002493
Takashi Iwai0ba21762007-04-16 11:29:14 +02002494 list_for_each_entry(codec, &bus->codec_list, list) {
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02002495 int err = snd_hda_codec_build_controls(codec);
Takashi Iwaif93d4612009-03-02 10:44:15 +01002496 if (err < 0) {
2497 printk(KERN_ERR "hda_codec: cannot build controls"
2498 "for #%d (error %d)\n", codec->addr, err);
2499 err = snd_hda_codec_reset(codec);
2500 if (err < 0) {
2501 printk(KERN_ERR
2502 "hda_codec: cannot revert codec\n");
2503 return err;
2504 }
2505 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002506 }
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02002507 return 0;
2508}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002509EXPORT_SYMBOL_HDA(snd_hda_build_controls);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002510
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02002511int snd_hda_codec_build_controls(struct hda_codec *codec)
2512{
2513 int err = 0;
Takashi Iwai11aeff02008-07-30 15:01:46 +02002514 hda_exec_init_verbs(codec);
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02002515 /* continue to initialize... */
2516 if (codec->patch_ops.init)
2517 err = codec->patch_ops.init(codec);
2518 if (!err && codec->patch_ops.build_controls)
2519 err = codec->patch_ops.build_controls(codec);
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02002520 if (err < 0)
2521 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002522 return 0;
2523}
2524
Linus Torvalds1da177e2005-04-16 15:20:36 -07002525/*
2526 * stream formats
2527 */
Takashi Iwaibefdf312005-08-22 13:57:55 +02002528struct hda_rate_tbl {
2529 unsigned int hz;
2530 unsigned int alsa_bits;
2531 unsigned int hda_fmt;
2532};
2533
2534static struct hda_rate_tbl rate_bits[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002535 /* rate in Hz, ALSA rate bitmask, HDA format value */
Nicolas Graziano9d8f53f2005-08-22 13:47:16 +02002536
2537 /* autodetected value used in snd_hda_query_supported_pcm */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002538 { 8000, SNDRV_PCM_RATE_8000, 0x0500 }, /* 1/6 x 48 */
2539 { 11025, SNDRV_PCM_RATE_11025, 0x4300 }, /* 1/4 x 44 */
2540 { 16000, SNDRV_PCM_RATE_16000, 0x0200 }, /* 1/3 x 48 */
2541 { 22050, SNDRV_PCM_RATE_22050, 0x4100 }, /* 1/2 x 44 */
2542 { 32000, SNDRV_PCM_RATE_32000, 0x0a00 }, /* 2/3 x 48 */
2543 { 44100, SNDRV_PCM_RATE_44100, 0x4000 }, /* 44 */
2544 { 48000, SNDRV_PCM_RATE_48000, 0x0000 }, /* 48 */
2545 { 88200, SNDRV_PCM_RATE_88200, 0x4800 }, /* 2 x 44 */
2546 { 96000, SNDRV_PCM_RATE_96000, 0x0800 }, /* 2 x 48 */
2547 { 176400, SNDRV_PCM_RATE_176400, 0x5800 },/* 4 x 44 */
2548 { 192000, SNDRV_PCM_RATE_192000, 0x1800 }, /* 4 x 48 */
Takashi Iwaia961f9f2007-04-12 13:08:09 +02002549#define AC_PAR_PCM_RATE_BITS 11
2550 /* up to bits 10, 384kHZ isn't supported properly */
2551
2552 /* not autodetected value */
2553 { 9600, SNDRV_PCM_RATE_KNOT, 0x0400 }, /* 1/5 x 48 */
Nicolas Graziano9d8f53f2005-08-22 13:47:16 +02002554
Takashi Iwaibefdf312005-08-22 13:57:55 +02002555 { 0 } /* terminator */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002556};
2557
2558/**
2559 * snd_hda_calc_stream_format - calculate format bitset
2560 * @rate: the sample rate
2561 * @channels: the number of channels
2562 * @format: the PCM format (SNDRV_PCM_FORMAT_XXX)
2563 * @maxbps: the max. bps
2564 *
2565 * Calculate the format bitset from the given rate, channels and th PCM format.
2566 *
2567 * Return zero if invalid.
2568 */
2569unsigned int snd_hda_calc_stream_format(unsigned int rate,
2570 unsigned int channels,
2571 unsigned int format,
2572 unsigned int maxbps)
2573{
2574 int i;
2575 unsigned int val = 0;
2576
Takashi Iwaibefdf312005-08-22 13:57:55 +02002577 for (i = 0; rate_bits[i].hz; i++)
2578 if (rate_bits[i].hz == rate) {
2579 val = rate_bits[i].hda_fmt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002580 break;
2581 }
Takashi Iwai0ba21762007-04-16 11:29:14 +02002582 if (!rate_bits[i].hz) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002583 snd_printdd("invalid rate %d\n", rate);
2584 return 0;
2585 }
2586
2587 if (channels == 0 || channels > 8) {
2588 snd_printdd("invalid channels %d\n", channels);
2589 return 0;
2590 }
2591 val |= channels - 1;
2592
2593 switch (snd_pcm_format_width(format)) {
2594 case 8: val |= 0x00; break;
2595 case 16: val |= 0x10; break;
2596 case 20:
2597 case 24:
2598 case 32:
Takashi Iwaib0bb3aa2009-07-03 23:25:37 +02002599 if (maxbps >= 32 || format == SNDRV_PCM_FORMAT_FLOAT_LE)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002600 val |= 0x40;
2601 else if (maxbps >= 24)
2602 val |= 0x30;
2603 else
2604 val |= 0x20;
2605 break;
2606 default:
Takashi Iwai0ba21762007-04-16 11:29:14 +02002607 snd_printdd("invalid format width %d\n",
2608 snd_pcm_format_width(format));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002609 return 0;
2610 }
2611
2612 return val;
2613}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002614EXPORT_SYMBOL_HDA(snd_hda_calc_stream_format);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002615
Takashi Iwai92c7c8a2009-03-24 07:32:14 +01002616static unsigned int get_pcm_param(struct hda_codec *codec, hda_nid_t nid)
2617{
2618 unsigned int val = 0;
2619 if (nid != codec->afg &&
2620 (get_wcaps(codec, nid) & AC_WCAP_FORMAT_OVRD))
2621 val = snd_hda_param_read(codec, nid, AC_PAR_PCM);
2622 if (!val || val == -1)
2623 val = snd_hda_param_read(codec, codec->afg, AC_PAR_PCM);
2624 if (!val || val == -1)
2625 return 0;
2626 return val;
2627}
2628
2629static unsigned int query_pcm_param(struct hda_codec *codec, hda_nid_t nid)
2630{
2631 return query_caps_hash(codec, nid, HDA_HASH_PARPCM_KEY(nid),
2632 get_pcm_param);
2633}
2634
2635static unsigned int get_stream_param(struct hda_codec *codec, hda_nid_t nid)
2636{
2637 unsigned int streams = snd_hda_param_read(codec, nid, AC_PAR_STREAM);
2638 if (!streams || streams == -1)
2639 streams = snd_hda_param_read(codec, codec->afg, AC_PAR_STREAM);
2640 if (!streams || streams == -1)
2641 return 0;
2642 return streams;
2643}
2644
2645static unsigned int query_stream_param(struct hda_codec *codec, hda_nid_t nid)
2646{
2647 return query_caps_hash(codec, nid, HDA_HASH_PARSTR_KEY(nid),
2648 get_stream_param);
2649}
2650
Linus Torvalds1da177e2005-04-16 15:20:36 -07002651/**
2652 * snd_hda_query_supported_pcm - query the supported PCM rates and formats
2653 * @codec: the HDA codec
2654 * @nid: NID to query
2655 * @ratesp: the pointer to store the detected rate bitflags
2656 * @formatsp: the pointer to store the detected formats
2657 * @bpsp: the pointer to store the detected format widths
2658 *
2659 * Queries the supported PCM rates and formats. The NULL @ratesp, @formatsp
2660 * or @bsps argument is ignored.
2661 *
2662 * Returns 0 if successful, otherwise a negative error code.
2663 */
Takashi Iwai986862bd2008-11-27 12:40:13 +01002664static int snd_hda_query_supported_pcm(struct hda_codec *codec, hda_nid_t nid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002665 u32 *ratesp, u64 *formatsp, unsigned int *bpsp)
2666{
Jaroslav Kyselaee504712009-03-17 14:30:31 +01002667 unsigned int i, val, wcaps;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002668
Jaroslav Kyselaee504712009-03-17 14:30:31 +01002669 wcaps = get_wcaps(codec, nid);
Takashi Iwai92c7c8a2009-03-24 07:32:14 +01002670 val = query_pcm_param(codec, nid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002671
2672 if (ratesp) {
2673 u32 rates = 0;
Takashi Iwaia961f9f2007-04-12 13:08:09 +02002674 for (i = 0; i < AC_PAR_PCM_RATE_BITS; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002675 if (val & (1 << i))
Takashi Iwaibefdf312005-08-22 13:57:55 +02002676 rates |= rate_bits[i].alsa_bits;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002677 }
Jaroslav Kyselaee504712009-03-17 14:30:31 +01002678 if (rates == 0) {
2679 snd_printk(KERN_ERR "hda_codec: rates == 0 "
2680 "(nid=0x%x, val=0x%x, ovrd=%i)\n",
2681 nid, val,
2682 (wcaps & AC_WCAP_FORMAT_OVRD) ? 1 : 0);
2683 return -EIO;
2684 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002685 *ratesp = rates;
2686 }
2687
2688 if (formatsp || bpsp) {
2689 u64 formats = 0;
Jaroslav Kyselaee504712009-03-17 14:30:31 +01002690 unsigned int streams, bps;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002691
Takashi Iwai92c7c8a2009-03-24 07:32:14 +01002692 streams = query_stream_param(codec, nid);
2693 if (!streams)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002694 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002695
2696 bps = 0;
2697 if (streams & AC_SUPFMT_PCM) {
2698 if (val & AC_SUPPCM_BITS_8) {
2699 formats |= SNDRV_PCM_FMTBIT_U8;
2700 bps = 8;
2701 }
2702 if (val & AC_SUPPCM_BITS_16) {
2703 formats |= SNDRV_PCM_FMTBIT_S16_LE;
2704 bps = 16;
2705 }
2706 if (wcaps & AC_WCAP_DIGITAL) {
2707 if (val & AC_SUPPCM_BITS_32)
2708 formats |= SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_LE;
2709 if (val & (AC_SUPPCM_BITS_20|AC_SUPPCM_BITS_24))
2710 formats |= SNDRV_PCM_FMTBIT_S32_LE;
2711 if (val & AC_SUPPCM_BITS_24)
2712 bps = 24;
2713 else if (val & AC_SUPPCM_BITS_20)
2714 bps = 20;
Takashi Iwai0ba21762007-04-16 11:29:14 +02002715 } else if (val & (AC_SUPPCM_BITS_20|AC_SUPPCM_BITS_24|
2716 AC_SUPPCM_BITS_32)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002717 formats |= SNDRV_PCM_FMTBIT_S32_LE;
2718 if (val & AC_SUPPCM_BITS_32)
2719 bps = 32;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002720 else if (val & AC_SUPPCM_BITS_24)
2721 bps = 24;
Nicolas Graziano33ef76512006-09-19 14:23:14 +02002722 else if (val & AC_SUPPCM_BITS_20)
2723 bps = 20;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002724 }
2725 }
Takashi Iwaib5025c52009-07-01 18:05:27 +02002726 if (streams & AC_SUPFMT_FLOAT32) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002727 formats |= SNDRV_PCM_FMTBIT_FLOAT_LE;
Takashi Iwaib0bb3aa2009-07-03 23:25:37 +02002728 if (!bps)
2729 bps = 32;
Takashi Iwaib5025c52009-07-01 18:05:27 +02002730 }
2731 if (streams == AC_SUPFMT_AC3) {
Takashi Iwai0ba21762007-04-16 11:29:14 +02002732 /* should be exclusive */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002733 /* temporary hack: we have still no proper support
2734 * for the direct AC3 stream...
2735 */
2736 formats |= SNDRV_PCM_FMTBIT_U8;
2737 bps = 8;
2738 }
Jaroslav Kyselaee504712009-03-17 14:30:31 +01002739 if (formats == 0) {
2740 snd_printk(KERN_ERR "hda_codec: formats == 0 "
2741 "(nid=0x%x, val=0x%x, ovrd=%i, "
2742 "streams=0x%x)\n",
2743 nid, val,
2744 (wcaps & AC_WCAP_FORMAT_OVRD) ? 1 : 0,
2745 streams);
2746 return -EIO;
2747 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002748 if (formatsp)
2749 *formatsp = formats;
2750 if (bpsp)
2751 *bpsp = bps;
2752 }
2753
2754 return 0;
2755}
2756
2757/**
Takashi Iwai0ba21762007-04-16 11:29:14 +02002758 * snd_hda_is_supported_format - check whether the given node supports
2759 * the format val
Linus Torvalds1da177e2005-04-16 15:20:36 -07002760 *
2761 * Returns 1 if supported, 0 if not.
2762 */
2763int snd_hda_is_supported_format(struct hda_codec *codec, hda_nid_t nid,
2764 unsigned int format)
2765{
2766 int i;
2767 unsigned int val = 0, rate, stream;
2768
Takashi Iwai92c7c8a2009-03-24 07:32:14 +01002769 val = query_pcm_param(codec, nid);
2770 if (!val)
2771 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002772
2773 rate = format & 0xff00;
Takashi Iwaia961f9f2007-04-12 13:08:09 +02002774 for (i = 0; i < AC_PAR_PCM_RATE_BITS; i++)
Takashi Iwaibefdf312005-08-22 13:57:55 +02002775 if (rate_bits[i].hda_fmt == rate) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002776 if (val & (1 << i))
2777 break;
2778 return 0;
2779 }
Takashi Iwaia961f9f2007-04-12 13:08:09 +02002780 if (i >= AC_PAR_PCM_RATE_BITS)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002781 return 0;
2782
Takashi Iwai92c7c8a2009-03-24 07:32:14 +01002783 stream = query_stream_param(codec, nid);
2784 if (!stream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002785 return 0;
2786
2787 if (stream & AC_SUPFMT_PCM) {
2788 switch (format & 0xf0) {
2789 case 0x00:
Takashi Iwai0ba21762007-04-16 11:29:14 +02002790 if (!(val & AC_SUPPCM_BITS_8))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002791 return 0;
2792 break;
2793 case 0x10:
Takashi Iwai0ba21762007-04-16 11:29:14 +02002794 if (!(val & AC_SUPPCM_BITS_16))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002795 return 0;
2796 break;
2797 case 0x20:
Takashi Iwai0ba21762007-04-16 11:29:14 +02002798 if (!(val & AC_SUPPCM_BITS_20))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002799 return 0;
2800 break;
2801 case 0x30:
Takashi Iwai0ba21762007-04-16 11:29:14 +02002802 if (!(val & AC_SUPPCM_BITS_24))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002803 return 0;
2804 break;
2805 case 0x40:
Takashi Iwai0ba21762007-04-16 11:29:14 +02002806 if (!(val & AC_SUPPCM_BITS_32))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002807 return 0;
2808 break;
2809 default:
2810 return 0;
2811 }
2812 } else {
2813 /* FIXME: check for float32 and AC3? */
2814 }
2815
2816 return 1;
2817}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002818EXPORT_SYMBOL_HDA(snd_hda_is_supported_format);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002819
2820/*
2821 * PCM stuff
2822 */
2823static int hda_pcm_default_open_close(struct hda_pcm_stream *hinfo,
2824 struct hda_codec *codec,
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01002825 struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002826{
2827 return 0;
2828}
2829
2830static int hda_pcm_default_prepare(struct hda_pcm_stream *hinfo,
2831 struct hda_codec *codec,
2832 unsigned int stream_tag,
2833 unsigned int format,
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01002834 struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002835{
2836 snd_hda_codec_setup_stream(codec, hinfo->nid, stream_tag, 0, format);
2837 return 0;
2838}
2839
2840static int hda_pcm_default_cleanup(struct hda_pcm_stream *hinfo,
2841 struct hda_codec *codec,
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01002842 struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002843{
Takashi Iwai888afa12008-03-18 09:57:50 +01002844 snd_hda_codec_cleanup_stream(codec, hinfo->nid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002845 return 0;
2846}
2847
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02002848static int set_pcm_default_values(struct hda_codec *codec,
2849 struct hda_pcm_stream *info)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002850{
Jaroslav Kyselaee504712009-03-17 14:30:31 +01002851 int err;
2852
Takashi Iwai0ba21762007-04-16 11:29:14 +02002853 /* query support PCM information from the given NID */
2854 if (info->nid && (!info->rates || !info->formats)) {
Jaroslav Kyselaee504712009-03-17 14:30:31 +01002855 err = snd_hda_query_supported_pcm(codec, info->nid,
Takashi Iwai0ba21762007-04-16 11:29:14 +02002856 info->rates ? NULL : &info->rates,
2857 info->formats ? NULL : &info->formats,
2858 info->maxbps ? NULL : &info->maxbps);
Jaroslav Kyselaee504712009-03-17 14:30:31 +01002859 if (err < 0)
2860 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002861 }
2862 if (info->ops.open == NULL)
2863 info->ops.open = hda_pcm_default_open_close;
2864 if (info->ops.close == NULL)
2865 info->ops.close = hda_pcm_default_open_close;
2866 if (info->ops.prepare == NULL) {
Takashi Iwaida3cec32008-08-08 17:12:14 +02002867 if (snd_BUG_ON(!info->nid))
2868 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002869 info->ops.prepare = hda_pcm_default_prepare;
2870 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002871 if (info->ops.cleanup == NULL) {
Takashi Iwaida3cec32008-08-08 17:12:14 +02002872 if (snd_BUG_ON(!info->nid))
2873 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002874 info->ops.cleanup = hda_pcm_default_cleanup;
2875 }
2876 return 0;
2877}
2878
Takashi Iwai176d5332008-07-30 15:01:44 +02002879/*
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002880 * get the empty PCM device number to assign
2881 */
2882static int get_empty_pcm_device(struct hda_bus *bus, int type)
2883{
2884 static const char *dev_name[HDA_PCM_NTYPES] = {
2885 "Audio", "SPDIF", "HDMI", "Modem"
2886 };
2887 /* starting device index for each PCM type */
2888 static int dev_idx[HDA_PCM_NTYPES] = {
2889 [HDA_PCM_TYPE_AUDIO] = 0,
2890 [HDA_PCM_TYPE_SPDIF] = 1,
2891 [HDA_PCM_TYPE_HDMI] = 3,
2892 [HDA_PCM_TYPE_MODEM] = 6
2893 };
2894 /* normal audio device indices; not linear to keep compatibility */
2895 static int audio_idx[4] = { 0, 2, 4, 5 };
2896 int i, dev;
2897
2898 switch (type) {
2899 case HDA_PCM_TYPE_AUDIO:
2900 for (i = 0; i < ARRAY_SIZE(audio_idx); i++) {
2901 dev = audio_idx[i];
2902 if (!test_bit(dev, bus->pcm_dev_bits))
Takashi Iwai82ad39f2009-03-03 15:00:35 +01002903 goto ok;
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002904 }
Takashi Iwai82ad39f2009-03-03 15:00:35 +01002905 snd_printk(KERN_WARNING "Too many audio devices\n");
2906 return -EAGAIN;
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002907 case HDA_PCM_TYPE_SPDIF:
2908 case HDA_PCM_TYPE_HDMI:
2909 case HDA_PCM_TYPE_MODEM:
2910 dev = dev_idx[type];
2911 if (test_bit(dev, bus->pcm_dev_bits)) {
2912 snd_printk(KERN_WARNING "%s already defined\n",
2913 dev_name[type]);
2914 return -EAGAIN;
2915 }
2916 break;
2917 default:
2918 snd_printk(KERN_WARNING "Invalid PCM type %d\n", type);
2919 return -EINVAL;
2920 }
Takashi Iwai82ad39f2009-03-03 15:00:35 +01002921 ok:
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002922 set_bit(dev, bus->pcm_dev_bits);
2923 return dev;
2924}
2925
2926/*
Takashi Iwai176d5332008-07-30 15:01:44 +02002927 * attach a new PCM stream
2928 */
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002929static int snd_hda_attach_pcm(struct hda_codec *codec, struct hda_pcm *pcm)
Takashi Iwai176d5332008-07-30 15:01:44 +02002930{
Takashi Iwai33fa35e2008-11-06 16:50:40 +01002931 struct hda_bus *bus = codec->bus;
Takashi Iwai176d5332008-07-30 15:01:44 +02002932 struct hda_pcm_stream *info;
2933 int stream, err;
2934
Takashi Iwaib91f0802008-11-04 08:43:08 +01002935 if (snd_BUG_ON(!pcm->name))
Takashi Iwai176d5332008-07-30 15:01:44 +02002936 return -EINVAL;
2937 for (stream = 0; stream < 2; stream++) {
2938 info = &pcm->stream[stream];
2939 if (info->substreams) {
2940 err = set_pcm_default_values(codec, info);
2941 if (err < 0)
2942 return err;
2943 }
2944 }
Takashi Iwai33fa35e2008-11-06 16:50:40 +01002945 return bus->ops.attach_pcm(bus, codec, pcm);
Takashi Iwai176d5332008-07-30 15:01:44 +02002946}
2947
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002948/* assign all PCMs of the given codec */
2949int snd_hda_codec_build_pcms(struct hda_codec *codec)
2950{
2951 unsigned int pcm;
2952 int err;
2953
2954 if (!codec->num_pcms) {
2955 if (!codec->patch_ops.build_pcms)
2956 return 0;
2957 err = codec->patch_ops.build_pcms(codec);
Takashi Iwai6e655bf2009-03-02 10:46:03 +01002958 if (err < 0) {
2959 printk(KERN_ERR "hda_codec: cannot build PCMs"
2960 "for #%d (error %d)\n", codec->addr, err);
2961 err = snd_hda_codec_reset(codec);
2962 if (err < 0) {
2963 printk(KERN_ERR
2964 "hda_codec: cannot revert codec\n");
2965 return err;
2966 }
2967 }
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002968 }
2969 for (pcm = 0; pcm < codec->num_pcms; pcm++) {
2970 struct hda_pcm *cpcm = &codec->pcm_info[pcm];
2971 int dev;
2972
2973 if (!cpcm->stream[0].substreams && !cpcm->stream[1].substreams)
Takashi Iwai41b5b012009-01-20 18:21:23 +01002974 continue; /* no substreams assigned */
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002975
2976 if (!cpcm->pcm) {
2977 dev = get_empty_pcm_device(codec->bus, cpcm->pcm_type);
2978 if (dev < 0)
Takashi Iwai6e655bf2009-03-02 10:46:03 +01002979 continue; /* no fatal error */
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002980 cpcm->device = dev;
2981 err = snd_hda_attach_pcm(codec, cpcm);
Takashi Iwai6e655bf2009-03-02 10:46:03 +01002982 if (err < 0) {
2983 printk(KERN_ERR "hda_codec: cannot attach "
2984 "PCM stream %d for codec #%d\n",
2985 dev, codec->addr);
2986 continue; /* no fatal error */
2987 }
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002988 }
2989 }
2990 return 0;
2991}
2992
Linus Torvalds1da177e2005-04-16 15:20:36 -07002993/**
2994 * snd_hda_build_pcms - build PCM information
2995 * @bus: the BUS
2996 *
2997 * Create PCM information for each codec included in the bus.
2998 *
2999 * The build_pcms codec patch is requested to set up codec->num_pcms and
3000 * codec->pcm_info properly. The array is referred by the top-level driver
3001 * to create its PCM instances.
3002 * The allocated codec->pcm_info should be released in codec->patch_ops.free
3003 * callback.
3004 *
3005 * At least, substreams, channels_min and channels_max must be filled for
3006 * each stream. substreams = 0 indicates that the stream doesn't exist.
3007 * When rates and/or formats are zero, the supported values are queried
3008 * from the given nid. The nid is used also by the default ops.prepare
3009 * and ops.cleanup callbacks.
3010 *
3011 * The driver needs to call ops.open in its open callback. Similarly,
3012 * ops.close is supposed to be called in the close callback.
3013 * ops.prepare should be called in the prepare or hw_params callback
3014 * with the proper parameters for set up.
3015 * ops.cleanup should be called in hw_free for clean up of streams.
3016 *
3017 * This function returns 0 if successfull, or a negative error code.
3018 */
Takashi Iwai529bd6c2008-11-27 14:17:01 +01003019int __devinit snd_hda_build_pcms(struct hda_bus *bus)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003020{
Takashi Iwai0ba21762007-04-16 11:29:14 +02003021 struct hda_codec *codec;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003022
Takashi Iwai0ba21762007-04-16 11:29:14 +02003023 list_for_each_entry(codec, &bus->codec_list, list) {
Takashi Iwai529bd6c2008-11-27 14:17:01 +01003024 int err = snd_hda_codec_build_pcms(codec);
3025 if (err < 0)
3026 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003027 }
3028 return 0;
3029}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003030EXPORT_SYMBOL_HDA(snd_hda_build_pcms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003031
Linus Torvalds1da177e2005-04-16 15:20:36 -07003032/**
3033 * snd_hda_check_board_config - compare the current codec with the config table
3034 * @codec: the HDA codec
Takashi Iwaif5fcc132006-11-24 17:07:44 +01003035 * @num_configs: number of config enums
3036 * @models: array of model name strings
Linus Torvalds1da177e2005-04-16 15:20:36 -07003037 * @tbl: configuration table, terminated by null entries
3038 *
3039 * Compares the modelname or PCI subsystem id of the current codec with the
3040 * given configuration table. If a matching entry is found, returns its
3041 * config value (supposed to be 0 or positive).
3042 *
3043 * If no entries are matching, the function returns a negative value.
3044 */
Takashi Iwai12f288b2007-08-02 15:51:59 +02003045int snd_hda_check_board_config(struct hda_codec *codec,
3046 int num_configs, const char **models,
3047 const struct snd_pci_quirk *tbl)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003048{
Takashi Iwaif44ac832008-07-30 15:01:45 +02003049 if (codec->modelname && models) {
Takashi Iwaif5fcc132006-11-24 17:07:44 +01003050 int i;
3051 for (i = 0; i < num_configs; i++) {
3052 if (models[i] &&
Takashi Iwaif44ac832008-07-30 15:01:45 +02003053 !strcmp(codec->modelname, models[i])) {
Takashi Iwaif5fcc132006-11-24 17:07:44 +01003054 snd_printd(KERN_INFO "hda_codec: model '%s' is "
3055 "selected\n", models[i]);
3056 return i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003057 }
3058 }
3059 }
3060
Takashi Iwaif5fcc132006-11-24 17:07:44 +01003061 if (!codec->bus->pci || !tbl)
3062 return -1;
3063
3064 tbl = snd_pci_quirk_lookup(codec->bus->pci, tbl);
3065 if (!tbl)
3066 return -1;
3067 if (tbl->value >= 0 && tbl->value < num_configs) {
Takashi Iwai62cf8722008-05-20 12:15:15 +02003068#ifdef CONFIG_SND_DEBUG_VERBOSE
Takashi Iwaif5fcc132006-11-24 17:07:44 +01003069 char tmp[10];
3070 const char *model = NULL;
3071 if (models)
3072 model = models[tbl->value];
3073 if (!model) {
3074 sprintf(tmp, "#%d", tbl->value);
3075 model = tmp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003076 }
Takashi Iwaif5fcc132006-11-24 17:07:44 +01003077 snd_printdd(KERN_INFO "hda_codec: model '%s' is selected "
3078 "for config %x:%x (%s)\n",
3079 model, tbl->subvendor, tbl->subdevice,
3080 (tbl->name ? tbl->name : "Unknown device"));
3081#endif
3082 return tbl->value;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003083 }
3084 return -1;
3085}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003086EXPORT_SYMBOL_HDA(snd_hda_check_board_config);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003087
3088/**
Mauro Carvalho Chehab2eda3442008-08-11 10:18:39 +02003089 * snd_hda_check_board_codec_sid_config - compare the current codec
3090 subsystem ID with the
3091 config table
3092
3093 This is important for Gateway notebooks with SB450 HDA Audio
3094 where the vendor ID of the PCI device is:
3095 ATI Technologies Inc SB450 HDA Audio [1002:437b]
3096 and the vendor/subvendor are found only at the codec.
3097
3098 * @codec: the HDA codec
3099 * @num_configs: number of config enums
3100 * @models: array of model name strings
3101 * @tbl: configuration table, terminated by null entries
3102 *
3103 * Compares the modelname or PCI subsystem id of the current codec with the
3104 * given configuration table. If a matching entry is found, returns its
3105 * config value (supposed to be 0 or positive).
3106 *
3107 * If no entries are matching, the function returns a negative value.
3108 */
3109int snd_hda_check_board_codec_sid_config(struct hda_codec *codec,
3110 int num_configs, const char **models,
3111 const struct snd_pci_quirk *tbl)
3112{
3113 const struct snd_pci_quirk *q;
3114
3115 /* Search for codec ID */
3116 for (q = tbl; q->subvendor; q++) {
3117 unsigned long vendorid = (q->subdevice) | (q->subvendor << 16);
3118
3119 if (vendorid == codec->subsystem_id)
3120 break;
3121 }
3122
3123 if (!q->subvendor)
3124 return -1;
3125
3126 tbl = q;
3127
3128 if (tbl->value >= 0 && tbl->value < num_configs) {
3129#ifdef CONFIG_SND_DEBUG_DETECT
3130 char tmp[10];
3131 const char *model = NULL;
3132 if (models)
3133 model = models[tbl->value];
3134 if (!model) {
3135 sprintf(tmp, "#%d", tbl->value);
3136 model = tmp;
3137 }
3138 snd_printdd(KERN_INFO "hda_codec: model '%s' is selected "
3139 "for config %x:%x (%s)\n",
3140 model, tbl->subvendor, tbl->subdevice,
3141 (tbl->name ? tbl->name : "Unknown device"));
3142#endif
3143 return tbl->value;
3144 }
3145 return -1;
3146}
3147EXPORT_SYMBOL_HDA(snd_hda_check_board_codec_sid_config);
3148
3149/**
Linus Torvalds1da177e2005-04-16 15:20:36 -07003150 * snd_hda_add_new_ctls - create controls from the array
3151 * @codec: the HDA codec
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01003152 * @knew: the array of struct snd_kcontrol_new
Linus Torvalds1da177e2005-04-16 15:20:36 -07003153 *
3154 * This helper function creates and add new controls in the given array.
3155 * The array must be terminated with an empty entry as terminator.
3156 *
3157 * Returns 0 if successful, or a negative error code.
3158 */
Takashi Iwai12f288b2007-08-02 15:51:59 +02003159int snd_hda_add_new_ctls(struct hda_codec *codec, struct snd_kcontrol_new *knew)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003160{
Takashi Iwaicb53c622007-08-10 17:21:45 +02003161 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003162
3163 for (; knew->name; knew++) {
Takashi Iwai54d17402005-11-21 16:33:22 +01003164 struct snd_kcontrol *kctl;
3165 kctl = snd_ctl_new1(knew, codec);
Takashi Iwai0ba21762007-04-16 11:29:14 +02003166 if (!kctl)
Takashi Iwai54d17402005-11-21 16:33:22 +01003167 return -ENOMEM;
Takashi Iwaid13bd412008-07-30 15:01:45 +02003168 err = snd_hda_ctl_add(codec, kctl);
Takashi Iwai54d17402005-11-21 16:33:22 +01003169 if (err < 0) {
Takashi Iwai0ba21762007-04-16 11:29:14 +02003170 if (!codec->addr)
Takashi Iwai54d17402005-11-21 16:33:22 +01003171 return err;
3172 kctl = snd_ctl_new1(knew, codec);
Takashi Iwai0ba21762007-04-16 11:29:14 +02003173 if (!kctl)
Takashi Iwai54d17402005-11-21 16:33:22 +01003174 return -ENOMEM;
3175 kctl->id.device = codec->addr;
Takashi Iwaid13bd412008-07-30 15:01:45 +02003176 err = snd_hda_ctl_add(codec, kctl);
Takashi Iwai0ba21762007-04-16 11:29:14 +02003177 if (err < 0)
Takashi Iwai54d17402005-11-21 16:33:22 +01003178 return err;
3179 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003180 }
3181 return 0;
3182}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003183EXPORT_SYMBOL_HDA(snd_hda_add_new_ctls);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003184
Takashi Iwaicb53c622007-08-10 17:21:45 +02003185#ifdef CONFIG_SND_HDA_POWER_SAVE
3186static void hda_set_power_state(struct hda_codec *codec, hda_nid_t fg,
3187 unsigned int power_state);
3188
3189static void hda_power_work(struct work_struct *work)
3190{
3191 struct hda_codec *codec =
3192 container_of(work, struct hda_codec, power_work.work);
Takashi Iwai33fa35e2008-11-06 16:50:40 +01003193 struct hda_bus *bus = codec->bus;
Takashi Iwaicb53c622007-08-10 17:21:45 +02003194
Maxim Levitsky2e492462007-09-03 15:26:57 +02003195 if (!codec->power_on || codec->power_count) {
3196 codec->power_transition = 0;
Takashi Iwaicb53c622007-08-10 17:21:45 +02003197 return;
Maxim Levitsky2e492462007-09-03 15:26:57 +02003198 }
Takashi Iwaicb53c622007-08-10 17:21:45 +02003199
3200 hda_call_codec_suspend(codec);
Takashi Iwai33fa35e2008-11-06 16:50:40 +01003201 if (bus->ops.pm_notify)
3202 bus->ops.pm_notify(bus);
Takashi Iwaicb53c622007-08-10 17:21:45 +02003203}
3204
3205static void hda_keep_power_on(struct hda_codec *codec)
3206{
3207 codec->power_count++;
3208 codec->power_on = 1;
3209}
3210
3211void snd_hda_power_up(struct hda_codec *codec)
3212{
Takashi Iwai33fa35e2008-11-06 16:50:40 +01003213 struct hda_bus *bus = codec->bus;
3214
Takashi Iwaicb53c622007-08-10 17:21:45 +02003215 codec->power_count++;
Takashi Iwaia221e282007-08-16 16:35:33 +02003216 if (codec->power_on || codec->power_transition)
Takashi Iwaicb53c622007-08-10 17:21:45 +02003217 return;
3218
3219 codec->power_on = 1;
Takashi Iwai33fa35e2008-11-06 16:50:40 +01003220 if (bus->ops.pm_notify)
3221 bus->ops.pm_notify(bus);
Takashi Iwaicb53c622007-08-10 17:21:45 +02003222 hda_call_codec_resume(codec);
3223 cancel_delayed_work(&codec->power_work);
Takashi Iwaia221e282007-08-16 16:35:33 +02003224 codec->power_transition = 0;
Takashi Iwaicb53c622007-08-10 17:21:45 +02003225}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003226EXPORT_SYMBOL_HDA(snd_hda_power_up);
Takashi Iwai1289e9e2008-11-27 15:47:11 +01003227
3228#define power_save(codec) \
3229 ((codec)->bus->power_save ? *(codec)->bus->power_save : 0)
Takashi Iwaicb53c622007-08-10 17:21:45 +02003230
Takashi Iwaifee2fba2008-11-27 12:43:28 +01003231#define power_save(codec) \
3232 ((codec)->bus->power_save ? *(codec)->bus->power_save : 0)
3233
Takashi Iwaicb53c622007-08-10 17:21:45 +02003234void snd_hda_power_down(struct hda_codec *codec)
3235{
3236 --codec->power_count;
Takashi Iwaia221e282007-08-16 16:35:33 +02003237 if (!codec->power_on || codec->power_count || codec->power_transition)
Takashi Iwaicb53c622007-08-10 17:21:45 +02003238 return;
Takashi Iwaifee2fba2008-11-27 12:43:28 +01003239 if (power_save(codec)) {
Takashi Iwaia221e282007-08-16 16:35:33 +02003240 codec->power_transition = 1; /* avoid reentrance */
Takashi Iwaic107b412009-01-13 17:46:37 +01003241 queue_delayed_work(codec->bus->workq, &codec->power_work,
Takashi Iwaifee2fba2008-11-27 12:43:28 +01003242 msecs_to_jiffies(power_save(codec) * 1000));
Takashi Iwaia221e282007-08-16 16:35:33 +02003243 }
Takashi Iwaicb53c622007-08-10 17:21:45 +02003244}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003245EXPORT_SYMBOL_HDA(snd_hda_power_down);
Takashi Iwaicb53c622007-08-10 17:21:45 +02003246
3247int snd_hda_check_amp_list_power(struct hda_codec *codec,
3248 struct hda_loopback_check *check,
3249 hda_nid_t nid)
3250{
3251 struct hda_amp_list *p;
3252 int ch, v;
3253
3254 if (!check->amplist)
3255 return 0;
3256 for (p = check->amplist; p->nid; p++) {
3257 if (p->nid == nid)
3258 break;
3259 }
3260 if (!p->nid)
3261 return 0; /* nothing changed */
3262
3263 for (p = check->amplist; p->nid; p++) {
3264 for (ch = 0; ch < 2; ch++) {
3265 v = snd_hda_codec_amp_read(codec, p->nid, ch, p->dir,
3266 p->idx);
3267 if (!(v & HDA_AMP_MUTE) && v > 0) {
3268 if (!check->power_on) {
3269 check->power_on = 1;
3270 snd_hda_power_up(codec);
3271 }
3272 return 1;
3273 }
3274 }
3275 }
3276 if (check->power_on) {
3277 check->power_on = 0;
3278 snd_hda_power_down(codec);
3279 }
3280 return 0;
3281}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003282EXPORT_SYMBOL_HDA(snd_hda_check_amp_list_power);
Takashi Iwaicb53c622007-08-10 17:21:45 +02003283#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07003284
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01003285/*
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01003286 * Channel mode helper
3287 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003288int snd_hda_ch_mode_info(struct hda_codec *codec,
3289 struct snd_ctl_elem_info *uinfo,
3290 const struct hda_channel_mode *chmode,
3291 int num_chmodes)
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01003292{
3293 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
3294 uinfo->count = 1;
3295 uinfo->value.enumerated.items = num_chmodes;
3296 if (uinfo->value.enumerated.item >= num_chmodes)
3297 uinfo->value.enumerated.item = num_chmodes - 1;
3298 sprintf(uinfo->value.enumerated.name, "%dch",
3299 chmode[uinfo->value.enumerated.item].channels);
3300 return 0;
3301}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003302EXPORT_SYMBOL_HDA(snd_hda_ch_mode_info);
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01003303
Takashi Iwai0ba21762007-04-16 11:29:14 +02003304int snd_hda_ch_mode_get(struct hda_codec *codec,
3305 struct snd_ctl_elem_value *ucontrol,
3306 const struct hda_channel_mode *chmode,
3307 int num_chmodes,
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01003308 int max_channels)
3309{
3310 int i;
3311
3312 for (i = 0; i < num_chmodes; i++) {
3313 if (max_channels == chmode[i].channels) {
3314 ucontrol->value.enumerated.item[0] = i;
3315 break;
3316 }
3317 }
3318 return 0;
3319}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003320EXPORT_SYMBOL_HDA(snd_hda_ch_mode_get);
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01003321
Takashi Iwai0ba21762007-04-16 11:29:14 +02003322int snd_hda_ch_mode_put(struct hda_codec *codec,
3323 struct snd_ctl_elem_value *ucontrol,
3324 const struct hda_channel_mode *chmode,
3325 int num_chmodes,
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01003326 int *max_channelsp)
3327{
3328 unsigned int mode;
3329
3330 mode = ucontrol->value.enumerated.item[0];
Takashi Iwai68ea7b22007-11-15 15:54:38 +01003331 if (mode >= num_chmodes)
3332 return -EINVAL;
Takashi Iwai82beb8f2007-08-10 17:09:26 +02003333 if (*max_channelsp == chmode[mode].channels)
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01003334 return 0;
3335 /* change the current channel setting */
3336 *max_channelsp = chmode[mode].channels;
3337 if (chmode[mode].sequence)
Takashi Iwai82beb8f2007-08-10 17:09:26 +02003338 snd_hda_sequence_write_cache(codec, chmode[mode].sequence);
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01003339 return 1;
3340}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003341EXPORT_SYMBOL_HDA(snd_hda_ch_mode_put);
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01003342
Linus Torvalds1da177e2005-04-16 15:20:36 -07003343/*
3344 * input MUX helper
3345 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003346int snd_hda_input_mux_info(const struct hda_input_mux *imux,
3347 struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003348{
3349 unsigned int index;
3350
3351 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
3352 uinfo->count = 1;
3353 uinfo->value.enumerated.items = imux->num_items;
Takashi Iwai5513b0c2007-10-09 11:58:41 +02003354 if (!imux->num_items)
3355 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003356 index = uinfo->value.enumerated.item;
3357 if (index >= imux->num_items)
3358 index = imux->num_items - 1;
3359 strcpy(uinfo->value.enumerated.name, imux->items[index].label);
3360 return 0;
3361}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003362EXPORT_SYMBOL_HDA(snd_hda_input_mux_info);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003363
Takashi Iwai0ba21762007-04-16 11:29:14 +02003364int snd_hda_input_mux_put(struct hda_codec *codec,
3365 const struct hda_input_mux *imux,
3366 struct snd_ctl_elem_value *ucontrol,
3367 hda_nid_t nid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003368 unsigned int *cur_val)
3369{
3370 unsigned int idx;
3371
Takashi Iwai5513b0c2007-10-09 11:58:41 +02003372 if (!imux->num_items)
3373 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003374 idx = ucontrol->value.enumerated.item[0];
3375 if (idx >= imux->num_items)
3376 idx = imux->num_items - 1;
Takashi Iwai82beb8f2007-08-10 17:09:26 +02003377 if (*cur_val == idx)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003378 return 0;
Takashi Iwai82beb8f2007-08-10 17:09:26 +02003379 snd_hda_codec_write_cache(codec, nid, 0, AC_VERB_SET_CONNECT_SEL,
3380 imux->items[idx].index);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003381 *cur_val = idx;
3382 return 1;
3383}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003384EXPORT_SYMBOL_HDA(snd_hda_input_mux_put);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003385
3386
3387/*
3388 * Multi-channel / digital-out PCM helper functions
3389 */
3390
Takashi Iwai6b97eb42007-04-05 14:51:48 +02003391/* setup SPDIF output stream */
3392static void setup_dig_out_stream(struct hda_codec *codec, hda_nid_t nid,
3393 unsigned int stream_tag, unsigned int format)
3394{
3395 /* turn off SPDIF once; otherwise the IEC958 bits won't be updated */
Takashi Iwai2f728532008-09-25 16:32:41 +02003396 if (codec->spdif_status_reset && (codec->spdif_ctls & AC_DIG1_ENABLE))
3397 set_dig_out_convert(codec, nid,
3398 codec->spdif_ctls & ~AC_DIG1_ENABLE & 0xff,
3399 -1);
Takashi Iwai6b97eb42007-04-05 14:51:48 +02003400 snd_hda_codec_setup_stream(codec, nid, stream_tag, 0, format);
Takashi Iwai2f728532008-09-25 16:32:41 +02003401 if (codec->slave_dig_outs) {
3402 hda_nid_t *d;
3403 for (d = codec->slave_dig_outs; *d; d++)
3404 snd_hda_codec_setup_stream(codec, *d, stream_tag, 0,
3405 format);
Matthew Ranostayde51ca12008-09-07 14:31:40 -04003406 }
Takashi Iwai2f728532008-09-25 16:32:41 +02003407 /* turn on again (if needed) */
3408 if (codec->spdif_status_reset && (codec->spdif_ctls & AC_DIG1_ENABLE))
3409 set_dig_out_convert(codec, nid,
3410 codec->spdif_ctls & 0xff, -1);
3411}
Matthew Ranostayde51ca12008-09-07 14:31:40 -04003412
Takashi Iwai2f728532008-09-25 16:32:41 +02003413static void cleanup_dig_out_stream(struct hda_codec *codec, hda_nid_t nid)
3414{
3415 snd_hda_codec_cleanup_stream(codec, nid);
3416 if (codec->slave_dig_outs) {
3417 hda_nid_t *d;
3418 for (d = codec->slave_dig_outs; *d; d++)
3419 snd_hda_codec_cleanup_stream(codec, *d);
3420 }
Takashi Iwai6b97eb42007-04-05 14:51:48 +02003421}
3422
Linus Torvalds1da177e2005-04-16 15:20:36 -07003423/*
3424 * open the digital out in the exclusive mode
3425 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003426int snd_hda_multi_out_dig_open(struct hda_codec *codec,
3427 struct hda_multi_out *mout)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003428{
Ingo Molnar62932df2006-01-16 16:34:20 +01003429 mutex_lock(&codec->spdif_mutex);
Takashi Iwai5930ca42007-04-16 11:23:56 +02003430 if (mout->dig_out_used == HDA_DIG_ANALOG_DUP)
3431 /* already opened as analog dup; reset it once */
Takashi Iwai2f728532008-09-25 16:32:41 +02003432 cleanup_dig_out_stream(codec, mout->dig_out_nid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003433 mout->dig_out_used = HDA_DIG_EXCLUSIVE;
Ingo Molnar62932df2006-01-16 16:34:20 +01003434 mutex_unlock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003435 return 0;
3436}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003437EXPORT_SYMBOL_HDA(snd_hda_multi_out_dig_open);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003438
Takashi Iwai6b97eb42007-04-05 14:51:48 +02003439int snd_hda_multi_out_dig_prepare(struct hda_codec *codec,
3440 struct hda_multi_out *mout,
3441 unsigned int stream_tag,
3442 unsigned int format,
3443 struct snd_pcm_substream *substream)
3444{
3445 mutex_lock(&codec->spdif_mutex);
3446 setup_dig_out_stream(codec, mout->dig_out_nid, stream_tag, format);
3447 mutex_unlock(&codec->spdif_mutex);
3448 return 0;
3449}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003450EXPORT_SYMBOL_HDA(snd_hda_multi_out_dig_prepare);
Takashi Iwai6b97eb42007-04-05 14:51:48 +02003451
Takashi Iwai9411e212009-02-13 11:32:28 +01003452int snd_hda_multi_out_dig_cleanup(struct hda_codec *codec,
3453 struct hda_multi_out *mout)
3454{
3455 mutex_lock(&codec->spdif_mutex);
3456 cleanup_dig_out_stream(codec, mout->dig_out_nid);
3457 mutex_unlock(&codec->spdif_mutex);
3458 return 0;
3459}
3460EXPORT_SYMBOL_HDA(snd_hda_multi_out_dig_cleanup);
3461
Linus Torvalds1da177e2005-04-16 15:20:36 -07003462/*
3463 * release the digital out
3464 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003465int snd_hda_multi_out_dig_close(struct hda_codec *codec,
3466 struct hda_multi_out *mout)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003467{
Ingo Molnar62932df2006-01-16 16:34:20 +01003468 mutex_lock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003469 mout->dig_out_used = 0;
Ingo Molnar62932df2006-01-16 16:34:20 +01003470 mutex_unlock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003471 return 0;
3472}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003473EXPORT_SYMBOL_HDA(snd_hda_multi_out_dig_close);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003474
3475/*
3476 * set up more restrictions for analog out
3477 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003478int snd_hda_multi_out_analog_open(struct hda_codec *codec,
3479 struct hda_multi_out *mout,
Takashi Iwai9a081602008-02-12 18:37:26 +01003480 struct snd_pcm_substream *substream,
3481 struct hda_pcm_stream *hinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003482{
Takashi Iwai9a081602008-02-12 18:37:26 +01003483 struct snd_pcm_runtime *runtime = substream->runtime;
3484 runtime->hw.channels_max = mout->max_channels;
3485 if (mout->dig_out_nid) {
3486 if (!mout->analog_rates) {
3487 mout->analog_rates = hinfo->rates;
3488 mout->analog_formats = hinfo->formats;
3489 mout->analog_maxbps = hinfo->maxbps;
3490 } else {
3491 runtime->hw.rates = mout->analog_rates;
3492 runtime->hw.formats = mout->analog_formats;
3493 hinfo->maxbps = mout->analog_maxbps;
3494 }
3495 if (!mout->spdif_rates) {
3496 snd_hda_query_supported_pcm(codec, mout->dig_out_nid,
3497 &mout->spdif_rates,
3498 &mout->spdif_formats,
3499 &mout->spdif_maxbps);
3500 }
3501 mutex_lock(&codec->spdif_mutex);
3502 if (mout->share_spdif) {
Takashi Iwai022b4662009-07-03 23:03:30 +02003503 if ((runtime->hw.rates & mout->spdif_rates) &&
3504 (runtime->hw.formats & mout->spdif_formats)) {
3505 runtime->hw.rates &= mout->spdif_rates;
3506 runtime->hw.formats &= mout->spdif_formats;
3507 if (mout->spdif_maxbps < hinfo->maxbps)
3508 hinfo->maxbps = mout->spdif_maxbps;
3509 } else {
3510 mout->share_spdif = 0;
3511 /* FIXME: need notify? */
3512 }
Takashi Iwai9a081602008-02-12 18:37:26 +01003513 }
Frederik Deweerdteaa99852008-04-14 13:11:44 +02003514 mutex_unlock(&codec->spdif_mutex);
Takashi Iwai9a081602008-02-12 18:37:26 +01003515 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003516 return snd_pcm_hw_constraint_step(substream->runtime, 0,
3517 SNDRV_PCM_HW_PARAM_CHANNELS, 2);
3518}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003519EXPORT_SYMBOL_HDA(snd_hda_multi_out_analog_open);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003520
3521/*
3522 * set up the i/o for analog out
3523 * when the digital out is available, copy the front out to digital out, too.
3524 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003525int snd_hda_multi_out_analog_prepare(struct hda_codec *codec,
3526 struct hda_multi_out *mout,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003527 unsigned int stream_tag,
3528 unsigned int format,
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01003529 struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003530{
3531 hda_nid_t *nids = mout->dac_nids;
3532 int chs = substream->runtime->channels;
3533 int i;
3534
Ingo Molnar62932df2006-01-16 16:34:20 +01003535 mutex_lock(&codec->spdif_mutex);
Takashi Iwai9a081602008-02-12 18:37:26 +01003536 if (mout->dig_out_nid && mout->share_spdif &&
3537 mout->dig_out_used != HDA_DIG_EXCLUSIVE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003538 if (chs == 2 &&
Takashi Iwai0ba21762007-04-16 11:29:14 +02003539 snd_hda_is_supported_format(codec, mout->dig_out_nid,
3540 format) &&
3541 !(codec->spdif_status & IEC958_AES0_NONAUDIO)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003542 mout->dig_out_used = HDA_DIG_ANALOG_DUP;
Takashi Iwai6b97eb42007-04-05 14:51:48 +02003543 setup_dig_out_stream(codec, mout->dig_out_nid,
3544 stream_tag, format);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003545 } else {
3546 mout->dig_out_used = 0;
Takashi Iwai2f728532008-09-25 16:32:41 +02003547 cleanup_dig_out_stream(codec, mout->dig_out_nid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003548 }
3549 }
Ingo Molnar62932df2006-01-16 16:34:20 +01003550 mutex_unlock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003551
3552 /* front */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003553 snd_hda_codec_setup_stream(codec, nids[HDA_FRONT], stream_tag,
3554 0, format);
Takashi Iwaid29240c2007-10-26 12:35:56 +02003555 if (!mout->no_share_stream &&
3556 mout->hp_nid && mout->hp_nid != nids[HDA_FRONT])
Linus Torvalds1da177e2005-04-16 15:20:36 -07003557 /* headphone out will just decode front left/right (stereo) */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003558 snd_hda_codec_setup_stream(codec, mout->hp_nid, stream_tag,
3559 0, format);
Takashi Iwai82bc9552006-03-21 11:24:42 +01003560 /* extra outputs copied from front */
3561 for (i = 0; i < ARRAY_SIZE(mout->extra_out_nid); i++)
Takashi Iwaid29240c2007-10-26 12:35:56 +02003562 if (!mout->no_share_stream && mout->extra_out_nid[i])
Takashi Iwai82bc9552006-03-21 11:24:42 +01003563 snd_hda_codec_setup_stream(codec,
3564 mout->extra_out_nid[i],
3565 stream_tag, 0, format);
3566
Linus Torvalds1da177e2005-04-16 15:20:36 -07003567 /* surrounds */
3568 for (i = 1; i < mout->num_dacs; i++) {
Takashi Iwai4b3acaf2005-06-10 19:48:10 +02003569 if (chs >= (i + 1) * 2) /* independent out */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003570 snd_hda_codec_setup_stream(codec, nids[i], stream_tag,
3571 i * 2, format);
Takashi Iwaid29240c2007-10-26 12:35:56 +02003572 else if (!mout->no_share_stream) /* copy front */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003573 snd_hda_codec_setup_stream(codec, nids[i], stream_tag,
3574 0, format);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003575 }
3576 return 0;
3577}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003578EXPORT_SYMBOL_HDA(snd_hda_multi_out_analog_prepare);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003579
3580/*
3581 * clean up the setting for analog out
3582 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003583int snd_hda_multi_out_analog_cleanup(struct hda_codec *codec,
3584 struct hda_multi_out *mout)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003585{
3586 hda_nid_t *nids = mout->dac_nids;
3587 int i;
3588
3589 for (i = 0; i < mout->num_dacs; i++)
Takashi Iwai888afa12008-03-18 09:57:50 +01003590 snd_hda_codec_cleanup_stream(codec, nids[i]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003591 if (mout->hp_nid)
Takashi Iwai888afa12008-03-18 09:57:50 +01003592 snd_hda_codec_cleanup_stream(codec, mout->hp_nid);
Takashi Iwai82bc9552006-03-21 11:24:42 +01003593 for (i = 0; i < ARRAY_SIZE(mout->extra_out_nid); i++)
3594 if (mout->extra_out_nid[i])
Takashi Iwai888afa12008-03-18 09:57:50 +01003595 snd_hda_codec_cleanup_stream(codec,
3596 mout->extra_out_nid[i]);
Ingo Molnar62932df2006-01-16 16:34:20 +01003597 mutex_lock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003598 if (mout->dig_out_nid && mout->dig_out_used == HDA_DIG_ANALOG_DUP) {
Takashi Iwai2f728532008-09-25 16:32:41 +02003599 cleanup_dig_out_stream(codec, mout->dig_out_nid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003600 mout->dig_out_used = 0;
3601 }
Ingo Molnar62932df2006-01-16 16:34:20 +01003602 mutex_unlock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003603 return 0;
3604}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003605EXPORT_SYMBOL_HDA(snd_hda_multi_out_analog_cleanup);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003606
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003607/*
Wu Fengguang6b345002008-10-07 14:21:41 +08003608 * Helper for automatic pin configuration
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003609 */
Kailang Yangdf694da2005-12-05 19:42:22 +01003610
Takashi Iwai12f288b2007-08-02 15:51:59 +02003611static int is_in_nid_list(hda_nid_t nid, hda_nid_t *list)
Kailang Yangdf694da2005-12-05 19:42:22 +01003612{
3613 for (; *list; list++)
3614 if (*list == nid)
3615 return 1;
3616 return 0;
3617}
3618
Steve Longerbeam81937d32007-05-08 15:33:03 +02003619
3620/*
3621 * Sort an associated group of pins according to their sequence numbers.
3622 */
3623static void sort_pins_by_sequence(hda_nid_t * pins, short * sequences,
3624 int num_pins)
3625{
3626 int i, j;
3627 short seq;
3628 hda_nid_t nid;
3629
3630 for (i = 0; i < num_pins; i++) {
3631 for (j = i + 1; j < num_pins; j++) {
3632 if (sequences[i] > sequences[j]) {
3633 seq = sequences[i];
3634 sequences[i] = sequences[j];
3635 sequences[j] = seq;
3636 nid = pins[i];
3637 pins[i] = pins[j];
3638 pins[j] = nid;
3639 }
3640 }
3641 }
3642}
3643
3644
Takashi Iwai82bc9552006-03-21 11:24:42 +01003645/*
3646 * Parse all pin widgets and store the useful pin nids to cfg
3647 *
3648 * The number of line-outs or any primary output is stored in line_outs,
3649 * and the corresponding output pins are assigned to line_out_pins[],
3650 * in the order of front, rear, CLFE, side, ...
3651 *
3652 * If more extra outputs (speaker and headphone) are found, the pins are
Takashi Iwaieb06ed82006-09-20 17:10:27 +02003653 * assisnged to hp_pins[] and speaker_pins[], respectively. If no line-out jack
Takashi Iwai82bc9552006-03-21 11:24:42 +01003654 * is detected, one of speaker of HP pins is assigned as the primary
3655 * output, i.e. to line_out_pins[0]. So, line_outs is always positive
3656 * if any analog output exists.
3657 *
3658 * The analog input pins are assigned to input_pins array.
3659 * The digital input/output pins are assigned to dig_in_pin and dig_out_pin,
3660 * respectively.
3661 */
Takashi Iwai12f288b2007-08-02 15:51:59 +02003662int snd_hda_parse_pin_def_config(struct hda_codec *codec,
3663 struct auto_pin_cfg *cfg,
3664 hda_nid_t *ignore_nids)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003665{
Takashi Iwai0ef6ce72008-01-22 15:35:37 +01003666 hda_nid_t nid, end_nid;
Steve Longerbeam81937d32007-05-08 15:33:03 +02003667 short seq, assoc_line_out, assoc_speaker;
3668 short sequences_line_out[ARRAY_SIZE(cfg->line_out_pins)];
3669 short sequences_speaker[ARRAY_SIZE(cfg->speaker_pins)];
Takashi Iwaif889fa92007-10-31 15:49:32 +01003670 short sequences_hp[ARRAY_SIZE(cfg->hp_pins)];
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003671
3672 memset(cfg, 0, sizeof(*cfg));
3673
Steve Longerbeam81937d32007-05-08 15:33:03 +02003674 memset(sequences_line_out, 0, sizeof(sequences_line_out));
3675 memset(sequences_speaker, 0, sizeof(sequences_speaker));
Takashi Iwaif889fa92007-10-31 15:49:32 +01003676 memset(sequences_hp, 0, sizeof(sequences_hp));
Steve Longerbeam81937d32007-05-08 15:33:03 +02003677 assoc_line_out = assoc_speaker = 0;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003678
Takashi Iwai0ef6ce72008-01-22 15:35:37 +01003679 end_nid = codec->start_nid + codec->num_nodes;
3680 for (nid = codec->start_nid; nid < end_nid; nid++) {
Takashi Iwai54d17402005-11-21 16:33:22 +01003681 unsigned int wid_caps = get_wcaps(codec, nid);
Takashi Iwaia22d5432009-07-27 12:54:26 +02003682 unsigned int wid_type = get_wcaps_type(wid_caps);
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003683 unsigned int def_conf;
3684 short assoc, loc;
3685
3686 /* read all default configuration for pin complex */
3687 if (wid_type != AC_WID_PIN)
3688 continue;
Kailang Yangdf694da2005-12-05 19:42:22 +01003689 /* ignore the given nids (e.g. pc-beep returns error) */
3690 if (ignore_nids && is_in_nid_list(nid, ignore_nids))
3691 continue;
3692
Takashi Iwaic17a1ab2009-02-23 09:28:12 +01003693 def_conf = snd_hda_codec_get_pincfg(codec, nid);
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003694 if (get_defcfg_connect(def_conf) == AC_JACK_PORT_NONE)
3695 continue;
3696 loc = get_defcfg_location(def_conf);
3697 switch (get_defcfg_device(def_conf)) {
3698 case AC_JACK_LINE_OUT:
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003699 seq = get_defcfg_sequence(def_conf);
3700 assoc = get_defcfg_association(def_conf);
Matthew Ranostay90da78b2008-01-24 11:48:01 +01003701
3702 if (!(wid_caps & AC_WCAP_STEREO))
3703 if (!cfg->mono_out_pin)
3704 cfg->mono_out_pin = nid;
Takashi Iwai0ba21762007-04-16 11:29:14 +02003705 if (!assoc)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003706 continue;
Takashi Iwai0ba21762007-04-16 11:29:14 +02003707 if (!assoc_line_out)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003708 assoc_line_out = assoc;
3709 else if (assoc_line_out != assoc)
3710 continue;
3711 if (cfg->line_outs >= ARRAY_SIZE(cfg->line_out_pins))
3712 continue;
3713 cfg->line_out_pins[cfg->line_outs] = nid;
Steve Longerbeam81937d32007-05-08 15:33:03 +02003714 sequences_line_out[cfg->line_outs] = seq;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003715 cfg->line_outs++;
3716 break;
Takashi Iwai8d88bc32005-11-17 11:09:23 +01003717 case AC_JACK_SPEAKER:
Steve Longerbeam81937d32007-05-08 15:33:03 +02003718 seq = get_defcfg_sequence(def_conf);
3719 assoc = get_defcfg_association(def_conf);
3720 if (! assoc)
3721 continue;
3722 if (! assoc_speaker)
3723 assoc_speaker = assoc;
3724 else if (assoc_speaker != assoc)
3725 continue;
Takashi Iwai82bc9552006-03-21 11:24:42 +01003726 if (cfg->speaker_outs >= ARRAY_SIZE(cfg->speaker_pins))
3727 continue;
3728 cfg->speaker_pins[cfg->speaker_outs] = nid;
Steve Longerbeam81937d32007-05-08 15:33:03 +02003729 sequences_speaker[cfg->speaker_outs] = seq;
Takashi Iwai82bc9552006-03-21 11:24:42 +01003730 cfg->speaker_outs++;
Takashi Iwai8d88bc32005-11-17 11:09:23 +01003731 break;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003732 case AC_JACK_HP_OUT:
Takashi Iwaif889fa92007-10-31 15:49:32 +01003733 seq = get_defcfg_sequence(def_conf);
3734 assoc = get_defcfg_association(def_conf);
Takashi Iwaieb06ed82006-09-20 17:10:27 +02003735 if (cfg->hp_outs >= ARRAY_SIZE(cfg->hp_pins))
3736 continue;
3737 cfg->hp_pins[cfg->hp_outs] = nid;
Takashi Iwaif889fa92007-10-31 15:49:32 +01003738 sequences_hp[cfg->hp_outs] = (assoc << 4) | seq;
Takashi Iwaieb06ed82006-09-20 17:10:27 +02003739 cfg->hp_outs++;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003740 break;
Takashi Iwai314634b2006-09-21 11:56:18 +02003741 case AC_JACK_MIC_IN: {
3742 int preferred, alt;
3743 if (loc == AC_JACK_LOC_FRONT) {
3744 preferred = AUTO_PIN_FRONT_MIC;
3745 alt = AUTO_PIN_MIC;
3746 } else {
3747 preferred = AUTO_PIN_MIC;
3748 alt = AUTO_PIN_FRONT_MIC;
3749 }
3750 if (!cfg->input_pins[preferred])
3751 cfg->input_pins[preferred] = nid;
3752 else if (!cfg->input_pins[alt])
3753 cfg->input_pins[alt] = nid;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003754 break;
Takashi Iwai314634b2006-09-21 11:56:18 +02003755 }
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003756 case AC_JACK_LINE_IN:
3757 if (loc == AC_JACK_LOC_FRONT)
3758 cfg->input_pins[AUTO_PIN_FRONT_LINE] = nid;
3759 else
3760 cfg->input_pins[AUTO_PIN_LINE] = nid;
3761 break;
3762 case AC_JACK_CD:
3763 cfg->input_pins[AUTO_PIN_CD] = nid;
3764 break;
3765 case AC_JACK_AUX:
3766 cfg->input_pins[AUTO_PIN_AUX] = nid;
3767 break;
3768 case AC_JACK_SPDIF_OUT:
Takashi Iwai1b52ae72009-01-20 17:17:29 +01003769 case AC_JACK_DIG_OTHER_OUT:
Takashi Iwai0852d7a2009-02-11 11:35:15 +01003770 if (cfg->dig_outs >= ARRAY_SIZE(cfg->dig_out_pins))
3771 continue;
3772 cfg->dig_out_pins[cfg->dig_outs] = nid;
3773 cfg->dig_out_type[cfg->dig_outs] =
3774 (loc == AC_JACK_LOC_HDMI) ?
3775 HDA_PCM_TYPE_HDMI : HDA_PCM_TYPE_SPDIF;
3776 cfg->dig_outs++;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003777 break;
3778 case AC_JACK_SPDIF_IN:
Takashi Iwai1b52ae72009-01-20 17:17:29 +01003779 case AC_JACK_DIG_OTHER_IN:
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003780 cfg->dig_in_pin = nid;
Takashi Iwai2297bd62009-01-20 18:24:13 +01003781 if (loc == AC_JACK_LOC_HDMI)
3782 cfg->dig_in_type = HDA_PCM_TYPE_HDMI;
3783 else
3784 cfg->dig_in_type = HDA_PCM_TYPE_SPDIF;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003785 break;
3786 }
3787 }
3788
Takashi Iwai5832fcf2008-02-12 18:30:12 +01003789 /* FIX-UP:
3790 * If no line-out is defined but multiple HPs are found,
3791 * some of them might be the real line-outs.
3792 */
3793 if (!cfg->line_outs && cfg->hp_outs > 1) {
3794 int i = 0;
3795 while (i < cfg->hp_outs) {
3796 /* The real HPs should have the sequence 0x0f */
3797 if ((sequences_hp[i] & 0x0f) == 0x0f) {
3798 i++;
3799 continue;
3800 }
3801 /* Move it to the line-out table */
3802 cfg->line_out_pins[cfg->line_outs] = cfg->hp_pins[i];
3803 sequences_line_out[cfg->line_outs] = sequences_hp[i];
3804 cfg->line_outs++;
3805 cfg->hp_outs--;
3806 memmove(cfg->hp_pins + i, cfg->hp_pins + i + 1,
3807 sizeof(cfg->hp_pins[0]) * (cfg->hp_outs - i));
3808 memmove(sequences_hp + i - 1, sequences_hp + i,
3809 sizeof(sequences_hp[0]) * (cfg->hp_outs - i));
3810 }
3811 }
3812
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003813 /* sort by sequence */
Steve Longerbeam81937d32007-05-08 15:33:03 +02003814 sort_pins_by_sequence(cfg->line_out_pins, sequences_line_out,
3815 cfg->line_outs);
3816 sort_pins_by_sequence(cfg->speaker_pins, sequences_speaker,
3817 cfg->speaker_outs);
Takashi Iwaif889fa92007-10-31 15:49:32 +01003818 sort_pins_by_sequence(cfg->hp_pins, sequences_hp,
3819 cfg->hp_outs);
Steve Longerbeam81937d32007-05-08 15:33:03 +02003820
Takashi Iwaif889fa92007-10-31 15:49:32 +01003821 /* if we have only one mic, make it AUTO_PIN_MIC */
3822 if (!cfg->input_pins[AUTO_PIN_MIC] &&
3823 cfg->input_pins[AUTO_PIN_FRONT_MIC]) {
3824 cfg->input_pins[AUTO_PIN_MIC] =
3825 cfg->input_pins[AUTO_PIN_FRONT_MIC];
3826 cfg->input_pins[AUTO_PIN_FRONT_MIC] = 0;
3827 }
3828 /* ditto for line-in */
3829 if (!cfg->input_pins[AUTO_PIN_LINE] &&
3830 cfg->input_pins[AUTO_PIN_FRONT_LINE]) {
3831 cfg->input_pins[AUTO_PIN_LINE] =
3832 cfg->input_pins[AUTO_PIN_FRONT_LINE];
3833 cfg->input_pins[AUTO_PIN_FRONT_LINE] = 0;
3834 }
3835
Steve Longerbeam81937d32007-05-08 15:33:03 +02003836 /*
3837 * FIX-UP: if no line-outs are detected, try to use speaker or HP pin
3838 * as a primary output
3839 */
3840 if (!cfg->line_outs) {
3841 if (cfg->speaker_outs) {
3842 cfg->line_outs = cfg->speaker_outs;
3843 memcpy(cfg->line_out_pins, cfg->speaker_pins,
3844 sizeof(cfg->speaker_pins));
3845 cfg->speaker_outs = 0;
3846 memset(cfg->speaker_pins, 0, sizeof(cfg->speaker_pins));
3847 cfg->line_out_type = AUTO_PIN_SPEAKER_OUT;
3848 } else if (cfg->hp_outs) {
3849 cfg->line_outs = cfg->hp_outs;
3850 memcpy(cfg->line_out_pins, cfg->hp_pins,
3851 sizeof(cfg->hp_pins));
3852 cfg->hp_outs = 0;
3853 memset(cfg->hp_pins, 0, sizeof(cfg->hp_pins));
3854 cfg->line_out_type = AUTO_PIN_HP_OUT;
3855 }
3856 }
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003857
Takashi Iwaicb8e2f82005-07-29 11:54:32 +02003858 /* Reorder the surround channels
3859 * ALSA sequence is front/surr/clfe/side
3860 * HDA sequence is:
3861 * 4-ch: front/surr => OK as it is
3862 * 6-ch: front/clfe/surr
Takashi Iwai9422db42007-04-20 16:11:43 +02003863 * 8-ch: front/clfe/rear/side|fc
Takashi Iwaicb8e2f82005-07-29 11:54:32 +02003864 */
3865 switch (cfg->line_outs) {
3866 case 3:
Takashi Iwaicb8e2f82005-07-29 11:54:32 +02003867 case 4:
3868 nid = cfg->line_out_pins[1];
Takashi Iwai9422db42007-04-20 16:11:43 +02003869 cfg->line_out_pins[1] = cfg->line_out_pins[2];
Takashi Iwaicb8e2f82005-07-29 11:54:32 +02003870 cfg->line_out_pins[2] = nid;
3871 break;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003872 }
3873
Takashi Iwai82bc9552006-03-21 11:24:42 +01003874 /*
3875 * debug prints of the parsed results
3876 */
3877 snd_printd("autoconfig: line_outs=%d (0x%x/0x%x/0x%x/0x%x/0x%x)\n",
3878 cfg->line_outs, cfg->line_out_pins[0], cfg->line_out_pins[1],
3879 cfg->line_out_pins[2], cfg->line_out_pins[3],
3880 cfg->line_out_pins[4]);
3881 snd_printd(" speaker_outs=%d (0x%x/0x%x/0x%x/0x%x/0x%x)\n",
3882 cfg->speaker_outs, cfg->speaker_pins[0],
3883 cfg->speaker_pins[1], cfg->speaker_pins[2],
3884 cfg->speaker_pins[3], cfg->speaker_pins[4]);
Takashi Iwaieb06ed82006-09-20 17:10:27 +02003885 snd_printd(" hp_outs=%d (0x%x/0x%x/0x%x/0x%x/0x%x)\n",
3886 cfg->hp_outs, cfg->hp_pins[0],
3887 cfg->hp_pins[1], cfg->hp_pins[2],
3888 cfg->hp_pins[3], cfg->hp_pins[4]);
Matthew Ranostay90da78b2008-01-24 11:48:01 +01003889 snd_printd(" mono: mono_out=0x%x\n", cfg->mono_out_pin);
Takashi Iwai0852d7a2009-02-11 11:35:15 +01003890 if (cfg->dig_outs)
3891 snd_printd(" dig-out=0x%x/0x%x\n",
3892 cfg->dig_out_pins[0], cfg->dig_out_pins[1]);
Takashi Iwai82bc9552006-03-21 11:24:42 +01003893 snd_printd(" inputs: mic=0x%x, fmic=0x%x, line=0x%x, fline=0x%x,"
3894 " cd=0x%x, aux=0x%x\n",
3895 cfg->input_pins[AUTO_PIN_MIC],
3896 cfg->input_pins[AUTO_PIN_FRONT_MIC],
3897 cfg->input_pins[AUTO_PIN_LINE],
3898 cfg->input_pins[AUTO_PIN_FRONT_LINE],
3899 cfg->input_pins[AUTO_PIN_CD],
3900 cfg->input_pins[AUTO_PIN_AUX]);
Takashi Iwai32d2c7f2009-02-11 11:33:13 +01003901 if (cfg->dig_in_pin)
Takashi Iwai89ce9e82009-01-20 17:15:57 +01003902 snd_printd(" dig-in=0x%x\n", cfg->dig_in_pin);
Takashi Iwai82bc9552006-03-21 11:24:42 +01003903
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003904 return 0;
3905}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003906EXPORT_SYMBOL_HDA(snd_hda_parse_pin_def_config);
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003907
Takashi Iwai4a471b72005-12-07 13:56:29 +01003908/* labels for input pins */
3909const char *auto_pin_cfg_labels[AUTO_PIN_LAST] = {
3910 "Mic", "Front Mic", "Line", "Front Line", "CD", "Aux"
3911};
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003912EXPORT_SYMBOL_HDA(auto_pin_cfg_labels);
Takashi Iwai4a471b72005-12-07 13:56:29 +01003913
3914
Linus Torvalds1da177e2005-04-16 15:20:36 -07003915#ifdef CONFIG_PM
3916/*
3917 * power management
3918 */
3919
3920/**
3921 * snd_hda_suspend - suspend the codecs
3922 * @bus: the HDA bus
Linus Torvalds1da177e2005-04-16 15:20:36 -07003923 *
3924 * Returns 0 if successful.
3925 */
Takashi Iwai8dd78332009-06-02 01:16:07 +02003926int snd_hda_suspend(struct hda_bus *bus)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003927{
Takashi Iwai0ba21762007-04-16 11:29:14 +02003928 struct hda_codec *codec;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003929
Takashi Iwai0ba21762007-04-16 11:29:14 +02003930 list_for_each_entry(codec, &bus->codec_list, list) {
Takashi Iwai0b7a2e92007-08-14 15:18:26 +02003931#ifdef CONFIG_SND_HDA_POWER_SAVE
3932 if (!codec->power_on)
3933 continue;
3934#endif
Takashi Iwaicb53c622007-08-10 17:21:45 +02003935 hda_call_codec_suspend(codec);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003936 }
3937 return 0;
3938}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003939EXPORT_SYMBOL_HDA(snd_hda_suspend);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003940
3941/**
3942 * snd_hda_resume - resume the codecs
3943 * @bus: the HDA bus
Linus Torvalds1da177e2005-04-16 15:20:36 -07003944 *
3945 * Returns 0 if successful.
Takashi Iwaicb53c622007-08-10 17:21:45 +02003946 *
3947 * This fucntion is defined only when POWER_SAVE isn't set.
3948 * In the power-save mode, the codec is resumed dynamically.
Linus Torvalds1da177e2005-04-16 15:20:36 -07003949 */
3950int snd_hda_resume(struct hda_bus *bus)
3951{
Takashi Iwai0ba21762007-04-16 11:29:14 +02003952 struct hda_codec *codec;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003953
Takashi Iwai0ba21762007-04-16 11:29:14 +02003954 list_for_each_entry(codec, &bus->codec_list, list) {
Maxim Levitskyd804ad92007-09-03 15:28:04 +02003955 if (snd_hda_codec_needs_resume(codec))
3956 hda_call_codec_resume(codec);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003957 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003958 return 0;
3959}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003960EXPORT_SYMBOL_HDA(snd_hda_resume);
Takashi Iwai1289e9e2008-11-27 15:47:11 +01003961#endif /* CONFIG_PM */
Takashi Iwaib2e18592008-07-30 15:01:44 +02003962
3963/*
3964 * generic arrays
3965 */
3966
3967/* get a new element from the given array
3968 * if it exceeds the pre-allocated array size, re-allocate the array
3969 */
3970void *snd_array_new(struct snd_array *array)
3971{
3972 if (array->used >= array->alloced) {
3973 int num = array->alloced + array->alloc_align;
Takashi Iwaib910d9a2008-11-07 00:26:52 +01003974 void *nlist;
3975 if (snd_BUG_ON(num >= 4096))
3976 return NULL;
3977 nlist = kcalloc(num + 1, array->elem_size, GFP_KERNEL);
Takashi Iwaib2e18592008-07-30 15:01:44 +02003978 if (!nlist)
3979 return NULL;
3980 if (array->list) {
3981 memcpy(nlist, array->list,
3982 array->elem_size * array->alloced);
3983 kfree(array->list);
3984 }
3985 array->list = nlist;
3986 array->alloced = num;
3987 }
Takashi Iwaif43aa022008-11-10 16:24:26 +01003988 return snd_array_elem(array, array->used++);
Takashi Iwaib2e18592008-07-30 15:01:44 +02003989}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003990EXPORT_SYMBOL_HDA(snd_array_new);
Takashi Iwaib2e18592008-07-30 15:01:44 +02003991
3992/* free the given array elements */
3993void snd_array_free(struct snd_array *array)
3994{
3995 kfree(array->list);
3996 array->used = 0;
3997 array->alloced = 0;
3998 array->list = NULL;
3999}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01004000EXPORT_SYMBOL_HDA(snd_array_free);
Takashi Iwaib2022262008-11-21 21:24:03 +01004001
4002/*
4003 * used by hda_proc.c and hda_eld.c
4004 */
4005void snd_print_pcm_rates(int pcm, char *buf, int buflen)
4006{
4007 static unsigned int rates[] = {
4008 8000, 11025, 16000, 22050, 32000, 44100, 48000, 88200,
4009 96000, 176400, 192000, 384000
4010 };
4011 int i, j;
4012
4013 for (i = 0, j = 0; i < ARRAY_SIZE(rates); i++)
4014 if (pcm & (1 << i))
4015 j += snprintf(buf + j, buflen - j, " %d", rates[i]);
4016
4017 buf[j] = '\0'; /* necessary when j == 0 */
4018}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01004019EXPORT_SYMBOL_HDA(snd_print_pcm_rates);
Takashi Iwaib2022262008-11-21 21:24:03 +01004020
4021void snd_print_pcm_bits(int pcm, char *buf, int buflen)
4022{
4023 static unsigned int bits[] = { 8, 16, 20, 24, 32 };
4024 int i, j;
4025
4026 for (i = 0, j = 0; i < ARRAY_SIZE(bits); i++)
4027 if (pcm & (AC_SUPPCM_BITS_8 << i))
4028 j += snprintf(buf + j, buflen - j, " %d", bits[i]);
4029
4030 buf[j] = '\0'; /* necessary when j == 0 */
4031}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01004032EXPORT_SYMBOL_HDA(snd_print_pcm_bits);
Takashi Iwai1289e9e2008-11-27 15:47:11 +01004033
4034MODULE_DESCRIPTION("HDA codec core");
4035MODULE_LICENSE("GPL");