blob: aa5540786111657f88609cedd0b9b388f25d3cb3 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * Universal Interface for Intel High Definition Audio Codec
3 *
4 * Copyright (c) 2004 Takashi Iwai <tiwai@suse.de>
5 *
6 *
7 * This driver is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This driver is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21
Linus Torvalds1da177e2005-04-16 15:20:36 -070022#include <linux/init.h>
23#include <linux/delay.h>
24#include <linux/slab.h>
25#include <linux/pci.h>
Ingo Molnar62932df2006-01-16 16:34:20 +010026#include <linux/mutex.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070027#include <sound/core.h>
28#include "hda_codec.h"
29#include <sound/asoundef.h>
Jaroslav Kysela302e9c52006-07-05 17:39:49 +020030#include <sound/tlv.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070031#include <sound/initval.h>
32#include "hda_local.h"
Takashi Iwai28073142007-07-27 18:58:06 +020033#include <sound/hda_hwdep.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070034
Linus Torvalds1da177e2005-04-16 15:20:36 -070035/*
36 * vendor / preset table
37 */
38
39struct hda_vendor_id {
40 unsigned int id;
41 const char *name;
42};
43
44/* codec vendor labels */
45static struct hda_vendor_id hda_vendor_ids[] = {
Takashi Iwaic8cd1282008-02-13 16:59:29 +010046 { 0x1002, "ATI" },
Takashi Iwaia9226252006-09-17 22:05:54 +020047 { 0x1057, "Motorola" },
Takashi Iwaic8cd1282008-02-13 16:59:29 +010048 { 0x1095, "Silicon Image" },
Takashi Iwai31117b72008-12-16 14:43:21 +010049 { 0x10de, "Nvidia" },
Takashi Iwaic8cd1282008-02-13 16:59:29 +010050 { 0x10ec, "Realtek" },
Takashi Iwai4e01f542009-04-16 08:53:34 +020051 { 0x1102, "Creative" },
Joseph Chanc577b8a2006-11-29 15:29:40 +010052 { 0x1106, "VIA" },
Matthew Ranostay7f168592007-10-18 17:38:17 +020053 { 0x111d, "IDT" },
Takashi Iwaic8cd1282008-02-13 16:59:29 +010054 { 0x11c1, "LSI" },
Takashi Iwai54b903e2005-05-15 14:30:10 +020055 { 0x11d4, "Analog Devices" },
Linus Torvalds1da177e2005-04-16 15:20:36 -070056 { 0x13f6, "C-Media" },
Takashi Iwaia9226252006-09-17 22:05:54 +020057 { 0x14f1, "Conexant" },
Takashi Iwaic8cd1282008-02-13 16:59:29 +010058 { 0x17e8, "Chrontel" },
59 { 0x1854, "LG" },
Mark Brown8199de32008-10-28 14:50:13 +000060 { 0x1aec, "Wolfson Microelectronics" },
Linus Torvalds1da177e2005-04-16 15:20:36 -070061 { 0x434d, "C-Media" },
Takashi Iwai74c61132008-12-18 09:11:33 +010062 { 0x8086, "Intel" },
Matt2f2f4252005-04-13 14:45:30 +020063 { 0x8384, "SigmaTel" },
Linus Torvalds1da177e2005-04-16 15:20:36 -070064 {} /* terminator */
65};
66
Takashi Iwai1289e9e2008-11-27 15:47:11 +010067static DEFINE_MUTEX(preset_mutex);
68static LIST_HEAD(hda_preset_tables);
69
70int snd_hda_add_codec_preset(struct hda_codec_preset_list *preset)
71{
72 mutex_lock(&preset_mutex);
73 list_add_tail(&preset->list, &hda_preset_tables);
74 mutex_unlock(&preset_mutex);
75 return 0;
76}
Takashi Iwaiff7a3262008-11-28 15:17:06 +010077EXPORT_SYMBOL_HDA(snd_hda_add_codec_preset);
Takashi Iwai1289e9e2008-11-27 15:47:11 +010078
79int snd_hda_delete_codec_preset(struct hda_codec_preset_list *preset)
80{
81 mutex_lock(&preset_mutex);
82 list_del(&preset->list);
83 mutex_unlock(&preset_mutex);
84 return 0;
85}
Takashi Iwaiff7a3262008-11-28 15:17:06 +010086EXPORT_SYMBOL_HDA(snd_hda_delete_codec_preset);
Linus Torvalds1da177e2005-04-16 15:20:36 -070087
Takashi Iwaicb53c622007-08-10 17:21:45 +020088#ifdef CONFIG_SND_HDA_POWER_SAVE
89static void hda_power_work(struct work_struct *work);
90static void hda_keep_power_on(struct hda_codec *codec);
91#else
92static inline void hda_keep_power_on(struct hda_codec *codec) {}
93#endif
94
Matthew Ranostay50a9f792008-10-25 01:05:45 -040095const char *snd_hda_get_jack_location(u32 cfg)
96{
97 static char *bases[7] = {
98 "N/A", "Rear", "Front", "Left", "Right", "Top", "Bottom",
99 };
100 static unsigned char specials_idx[] = {
101 0x07, 0x08,
102 0x17, 0x18, 0x19,
103 0x37, 0x38
104 };
105 static char *specials[] = {
106 "Rear Panel", "Drive Bar",
107 "Riser", "HDMI", "ATAPI",
108 "Mobile-In", "Mobile-Out"
109 };
110 int i;
111 cfg = (cfg & AC_DEFCFG_LOCATION) >> AC_DEFCFG_LOCATION_SHIFT;
112 if ((cfg & 0x0f) < 7)
113 return bases[cfg & 0x0f];
114 for (i = 0; i < ARRAY_SIZE(specials_idx); i++) {
115 if (cfg == specials_idx[i])
116 return specials[i];
117 }
118 return "UNKNOWN";
119}
Takashi Iwaiff7a3262008-11-28 15:17:06 +0100120EXPORT_SYMBOL_HDA(snd_hda_get_jack_location);
Matthew Ranostay50a9f792008-10-25 01:05:45 -0400121
122const char *snd_hda_get_jack_connectivity(u32 cfg)
123{
124 static char *jack_locations[4] = { "Ext", "Int", "Sep", "Oth" };
125
126 return jack_locations[(cfg >> (AC_DEFCFG_LOCATION_SHIFT + 4)) & 3];
127}
Takashi Iwaiff7a3262008-11-28 15:17:06 +0100128EXPORT_SYMBOL_HDA(snd_hda_get_jack_connectivity);
Matthew Ranostay50a9f792008-10-25 01:05:45 -0400129
130const char *snd_hda_get_jack_type(u32 cfg)
131{
132 static char *jack_types[16] = {
133 "Line Out", "Speaker", "HP Out", "CD",
134 "SPDIF Out", "Digital Out", "Modem Line", "Modem Hand",
135 "Line In", "Aux", "Mic", "Telephony",
136 "SPDIF In", "Digitial In", "Reserved", "Other"
137 };
138
139 return jack_types[(cfg & AC_DEFCFG_DEVICE)
140 >> AC_DEFCFG_DEVICE_SHIFT];
141}
Takashi Iwaiff7a3262008-11-28 15:17:06 +0100142EXPORT_SYMBOL_HDA(snd_hda_get_jack_type);
Matthew Ranostay50a9f792008-10-25 01:05:45 -0400143
Takashi Iwai33fa35e2008-11-06 16:50:40 +0100144/*
145 * Compose a 32bit command word to be sent to the HD-audio controller
146 */
147static inline unsigned int
148make_codec_cmd(struct hda_codec *codec, hda_nid_t nid, int direct,
149 unsigned int verb, unsigned int parm)
150{
151 u32 val;
152
Takashi Iwai82e1b802009-07-17 12:47:34 +0200153 if ((codec->addr & ~0xf) || (direct & ~1) || (nid & ~0x7f) ||
154 (verb & ~0xfff) || (parm & ~0xffff)) {
Wu Fengguang6430aee2009-07-17 16:49:19 +0800155 printk(KERN_ERR "hda-codec: out of range cmd %x:%x:%x:%x:%x\n",
156 codec->addr, direct, nid, verb, parm);
157 return ~0;
158 }
159
160 val = (u32)codec->addr << 28;
Takashi Iwai33fa35e2008-11-06 16:50:40 +0100161 val |= (u32)direct << 27;
162 val |= (u32)nid << 20;
163 val |= verb << 8;
164 val |= parm;
165 return val;
166}
167
Takashi Iwaiaa2936f2009-05-26 16:07:57 +0200168/*
169 * Send and receive a verb
170 */
171static int codec_exec_verb(struct hda_codec *codec, unsigned int cmd,
172 unsigned int *res)
173{
174 struct hda_bus *bus = codec->bus;
Takashi Iwai8dd78332009-06-02 01:16:07 +0200175 int err;
Takashi Iwaiaa2936f2009-05-26 16:07:57 +0200176
Wu Fengguang6430aee2009-07-17 16:49:19 +0800177 if (cmd == ~0)
178 return -1;
179
Takashi Iwaiaa2936f2009-05-26 16:07:57 +0200180 if (res)
181 *res = -1;
Takashi Iwai8dd78332009-06-02 01:16:07 +0200182 again:
Takashi Iwaiaa2936f2009-05-26 16:07:57 +0200183 snd_hda_power_up(codec);
184 mutex_lock(&bus->cmd_mutex);
Takashi Iwaiaa2936f2009-05-26 16:07:57 +0200185 err = bus->ops.command(bus, cmd);
Takashi Iwai8dd78332009-06-02 01:16:07 +0200186 if (!err && res)
187 *res = bus->ops.get_response(bus);
Takashi Iwaiaa2936f2009-05-26 16:07:57 +0200188 mutex_unlock(&bus->cmd_mutex);
189 snd_hda_power_down(codec);
Takashi Iwai8dd78332009-06-02 01:16:07 +0200190 if (res && *res == -1 && bus->rirb_error) {
191 if (bus->response_reset) {
192 snd_printd("hda_codec: resetting BUS due to "
193 "fatal communication error\n");
194 bus->ops.bus_reset(bus);
195 }
196 goto again;
197 }
198 /* clear reset-flag when the communication gets recovered */
199 if (!err)
200 bus->response_reset = 0;
Takashi Iwaiaa2936f2009-05-26 16:07:57 +0200201 return err;
202}
203
Linus Torvalds1da177e2005-04-16 15:20:36 -0700204/**
205 * snd_hda_codec_read - send a command and get the response
206 * @codec: the HDA codec
207 * @nid: NID to send the command
208 * @direct: direct flag
209 * @verb: the verb to send
210 * @parm: the parameter for the verb
211 *
212 * Send a single command and read the corresponding response.
213 *
214 * Returns the obtained response value, or -1 for an error.
215 */
Takashi Iwai0ba21762007-04-16 11:29:14 +0200216unsigned int snd_hda_codec_read(struct hda_codec *codec, hda_nid_t nid,
217 int direct,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700218 unsigned int verb, unsigned int parm)
219{
Takashi Iwaiaa2936f2009-05-26 16:07:57 +0200220 unsigned cmd = make_codec_cmd(codec, nid, direct, verb, parm);
221 unsigned int res;
222 codec_exec_verb(codec, cmd, &res);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700223 return res;
224}
Takashi Iwaiff7a3262008-11-28 15:17:06 +0100225EXPORT_SYMBOL_HDA(snd_hda_codec_read);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700226
227/**
228 * snd_hda_codec_write - send a single command without waiting for response
229 * @codec: the HDA codec
230 * @nid: NID to send the command
231 * @direct: direct flag
232 * @verb: the verb to send
233 * @parm: the parameter for the verb
234 *
235 * Send a single command without waiting for response.
236 *
237 * Returns 0 if successful, or a negative error code.
238 */
239int snd_hda_codec_write(struct hda_codec *codec, hda_nid_t nid, int direct,
240 unsigned int verb, unsigned int parm)
241{
Takashi Iwaiaa2936f2009-05-26 16:07:57 +0200242 unsigned int cmd = make_codec_cmd(codec, nid, direct, verb, parm);
Takashi Iwai33fa35e2008-11-06 16:50:40 +0100243 unsigned int res;
Takashi Iwaib20f3b82009-06-02 01:20:22 +0200244 return codec_exec_verb(codec, cmd,
245 codec->bus->sync_write ? &res : NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700246}
Takashi Iwaiff7a3262008-11-28 15:17:06 +0100247EXPORT_SYMBOL_HDA(snd_hda_codec_write);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700248
249/**
250 * snd_hda_sequence_write - sequence writes
251 * @codec: the HDA codec
252 * @seq: VERB array to send
253 *
254 * Send the commands sequentially from the given array.
255 * The array must be terminated with NID=0.
256 */
257void snd_hda_sequence_write(struct hda_codec *codec, const struct hda_verb *seq)
258{
259 for (; seq->nid; seq++)
260 snd_hda_codec_write(codec, seq->nid, 0, seq->verb, seq->param);
261}
Takashi Iwaiff7a3262008-11-28 15:17:06 +0100262EXPORT_SYMBOL_HDA(snd_hda_sequence_write);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700263
264/**
265 * snd_hda_get_sub_nodes - get the range of sub nodes
266 * @codec: the HDA codec
267 * @nid: NID to parse
268 * @start_id: the pointer to store the start NID
269 *
270 * Parse the NID and store the start NID of its sub-nodes.
271 * Returns the number of sub-nodes.
272 */
Takashi Iwai0ba21762007-04-16 11:29:14 +0200273int snd_hda_get_sub_nodes(struct hda_codec *codec, hda_nid_t nid,
274 hda_nid_t *start_id)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700275{
276 unsigned int parm;
277
278 parm = snd_hda_param_read(codec, nid, AC_PAR_NODE_COUNT);
Danny Tholene8a7f132007-09-11 21:41:56 +0200279 if (parm == -1)
280 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700281 *start_id = (parm >> 16) & 0x7fff;
282 return (int)(parm & 0x7fff);
283}
Takashi Iwaiff7a3262008-11-28 15:17:06 +0100284EXPORT_SYMBOL_HDA(snd_hda_get_sub_nodes);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700285
286/**
287 * snd_hda_get_connections - get connection list
288 * @codec: the HDA codec
289 * @nid: NID to parse
290 * @conn_list: connection list array
291 * @max_conns: max. number of connections to store
292 *
293 * Parses the connection list of the given widget and stores the list
294 * of NIDs.
295 *
296 * Returns the number of connections, or a negative error code.
297 */
298int snd_hda_get_connections(struct hda_codec *codec, hda_nid_t nid,
299 hda_nid_t *conn_list, int max_conns)
300{
301 unsigned int parm;
Takashi Iwai54d17402005-11-21 16:33:22 +0100302 int i, conn_len, conns;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700303 unsigned int shift, num_elems, mask;
Takashi Iwai54d17402005-11-21 16:33:22 +0100304 hda_nid_t prev_nid;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700305
Takashi Iwaida3cec32008-08-08 17:12:14 +0200306 if (snd_BUG_ON(!conn_list || max_conns <= 0))
307 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700308
Jaroslav Kysela16a433d2009-07-22 16:20:40 +0200309 if ((get_wcaps(codec, nid) & AC_WCAP_CONN_LIST) == 0) {
310 snd_printk(KERN_WARNING "hda_codec: "
311 "connection list not available for 0x%x\n", nid);
312 return -EINVAL;
313 }
314
Linus Torvalds1da177e2005-04-16 15:20:36 -0700315 parm = snd_hda_param_read(codec, nid, AC_PAR_CONNLIST_LEN);
316 if (parm & AC_CLIST_LONG) {
317 /* long form */
318 shift = 16;
319 num_elems = 2;
320 } else {
321 /* short form */
322 shift = 8;
323 num_elems = 4;
324 }
325 conn_len = parm & AC_CLIST_LENGTH;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700326 mask = (1 << (shift-1)) - 1;
327
Takashi Iwai0ba21762007-04-16 11:29:14 +0200328 if (!conn_len)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700329 return 0; /* no connection */
330
331 if (conn_len == 1) {
332 /* single connection */
Takashi Iwai0ba21762007-04-16 11:29:14 +0200333 parm = snd_hda_codec_read(codec, nid, 0,
334 AC_VERB_GET_CONNECT_LIST, 0);
Takashi Iwai3c6aae42009-07-10 12:52:27 +0200335 if (parm == -1 && codec->bus->rirb_error)
336 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700337 conn_list[0] = parm & mask;
338 return 1;
339 }
340
341 /* multi connection */
342 conns = 0;
Takashi Iwai54d17402005-11-21 16:33:22 +0100343 prev_nid = 0;
344 for (i = 0; i < conn_len; i++) {
345 int range_val;
346 hda_nid_t val, n;
347
Takashi Iwai3c6aae42009-07-10 12:52:27 +0200348 if (i % num_elems == 0) {
Takashi Iwai54d17402005-11-21 16:33:22 +0100349 parm = snd_hda_codec_read(codec, nid, 0,
350 AC_VERB_GET_CONNECT_LIST, i);
Takashi Iwai3c6aae42009-07-10 12:52:27 +0200351 if (parm == -1 && codec->bus->rirb_error)
352 return -EIO;
353 }
Takashi Iwai0ba21762007-04-16 11:29:14 +0200354 range_val = !!(parm & (1 << (shift-1))); /* ranges */
Takashi Iwai54d17402005-11-21 16:33:22 +0100355 val = parm & mask;
Jaroslav Kysela2e9bf242009-07-18 11:48:19 +0200356 if (val == 0) {
357 snd_printk(KERN_WARNING "hda_codec: "
358 "invalid CONNECT_LIST verb %x[%i]:%x\n",
359 nid, i, parm);
360 return 0;
361 }
Takashi Iwai54d17402005-11-21 16:33:22 +0100362 parm >>= shift;
363 if (range_val) {
364 /* ranges between the previous and this one */
Takashi Iwai0ba21762007-04-16 11:29:14 +0200365 if (!prev_nid || prev_nid >= val) {
366 snd_printk(KERN_WARNING "hda_codec: "
367 "invalid dep_range_val %x:%x\n",
368 prev_nid, val);
Takashi Iwai54d17402005-11-21 16:33:22 +0100369 continue;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700370 }
Takashi Iwai54d17402005-11-21 16:33:22 +0100371 for (n = prev_nid + 1; n <= val; n++) {
372 if (conns >= max_conns) {
Takashi Iwai0ba21762007-04-16 11:29:14 +0200373 snd_printk(KERN_ERR
374 "Too many connections\n");
Takashi Iwai54d17402005-11-21 16:33:22 +0100375 return -EINVAL;
376 }
377 conn_list[conns++] = n;
378 }
379 } else {
380 if (conns >= max_conns) {
381 snd_printk(KERN_ERR "Too many connections\n");
382 return -EINVAL;
383 }
384 conn_list[conns++] = val;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700385 }
Takashi Iwai54d17402005-11-21 16:33:22 +0100386 prev_nid = val;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700387 }
388 return conns;
389}
Takashi Iwaiff7a3262008-11-28 15:17:06 +0100390EXPORT_SYMBOL_HDA(snd_hda_get_connections);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700391
392
393/**
394 * snd_hda_queue_unsol_event - add an unsolicited event to queue
395 * @bus: the BUS
396 * @res: unsolicited event (lower 32bit of RIRB entry)
397 * @res_ex: codec addr and flags (upper 32bit or RIRB entry)
398 *
399 * Adds the given event to the queue. The events are processed in
400 * the workqueue asynchronously. Call this function in the interrupt
401 * hanlder when RIRB receives an unsolicited event.
402 *
403 * Returns 0 if successful, or a negative error code.
404 */
405int snd_hda_queue_unsol_event(struct hda_bus *bus, u32 res, u32 res_ex)
406{
407 struct hda_bus_unsolicited *unsol;
408 unsigned int wp;
409
Takashi Iwai0ba21762007-04-16 11:29:14 +0200410 unsol = bus->unsol;
411 if (!unsol)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700412 return 0;
413
414 wp = (unsol->wp + 1) % HDA_UNSOL_QUEUE_SIZE;
415 unsol->wp = wp;
416
417 wp <<= 1;
418 unsol->queue[wp] = res;
419 unsol->queue[wp + 1] = res_ex;
420
Takashi Iwai6acaed32009-01-12 10:09:24 +0100421 queue_work(bus->workq, &unsol->work);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700422
423 return 0;
424}
Takashi Iwaiff7a3262008-11-28 15:17:06 +0100425EXPORT_SYMBOL_HDA(snd_hda_queue_unsol_event);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700426
427/*
Wu Fengguang5c1d1a92008-10-07 14:17:53 +0800428 * process queued unsolicited events
Linus Torvalds1da177e2005-04-16 15:20:36 -0700429 */
David Howellsc4028952006-11-22 14:57:56 +0000430static void process_unsol_events(struct work_struct *work)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700431{
David Howellsc4028952006-11-22 14:57:56 +0000432 struct hda_bus_unsolicited *unsol =
433 container_of(work, struct hda_bus_unsolicited, work);
434 struct hda_bus *bus = unsol->bus;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700435 struct hda_codec *codec;
436 unsigned int rp, caddr, res;
437
438 while (unsol->rp != unsol->wp) {
439 rp = (unsol->rp + 1) % HDA_UNSOL_QUEUE_SIZE;
440 unsol->rp = rp;
441 rp <<= 1;
442 res = unsol->queue[rp];
443 caddr = unsol->queue[rp + 1];
Takashi Iwai0ba21762007-04-16 11:29:14 +0200444 if (!(caddr & (1 << 4))) /* no unsolicited event? */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700445 continue;
446 codec = bus->caddr_tbl[caddr & 0x0f];
447 if (codec && codec->patch_ops.unsol_event)
448 codec->patch_ops.unsol_event(codec, res);
449 }
450}
451
452/*
453 * initialize unsolicited queue
454 */
Takashi Iwai6c1f45e2008-07-30 15:01:45 +0200455static int init_unsol_queue(struct hda_bus *bus)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700456{
457 struct hda_bus_unsolicited *unsol;
458
Takashi Iwai9f146bb2005-11-17 11:07:49 +0100459 if (bus->unsol) /* already initialized */
460 return 0;
461
Takashi Iwaie560d8d2005-09-09 14:21:46 +0200462 unsol = kzalloc(sizeof(*unsol), GFP_KERNEL);
Takashi Iwai0ba21762007-04-16 11:29:14 +0200463 if (!unsol) {
464 snd_printk(KERN_ERR "hda_codec: "
465 "can't allocate unsolicited queue\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700466 return -ENOMEM;
467 }
David Howellsc4028952006-11-22 14:57:56 +0000468 INIT_WORK(&unsol->work, process_unsol_events);
469 unsol->bus = bus;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700470 bus->unsol = unsol;
471 return 0;
472}
473
474/*
475 * destructor
476 */
477static void snd_hda_codec_free(struct hda_codec *codec);
478
479static int snd_hda_bus_free(struct hda_bus *bus)
480{
Takashi Iwai0ba21762007-04-16 11:29:14 +0200481 struct hda_codec *codec, *n;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700482
Takashi Iwai0ba21762007-04-16 11:29:14 +0200483 if (!bus)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700484 return 0;
Takashi Iwai6acaed32009-01-12 10:09:24 +0100485 if (bus->workq)
486 flush_workqueue(bus->workq);
487 if (bus->unsol)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700488 kfree(bus->unsol);
Takashi Iwai0ba21762007-04-16 11:29:14 +0200489 list_for_each_entry_safe(codec, n, &bus->codec_list, list) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700490 snd_hda_codec_free(codec);
491 }
492 if (bus->ops.private_free)
493 bus->ops.private_free(bus);
Takashi Iwai6acaed32009-01-12 10:09:24 +0100494 if (bus->workq)
495 destroy_workqueue(bus->workq);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700496 kfree(bus);
497 return 0;
498}
499
Takashi Iwaic8b6bf92005-11-17 14:57:47 +0100500static int snd_hda_bus_dev_free(struct snd_device *device)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700501{
502 struct hda_bus *bus = device->device_data;
Takashi Iwaib94d35392008-11-21 09:08:06 +0100503 bus->shutdown = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700504 return snd_hda_bus_free(bus);
505}
506
Takashi Iwaid7ffba12008-07-30 15:01:46 +0200507#ifdef CONFIG_SND_HDA_HWDEP
508static int snd_hda_bus_dev_register(struct snd_device *device)
509{
510 struct hda_bus *bus = device->device_data;
511 struct hda_codec *codec;
512 list_for_each_entry(codec, &bus->codec_list, list) {
513 snd_hda_hwdep_add_sysfs(codec);
514 }
515 return 0;
516}
517#else
518#define snd_hda_bus_dev_register NULL
519#endif
520
Linus Torvalds1da177e2005-04-16 15:20:36 -0700521/**
522 * snd_hda_bus_new - create a HDA bus
523 * @card: the card entry
524 * @temp: the template for hda_bus information
525 * @busp: the pointer to store the created bus instance
526 *
527 * Returns 0 if successful, or a negative error code.
528 */
Takashi Iwai1289e9e2008-11-27 15:47:11 +0100529int /*__devinit*/ snd_hda_bus_new(struct snd_card *card,
Takashi Iwai756e2b02007-04-16 11:27:07 +0200530 const struct hda_bus_template *temp,
531 struct hda_bus **busp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700532{
533 struct hda_bus *bus;
534 int err;
Takashi Iwaic8b6bf92005-11-17 14:57:47 +0100535 static struct snd_device_ops dev_ops = {
Takashi Iwaid7ffba12008-07-30 15:01:46 +0200536 .dev_register = snd_hda_bus_dev_register,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700537 .dev_free = snd_hda_bus_dev_free,
538 };
539
Takashi Iwaida3cec32008-08-08 17:12:14 +0200540 if (snd_BUG_ON(!temp))
541 return -EINVAL;
542 if (snd_BUG_ON(!temp->ops.command || !temp->ops.get_response))
543 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700544
545 if (busp)
546 *busp = NULL;
547
Takashi Iwaie560d8d2005-09-09 14:21:46 +0200548 bus = kzalloc(sizeof(*bus), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700549 if (bus == NULL) {
550 snd_printk(KERN_ERR "can't allocate struct hda_bus\n");
551 return -ENOMEM;
552 }
553
554 bus->card = card;
555 bus->private_data = temp->private_data;
556 bus->pci = temp->pci;
557 bus->modelname = temp->modelname;
Takashi Iwaifee2fba2008-11-27 12:43:28 +0100558 bus->power_save = temp->power_save;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700559 bus->ops = temp->ops;
560
Ingo Molnar62932df2006-01-16 16:34:20 +0100561 mutex_init(&bus->cmd_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700562 INIT_LIST_HEAD(&bus->codec_list);
563
Takashi Iwaie8c0ee52009-02-05 07:34:28 +0100564 snprintf(bus->workq_name, sizeof(bus->workq_name),
565 "hd-audio%d", card->number);
566 bus->workq = create_singlethread_workqueue(bus->workq_name);
Takashi Iwai6acaed32009-01-12 10:09:24 +0100567 if (!bus->workq) {
Takashi Iwaie8c0ee52009-02-05 07:34:28 +0100568 snd_printk(KERN_ERR "cannot create workqueue %s\n",
569 bus->workq_name);
Takashi Iwai6acaed32009-01-12 10:09:24 +0100570 kfree(bus);
571 return -ENOMEM;
572 }
573
Takashi Iwai0ba21762007-04-16 11:29:14 +0200574 err = snd_device_new(card, SNDRV_DEV_BUS, bus, &dev_ops);
575 if (err < 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700576 snd_hda_bus_free(bus);
577 return err;
578 }
579 if (busp)
580 *busp = bus;
581 return 0;
582}
Takashi Iwaiff7a3262008-11-28 15:17:06 +0100583EXPORT_SYMBOL_HDA(snd_hda_bus_new);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700584
Takashi Iwai82467612007-07-27 19:15:54 +0200585#ifdef CONFIG_SND_HDA_GENERIC
586#define is_generic_config(codec) \
Takashi Iwaif44ac832008-07-30 15:01:45 +0200587 (codec->modelname && !strcmp(codec->modelname, "generic"))
Takashi Iwai82467612007-07-27 19:15:54 +0200588#else
589#define is_generic_config(codec) 0
590#endif
591
Takashi Iwai645f10c2008-11-28 15:07:37 +0100592#ifdef MODULE
Takashi Iwai1289e9e2008-11-27 15:47:11 +0100593#define HDA_MODREQ_MAX_COUNT 2 /* two request_modules()'s */
594#else
Takashi Iwai645f10c2008-11-28 15:07:37 +0100595#define HDA_MODREQ_MAX_COUNT 0 /* all presets are statically linked */
Takashi Iwai1289e9e2008-11-27 15:47:11 +0100596#endif
597
Linus Torvalds1da177e2005-04-16 15:20:36 -0700598/*
599 * find a matching codec preset
600 */
Takashi Iwai6c1f45e2008-07-30 15:01:45 +0200601static const struct hda_codec_preset *
Takashi Iwai756e2b02007-04-16 11:27:07 +0200602find_codec_preset(struct hda_codec *codec)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700603{
Takashi Iwai1289e9e2008-11-27 15:47:11 +0100604 struct hda_codec_preset_list *tbl;
605 const struct hda_codec_preset *preset;
606 int mod_requested = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700607
Takashi Iwai82467612007-07-27 19:15:54 +0200608 if (is_generic_config(codec))
Takashi Iwaid5ad6302007-03-07 15:55:59 +0100609 return NULL; /* use the generic parser */
610
Takashi Iwai1289e9e2008-11-27 15:47:11 +0100611 again:
612 mutex_lock(&preset_mutex);
613 list_for_each_entry(tbl, &hda_preset_tables, list) {
614 if (!try_module_get(tbl->owner)) {
615 snd_printk(KERN_ERR "hda_codec: cannot module_get\n");
616 continue;
617 }
618 for (preset = tbl->preset; preset->id; preset++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700619 u32 mask = preset->mask;
Marc Boucherca7cfae2008-01-22 15:32:25 +0100620 if (preset->afg && preset->afg != codec->afg)
621 continue;
622 if (preset->mfg && preset->mfg != codec->mfg)
623 continue;
Takashi Iwai0ba21762007-04-16 11:29:14 +0200624 if (!mask)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700625 mask = ~0;
Takashi Iwai9c7f8522006-06-28 15:08:22 +0200626 if (preset->id == (codec->vendor_id & mask) &&
Takashi Iwai0ba21762007-04-16 11:29:14 +0200627 (!preset->rev ||
Takashi Iwai1289e9e2008-11-27 15:47:11 +0100628 preset->rev == codec->revision_id)) {
629 mutex_unlock(&preset_mutex);
630 codec->owner = tbl->owner;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700631 return preset;
Takashi Iwai1289e9e2008-11-27 15:47:11 +0100632 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700633 }
Takashi Iwai1289e9e2008-11-27 15:47:11 +0100634 module_put(tbl->owner);
635 }
636 mutex_unlock(&preset_mutex);
637
638 if (mod_requested < HDA_MODREQ_MAX_COUNT) {
639 char name[32];
640 if (!mod_requested)
641 snprintf(name, sizeof(name), "snd-hda-codec-id:%08x",
642 codec->vendor_id);
643 else
644 snprintf(name, sizeof(name), "snd-hda-codec-id:%04x*",
645 (codec->vendor_id >> 16) & 0xffff);
646 request_module(name);
647 mod_requested++;
648 goto again;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700649 }
650 return NULL;
651}
652
653/*
Takashi Iwaif44ac832008-07-30 15:01:45 +0200654 * get_codec_name - store the codec name
Linus Torvalds1da177e2005-04-16 15:20:36 -0700655 */
Takashi Iwaif44ac832008-07-30 15:01:45 +0200656static int get_codec_name(struct hda_codec *codec)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700657{
658 const struct hda_vendor_id *c;
659 const char *vendor = NULL;
660 u16 vendor_id = codec->vendor_id >> 16;
Takashi Iwai812a2cc2009-05-16 10:00:49 +0200661 char tmp[16];
662
663 if (codec->vendor_name)
664 goto get_chip_name;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700665
666 for (c = hda_vendor_ids; c->id; c++) {
667 if (c->id == vendor_id) {
668 vendor = c->name;
669 break;
670 }
671 }
Takashi Iwai0ba21762007-04-16 11:29:14 +0200672 if (!vendor) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700673 sprintf(tmp, "Generic %04x", vendor_id);
674 vendor = tmp;
675 }
Takashi Iwai812a2cc2009-05-16 10:00:49 +0200676 codec->vendor_name = kstrdup(vendor, GFP_KERNEL);
677 if (!codec->vendor_name)
678 return -ENOMEM;
679
680 get_chip_name:
681 if (codec->chip_name)
682 return 0;
683
Linus Torvalds1da177e2005-04-16 15:20:36 -0700684 if (codec->preset && codec->preset->name)
Takashi Iwai812a2cc2009-05-16 10:00:49 +0200685 codec->chip_name = kstrdup(codec->preset->name, GFP_KERNEL);
686 else {
687 sprintf(tmp, "ID %x", codec->vendor_id & 0xffff);
688 codec->chip_name = kstrdup(tmp, GFP_KERNEL);
689 }
690 if (!codec->chip_name)
Takashi Iwaif44ac832008-07-30 15:01:45 +0200691 return -ENOMEM;
692 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700693}
694
695/*
Sasha Khapyorsky673b6832005-08-11 11:00:16 +0200696 * look for an AFG and MFG nodes
Linus Torvalds1da177e2005-04-16 15:20:36 -0700697 */
Takashi Iwai1289e9e2008-11-27 15:47:11 +0100698static void /*__devinit*/ setup_fg_nodes(struct hda_codec *codec)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700699{
Takashi Iwai93e82ae2009-04-17 18:04:41 +0200700 int i, total_nodes, function_id;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700701 hda_nid_t nid;
702
703 total_nodes = snd_hda_get_sub_nodes(codec, AC_NODE_ROOT, &nid);
704 for (i = 0; i < total_nodes; i++, nid++) {
Takashi Iwai93e82ae2009-04-17 18:04:41 +0200705 function_id = snd_hda_param_read(codec, nid,
Pascal de Bruijn234b4342009-03-23 11:15:59 +0100706 AC_PAR_FUNCTION_TYPE) & 0xff;
Takashi Iwai93e82ae2009-04-17 18:04:41 +0200707 switch (function_id) {
Sasha Khapyorsky673b6832005-08-11 11:00:16 +0200708 case AC_GRP_AUDIO_FUNCTION:
709 codec->afg = nid;
Takashi Iwai93e82ae2009-04-17 18:04:41 +0200710 codec->function_id = function_id;
Sasha Khapyorsky673b6832005-08-11 11:00:16 +0200711 break;
712 case AC_GRP_MODEM_FUNCTION:
713 codec->mfg = nid;
Takashi Iwai93e82ae2009-04-17 18:04:41 +0200714 codec->function_id = function_id;
Sasha Khapyorsky673b6832005-08-11 11:00:16 +0200715 break;
716 default:
717 break;
718 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700719 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700720}
721
722/*
Takashi Iwai54d17402005-11-21 16:33:22 +0100723 * read widget caps for each widget and store in cache
724 */
725static int read_widget_caps(struct hda_codec *codec, hda_nid_t fg_node)
726{
727 int i;
728 hda_nid_t nid;
729
730 codec->num_nodes = snd_hda_get_sub_nodes(codec, fg_node,
731 &codec->start_nid);
732 codec->wcaps = kmalloc(codec->num_nodes * 4, GFP_KERNEL);
Takashi Iwai0ba21762007-04-16 11:29:14 +0200733 if (!codec->wcaps)
Takashi Iwai54d17402005-11-21 16:33:22 +0100734 return -ENOMEM;
735 nid = codec->start_nid;
736 for (i = 0; i < codec->num_nodes; i++, nid++)
737 codec->wcaps[i] = snd_hda_param_read(codec, nid,
738 AC_PAR_AUDIO_WIDGET_CAP);
739 return 0;
740}
741
Takashi Iwai3be14142009-02-20 14:11:16 +0100742/* read all pin default configurations and save codec->init_pins */
743static int read_pin_defaults(struct hda_codec *codec)
744{
745 int i;
746 hda_nid_t nid = codec->start_nid;
747
748 for (i = 0; i < codec->num_nodes; i++, nid++) {
749 struct hda_pincfg *pin;
750 unsigned int wcaps = get_wcaps(codec, nid);
751 unsigned int wid_type = (wcaps & AC_WCAP_TYPE) >>
752 AC_WCAP_TYPE_SHIFT;
753 if (wid_type != AC_WID_PIN)
754 continue;
755 pin = snd_array_new(&codec->init_pins);
756 if (!pin)
757 return -ENOMEM;
758 pin->nid = nid;
759 pin->cfg = snd_hda_codec_read(codec, nid, 0,
760 AC_VERB_GET_CONFIG_DEFAULT, 0);
761 }
762 return 0;
763}
764
765/* look up the given pin config list and return the item matching with NID */
766static struct hda_pincfg *look_up_pincfg(struct hda_codec *codec,
767 struct snd_array *array,
768 hda_nid_t nid)
769{
770 int i;
771 for (i = 0; i < array->used; i++) {
772 struct hda_pincfg *pin = snd_array_elem(array, i);
773 if (pin->nid == nid)
774 return pin;
775 }
776 return NULL;
777}
778
779/* write a config value for the given NID */
780static void set_pincfg(struct hda_codec *codec, hda_nid_t nid,
781 unsigned int cfg)
782{
783 int i;
784 for (i = 0; i < 4; i++) {
785 snd_hda_codec_write(codec, nid, 0,
786 AC_VERB_SET_CONFIG_DEFAULT_BYTES_0 + i,
787 cfg & 0xff);
788 cfg >>= 8;
789 }
790}
791
792/* set the current pin config value for the given NID.
793 * the value is cached, and read via snd_hda_codec_get_pincfg()
794 */
795int snd_hda_add_pincfg(struct hda_codec *codec, struct snd_array *list,
796 hda_nid_t nid, unsigned int cfg)
797{
798 struct hda_pincfg *pin;
Takashi Iwai5e7b8e02009-02-23 09:45:59 +0100799 unsigned int oldcfg;
Takashi Iwai3be14142009-02-20 14:11:16 +0100800
Takashi Iwai5e7b8e02009-02-23 09:45:59 +0100801 oldcfg = snd_hda_codec_get_pincfg(codec, nid);
Takashi Iwai3be14142009-02-20 14:11:16 +0100802 pin = look_up_pincfg(codec, list, nid);
803 if (!pin) {
804 pin = snd_array_new(list);
805 if (!pin)
806 return -ENOMEM;
807 pin->nid = nid;
808 }
809 pin->cfg = cfg;
Takashi Iwai5e7b8e02009-02-23 09:45:59 +0100810
811 /* change only when needed; e.g. if the pincfg is already present
812 * in user_pins[], don't write it
813 */
814 cfg = snd_hda_codec_get_pincfg(codec, nid);
815 if (oldcfg != cfg)
816 set_pincfg(codec, nid, cfg);
Takashi Iwai3be14142009-02-20 14:11:16 +0100817 return 0;
818}
819
820int snd_hda_codec_set_pincfg(struct hda_codec *codec,
821 hda_nid_t nid, unsigned int cfg)
822{
Takashi Iwai346ff702009-02-23 09:42:57 +0100823 return snd_hda_add_pincfg(codec, &codec->driver_pins, nid, cfg);
Takashi Iwai3be14142009-02-20 14:11:16 +0100824}
825EXPORT_SYMBOL_HDA(snd_hda_codec_set_pincfg);
826
827/* get the current pin config value of the given pin NID */
828unsigned int snd_hda_codec_get_pincfg(struct hda_codec *codec, hda_nid_t nid)
829{
830 struct hda_pincfg *pin;
831
Takashi Iwai3be14142009-02-20 14:11:16 +0100832#ifdef CONFIG_SND_HDA_HWDEP
Takashi Iwai346ff702009-02-23 09:42:57 +0100833 pin = look_up_pincfg(codec, &codec->user_pins, nid);
Takashi Iwai3be14142009-02-20 14:11:16 +0100834 if (pin)
835 return pin->cfg;
836#endif
Takashi Iwai5e7b8e02009-02-23 09:45:59 +0100837 pin = look_up_pincfg(codec, &codec->driver_pins, nid);
838 if (pin)
839 return pin->cfg;
Takashi Iwai3be14142009-02-20 14:11:16 +0100840 pin = look_up_pincfg(codec, &codec->init_pins, nid);
841 if (pin)
842 return pin->cfg;
843 return 0;
844}
845EXPORT_SYMBOL_HDA(snd_hda_codec_get_pincfg);
846
847/* restore all current pin configs */
848static void restore_pincfgs(struct hda_codec *codec)
849{
850 int i;
851 for (i = 0; i < codec->init_pins.used; i++) {
852 struct hda_pincfg *pin = snd_array_elem(&codec->init_pins, i);
853 set_pincfg(codec, pin->nid,
854 snd_hda_codec_get_pincfg(codec, pin->nid));
855 }
856}
Takashi Iwai54d17402005-11-21 16:33:22 +0100857
Takashi Iwai01751f52007-08-10 16:59:39 +0200858static void init_hda_cache(struct hda_cache_rec *cache,
859 unsigned int record_size);
Takashi Iwai1fcaee62007-08-23 00:01:09 +0200860static void free_hda_cache(struct hda_cache_rec *cache);
Takashi Iwai01751f52007-08-10 16:59:39 +0200861
Takashi Iwai3be14142009-02-20 14:11:16 +0100862/* restore the initial pin cfgs and release all pincfg lists */
863static void restore_init_pincfgs(struct hda_codec *codec)
864{
Takashi Iwai346ff702009-02-23 09:42:57 +0100865 /* first free driver_pins and user_pins, then call restore_pincfg
Takashi Iwai3be14142009-02-20 14:11:16 +0100866 * so that only the values in init_pins are restored
867 */
Takashi Iwai346ff702009-02-23 09:42:57 +0100868 snd_array_free(&codec->driver_pins);
Takashi Iwai3be14142009-02-20 14:11:16 +0100869#ifdef CONFIG_SND_HDA_HWDEP
Takashi Iwai346ff702009-02-23 09:42:57 +0100870 snd_array_free(&codec->user_pins);
Takashi Iwai3be14142009-02-20 14:11:16 +0100871#endif
872 restore_pincfgs(codec);
873 snd_array_free(&codec->init_pins);
874}
875
Takashi Iwai54d17402005-11-21 16:33:22 +0100876/*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700877 * codec destructor
878 */
879static void snd_hda_codec_free(struct hda_codec *codec)
880{
Takashi Iwai0ba21762007-04-16 11:29:14 +0200881 if (!codec)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700882 return;
Takashi Iwai3be14142009-02-20 14:11:16 +0100883 restore_init_pincfgs(codec);
Takashi Iwaicb53c622007-08-10 17:21:45 +0200884#ifdef CONFIG_SND_HDA_POWER_SAVE
885 cancel_delayed_work(&codec->power_work);
Takashi Iwai6acaed32009-01-12 10:09:24 +0100886 flush_workqueue(codec->bus->workq);
Takashi Iwaicb53c622007-08-10 17:21:45 +0200887#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700888 list_del(&codec->list);
Takashi Iwaid13bd412008-07-30 15:01:45 +0200889 snd_array_free(&codec->mixers);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700890 codec->bus->caddr_tbl[codec->addr] = NULL;
891 if (codec->patch_ops.free)
892 codec->patch_ops.free(codec);
Takashi Iwai1289e9e2008-11-27 15:47:11 +0100893 module_put(codec->owner);
Takashi Iwai01751f52007-08-10 16:59:39 +0200894 free_hda_cache(&codec->amp_cache);
Takashi Iwaib3ac5632007-08-10 17:03:40 +0200895 free_hda_cache(&codec->cmd_cache);
Takashi Iwai812a2cc2009-05-16 10:00:49 +0200896 kfree(codec->vendor_name);
897 kfree(codec->chip_name);
Takashi Iwaif44ac832008-07-30 15:01:45 +0200898 kfree(codec->modelname);
Takashi Iwai54d17402005-11-21 16:33:22 +0100899 kfree(codec->wcaps);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700900 kfree(codec);
901}
902
Takashi Iwaibb6ac722009-03-13 09:02:42 +0100903static void hda_set_power_state(struct hda_codec *codec, hda_nid_t fg,
904 unsigned int power_state);
905
Linus Torvalds1da177e2005-04-16 15:20:36 -0700906/**
907 * snd_hda_codec_new - create a HDA codec
908 * @bus: the bus to assign
909 * @codec_addr: the codec address
910 * @codecp: the pointer to store the generated codec
911 *
912 * Returns 0 if successful, or a negative error code.
913 */
Takashi Iwai1289e9e2008-11-27 15:47:11 +0100914int /*__devinit*/ snd_hda_codec_new(struct hda_bus *bus, unsigned int codec_addr,
Takashi Iwaia1e21c92009-06-17 09:33:52 +0200915 struct hda_codec **codecp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700916{
917 struct hda_codec *codec;
Jaroslav Kyselaba443682008-08-13 20:55:32 +0200918 char component[31];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700919 int err;
920
Takashi Iwaida3cec32008-08-08 17:12:14 +0200921 if (snd_BUG_ON(!bus))
922 return -EINVAL;
923 if (snd_BUG_ON(codec_addr > HDA_MAX_CODEC_ADDRESS))
924 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700925
926 if (bus->caddr_tbl[codec_addr]) {
Takashi Iwai0ba21762007-04-16 11:29:14 +0200927 snd_printk(KERN_ERR "hda_codec: "
928 "address 0x%x is already occupied\n", codec_addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700929 return -EBUSY;
930 }
931
Takashi Iwaie560d8d2005-09-09 14:21:46 +0200932 codec = kzalloc(sizeof(*codec), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700933 if (codec == NULL) {
934 snd_printk(KERN_ERR "can't allocate struct hda_codec\n");
935 return -ENOMEM;
936 }
937
938 codec->bus = bus;
939 codec->addr = codec_addr;
Ingo Molnar62932df2006-01-16 16:34:20 +0100940 mutex_init(&codec->spdif_mutex);
Wu Fengguang5a9e02e2009-01-09 16:45:24 +0800941 mutex_init(&codec->control_mutex);
Takashi Iwai01751f52007-08-10 16:59:39 +0200942 init_hda_cache(&codec->amp_cache, sizeof(struct hda_amp_info));
Takashi Iwaib3ac5632007-08-10 17:03:40 +0200943 init_hda_cache(&codec->cmd_cache, sizeof(struct hda_cache_head));
Takashi Iwaid13bd412008-07-30 15:01:45 +0200944 snd_array_init(&codec->mixers, sizeof(struct snd_kcontrol *), 32);
Takashi Iwai3be14142009-02-20 14:11:16 +0100945 snd_array_init(&codec->init_pins, sizeof(struct hda_pincfg), 16);
Takashi Iwai346ff702009-02-23 09:42:57 +0100946 snd_array_init(&codec->driver_pins, sizeof(struct hda_pincfg), 16);
Takashi Iwai6c1f45e2008-07-30 15:01:45 +0200947 if (codec->bus->modelname) {
948 codec->modelname = kstrdup(codec->bus->modelname, GFP_KERNEL);
949 if (!codec->modelname) {
950 snd_hda_codec_free(codec);
951 return -ENODEV;
952 }
953 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700954
Takashi Iwaicb53c622007-08-10 17:21:45 +0200955#ifdef CONFIG_SND_HDA_POWER_SAVE
956 INIT_DELAYED_WORK(&codec->power_work, hda_power_work);
957 /* snd_hda_codec_new() marks the codec as power-up, and leave it as is.
958 * the caller has to power down appropriatley after initialization
959 * phase.
960 */
961 hda_keep_power_on(codec);
962#endif
963
Linus Torvalds1da177e2005-04-16 15:20:36 -0700964 list_add_tail(&codec->list, &bus->codec_list);
965 bus->caddr_tbl[codec_addr] = codec;
966
Takashi Iwai0ba21762007-04-16 11:29:14 +0200967 codec->vendor_id = snd_hda_param_read(codec, AC_NODE_ROOT,
968 AC_PAR_VENDOR_ID);
Takashi Iwai111d3af2006-02-16 18:17:58 +0100969 if (codec->vendor_id == -1)
970 /* read again, hopefully the access method was corrected
971 * in the last read...
972 */
973 codec->vendor_id = snd_hda_param_read(codec, AC_NODE_ROOT,
974 AC_PAR_VENDOR_ID);
Takashi Iwai0ba21762007-04-16 11:29:14 +0200975 codec->subsystem_id = snd_hda_param_read(codec, AC_NODE_ROOT,
976 AC_PAR_SUBSYSTEM_ID);
977 codec->revision_id = snd_hda_param_read(codec, AC_NODE_ROOT,
978 AC_PAR_REV_ID);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700979
Sasha Khapyorsky673b6832005-08-11 11:00:16 +0200980 setup_fg_nodes(codec);
Takashi Iwai0ba21762007-04-16 11:29:14 +0200981 if (!codec->afg && !codec->mfg) {
Sasha Khapyorsky673b6832005-08-11 11:00:16 +0200982 snd_printdd("hda_codec: no AFG or MFG node found\n");
Takashi Iwai3be14142009-02-20 14:11:16 +0100983 err = -ENODEV;
984 goto error;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700985 }
986
Takashi Iwai3be14142009-02-20 14:11:16 +0100987 err = read_widget_caps(codec, codec->afg ? codec->afg : codec->mfg);
988 if (err < 0) {
Takashi Iwai54d17402005-11-21 16:33:22 +0100989 snd_printk(KERN_ERR "hda_codec: cannot malloc\n");
Takashi Iwai3be14142009-02-20 14:11:16 +0100990 goto error;
Takashi Iwai54d17402005-11-21 16:33:22 +0100991 }
Takashi Iwai3be14142009-02-20 14:11:16 +0100992 err = read_pin_defaults(codec);
993 if (err < 0)
994 goto error;
Takashi Iwai54d17402005-11-21 16:33:22 +0100995
Takashi Iwai0ba21762007-04-16 11:29:14 +0200996 if (!codec->subsystem_id) {
Takashi Iwai86284e42005-10-11 15:05:54 +0200997 hda_nid_t nid = codec->afg ? codec->afg : codec->mfg;
Takashi Iwai0ba21762007-04-16 11:29:14 +0200998 codec->subsystem_id =
999 snd_hda_codec_read(codec, nid, 0,
1000 AC_VERB_GET_SUBSYSTEM_ID, 0);
Takashi Iwai86284e42005-10-11 15:05:54 +02001001 }
1002
Takashi Iwaibb6ac722009-03-13 09:02:42 +01001003 /* power-up all before initialization */
1004 hda_set_power_state(codec,
1005 codec->afg ? codec->afg : codec->mfg,
1006 AC_PWRST_D0);
1007
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001008 snd_hda_codec_proc_new(codec);
1009
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001010 snd_hda_create_hwdep(codec);
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001011
1012 sprintf(component, "HDA:%08x,%08x,%08x", codec->vendor_id,
1013 codec->subsystem_id, codec->revision_id);
1014 snd_component_add(codec->bus->card, component);
1015
1016 if (codecp)
1017 *codecp = codec;
1018 return 0;
Takashi Iwai3be14142009-02-20 14:11:16 +01001019
1020 error:
1021 snd_hda_codec_free(codec);
1022 return err;
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001023}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001024EXPORT_SYMBOL_HDA(snd_hda_codec_new);
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001025
1026int snd_hda_codec_configure(struct hda_codec *codec)
1027{
1028 int err;
1029
Takashi Iwaid5ad6302007-03-07 15:55:59 +01001030 codec->preset = find_codec_preset(codec);
Takashi Iwai812a2cc2009-05-16 10:00:49 +02001031 if (!codec->vendor_name || !codec->chip_name) {
Takashi Iwaif44ac832008-07-30 15:01:45 +02001032 err = get_codec_name(codec);
1033 if (err < 0)
1034 return err;
1035 }
Takashi Iwai43ea1d42007-04-26 19:12:08 +02001036 /* audio codec should override the mixer name */
Takashi Iwaif44ac832008-07-30 15:01:45 +02001037 if (codec->afg || !*codec->bus->card->mixername)
Takashi Iwai812a2cc2009-05-16 10:00:49 +02001038 snprintf(codec->bus->card->mixername,
1039 sizeof(codec->bus->card->mixername),
1040 "%s %s", codec->vendor_name, codec->chip_name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001041
Takashi Iwai82467612007-07-27 19:15:54 +02001042 if (is_generic_config(codec)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001043 err = snd_hda_parse_generic_codec(codec);
Takashi Iwai82467612007-07-27 19:15:54 +02001044 goto patched;
1045 }
Takashi Iwai82467612007-07-27 19:15:54 +02001046 if (codec->preset && codec->preset->patch) {
1047 err = codec->preset->patch(codec);
1048 goto patched;
1049 }
1050
1051 /* call the default parser */
Takashi Iwai82467612007-07-27 19:15:54 +02001052 err = snd_hda_parse_generic_codec(codec);
Takashi Iwai35a1e0c2007-10-19 08:13:40 +02001053 if (err < 0)
1054 printk(KERN_ERR "hda-codec: No codec parser is available\n");
Takashi Iwai82467612007-07-27 19:15:54 +02001055
1056 patched:
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001057 if (!err && codec->patch_ops.unsol_event)
1058 err = init_unsol_queue(codec->bus);
1059 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001060}
Takashi Iwaia1e21c92009-06-17 09:33:52 +02001061EXPORT_SYMBOL_HDA(snd_hda_codec_configure);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001062
1063/**
1064 * snd_hda_codec_setup_stream - set up the codec for streaming
1065 * @codec: the CODEC to set up
1066 * @nid: the NID to set up
1067 * @stream_tag: stream tag to pass, it's between 0x1 and 0xf.
1068 * @channel_id: channel id to pass, zero based.
1069 * @format: stream format.
1070 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02001071void snd_hda_codec_setup_stream(struct hda_codec *codec, hda_nid_t nid,
1072 u32 stream_tag,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001073 int channel_id, int format)
1074{
Takashi Iwai0ba21762007-04-16 11:29:14 +02001075 if (!nid)
Takashi Iwaid21b37e2005-04-20 13:45:55 +02001076 return;
1077
Takashi Iwai0ba21762007-04-16 11:29:14 +02001078 snd_printdd("hda_codec_setup_stream: "
1079 "NID=0x%x, stream=0x%x, channel=%d, format=0x%x\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07001080 nid, stream_tag, channel_id, format);
1081 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CHANNEL_STREAMID,
1082 (stream_tag << 4) | channel_id);
1083 msleep(1);
1084 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_STREAM_FORMAT, format);
1085}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001086EXPORT_SYMBOL_HDA(snd_hda_codec_setup_stream);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001087
Takashi Iwai888afa12008-03-18 09:57:50 +01001088void snd_hda_codec_cleanup_stream(struct hda_codec *codec, hda_nid_t nid)
1089{
1090 if (!nid)
1091 return;
1092
1093 snd_printdd("hda_codec_cleanup_stream: NID=0x%x\n", nid);
1094 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CHANNEL_STREAMID, 0);
1095#if 0 /* keep the format */
1096 msleep(1);
1097 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_STREAM_FORMAT, 0);
1098#endif
1099}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001100EXPORT_SYMBOL_HDA(snd_hda_codec_cleanup_stream);
Takashi Iwai888afa12008-03-18 09:57:50 +01001101
Linus Torvalds1da177e2005-04-16 15:20:36 -07001102/*
1103 * amp access functions
1104 */
1105
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001106/* FIXME: more better hash key? */
1107#define HDA_HASH_KEY(nid,dir,idx) (u32)((nid) + ((idx) << 16) + ((dir) << 24))
Takashi Iwai1327a322009-03-23 13:07:47 +01001108#define HDA_HASH_PINCAP_KEY(nid) (u32)((nid) + (0x02 << 24))
Takashi Iwai92c7c8a2009-03-24 07:32:14 +01001109#define HDA_HASH_PARPCM_KEY(nid) (u32)((nid) + (0x03 << 24))
1110#define HDA_HASH_PARSTR_KEY(nid) (u32)((nid) + (0x04 << 24))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001111#define INFO_AMP_CAPS (1<<0)
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001112#define INFO_AMP_VOL(ch) (1 << (1 + (ch)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001113
1114/* initialize the hash table */
Takashi Iwai1289e9e2008-11-27 15:47:11 +01001115static void /*__devinit*/ init_hda_cache(struct hda_cache_rec *cache,
Takashi Iwai01751f52007-08-10 16:59:39 +02001116 unsigned int record_size)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001117{
Takashi Iwai01751f52007-08-10 16:59:39 +02001118 memset(cache, 0, sizeof(*cache));
1119 memset(cache->hash, 0xff, sizeof(cache->hash));
Takashi Iwai603c4012008-07-30 15:01:44 +02001120 snd_array_init(&cache->buf, record_size, 64);
Takashi Iwai01751f52007-08-10 16:59:39 +02001121}
1122
Takashi Iwai1fcaee62007-08-23 00:01:09 +02001123static void free_hda_cache(struct hda_cache_rec *cache)
Takashi Iwai01751f52007-08-10 16:59:39 +02001124{
Takashi Iwai603c4012008-07-30 15:01:44 +02001125 snd_array_free(&cache->buf);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001126}
1127
1128/* query the hash. allocate an entry if not found. */
Takashi Iwai01751f52007-08-10 16:59:39 +02001129static struct hda_cache_head *get_alloc_hash(struct hda_cache_rec *cache,
1130 u32 key)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001131{
Takashi Iwai01751f52007-08-10 16:59:39 +02001132 u16 idx = key % (u16)ARRAY_SIZE(cache->hash);
1133 u16 cur = cache->hash[idx];
1134 struct hda_cache_head *info;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001135
1136 while (cur != 0xffff) {
Takashi Iwaif43aa022008-11-10 16:24:26 +01001137 info = snd_array_elem(&cache->buf, cur);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001138 if (info->key == key)
1139 return info;
1140 cur = info->next;
1141 }
1142
1143 /* add a new hash entry */
Takashi Iwai603c4012008-07-30 15:01:44 +02001144 info = snd_array_new(&cache->buf);
Takashi Iwaic2174292008-11-07 00:23:30 +01001145 if (!info)
1146 return NULL;
Takashi Iwaif43aa022008-11-10 16:24:26 +01001147 cur = snd_array_index(&cache->buf, info);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001148 info->key = key;
Takashi Iwai01751f52007-08-10 16:59:39 +02001149 info->val = 0;
1150 info->next = cache->hash[idx];
1151 cache->hash[idx] = cur;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001152
1153 return info;
1154}
1155
Takashi Iwai01751f52007-08-10 16:59:39 +02001156/* query and allocate an amp hash entry */
1157static inline struct hda_amp_info *
1158get_alloc_amp_hash(struct hda_codec *codec, u32 key)
1159{
1160 return (struct hda_amp_info *)get_alloc_hash(&codec->amp_cache, key);
1161}
1162
Linus Torvalds1da177e2005-04-16 15:20:36 -07001163/*
1164 * query AMP capabilities for the given widget and direction
1165 */
Matthew Ranostay09a99952008-01-24 11:49:21 +01001166u32 query_amp_caps(struct hda_codec *codec, hda_nid_t nid, int direction)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001167{
Takashi Iwai0ba21762007-04-16 11:29:14 +02001168 struct hda_amp_info *info;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001169
Takashi Iwai0ba21762007-04-16 11:29:14 +02001170 info = get_alloc_amp_hash(codec, HDA_HASH_KEY(nid, direction, 0));
1171 if (!info)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001172 return 0;
Takashi Iwai01751f52007-08-10 16:59:39 +02001173 if (!(info->head.val & INFO_AMP_CAPS)) {
Takashi Iwai0ba21762007-04-16 11:29:14 +02001174 if (!(get_wcaps(codec, nid) & AC_WCAP_AMP_OVRD))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001175 nid = codec->afg;
Takashi Iwai0ba21762007-04-16 11:29:14 +02001176 info->amp_caps = snd_hda_param_read(codec, nid,
1177 direction == HDA_OUTPUT ?
1178 AC_PAR_AMP_OUT_CAP :
1179 AC_PAR_AMP_IN_CAP);
Takashi Iwaib75e53f2007-05-10 16:56:09 +02001180 if (info->amp_caps)
Takashi Iwai01751f52007-08-10 16:59:39 +02001181 info->head.val |= INFO_AMP_CAPS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001182 }
1183 return info->amp_caps;
1184}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001185EXPORT_SYMBOL_HDA(query_amp_caps);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001186
Takashi Iwai897cc182007-05-29 19:01:37 +02001187int snd_hda_override_amp_caps(struct hda_codec *codec, hda_nid_t nid, int dir,
1188 unsigned int caps)
1189{
1190 struct hda_amp_info *info;
1191
1192 info = get_alloc_amp_hash(codec, HDA_HASH_KEY(nid, dir, 0));
1193 if (!info)
1194 return -EINVAL;
1195 info->amp_caps = caps;
Takashi Iwai01751f52007-08-10 16:59:39 +02001196 info->head.val |= INFO_AMP_CAPS;
Takashi Iwai897cc182007-05-29 19:01:37 +02001197 return 0;
1198}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001199EXPORT_SYMBOL_HDA(snd_hda_override_amp_caps);
Takashi Iwai897cc182007-05-29 19:01:37 +02001200
Takashi Iwai92c7c8a2009-03-24 07:32:14 +01001201static unsigned int
1202query_caps_hash(struct hda_codec *codec, hda_nid_t nid, u32 key,
1203 unsigned int (*func)(struct hda_codec *, hda_nid_t))
Takashi Iwai1327a322009-03-23 13:07:47 +01001204{
1205 struct hda_amp_info *info;
1206
Takashi Iwai92c7c8a2009-03-24 07:32:14 +01001207 info = get_alloc_amp_hash(codec, key);
Takashi Iwai1327a322009-03-23 13:07:47 +01001208 if (!info)
1209 return 0;
1210 if (!info->head.val) {
Takashi Iwai1327a322009-03-23 13:07:47 +01001211 info->head.val |= INFO_AMP_CAPS;
Takashi Iwai92c7c8a2009-03-24 07:32:14 +01001212 info->amp_caps = func(codec, nid);
Takashi Iwai1327a322009-03-23 13:07:47 +01001213 }
1214 return info->amp_caps;
1215}
Takashi Iwai92c7c8a2009-03-24 07:32:14 +01001216
1217static unsigned int read_pin_cap(struct hda_codec *codec, hda_nid_t nid)
1218{
1219 return snd_hda_param_read(codec, nid, AC_PAR_PIN_CAP);
1220}
1221
1222u32 snd_hda_query_pin_caps(struct hda_codec *codec, hda_nid_t nid)
1223{
1224 return query_caps_hash(codec, nid, HDA_HASH_PINCAP_KEY(nid),
1225 read_pin_cap);
1226}
Takashi Iwai1327a322009-03-23 13:07:47 +01001227EXPORT_SYMBOL_HDA(snd_hda_query_pin_caps);
1228
Linus Torvalds1da177e2005-04-16 15:20:36 -07001229/*
1230 * read the current volume to info
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001231 * if the cache exists, read the cache value.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001232 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02001233static unsigned int get_vol_mute(struct hda_codec *codec,
1234 struct hda_amp_info *info, hda_nid_t nid,
1235 int ch, int direction, int index)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001236{
1237 u32 val, parm;
1238
Takashi Iwai01751f52007-08-10 16:59:39 +02001239 if (info->head.val & INFO_AMP_VOL(ch))
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001240 return info->vol[ch];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001241
1242 parm = ch ? AC_AMP_GET_RIGHT : AC_AMP_GET_LEFT;
1243 parm |= direction == HDA_OUTPUT ? AC_AMP_GET_OUTPUT : AC_AMP_GET_INPUT;
1244 parm |= index;
Takashi Iwai0ba21762007-04-16 11:29:14 +02001245 val = snd_hda_codec_read(codec, nid, 0,
1246 AC_VERB_GET_AMP_GAIN_MUTE, parm);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001247 info->vol[ch] = val & 0xff;
Takashi Iwai01751f52007-08-10 16:59:39 +02001248 info->head.val |= INFO_AMP_VOL(ch);
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001249 return info->vol[ch];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001250}
1251
1252/*
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001253 * write the current volume in info to the h/w and update the cache
Linus Torvalds1da177e2005-04-16 15:20:36 -07001254 */
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001255static void put_vol_mute(struct hda_codec *codec, struct hda_amp_info *info,
Takashi Iwai0ba21762007-04-16 11:29:14 +02001256 hda_nid_t nid, int ch, int direction, int index,
1257 int val)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001258{
1259 u32 parm;
1260
1261 parm = ch ? AC_AMP_SET_RIGHT : AC_AMP_SET_LEFT;
1262 parm |= direction == HDA_OUTPUT ? AC_AMP_SET_OUTPUT : AC_AMP_SET_INPUT;
1263 parm |= index << AC_AMP_SET_INDEX_SHIFT;
1264 parm |= val;
1265 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, parm);
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001266 info->vol[ch] = val;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001267}
1268
1269/*
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001270 * read AMP value. The volume is between 0 to 0x7f, 0x80 = mute bit.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001271 */
Takashi Iwai834be882006-03-01 14:16:17 +01001272int snd_hda_codec_amp_read(struct hda_codec *codec, hda_nid_t nid, int ch,
1273 int direction, int index)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001274{
Takashi Iwai0ba21762007-04-16 11:29:14 +02001275 struct hda_amp_info *info;
1276 info = get_alloc_amp_hash(codec, HDA_HASH_KEY(nid, direction, index));
1277 if (!info)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001278 return 0;
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001279 return get_vol_mute(codec, info, nid, ch, direction, index);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001280}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001281EXPORT_SYMBOL_HDA(snd_hda_codec_amp_read);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001282
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001283/*
1284 * update the AMP value, mask = bit mask to set, val = the value
1285 */
Takashi Iwai834be882006-03-01 14:16:17 +01001286int snd_hda_codec_amp_update(struct hda_codec *codec, hda_nid_t nid, int ch,
1287 int direction, int idx, int mask, int val)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001288{
Takashi Iwai0ba21762007-04-16 11:29:14 +02001289 struct hda_amp_info *info;
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001290
Takashi Iwai0ba21762007-04-16 11:29:14 +02001291 info = get_alloc_amp_hash(codec, HDA_HASH_KEY(nid, direction, idx));
1292 if (!info)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001293 return 0;
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001294 val &= mask;
1295 val |= get_vol_mute(codec, info, nid, ch, direction, idx) & ~mask;
Takashi Iwai82beb8f2007-08-10 17:09:26 +02001296 if (info->vol[ch] == val)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001297 return 0;
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001298 put_vol_mute(codec, info, nid, ch, direction, idx, val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001299 return 1;
1300}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001301EXPORT_SYMBOL_HDA(snd_hda_codec_amp_update);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001302
Takashi Iwai47fd8302007-08-10 17:11:07 +02001303/*
1304 * update the AMP stereo with the same mask and value
1305 */
1306int snd_hda_codec_amp_stereo(struct hda_codec *codec, hda_nid_t nid,
1307 int direction, int idx, int mask, int val)
1308{
1309 int ch, ret = 0;
1310 for (ch = 0; ch < 2; ch++)
1311 ret |= snd_hda_codec_amp_update(codec, nid, ch, direction,
1312 idx, mask, val);
1313 return ret;
1314}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001315EXPORT_SYMBOL_HDA(snd_hda_codec_amp_stereo);
Takashi Iwai47fd8302007-08-10 17:11:07 +02001316
Takashi Iwaicb53c622007-08-10 17:21:45 +02001317#ifdef SND_HDA_NEEDS_RESUME
Takashi Iwaib3ac5632007-08-10 17:03:40 +02001318/* resume the all amp commands from the cache */
1319void snd_hda_codec_resume_amp(struct hda_codec *codec)
1320{
Takashi Iwai603c4012008-07-30 15:01:44 +02001321 struct hda_amp_info *buffer = codec->amp_cache.buf.list;
Takashi Iwaib3ac5632007-08-10 17:03:40 +02001322 int i;
1323
Takashi Iwai603c4012008-07-30 15:01:44 +02001324 for (i = 0; i < codec->amp_cache.buf.used; i++, buffer++) {
Takashi Iwaib3ac5632007-08-10 17:03:40 +02001325 u32 key = buffer->head.key;
1326 hda_nid_t nid;
1327 unsigned int idx, dir, ch;
1328 if (!key)
1329 continue;
1330 nid = key & 0xff;
1331 idx = (key >> 16) & 0xff;
1332 dir = (key >> 24) & 0xff;
1333 for (ch = 0; ch < 2; ch++) {
1334 if (!(buffer->head.val & INFO_AMP_VOL(ch)))
1335 continue;
1336 put_vol_mute(codec, buffer, nid, ch, dir, idx,
1337 buffer->vol[ch]);
1338 }
1339 }
1340}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001341EXPORT_SYMBOL_HDA(snd_hda_codec_resume_amp);
Takashi Iwaicb53c622007-08-10 17:21:45 +02001342#endif /* SND_HDA_NEEDS_RESUME */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001343
Linus Torvalds1da177e2005-04-16 15:20:36 -07001344/* volume */
Takashi Iwai0ba21762007-04-16 11:29:14 +02001345int snd_hda_mixer_amp_volume_info(struct snd_kcontrol *kcontrol,
1346 struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001347{
1348 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1349 u16 nid = get_amp_nid(kcontrol);
1350 u8 chs = get_amp_channels(kcontrol);
1351 int dir = get_amp_direction(kcontrol);
Takashi Iwai29fdbec2009-01-20 13:07:55 +01001352 unsigned int ofs = get_amp_offset(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001353 u32 caps;
1354
1355 caps = query_amp_caps(codec, nid, dir);
Takashi Iwai0ba21762007-04-16 11:29:14 +02001356 /* num steps */
1357 caps = (caps & AC_AMPCAP_NUM_STEPS) >> AC_AMPCAP_NUM_STEPS_SHIFT;
1358 if (!caps) {
1359 printk(KERN_WARNING "hda_codec: "
Takashi Iwai9c8f2ab2008-01-11 16:12:23 +01001360 "num_steps = 0 for NID=0x%x (ctl = %s)\n", nid,
1361 kcontrol->id.name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001362 return -EINVAL;
1363 }
Takashi Iwai29fdbec2009-01-20 13:07:55 +01001364 if (ofs < caps)
1365 caps -= ofs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001366 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
1367 uinfo->count = chs == 3 ? 2 : 1;
1368 uinfo->value.integer.min = 0;
1369 uinfo->value.integer.max = caps;
1370 return 0;
1371}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001372EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_volume_info);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001373
Takashi Iwai29fdbec2009-01-20 13:07:55 +01001374
1375static inline unsigned int
1376read_amp_value(struct hda_codec *codec, hda_nid_t nid,
1377 int ch, int dir, int idx, unsigned int ofs)
1378{
1379 unsigned int val;
1380 val = snd_hda_codec_amp_read(codec, nid, ch, dir, idx);
1381 val &= HDA_AMP_VOLMASK;
1382 if (val >= ofs)
1383 val -= ofs;
1384 else
1385 val = 0;
1386 return val;
1387}
1388
1389static inline int
1390update_amp_value(struct hda_codec *codec, hda_nid_t nid,
1391 int ch, int dir, int idx, unsigned int ofs,
1392 unsigned int val)
1393{
1394 if (val > 0)
1395 val += ofs;
1396 return snd_hda_codec_amp_update(codec, nid, ch, dir, idx,
1397 HDA_AMP_VOLMASK, val);
1398}
1399
Takashi Iwai0ba21762007-04-16 11:29:14 +02001400int snd_hda_mixer_amp_volume_get(struct snd_kcontrol *kcontrol,
1401 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001402{
1403 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1404 hda_nid_t nid = get_amp_nid(kcontrol);
1405 int chs = get_amp_channels(kcontrol);
1406 int dir = get_amp_direction(kcontrol);
1407 int idx = get_amp_index(kcontrol);
Takashi Iwai29fdbec2009-01-20 13:07:55 +01001408 unsigned int ofs = get_amp_offset(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001409 long *valp = ucontrol->value.integer.value;
1410
1411 if (chs & 1)
Takashi Iwai29fdbec2009-01-20 13:07:55 +01001412 *valp++ = read_amp_value(codec, nid, 0, dir, idx, ofs);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001413 if (chs & 2)
Takashi Iwai29fdbec2009-01-20 13:07:55 +01001414 *valp = read_amp_value(codec, nid, 1, dir, idx, ofs);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001415 return 0;
1416}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001417EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_volume_get);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001418
Takashi Iwai0ba21762007-04-16 11:29:14 +02001419int snd_hda_mixer_amp_volume_put(struct snd_kcontrol *kcontrol,
1420 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001421{
1422 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1423 hda_nid_t nid = get_amp_nid(kcontrol);
1424 int chs = get_amp_channels(kcontrol);
1425 int dir = get_amp_direction(kcontrol);
1426 int idx = get_amp_index(kcontrol);
Takashi Iwai29fdbec2009-01-20 13:07:55 +01001427 unsigned int ofs = get_amp_offset(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001428 long *valp = ucontrol->value.integer.value;
1429 int change = 0;
1430
Takashi Iwaicb53c622007-08-10 17:21:45 +02001431 snd_hda_power_up(codec);
Nicolas Grazianob9f5a892005-07-29 12:17:20 +02001432 if (chs & 1) {
Takashi Iwai29fdbec2009-01-20 13:07:55 +01001433 change = update_amp_value(codec, nid, 0, dir, idx, ofs, *valp);
Nicolas Grazianob9f5a892005-07-29 12:17:20 +02001434 valp++;
1435 }
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001436 if (chs & 2)
Takashi Iwai29fdbec2009-01-20 13:07:55 +01001437 change |= update_amp_value(codec, nid, 1, dir, idx, ofs, *valp);
Takashi Iwaicb53c622007-08-10 17:21:45 +02001438 snd_hda_power_down(codec);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001439 return change;
1440}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001441EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_volume_put);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001442
Jaroslav Kysela302e9c52006-07-05 17:39:49 +02001443int snd_hda_mixer_amp_tlv(struct snd_kcontrol *kcontrol, int op_flag,
1444 unsigned int size, unsigned int __user *_tlv)
1445{
1446 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1447 hda_nid_t nid = get_amp_nid(kcontrol);
1448 int dir = get_amp_direction(kcontrol);
Takashi Iwai29fdbec2009-01-20 13:07:55 +01001449 unsigned int ofs = get_amp_offset(kcontrol);
Jaroslav Kysela302e9c52006-07-05 17:39:49 +02001450 u32 caps, val1, val2;
1451
1452 if (size < 4 * sizeof(unsigned int))
1453 return -ENOMEM;
1454 caps = query_amp_caps(codec, nid, dir);
Takashi Iwai0ba21762007-04-16 11:29:14 +02001455 val2 = (caps & AC_AMPCAP_STEP_SIZE) >> AC_AMPCAP_STEP_SIZE_SHIFT;
1456 val2 = (val2 + 1) * 25;
Jaroslav Kysela302e9c52006-07-05 17:39:49 +02001457 val1 = -((caps & AC_AMPCAP_OFFSET) >> AC_AMPCAP_OFFSET_SHIFT);
Takashi Iwai29fdbec2009-01-20 13:07:55 +01001458 val1 += ofs;
Jaroslav Kysela302e9c52006-07-05 17:39:49 +02001459 val1 = ((int)val1) * ((int)val2);
Jaroslav Kysela302e9c52006-07-05 17:39:49 +02001460 if (put_user(SNDRV_CTL_TLVT_DB_SCALE, _tlv))
1461 return -EFAULT;
1462 if (put_user(2 * sizeof(unsigned int), _tlv + 1))
1463 return -EFAULT;
1464 if (put_user(val1, _tlv + 2))
1465 return -EFAULT;
1466 if (put_user(val2, _tlv + 3))
1467 return -EFAULT;
1468 return 0;
1469}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001470EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_tlv);
Jaroslav Kysela302e9c52006-07-05 17:39:49 +02001471
Takashi Iwai2134ea42008-01-10 16:53:55 +01001472/*
1473 * set (static) TLV for virtual master volume; recalculated as max 0dB
1474 */
1475void snd_hda_set_vmaster_tlv(struct hda_codec *codec, hda_nid_t nid, int dir,
1476 unsigned int *tlv)
1477{
1478 u32 caps;
1479 int nums, step;
1480
1481 caps = query_amp_caps(codec, nid, dir);
1482 nums = (caps & AC_AMPCAP_NUM_STEPS) >> AC_AMPCAP_NUM_STEPS_SHIFT;
1483 step = (caps & AC_AMPCAP_STEP_SIZE) >> AC_AMPCAP_STEP_SIZE_SHIFT;
1484 step = (step + 1) * 25;
1485 tlv[0] = SNDRV_CTL_TLVT_DB_SCALE;
1486 tlv[1] = 2 * sizeof(unsigned int);
1487 tlv[2] = -nums * step;
1488 tlv[3] = step;
1489}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001490EXPORT_SYMBOL_HDA(snd_hda_set_vmaster_tlv);
Takashi Iwai2134ea42008-01-10 16:53:55 +01001491
1492/* find a mixer control element with the given name */
Takashi Iwai09f99702008-02-04 12:31:13 +01001493static struct snd_kcontrol *
1494_snd_hda_find_mixer_ctl(struct hda_codec *codec,
1495 const char *name, int idx)
Takashi Iwai2134ea42008-01-10 16:53:55 +01001496{
1497 struct snd_ctl_elem_id id;
1498 memset(&id, 0, sizeof(id));
1499 id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
Takashi Iwai09f99702008-02-04 12:31:13 +01001500 id.index = idx;
Takashi Iwai18cb7102009-04-16 10:22:24 +02001501 if (snd_BUG_ON(strlen(name) >= sizeof(id.name)))
1502 return NULL;
Takashi Iwai2134ea42008-01-10 16:53:55 +01001503 strcpy(id.name, name);
1504 return snd_ctl_find_id(codec->bus->card, &id);
1505}
1506
Takashi Iwai09f99702008-02-04 12:31:13 +01001507struct snd_kcontrol *snd_hda_find_mixer_ctl(struct hda_codec *codec,
1508 const char *name)
1509{
1510 return _snd_hda_find_mixer_ctl(codec, name, 0);
1511}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001512EXPORT_SYMBOL_HDA(snd_hda_find_mixer_ctl);
Takashi Iwai09f99702008-02-04 12:31:13 +01001513
Takashi Iwaid13bd412008-07-30 15:01:45 +02001514/* Add a control element and assign to the codec */
1515int snd_hda_ctl_add(struct hda_codec *codec, struct snd_kcontrol *kctl)
1516{
1517 int err;
1518 struct snd_kcontrol **knewp;
1519
1520 err = snd_ctl_add(codec->bus->card, kctl);
1521 if (err < 0)
1522 return err;
1523 knewp = snd_array_new(&codec->mixers);
1524 if (!knewp)
1525 return -ENOMEM;
1526 *knewp = kctl;
1527 return 0;
1528}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001529EXPORT_SYMBOL_HDA(snd_hda_ctl_add);
Takashi Iwaid13bd412008-07-30 15:01:45 +02001530
1531/* Clear all controls assigned to the given codec */
1532void snd_hda_ctls_clear(struct hda_codec *codec)
1533{
1534 int i;
1535 struct snd_kcontrol **kctls = codec->mixers.list;
1536 for (i = 0; i < codec->mixers.used; i++)
1537 snd_ctl_remove(codec->bus->card, kctls[i]);
1538 snd_array_free(&codec->mixers);
1539}
1540
Takashi Iwaia65d6292009-02-23 16:57:04 +01001541/* pseudo device locking
1542 * toggle card->shutdown to allow/disallow the device access (as a hack)
1543 */
1544static int hda_lock_devices(struct snd_card *card)
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001545{
Takashi Iwaia65d6292009-02-23 16:57:04 +01001546 spin_lock(&card->files_lock);
1547 if (card->shutdown) {
1548 spin_unlock(&card->files_lock);
1549 return -EINVAL;
1550 }
1551 card->shutdown = 1;
1552 spin_unlock(&card->files_lock);
1553 return 0;
1554}
1555
1556static void hda_unlock_devices(struct snd_card *card)
1557{
1558 spin_lock(&card->files_lock);
1559 card->shutdown = 0;
1560 spin_unlock(&card->files_lock);
1561}
1562
1563int snd_hda_codec_reset(struct hda_codec *codec)
1564{
1565 struct snd_card *card = codec->bus->card;
1566 int i, pcm;
1567
1568 if (hda_lock_devices(card) < 0)
1569 return -EBUSY;
1570 /* check whether the codec isn't used by any mixer or PCM streams */
1571 if (!list_empty(&card->ctl_files)) {
1572 hda_unlock_devices(card);
1573 return -EBUSY;
1574 }
1575 for (pcm = 0; pcm < codec->num_pcms; pcm++) {
1576 struct hda_pcm *cpcm = &codec->pcm_info[pcm];
1577 if (!cpcm->pcm)
1578 continue;
1579 if (cpcm->pcm->streams[0].substream_opened ||
1580 cpcm->pcm->streams[1].substream_opened) {
1581 hda_unlock_devices(card);
1582 return -EBUSY;
1583 }
1584 }
1585
1586 /* OK, let it free */
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001587
1588#ifdef CONFIG_SND_HDA_POWER_SAVE
1589 cancel_delayed_work(&codec->power_work);
Takashi Iwai6acaed32009-01-12 10:09:24 +01001590 flush_workqueue(codec->bus->workq);
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001591#endif
1592 snd_hda_ctls_clear(codec);
1593 /* relase PCMs */
1594 for (i = 0; i < codec->num_pcms; i++) {
Takashi Iwai529bd6c2008-11-27 14:17:01 +01001595 if (codec->pcm_info[i].pcm) {
Takashi Iwaia65d6292009-02-23 16:57:04 +01001596 snd_device_free(card, codec->pcm_info[i].pcm);
Takashi Iwai529bd6c2008-11-27 14:17:01 +01001597 clear_bit(codec->pcm_info[i].device,
1598 codec->bus->pcm_dev_bits);
1599 }
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001600 }
1601 if (codec->patch_ops.free)
1602 codec->patch_ops.free(codec);
Takashi Iwai56d17712008-11-28 14:36:23 +01001603 codec->proc_widget_hook = NULL;
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001604 codec->spec = NULL;
1605 free_hda_cache(&codec->amp_cache);
1606 free_hda_cache(&codec->cmd_cache);
Takashi Iwai827057f2008-12-19 10:12:02 +01001607 init_hda_cache(&codec->amp_cache, sizeof(struct hda_amp_info));
1608 init_hda_cache(&codec->cmd_cache, sizeof(struct hda_cache_head));
Takashi Iwai346ff702009-02-23 09:42:57 +01001609 /* free only driver_pins so that init_pins + user_pins are restored */
1610 snd_array_free(&codec->driver_pins);
Takashi Iwai3be14142009-02-20 14:11:16 +01001611 restore_pincfgs(codec);
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001612 codec->num_pcms = 0;
1613 codec->pcm_info = NULL;
1614 codec->preset = NULL;
Takashi Iwaid1f1af22009-03-02 10:35:29 +01001615 memset(&codec->patch_ops, 0, sizeof(codec->patch_ops));
1616 codec->slave_dig_outs = NULL;
1617 codec->spdif_status_reset = 0;
Takashi Iwai1289e9e2008-11-27 15:47:11 +01001618 module_put(codec->owner);
1619 codec->owner = NULL;
Takashi Iwaia65d6292009-02-23 16:57:04 +01001620
1621 /* allow device access again */
1622 hda_unlock_devices(card);
1623 return 0;
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001624}
1625
Takashi Iwai2134ea42008-01-10 16:53:55 +01001626/* create a virtual master control and add slaves */
1627int snd_hda_add_vmaster(struct hda_codec *codec, char *name,
1628 unsigned int *tlv, const char **slaves)
1629{
1630 struct snd_kcontrol *kctl;
1631 const char **s;
1632 int err;
1633
Takashi Iwai2f085542008-02-22 18:43:50 +01001634 for (s = slaves; *s && !snd_hda_find_mixer_ctl(codec, *s); s++)
1635 ;
1636 if (!*s) {
1637 snd_printdd("No slave found for %s\n", name);
1638 return 0;
1639 }
Takashi Iwai2134ea42008-01-10 16:53:55 +01001640 kctl = snd_ctl_make_virtual_master(name, tlv);
1641 if (!kctl)
1642 return -ENOMEM;
Takashi Iwaid13bd412008-07-30 15:01:45 +02001643 err = snd_hda_ctl_add(codec, kctl);
Takashi Iwai2134ea42008-01-10 16:53:55 +01001644 if (err < 0)
1645 return err;
1646
1647 for (s = slaves; *s; s++) {
1648 struct snd_kcontrol *sctl;
Takashi Iwai7a411ee2009-03-06 10:08:14 +01001649 int i = 0;
1650 for (;;) {
1651 sctl = _snd_hda_find_mixer_ctl(codec, *s, i);
1652 if (!sctl) {
1653 if (!i)
1654 snd_printdd("Cannot find slave %s, "
1655 "skipped\n", *s);
1656 break;
1657 }
1658 err = snd_ctl_add_slave(kctl, sctl);
1659 if (err < 0)
1660 return err;
1661 i++;
Takashi Iwai2134ea42008-01-10 16:53:55 +01001662 }
Takashi Iwai2134ea42008-01-10 16:53:55 +01001663 }
1664 return 0;
1665}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001666EXPORT_SYMBOL_HDA(snd_hda_add_vmaster);
Takashi Iwai2134ea42008-01-10 16:53:55 +01001667
Linus Torvalds1da177e2005-04-16 15:20:36 -07001668/* switch */
Takashi Iwai0ba21762007-04-16 11:29:14 +02001669int snd_hda_mixer_amp_switch_info(struct snd_kcontrol *kcontrol,
1670 struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001671{
1672 int chs = get_amp_channels(kcontrol);
1673
1674 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
1675 uinfo->count = chs == 3 ? 2 : 1;
1676 uinfo->value.integer.min = 0;
1677 uinfo->value.integer.max = 1;
1678 return 0;
1679}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001680EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_switch_info);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001681
Takashi Iwai0ba21762007-04-16 11:29:14 +02001682int snd_hda_mixer_amp_switch_get(struct snd_kcontrol *kcontrol,
1683 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001684{
1685 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1686 hda_nid_t nid = get_amp_nid(kcontrol);
1687 int chs = get_amp_channels(kcontrol);
1688 int dir = get_amp_direction(kcontrol);
1689 int idx = get_amp_index(kcontrol);
1690 long *valp = ucontrol->value.integer.value;
1691
1692 if (chs & 1)
Takashi Iwai0ba21762007-04-16 11:29:14 +02001693 *valp++ = (snd_hda_codec_amp_read(codec, nid, 0, dir, idx) &
Takashi Iwai47fd8302007-08-10 17:11:07 +02001694 HDA_AMP_MUTE) ? 0 : 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001695 if (chs & 2)
Takashi Iwai0ba21762007-04-16 11:29:14 +02001696 *valp = (snd_hda_codec_amp_read(codec, nid, 1, dir, idx) &
Takashi Iwai47fd8302007-08-10 17:11:07 +02001697 HDA_AMP_MUTE) ? 0 : 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001698 return 0;
1699}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001700EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_switch_get);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001701
Takashi Iwai0ba21762007-04-16 11:29:14 +02001702int snd_hda_mixer_amp_switch_put(struct snd_kcontrol *kcontrol,
1703 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001704{
1705 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1706 hda_nid_t nid = get_amp_nid(kcontrol);
1707 int chs = get_amp_channels(kcontrol);
1708 int dir = get_amp_direction(kcontrol);
1709 int idx = get_amp_index(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001710 long *valp = ucontrol->value.integer.value;
1711 int change = 0;
1712
Takashi Iwaicb53c622007-08-10 17:21:45 +02001713 snd_hda_power_up(codec);
Nicolas Grazianob9f5a892005-07-29 12:17:20 +02001714 if (chs & 1) {
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001715 change = snd_hda_codec_amp_update(codec, nid, 0, dir, idx,
Takashi Iwai47fd8302007-08-10 17:11:07 +02001716 HDA_AMP_MUTE,
1717 *valp ? 0 : HDA_AMP_MUTE);
Nicolas Grazianob9f5a892005-07-29 12:17:20 +02001718 valp++;
1719 }
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001720 if (chs & 2)
1721 change |= snd_hda_codec_amp_update(codec, nid, 1, dir, idx,
Takashi Iwai47fd8302007-08-10 17:11:07 +02001722 HDA_AMP_MUTE,
1723 *valp ? 0 : HDA_AMP_MUTE);
Takashi Iwaicb53c622007-08-10 17:21:45 +02001724#ifdef CONFIG_SND_HDA_POWER_SAVE
1725 if (codec->patch_ops.check_power_status)
1726 codec->patch_ops.check_power_status(codec, nid);
1727#endif
1728 snd_hda_power_down(codec);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001729 return change;
1730}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001731EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_switch_put);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001732
1733/*
Takashi Iwai985be542005-11-02 18:26:49 +01001734 * bound volume controls
1735 *
1736 * bind multiple volumes (# indices, from 0)
1737 */
1738
1739#define AMP_VAL_IDX_SHIFT 19
1740#define AMP_VAL_IDX_MASK (0x0f<<19)
1741
Takashi Iwai0ba21762007-04-16 11:29:14 +02001742int snd_hda_mixer_bind_switch_get(struct snd_kcontrol *kcontrol,
1743 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai985be542005-11-02 18:26:49 +01001744{
1745 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1746 unsigned long pval;
1747 int err;
1748
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001749 mutex_lock(&codec->control_mutex);
Takashi Iwai985be542005-11-02 18:26:49 +01001750 pval = kcontrol->private_value;
1751 kcontrol->private_value = pval & ~AMP_VAL_IDX_MASK; /* index 0 */
1752 err = snd_hda_mixer_amp_switch_get(kcontrol, ucontrol);
1753 kcontrol->private_value = pval;
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001754 mutex_unlock(&codec->control_mutex);
Takashi Iwai985be542005-11-02 18:26:49 +01001755 return err;
1756}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001757EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_switch_get);
Takashi Iwai985be542005-11-02 18:26:49 +01001758
Takashi Iwai0ba21762007-04-16 11:29:14 +02001759int snd_hda_mixer_bind_switch_put(struct snd_kcontrol *kcontrol,
1760 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai985be542005-11-02 18:26:49 +01001761{
1762 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1763 unsigned long pval;
1764 int i, indices, err = 0, change = 0;
1765
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001766 mutex_lock(&codec->control_mutex);
Takashi Iwai985be542005-11-02 18:26:49 +01001767 pval = kcontrol->private_value;
1768 indices = (pval & AMP_VAL_IDX_MASK) >> AMP_VAL_IDX_SHIFT;
1769 for (i = 0; i < indices; i++) {
Takashi Iwai0ba21762007-04-16 11:29:14 +02001770 kcontrol->private_value = (pval & ~AMP_VAL_IDX_MASK) |
1771 (i << AMP_VAL_IDX_SHIFT);
Takashi Iwai985be542005-11-02 18:26:49 +01001772 err = snd_hda_mixer_amp_switch_put(kcontrol, ucontrol);
1773 if (err < 0)
1774 break;
1775 change |= err;
1776 }
1777 kcontrol->private_value = pval;
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001778 mutex_unlock(&codec->control_mutex);
Takashi Iwai985be542005-11-02 18:26:49 +01001779 return err < 0 ? err : change;
1780}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001781EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_switch_put);
Takashi Iwai985be542005-11-02 18:26:49 +01001782
1783/*
Takashi Iwai532d5382007-07-27 19:02:40 +02001784 * generic bound volume/swtich controls
1785 */
1786int snd_hda_mixer_bind_ctls_info(struct snd_kcontrol *kcontrol,
1787 struct snd_ctl_elem_info *uinfo)
1788{
1789 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1790 struct hda_bind_ctls *c;
1791 int err;
1792
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001793 mutex_lock(&codec->control_mutex);
Serge A. Suchkov14c65f92008-02-22 18:43:16 +01001794 c = (struct hda_bind_ctls *)kcontrol->private_value;
Takashi Iwai532d5382007-07-27 19:02:40 +02001795 kcontrol->private_value = *c->values;
1796 err = c->ops->info(kcontrol, uinfo);
1797 kcontrol->private_value = (long)c;
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001798 mutex_unlock(&codec->control_mutex);
Takashi Iwai532d5382007-07-27 19:02:40 +02001799 return err;
1800}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001801EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_ctls_info);
Takashi Iwai532d5382007-07-27 19:02:40 +02001802
1803int snd_hda_mixer_bind_ctls_get(struct snd_kcontrol *kcontrol,
1804 struct snd_ctl_elem_value *ucontrol)
1805{
1806 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1807 struct hda_bind_ctls *c;
1808 int err;
1809
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001810 mutex_lock(&codec->control_mutex);
Serge A. Suchkov14c65f92008-02-22 18:43:16 +01001811 c = (struct hda_bind_ctls *)kcontrol->private_value;
Takashi Iwai532d5382007-07-27 19:02:40 +02001812 kcontrol->private_value = *c->values;
1813 err = c->ops->get(kcontrol, ucontrol);
1814 kcontrol->private_value = (long)c;
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001815 mutex_unlock(&codec->control_mutex);
Takashi Iwai532d5382007-07-27 19:02:40 +02001816 return err;
1817}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001818EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_ctls_get);
Takashi Iwai532d5382007-07-27 19:02:40 +02001819
1820int snd_hda_mixer_bind_ctls_put(struct snd_kcontrol *kcontrol,
1821 struct snd_ctl_elem_value *ucontrol)
1822{
1823 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1824 struct hda_bind_ctls *c;
1825 unsigned long *vals;
1826 int err = 0, change = 0;
1827
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001828 mutex_lock(&codec->control_mutex);
Serge A. Suchkov14c65f92008-02-22 18:43:16 +01001829 c = (struct hda_bind_ctls *)kcontrol->private_value;
Takashi Iwai532d5382007-07-27 19:02:40 +02001830 for (vals = c->values; *vals; vals++) {
1831 kcontrol->private_value = *vals;
1832 err = c->ops->put(kcontrol, ucontrol);
1833 if (err < 0)
1834 break;
1835 change |= err;
1836 }
1837 kcontrol->private_value = (long)c;
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001838 mutex_unlock(&codec->control_mutex);
Takashi Iwai532d5382007-07-27 19:02:40 +02001839 return err < 0 ? err : change;
1840}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001841EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_ctls_put);
Takashi Iwai532d5382007-07-27 19:02:40 +02001842
1843int snd_hda_mixer_bind_tlv(struct snd_kcontrol *kcontrol, int op_flag,
1844 unsigned int size, unsigned int __user *tlv)
1845{
1846 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1847 struct hda_bind_ctls *c;
1848 int err;
1849
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001850 mutex_lock(&codec->control_mutex);
Serge A. Suchkov14c65f92008-02-22 18:43:16 +01001851 c = (struct hda_bind_ctls *)kcontrol->private_value;
Takashi Iwai532d5382007-07-27 19:02:40 +02001852 kcontrol->private_value = *c->values;
1853 err = c->ops->tlv(kcontrol, op_flag, size, tlv);
1854 kcontrol->private_value = (long)c;
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001855 mutex_unlock(&codec->control_mutex);
Takashi Iwai532d5382007-07-27 19:02:40 +02001856 return err;
1857}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001858EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_tlv);
Takashi Iwai532d5382007-07-27 19:02:40 +02001859
1860struct hda_ctl_ops snd_hda_bind_vol = {
1861 .info = snd_hda_mixer_amp_volume_info,
1862 .get = snd_hda_mixer_amp_volume_get,
1863 .put = snd_hda_mixer_amp_volume_put,
1864 .tlv = snd_hda_mixer_amp_tlv
1865};
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001866EXPORT_SYMBOL_HDA(snd_hda_bind_vol);
Takashi Iwai532d5382007-07-27 19:02:40 +02001867
1868struct hda_ctl_ops snd_hda_bind_sw = {
1869 .info = snd_hda_mixer_amp_switch_info,
1870 .get = snd_hda_mixer_amp_switch_get,
1871 .put = snd_hda_mixer_amp_switch_put,
1872 .tlv = snd_hda_mixer_amp_tlv
1873};
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001874EXPORT_SYMBOL_HDA(snd_hda_bind_sw);
Takashi Iwai532d5382007-07-27 19:02:40 +02001875
1876/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07001877 * SPDIF out controls
1878 */
1879
Takashi Iwai0ba21762007-04-16 11:29:14 +02001880static int snd_hda_spdif_mask_info(struct snd_kcontrol *kcontrol,
1881 struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001882{
1883 uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
1884 uinfo->count = 1;
1885 return 0;
1886}
1887
Takashi Iwai0ba21762007-04-16 11:29:14 +02001888static int snd_hda_spdif_cmask_get(struct snd_kcontrol *kcontrol,
1889 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001890{
1891 ucontrol->value.iec958.status[0] = IEC958_AES0_PROFESSIONAL |
1892 IEC958_AES0_NONAUDIO |
1893 IEC958_AES0_CON_EMPHASIS_5015 |
1894 IEC958_AES0_CON_NOT_COPYRIGHT;
1895 ucontrol->value.iec958.status[1] = IEC958_AES1_CON_CATEGORY |
1896 IEC958_AES1_CON_ORIGINAL;
1897 return 0;
1898}
1899
Takashi Iwai0ba21762007-04-16 11:29:14 +02001900static int snd_hda_spdif_pmask_get(struct snd_kcontrol *kcontrol,
1901 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001902{
1903 ucontrol->value.iec958.status[0] = IEC958_AES0_PROFESSIONAL |
1904 IEC958_AES0_NONAUDIO |
1905 IEC958_AES0_PRO_EMPHASIS_5015;
1906 return 0;
1907}
1908
Takashi Iwai0ba21762007-04-16 11:29:14 +02001909static int snd_hda_spdif_default_get(struct snd_kcontrol *kcontrol,
1910 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001911{
1912 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1913
1914 ucontrol->value.iec958.status[0] = codec->spdif_status & 0xff;
1915 ucontrol->value.iec958.status[1] = (codec->spdif_status >> 8) & 0xff;
1916 ucontrol->value.iec958.status[2] = (codec->spdif_status >> 16) & 0xff;
1917 ucontrol->value.iec958.status[3] = (codec->spdif_status >> 24) & 0xff;
1918
1919 return 0;
1920}
1921
1922/* convert from SPDIF status bits to HDA SPDIF bits
1923 * bit 0 (DigEn) is always set zero (to be filled later)
1924 */
1925static unsigned short convert_from_spdif_status(unsigned int sbits)
1926{
1927 unsigned short val = 0;
1928
1929 if (sbits & IEC958_AES0_PROFESSIONAL)
Takashi Iwai0ba21762007-04-16 11:29:14 +02001930 val |= AC_DIG1_PROFESSIONAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001931 if (sbits & IEC958_AES0_NONAUDIO)
Takashi Iwai0ba21762007-04-16 11:29:14 +02001932 val |= AC_DIG1_NONAUDIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001933 if (sbits & IEC958_AES0_PROFESSIONAL) {
Takashi Iwai0ba21762007-04-16 11:29:14 +02001934 if ((sbits & IEC958_AES0_PRO_EMPHASIS) ==
1935 IEC958_AES0_PRO_EMPHASIS_5015)
1936 val |= AC_DIG1_EMPHASIS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001937 } else {
Takashi Iwai0ba21762007-04-16 11:29:14 +02001938 if ((sbits & IEC958_AES0_CON_EMPHASIS) ==
1939 IEC958_AES0_CON_EMPHASIS_5015)
1940 val |= AC_DIG1_EMPHASIS;
1941 if (!(sbits & IEC958_AES0_CON_NOT_COPYRIGHT))
1942 val |= AC_DIG1_COPYRIGHT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001943 if (sbits & (IEC958_AES1_CON_ORIGINAL << 8))
Takashi Iwai0ba21762007-04-16 11:29:14 +02001944 val |= AC_DIG1_LEVEL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001945 val |= sbits & (IEC958_AES1_CON_CATEGORY << 8);
1946 }
1947 return val;
1948}
1949
1950/* convert to SPDIF status bits from HDA SPDIF bits
1951 */
1952static unsigned int convert_to_spdif_status(unsigned short val)
1953{
1954 unsigned int sbits = 0;
1955
Takashi Iwai0ba21762007-04-16 11:29:14 +02001956 if (val & AC_DIG1_NONAUDIO)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001957 sbits |= IEC958_AES0_NONAUDIO;
Takashi Iwai0ba21762007-04-16 11:29:14 +02001958 if (val & AC_DIG1_PROFESSIONAL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001959 sbits |= IEC958_AES0_PROFESSIONAL;
1960 if (sbits & IEC958_AES0_PROFESSIONAL) {
Takashi Iwai0ba21762007-04-16 11:29:14 +02001961 if (sbits & AC_DIG1_EMPHASIS)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001962 sbits |= IEC958_AES0_PRO_EMPHASIS_5015;
1963 } else {
Takashi Iwai0ba21762007-04-16 11:29:14 +02001964 if (val & AC_DIG1_EMPHASIS)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001965 sbits |= IEC958_AES0_CON_EMPHASIS_5015;
Takashi Iwai0ba21762007-04-16 11:29:14 +02001966 if (!(val & AC_DIG1_COPYRIGHT))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001967 sbits |= IEC958_AES0_CON_NOT_COPYRIGHT;
Takashi Iwai0ba21762007-04-16 11:29:14 +02001968 if (val & AC_DIG1_LEVEL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001969 sbits |= (IEC958_AES1_CON_ORIGINAL << 8);
1970 sbits |= val & (0x7f << 8);
1971 }
1972 return sbits;
1973}
1974
Takashi Iwai2f728532008-09-25 16:32:41 +02001975/* set digital convert verbs both for the given NID and its slaves */
1976static void set_dig_out(struct hda_codec *codec, hda_nid_t nid,
1977 int verb, int val)
1978{
1979 hda_nid_t *d;
1980
Takashi Iwai9e976972008-11-25 08:17:20 +01001981 snd_hda_codec_write_cache(codec, nid, 0, verb, val);
Takashi Iwai2f728532008-09-25 16:32:41 +02001982 d = codec->slave_dig_outs;
1983 if (!d)
1984 return;
1985 for (; *d; d++)
Takashi Iwai9e976972008-11-25 08:17:20 +01001986 snd_hda_codec_write_cache(codec, *d, 0, verb, val);
Takashi Iwai2f728532008-09-25 16:32:41 +02001987}
1988
1989static inline void set_dig_out_convert(struct hda_codec *codec, hda_nid_t nid,
1990 int dig1, int dig2)
1991{
1992 if (dig1 != -1)
1993 set_dig_out(codec, nid, AC_VERB_SET_DIGI_CONVERT_1, dig1);
1994 if (dig2 != -1)
1995 set_dig_out(codec, nid, AC_VERB_SET_DIGI_CONVERT_2, dig2);
1996}
1997
Takashi Iwai0ba21762007-04-16 11:29:14 +02001998static int snd_hda_spdif_default_put(struct snd_kcontrol *kcontrol,
1999 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002000{
2001 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2002 hda_nid_t nid = kcontrol->private_value;
2003 unsigned short val;
2004 int change;
2005
Ingo Molnar62932df2006-01-16 16:34:20 +01002006 mutex_lock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002007 codec->spdif_status = ucontrol->value.iec958.status[0] |
2008 ((unsigned int)ucontrol->value.iec958.status[1] << 8) |
2009 ((unsigned int)ucontrol->value.iec958.status[2] << 16) |
2010 ((unsigned int)ucontrol->value.iec958.status[3] << 24);
2011 val = convert_from_spdif_status(codec->spdif_status);
2012 val |= codec->spdif_ctls & 1;
2013 change = codec->spdif_ctls != val;
2014 codec->spdif_ctls = val;
2015
Takashi Iwai2f728532008-09-25 16:32:41 +02002016 if (change)
2017 set_dig_out_convert(codec, nid, val & 0xff, (val >> 8) & 0xff);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002018
Ingo Molnar62932df2006-01-16 16:34:20 +01002019 mutex_unlock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002020 return change;
2021}
2022
Takashi Iwaia5ce8892007-07-23 15:42:26 +02002023#define snd_hda_spdif_out_switch_info snd_ctl_boolean_mono_info
Linus Torvalds1da177e2005-04-16 15:20:36 -07002024
Takashi Iwai0ba21762007-04-16 11:29:14 +02002025static int snd_hda_spdif_out_switch_get(struct snd_kcontrol *kcontrol,
2026 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002027{
2028 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2029
Takashi Iwai0ba21762007-04-16 11:29:14 +02002030 ucontrol->value.integer.value[0] = codec->spdif_ctls & AC_DIG1_ENABLE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002031 return 0;
2032}
2033
Takashi Iwai0ba21762007-04-16 11:29:14 +02002034static int snd_hda_spdif_out_switch_put(struct snd_kcontrol *kcontrol,
2035 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002036{
2037 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2038 hda_nid_t nid = kcontrol->private_value;
2039 unsigned short val;
2040 int change;
2041
Ingo Molnar62932df2006-01-16 16:34:20 +01002042 mutex_lock(&codec->spdif_mutex);
Takashi Iwai0ba21762007-04-16 11:29:14 +02002043 val = codec->spdif_ctls & ~AC_DIG1_ENABLE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002044 if (ucontrol->value.integer.value[0])
Takashi Iwai0ba21762007-04-16 11:29:14 +02002045 val |= AC_DIG1_ENABLE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002046 change = codec->spdif_ctls != val;
Takashi Iwai82beb8f2007-08-10 17:09:26 +02002047 if (change) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002048 codec->spdif_ctls = val;
Takashi Iwai2f728532008-09-25 16:32:41 +02002049 set_dig_out_convert(codec, nid, val & 0xff, -1);
Takashi Iwai0ba21762007-04-16 11:29:14 +02002050 /* unmute amp switch (if any) */
2051 if ((get_wcaps(codec, nid) & AC_WCAP_OUT_AMP) &&
Takashi Iwai47fd8302007-08-10 17:11:07 +02002052 (val & AC_DIG1_ENABLE))
2053 snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0,
2054 HDA_AMP_MUTE, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002055 }
Ingo Molnar62932df2006-01-16 16:34:20 +01002056 mutex_unlock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002057 return change;
2058}
2059
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01002060static struct snd_kcontrol_new dig_mixes[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002061 {
2062 .access = SNDRV_CTL_ELEM_ACCESS_READ,
2063 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2064 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,CON_MASK),
2065 .info = snd_hda_spdif_mask_info,
2066 .get = snd_hda_spdif_cmask_get,
2067 },
2068 {
2069 .access = SNDRV_CTL_ELEM_ACCESS_READ,
2070 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2071 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,PRO_MASK),
2072 .info = snd_hda_spdif_mask_info,
2073 .get = snd_hda_spdif_pmask_get,
2074 },
2075 {
2076 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2077 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT),
2078 .info = snd_hda_spdif_mask_info,
2079 .get = snd_hda_spdif_default_get,
2080 .put = snd_hda_spdif_default_put,
2081 },
2082 {
2083 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2084 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,SWITCH),
2085 .info = snd_hda_spdif_out_switch_info,
2086 .get = snd_hda_spdif_out_switch_get,
2087 .put = snd_hda_spdif_out_switch_put,
2088 },
2089 { } /* end */
2090};
2091
Takashi Iwai09f99702008-02-04 12:31:13 +01002092#define SPDIF_MAX_IDX 4 /* 4 instances should be enough to probe */
2093
Linus Torvalds1da177e2005-04-16 15:20:36 -07002094/**
2095 * snd_hda_create_spdif_out_ctls - create Output SPDIF-related controls
2096 * @codec: the HDA codec
2097 * @nid: audio out widget NID
2098 *
2099 * Creates controls related with the SPDIF output.
2100 * Called from each patch supporting the SPDIF out.
2101 *
2102 * Returns 0 if successful, or a negative error code.
2103 */
Takashi Iwai12f288b2007-08-02 15:51:59 +02002104int snd_hda_create_spdif_out_ctls(struct hda_codec *codec, hda_nid_t nid)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002105{
2106 int err;
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01002107 struct snd_kcontrol *kctl;
2108 struct snd_kcontrol_new *dig_mix;
Takashi Iwai09f99702008-02-04 12:31:13 +01002109 int idx;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002110
Takashi Iwai09f99702008-02-04 12:31:13 +01002111 for (idx = 0; idx < SPDIF_MAX_IDX; idx++) {
2112 if (!_snd_hda_find_mixer_ctl(codec, "IEC958 Playback Switch",
2113 idx))
2114 break;
2115 }
2116 if (idx >= SPDIF_MAX_IDX) {
2117 printk(KERN_ERR "hda_codec: too many IEC958 outputs\n");
2118 return -EBUSY;
2119 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002120 for (dig_mix = dig_mixes; dig_mix->name; dig_mix++) {
2121 kctl = snd_ctl_new1(dig_mix, codec);
Takashi Iwaib91f0802008-11-04 08:43:08 +01002122 if (!kctl)
2123 return -ENOMEM;
Takashi Iwai09f99702008-02-04 12:31:13 +01002124 kctl->id.index = idx;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002125 kctl->private_value = nid;
Takashi Iwaid13bd412008-07-30 15:01:45 +02002126 err = snd_hda_ctl_add(codec, kctl);
Takashi Iwai0ba21762007-04-16 11:29:14 +02002127 if (err < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002128 return err;
2129 }
Takashi Iwai0ba21762007-04-16 11:29:14 +02002130 codec->spdif_ctls =
Andrew Paprocki3982d172007-12-19 12:13:44 +01002131 snd_hda_codec_read(codec, nid, 0,
2132 AC_VERB_GET_DIGI_CONVERT_1, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002133 codec->spdif_status = convert_to_spdif_status(codec->spdif_ctls);
2134 return 0;
2135}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002136EXPORT_SYMBOL_HDA(snd_hda_create_spdif_out_ctls);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002137
2138/*
Takashi Iwai9a081602008-02-12 18:37:26 +01002139 * SPDIF sharing with analog output
2140 */
2141static int spdif_share_sw_get(struct snd_kcontrol *kcontrol,
2142 struct snd_ctl_elem_value *ucontrol)
2143{
2144 struct hda_multi_out *mout = snd_kcontrol_chip(kcontrol);
2145 ucontrol->value.integer.value[0] = mout->share_spdif;
2146 return 0;
2147}
2148
2149static int spdif_share_sw_put(struct snd_kcontrol *kcontrol,
2150 struct snd_ctl_elem_value *ucontrol)
2151{
2152 struct hda_multi_out *mout = snd_kcontrol_chip(kcontrol);
2153 mout->share_spdif = !!ucontrol->value.integer.value[0];
2154 return 0;
2155}
2156
2157static struct snd_kcontrol_new spdif_share_sw = {
2158 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2159 .name = "IEC958 Default PCM Playback Switch",
2160 .info = snd_ctl_boolean_mono_info,
2161 .get = spdif_share_sw_get,
2162 .put = spdif_share_sw_put,
2163};
2164
2165int snd_hda_create_spdif_share_sw(struct hda_codec *codec,
2166 struct hda_multi_out *mout)
2167{
2168 if (!mout->dig_out_nid)
2169 return 0;
2170 /* ATTENTION: here mout is passed as private_data, instead of codec */
Takashi Iwaid13bd412008-07-30 15:01:45 +02002171 return snd_hda_ctl_add(codec,
Takashi Iwai9a081602008-02-12 18:37:26 +01002172 snd_ctl_new1(&spdif_share_sw, mout));
2173}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002174EXPORT_SYMBOL_HDA(snd_hda_create_spdif_share_sw);
Takashi Iwai9a081602008-02-12 18:37:26 +01002175
2176/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002177 * SPDIF input
2178 */
2179
2180#define snd_hda_spdif_in_switch_info snd_hda_spdif_out_switch_info
2181
Takashi Iwai0ba21762007-04-16 11:29:14 +02002182static int snd_hda_spdif_in_switch_get(struct snd_kcontrol *kcontrol,
2183 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002184{
2185 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2186
2187 ucontrol->value.integer.value[0] = codec->spdif_in_enable;
2188 return 0;
2189}
2190
Takashi Iwai0ba21762007-04-16 11:29:14 +02002191static int snd_hda_spdif_in_switch_put(struct snd_kcontrol *kcontrol,
2192 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002193{
2194 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2195 hda_nid_t nid = kcontrol->private_value;
2196 unsigned int val = !!ucontrol->value.integer.value[0];
2197 int change;
2198
Ingo Molnar62932df2006-01-16 16:34:20 +01002199 mutex_lock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002200 change = codec->spdif_in_enable != val;
Takashi Iwai82beb8f2007-08-10 17:09:26 +02002201 if (change) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002202 codec->spdif_in_enable = val;
Takashi Iwai82beb8f2007-08-10 17:09:26 +02002203 snd_hda_codec_write_cache(codec, nid, 0,
2204 AC_VERB_SET_DIGI_CONVERT_1, val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002205 }
Ingo Molnar62932df2006-01-16 16:34:20 +01002206 mutex_unlock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002207 return change;
2208}
2209
Takashi Iwai0ba21762007-04-16 11:29:14 +02002210static int snd_hda_spdif_in_status_get(struct snd_kcontrol *kcontrol,
2211 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002212{
2213 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2214 hda_nid_t nid = kcontrol->private_value;
2215 unsigned short val;
2216 unsigned int sbits;
2217
Andrew Paprocki3982d172007-12-19 12:13:44 +01002218 val = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_DIGI_CONVERT_1, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002219 sbits = convert_to_spdif_status(val);
2220 ucontrol->value.iec958.status[0] = sbits;
2221 ucontrol->value.iec958.status[1] = sbits >> 8;
2222 ucontrol->value.iec958.status[2] = sbits >> 16;
2223 ucontrol->value.iec958.status[3] = sbits >> 24;
2224 return 0;
2225}
2226
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01002227static struct snd_kcontrol_new dig_in_ctls[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002228 {
2229 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2230 .name = SNDRV_CTL_NAME_IEC958("",CAPTURE,SWITCH),
2231 .info = snd_hda_spdif_in_switch_info,
2232 .get = snd_hda_spdif_in_switch_get,
2233 .put = snd_hda_spdif_in_switch_put,
2234 },
2235 {
2236 .access = SNDRV_CTL_ELEM_ACCESS_READ,
2237 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2238 .name = SNDRV_CTL_NAME_IEC958("",CAPTURE,DEFAULT),
2239 .info = snd_hda_spdif_mask_info,
2240 .get = snd_hda_spdif_in_status_get,
2241 },
2242 { } /* end */
2243};
2244
2245/**
2246 * snd_hda_create_spdif_in_ctls - create Input SPDIF-related controls
2247 * @codec: the HDA codec
2248 * @nid: audio in widget NID
2249 *
2250 * Creates controls related with the SPDIF input.
2251 * Called from each patch supporting the SPDIF in.
2252 *
2253 * Returns 0 if successful, or a negative error code.
2254 */
Takashi Iwai12f288b2007-08-02 15:51:59 +02002255int snd_hda_create_spdif_in_ctls(struct hda_codec *codec, hda_nid_t nid)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002256{
2257 int err;
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01002258 struct snd_kcontrol *kctl;
2259 struct snd_kcontrol_new *dig_mix;
Takashi Iwai09f99702008-02-04 12:31:13 +01002260 int idx;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002261
Takashi Iwai09f99702008-02-04 12:31:13 +01002262 for (idx = 0; idx < SPDIF_MAX_IDX; idx++) {
2263 if (!_snd_hda_find_mixer_ctl(codec, "IEC958 Capture Switch",
2264 idx))
2265 break;
2266 }
2267 if (idx >= SPDIF_MAX_IDX) {
2268 printk(KERN_ERR "hda_codec: too many IEC958 inputs\n");
2269 return -EBUSY;
2270 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002271 for (dig_mix = dig_in_ctls; dig_mix->name; dig_mix++) {
2272 kctl = snd_ctl_new1(dig_mix, codec);
Takashi Iwaic8dcdf82009-02-06 16:21:20 +01002273 if (!kctl)
2274 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002275 kctl->private_value = nid;
Takashi Iwaid13bd412008-07-30 15:01:45 +02002276 err = snd_hda_ctl_add(codec, kctl);
Takashi Iwai0ba21762007-04-16 11:29:14 +02002277 if (err < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002278 return err;
2279 }
Takashi Iwai0ba21762007-04-16 11:29:14 +02002280 codec->spdif_in_enable =
Andrew Paprocki3982d172007-12-19 12:13:44 +01002281 snd_hda_codec_read(codec, nid, 0,
2282 AC_VERB_GET_DIGI_CONVERT_1, 0) &
Takashi Iwai0ba21762007-04-16 11:29:14 +02002283 AC_DIG1_ENABLE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002284 return 0;
2285}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002286EXPORT_SYMBOL_HDA(snd_hda_create_spdif_in_ctls);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002287
Takashi Iwaicb53c622007-08-10 17:21:45 +02002288#ifdef SND_HDA_NEEDS_RESUME
Takashi Iwai82beb8f2007-08-10 17:09:26 +02002289/*
2290 * command cache
2291 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002292
Takashi Iwaib3ac5632007-08-10 17:03:40 +02002293/* build a 32bit cache key with the widget id and the command parameter */
2294#define build_cmd_cache_key(nid, verb) ((verb << 8) | nid)
2295#define get_cmd_cache_nid(key) ((key) & 0xff)
2296#define get_cmd_cache_cmd(key) (((key) >> 8) & 0xffff)
2297
2298/**
2299 * snd_hda_codec_write_cache - send a single command with caching
2300 * @codec: the HDA codec
2301 * @nid: NID to send the command
2302 * @direct: direct flag
2303 * @verb: the verb to send
2304 * @parm: the parameter for the verb
2305 *
2306 * Send a single command without waiting for response.
2307 *
2308 * Returns 0 if successful, or a negative error code.
2309 */
2310int snd_hda_codec_write_cache(struct hda_codec *codec, hda_nid_t nid,
2311 int direct, unsigned int verb, unsigned int parm)
2312{
Takashi Iwaiaa2936f2009-05-26 16:07:57 +02002313 int err = snd_hda_codec_write(codec, nid, direct, verb, parm);
2314 struct hda_cache_head *c;
2315 u32 key;
Takashi Iwai33fa35e2008-11-06 16:50:40 +01002316
Takashi Iwaiaa2936f2009-05-26 16:07:57 +02002317 if (err < 0)
2318 return err;
2319 /* parm may contain the verb stuff for get/set amp */
2320 verb = verb | (parm >> 8);
2321 parm &= 0xff;
2322 key = build_cmd_cache_key(nid, verb);
2323 mutex_lock(&codec->bus->cmd_mutex);
2324 c = get_alloc_hash(&codec->cmd_cache, key);
2325 if (c)
2326 c->val = parm;
2327 mutex_unlock(&codec->bus->cmd_mutex);
2328 return 0;
Takashi Iwaib3ac5632007-08-10 17:03:40 +02002329}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002330EXPORT_SYMBOL_HDA(snd_hda_codec_write_cache);
Takashi Iwaib3ac5632007-08-10 17:03:40 +02002331
2332/* resume the all commands from the cache */
2333void snd_hda_codec_resume_cache(struct hda_codec *codec)
2334{
Takashi Iwai603c4012008-07-30 15:01:44 +02002335 struct hda_cache_head *buffer = codec->cmd_cache.buf.list;
Takashi Iwaib3ac5632007-08-10 17:03:40 +02002336 int i;
2337
Takashi Iwai603c4012008-07-30 15:01:44 +02002338 for (i = 0; i < codec->cmd_cache.buf.used; i++, buffer++) {
Takashi Iwaib3ac5632007-08-10 17:03:40 +02002339 u32 key = buffer->key;
2340 if (!key)
2341 continue;
2342 snd_hda_codec_write(codec, get_cmd_cache_nid(key), 0,
2343 get_cmd_cache_cmd(key), buffer->val);
2344 }
2345}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002346EXPORT_SYMBOL_HDA(snd_hda_codec_resume_cache);
Takashi Iwaib3ac5632007-08-10 17:03:40 +02002347
2348/**
2349 * snd_hda_sequence_write_cache - sequence writes with caching
2350 * @codec: the HDA codec
2351 * @seq: VERB array to send
2352 *
2353 * Send the commands sequentially from the given array.
2354 * Thte commands are recorded on cache for power-save and resume.
2355 * The array must be terminated with NID=0.
2356 */
2357void snd_hda_sequence_write_cache(struct hda_codec *codec,
2358 const struct hda_verb *seq)
2359{
2360 for (; seq->nid; seq++)
2361 snd_hda_codec_write_cache(codec, seq->nid, 0, seq->verb,
2362 seq->param);
2363}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002364EXPORT_SYMBOL_HDA(snd_hda_sequence_write_cache);
Takashi Iwaicb53c622007-08-10 17:21:45 +02002365#endif /* SND_HDA_NEEDS_RESUME */
Takashi Iwaib3ac5632007-08-10 17:03:40 +02002366
Takashi Iwai54d17402005-11-21 16:33:22 +01002367/*
2368 * set power state of the codec
2369 */
2370static void hda_set_power_state(struct hda_codec *codec, hda_nid_t fg,
2371 unsigned int power_state)
2372{
Takashi Iwaicb53c622007-08-10 17:21:45 +02002373 hda_nid_t nid;
2374 int i;
Takashi Iwai54d17402005-11-21 16:33:22 +01002375
Takashi Iwai05ff7e12009-07-22 12:39:24 +02002376 /* this delay seems necessary to avoid click noise at power-down */
2377 if (power_state == AC_PWRST_D3)
2378 msleep(100);
2379 snd_hda_codec_read(codec, fg, 0, AC_VERB_SET_POWER_STATE,
Takashi Iwai54d17402005-11-21 16:33:22 +01002380 power_state);
Takashi Iwai05ff7e12009-07-22 12:39:24 +02002381 /* partial workaround for "azx_get_response timeout" */
2382 if (power_state == AC_PWRST_D0)
2383 msleep(10);
Takashi Iwai54d17402005-11-21 16:33:22 +01002384
Takashi Iwaicb53c622007-08-10 17:21:45 +02002385 nid = codec->start_nid;
2386 for (i = 0; i < codec->num_nodes; i++, nid++) {
Takashi Iwai7eba5c92007-11-14 14:53:42 +01002387 unsigned int wcaps = get_wcaps(codec, nid);
2388 if (wcaps & AC_WCAP_POWER) {
2389 unsigned int wid_type = (wcaps & AC_WCAP_TYPE) >>
2390 AC_WCAP_TYPE_SHIFT;
Takashi Iwaia3b48c82009-04-21 13:37:29 +02002391 if (power_state == AC_PWRST_D3 &&
2392 wid_type == AC_WID_PIN) {
Takashi Iwai7eba5c92007-11-14 14:53:42 +01002393 unsigned int pincap;
2394 /*
2395 * don't power down the widget if it controls
2396 * eapd and EAPD_BTLENABLE is set.
2397 */
Takashi Iwai14bafe32009-03-23 16:35:39 +01002398 pincap = snd_hda_query_pin_caps(codec, nid);
Takashi Iwai7eba5c92007-11-14 14:53:42 +01002399 if (pincap & AC_PINCAP_EAPD) {
2400 int eapd = snd_hda_codec_read(codec,
2401 nid, 0,
2402 AC_VERB_GET_EAPD_BTLENABLE, 0);
2403 eapd &= 0x02;
Takashi Iwaia3b48c82009-04-21 13:37:29 +02002404 if (eapd)
Takashi Iwai7eba5c92007-11-14 14:53:42 +01002405 continue;
2406 }
Takashi Iwai1194b5b2007-10-10 10:04:26 +02002407 }
Takashi Iwai54d17402005-11-21 16:33:22 +01002408 snd_hda_codec_write(codec, nid, 0,
2409 AC_VERB_SET_POWER_STATE,
2410 power_state);
Takashi Iwai1194b5b2007-10-10 10:04:26 +02002411 }
Takashi Iwai54d17402005-11-21 16:33:22 +01002412 }
2413
Takashi Iwaicb53c622007-08-10 17:21:45 +02002414 if (power_state == AC_PWRST_D0) {
2415 unsigned long end_time;
2416 int state;
Takashi Iwai54d17402005-11-21 16:33:22 +01002417 msleep(10);
Takashi Iwaicb53c622007-08-10 17:21:45 +02002418 /* wait until the codec reachs to D0 */
2419 end_time = jiffies + msecs_to_jiffies(500);
2420 do {
2421 state = snd_hda_codec_read(codec, fg, 0,
2422 AC_VERB_GET_POWER_STATE, 0);
2423 if (state == power_state)
2424 break;
2425 msleep(1);
2426 } while (time_after_eq(end_time, jiffies));
2427 }
Takashi Iwai54d17402005-11-21 16:33:22 +01002428}
2429
Takashi Iwai11aeff02008-07-30 15:01:46 +02002430#ifdef CONFIG_SND_HDA_HWDEP
2431/* execute additional init verbs */
2432static void hda_exec_init_verbs(struct hda_codec *codec)
2433{
2434 if (codec->init_verbs.list)
2435 snd_hda_sequence_write(codec, codec->init_verbs.list);
2436}
2437#else
2438static inline void hda_exec_init_verbs(struct hda_codec *codec) {}
2439#endif
2440
Takashi Iwaicb53c622007-08-10 17:21:45 +02002441#ifdef SND_HDA_NEEDS_RESUME
2442/*
2443 * call suspend and power-down; used both from PM and power-save
2444 */
2445static void hda_call_codec_suspend(struct hda_codec *codec)
2446{
2447 if (codec->patch_ops.suspend)
2448 codec->patch_ops.suspend(codec, PMSG_SUSPEND);
2449 hda_set_power_state(codec,
2450 codec->afg ? codec->afg : codec->mfg,
2451 AC_PWRST_D3);
2452#ifdef CONFIG_SND_HDA_POWER_SAVE
2453 cancel_delayed_work(&codec->power_work);
Takashi Iwai95e99fd2007-08-13 15:29:04 +02002454 codec->power_on = 0;
Takashi Iwaia221e282007-08-16 16:35:33 +02002455 codec->power_transition = 0;
Takashi Iwaicb53c622007-08-10 17:21:45 +02002456#endif
2457}
2458
2459/*
2460 * kick up codec; used both from PM and power-save
2461 */
2462static void hda_call_codec_resume(struct hda_codec *codec)
2463{
2464 hda_set_power_state(codec,
2465 codec->afg ? codec->afg : codec->mfg,
2466 AC_PWRST_D0);
Takashi Iwai3be14142009-02-20 14:11:16 +01002467 restore_pincfgs(codec); /* restore all current pin configs */
Takashi Iwai11aeff02008-07-30 15:01:46 +02002468 hda_exec_init_verbs(codec);
Takashi Iwaicb53c622007-08-10 17:21:45 +02002469 if (codec->patch_ops.resume)
2470 codec->patch_ops.resume(codec);
2471 else {
Takashi Iwai9d99f312007-08-14 15:15:52 +02002472 if (codec->patch_ops.init)
2473 codec->patch_ops.init(codec);
Takashi Iwaicb53c622007-08-10 17:21:45 +02002474 snd_hda_codec_resume_amp(codec);
2475 snd_hda_codec_resume_cache(codec);
2476 }
2477}
2478#endif /* SND_HDA_NEEDS_RESUME */
2479
Takashi Iwai54d17402005-11-21 16:33:22 +01002480
Linus Torvalds1da177e2005-04-16 15:20:36 -07002481/**
2482 * snd_hda_build_controls - build mixer controls
2483 * @bus: the BUS
2484 *
2485 * Creates mixer controls for each codec included in the bus.
2486 *
2487 * Returns 0 if successful, otherwise a negative error code.
2488 */
Takashi Iwai1289e9e2008-11-27 15:47:11 +01002489int /*__devinit*/ snd_hda_build_controls(struct hda_bus *bus)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002490{
Takashi Iwai0ba21762007-04-16 11:29:14 +02002491 struct hda_codec *codec;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002492
Takashi Iwai0ba21762007-04-16 11:29:14 +02002493 list_for_each_entry(codec, &bus->codec_list, list) {
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02002494 int err = snd_hda_codec_build_controls(codec);
Takashi Iwaif93d4612009-03-02 10:44:15 +01002495 if (err < 0) {
2496 printk(KERN_ERR "hda_codec: cannot build controls"
2497 "for #%d (error %d)\n", codec->addr, err);
2498 err = snd_hda_codec_reset(codec);
2499 if (err < 0) {
2500 printk(KERN_ERR
2501 "hda_codec: cannot revert codec\n");
2502 return err;
2503 }
2504 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002505 }
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02002506 return 0;
2507}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002508EXPORT_SYMBOL_HDA(snd_hda_build_controls);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002509
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02002510int snd_hda_codec_build_controls(struct hda_codec *codec)
2511{
2512 int err = 0;
Takashi Iwai11aeff02008-07-30 15:01:46 +02002513 hda_exec_init_verbs(codec);
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02002514 /* continue to initialize... */
2515 if (codec->patch_ops.init)
2516 err = codec->patch_ops.init(codec);
2517 if (!err && codec->patch_ops.build_controls)
2518 err = codec->patch_ops.build_controls(codec);
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02002519 if (err < 0)
2520 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002521 return 0;
2522}
2523
Linus Torvalds1da177e2005-04-16 15:20:36 -07002524/*
2525 * stream formats
2526 */
Takashi Iwaibefdf312005-08-22 13:57:55 +02002527struct hda_rate_tbl {
2528 unsigned int hz;
2529 unsigned int alsa_bits;
2530 unsigned int hda_fmt;
2531};
2532
2533static struct hda_rate_tbl rate_bits[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002534 /* rate in Hz, ALSA rate bitmask, HDA format value */
Nicolas Graziano9d8f53f2005-08-22 13:47:16 +02002535
2536 /* autodetected value used in snd_hda_query_supported_pcm */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002537 { 8000, SNDRV_PCM_RATE_8000, 0x0500 }, /* 1/6 x 48 */
2538 { 11025, SNDRV_PCM_RATE_11025, 0x4300 }, /* 1/4 x 44 */
2539 { 16000, SNDRV_PCM_RATE_16000, 0x0200 }, /* 1/3 x 48 */
2540 { 22050, SNDRV_PCM_RATE_22050, 0x4100 }, /* 1/2 x 44 */
2541 { 32000, SNDRV_PCM_RATE_32000, 0x0a00 }, /* 2/3 x 48 */
2542 { 44100, SNDRV_PCM_RATE_44100, 0x4000 }, /* 44 */
2543 { 48000, SNDRV_PCM_RATE_48000, 0x0000 }, /* 48 */
2544 { 88200, SNDRV_PCM_RATE_88200, 0x4800 }, /* 2 x 44 */
2545 { 96000, SNDRV_PCM_RATE_96000, 0x0800 }, /* 2 x 48 */
2546 { 176400, SNDRV_PCM_RATE_176400, 0x5800 },/* 4 x 44 */
2547 { 192000, SNDRV_PCM_RATE_192000, 0x1800 }, /* 4 x 48 */
Takashi Iwaia961f9f2007-04-12 13:08:09 +02002548#define AC_PAR_PCM_RATE_BITS 11
2549 /* up to bits 10, 384kHZ isn't supported properly */
2550
2551 /* not autodetected value */
2552 { 9600, SNDRV_PCM_RATE_KNOT, 0x0400 }, /* 1/5 x 48 */
Nicolas Graziano9d8f53f2005-08-22 13:47:16 +02002553
Takashi Iwaibefdf312005-08-22 13:57:55 +02002554 { 0 } /* terminator */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002555};
2556
2557/**
2558 * snd_hda_calc_stream_format - calculate format bitset
2559 * @rate: the sample rate
2560 * @channels: the number of channels
2561 * @format: the PCM format (SNDRV_PCM_FORMAT_XXX)
2562 * @maxbps: the max. bps
2563 *
2564 * Calculate the format bitset from the given rate, channels and th PCM format.
2565 *
2566 * Return zero if invalid.
2567 */
2568unsigned int snd_hda_calc_stream_format(unsigned int rate,
2569 unsigned int channels,
2570 unsigned int format,
2571 unsigned int maxbps)
2572{
2573 int i;
2574 unsigned int val = 0;
2575
Takashi Iwaibefdf312005-08-22 13:57:55 +02002576 for (i = 0; rate_bits[i].hz; i++)
2577 if (rate_bits[i].hz == rate) {
2578 val = rate_bits[i].hda_fmt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002579 break;
2580 }
Takashi Iwai0ba21762007-04-16 11:29:14 +02002581 if (!rate_bits[i].hz) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002582 snd_printdd("invalid rate %d\n", rate);
2583 return 0;
2584 }
2585
2586 if (channels == 0 || channels > 8) {
2587 snd_printdd("invalid channels %d\n", channels);
2588 return 0;
2589 }
2590 val |= channels - 1;
2591
2592 switch (snd_pcm_format_width(format)) {
2593 case 8: val |= 0x00; break;
2594 case 16: val |= 0x10; break;
2595 case 20:
2596 case 24:
2597 case 32:
Takashi Iwaib0bb3aa2009-07-03 23:25:37 +02002598 if (maxbps >= 32 || format == SNDRV_PCM_FORMAT_FLOAT_LE)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002599 val |= 0x40;
2600 else if (maxbps >= 24)
2601 val |= 0x30;
2602 else
2603 val |= 0x20;
2604 break;
2605 default:
Takashi Iwai0ba21762007-04-16 11:29:14 +02002606 snd_printdd("invalid format width %d\n",
2607 snd_pcm_format_width(format));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002608 return 0;
2609 }
2610
2611 return val;
2612}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002613EXPORT_SYMBOL_HDA(snd_hda_calc_stream_format);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002614
Takashi Iwai92c7c8a2009-03-24 07:32:14 +01002615static unsigned int get_pcm_param(struct hda_codec *codec, hda_nid_t nid)
2616{
2617 unsigned int val = 0;
2618 if (nid != codec->afg &&
2619 (get_wcaps(codec, nid) & AC_WCAP_FORMAT_OVRD))
2620 val = snd_hda_param_read(codec, nid, AC_PAR_PCM);
2621 if (!val || val == -1)
2622 val = snd_hda_param_read(codec, codec->afg, AC_PAR_PCM);
2623 if (!val || val == -1)
2624 return 0;
2625 return val;
2626}
2627
2628static unsigned int query_pcm_param(struct hda_codec *codec, hda_nid_t nid)
2629{
2630 return query_caps_hash(codec, nid, HDA_HASH_PARPCM_KEY(nid),
2631 get_pcm_param);
2632}
2633
2634static unsigned int get_stream_param(struct hda_codec *codec, hda_nid_t nid)
2635{
2636 unsigned int streams = snd_hda_param_read(codec, nid, AC_PAR_STREAM);
2637 if (!streams || streams == -1)
2638 streams = snd_hda_param_read(codec, codec->afg, AC_PAR_STREAM);
2639 if (!streams || streams == -1)
2640 return 0;
2641 return streams;
2642}
2643
2644static unsigned int query_stream_param(struct hda_codec *codec, hda_nid_t nid)
2645{
2646 return query_caps_hash(codec, nid, HDA_HASH_PARSTR_KEY(nid),
2647 get_stream_param);
2648}
2649
Linus Torvalds1da177e2005-04-16 15:20:36 -07002650/**
2651 * snd_hda_query_supported_pcm - query the supported PCM rates and formats
2652 * @codec: the HDA codec
2653 * @nid: NID to query
2654 * @ratesp: the pointer to store the detected rate bitflags
2655 * @formatsp: the pointer to store the detected formats
2656 * @bpsp: the pointer to store the detected format widths
2657 *
2658 * Queries the supported PCM rates and formats. The NULL @ratesp, @formatsp
2659 * or @bsps argument is ignored.
2660 *
2661 * Returns 0 if successful, otherwise a negative error code.
2662 */
Takashi Iwai986862bd2008-11-27 12:40:13 +01002663static int snd_hda_query_supported_pcm(struct hda_codec *codec, hda_nid_t nid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002664 u32 *ratesp, u64 *formatsp, unsigned int *bpsp)
2665{
Jaroslav Kyselaee504712009-03-17 14:30:31 +01002666 unsigned int i, val, wcaps;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002667
Jaroslav Kyselaee504712009-03-17 14:30:31 +01002668 wcaps = get_wcaps(codec, nid);
Takashi Iwai92c7c8a2009-03-24 07:32:14 +01002669 val = query_pcm_param(codec, nid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002670
2671 if (ratesp) {
2672 u32 rates = 0;
Takashi Iwaia961f9f2007-04-12 13:08:09 +02002673 for (i = 0; i < AC_PAR_PCM_RATE_BITS; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002674 if (val & (1 << i))
Takashi Iwaibefdf312005-08-22 13:57:55 +02002675 rates |= rate_bits[i].alsa_bits;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002676 }
Jaroslav Kyselaee504712009-03-17 14:30:31 +01002677 if (rates == 0) {
2678 snd_printk(KERN_ERR "hda_codec: rates == 0 "
2679 "(nid=0x%x, val=0x%x, ovrd=%i)\n",
2680 nid, val,
2681 (wcaps & AC_WCAP_FORMAT_OVRD) ? 1 : 0);
2682 return -EIO;
2683 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002684 *ratesp = rates;
2685 }
2686
2687 if (formatsp || bpsp) {
2688 u64 formats = 0;
Jaroslav Kyselaee504712009-03-17 14:30:31 +01002689 unsigned int streams, bps;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002690
Takashi Iwai92c7c8a2009-03-24 07:32:14 +01002691 streams = query_stream_param(codec, nid);
2692 if (!streams)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002693 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002694
2695 bps = 0;
2696 if (streams & AC_SUPFMT_PCM) {
2697 if (val & AC_SUPPCM_BITS_8) {
2698 formats |= SNDRV_PCM_FMTBIT_U8;
2699 bps = 8;
2700 }
2701 if (val & AC_SUPPCM_BITS_16) {
2702 formats |= SNDRV_PCM_FMTBIT_S16_LE;
2703 bps = 16;
2704 }
2705 if (wcaps & AC_WCAP_DIGITAL) {
2706 if (val & AC_SUPPCM_BITS_32)
2707 formats |= SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_LE;
2708 if (val & (AC_SUPPCM_BITS_20|AC_SUPPCM_BITS_24))
2709 formats |= SNDRV_PCM_FMTBIT_S32_LE;
2710 if (val & AC_SUPPCM_BITS_24)
2711 bps = 24;
2712 else if (val & AC_SUPPCM_BITS_20)
2713 bps = 20;
Takashi Iwai0ba21762007-04-16 11:29:14 +02002714 } else if (val & (AC_SUPPCM_BITS_20|AC_SUPPCM_BITS_24|
2715 AC_SUPPCM_BITS_32)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002716 formats |= SNDRV_PCM_FMTBIT_S32_LE;
2717 if (val & AC_SUPPCM_BITS_32)
2718 bps = 32;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002719 else if (val & AC_SUPPCM_BITS_24)
2720 bps = 24;
Nicolas Graziano33ef76512006-09-19 14:23:14 +02002721 else if (val & AC_SUPPCM_BITS_20)
2722 bps = 20;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002723 }
2724 }
Takashi Iwaib5025c52009-07-01 18:05:27 +02002725 if (streams & AC_SUPFMT_FLOAT32) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002726 formats |= SNDRV_PCM_FMTBIT_FLOAT_LE;
Takashi Iwaib0bb3aa2009-07-03 23:25:37 +02002727 if (!bps)
2728 bps = 32;
Takashi Iwaib5025c52009-07-01 18:05:27 +02002729 }
2730 if (streams == AC_SUPFMT_AC3) {
Takashi Iwai0ba21762007-04-16 11:29:14 +02002731 /* should be exclusive */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002732 /* temporary hack: we have still no proper support
2733 * for the direct AC3 stream...
2734 */
2735 formats |= SNDRV_PCM_FMTBIT_U8;
2736 bps = 8;
2737 }
Jaroslav Kyselaee504712009-03-17 14:30:31 +01002738 if (formats == 0) {
2739 snd_printk(KERN_ERR "hda_codec: formats == 0 "
2740 "(nid=0x%x, val=0x%x, ovrd=%i, "
2741 "streams=0x%x)\n",
2742 nid, val,
2743 (wcaps & AC_WCAP_FORMAT_OVRD) ? 1 : 0,
2744 streams);
2745 return -EIO;
2746 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002747 if (formatsp)
2748 *formatsp = formats;
2749 if (bpsp)
2750 *bpsp = bps;
2751 }
2752
2753 return 0;
2754}
2755
2756/**
Takashi Iwai0ba21762007-04-16 11:29:14 +02002757 * snd_hda_is_supported_format - check whether the given node supports
2758 * the format val
Linus Torvalds1da177e2005-04-16 15:20:36 -07002759 *
2760 * Returns 1 if supported, 0 if not.
2761 */
2762int snd_hda_is_supported_format(struct hda_codec *codec, hda_nid_t nid,
2763 unsigned int format)
2764{
2765 int i;
2766 unsigned int val = 0, rate, stream;
2767
Takashi Iwai92c7c8a2009-03-24 07:32:14 +01002768 val = query_pcm_param(codec, nid);
2769 if (!val)
2770 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002771
2772 rate = format & 0xff00;
Takashi Iwaia961f9f2007-04-12 13:08:09 +02002773 for (i = 0; i < AC_PAR_PCM_RATE_BITS; i++)
Takashi Iwaibefdf312005-08-22 13:57:55 +02002774 if (rate_bits[i].hda_fmt == rate) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002775 if (val & (1 << i))
2776 break;
2777 return 0;
2778 }
Takashi Iwaia961f9f2007-04-12 13:08:09 +02002779 if (i >= AC_PAR_PCM_RATE_BITS)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002780 return 0;
2781
Takashi Iwai92c7c8a2009-03-24 07:32:14 +01002782 stream = query_stream_param(codec, nid);
2783 if (!stream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002784 return 0;
2785
2786 if (stream & AC_SUPFMT_PCM) {
2787 switch (format & 0xf0) {
2788 case 0x00:
Takashi Iwai0ba21762007-04-16 11:29:14 +02002789 if (!(val & AC_SUPPCM_BITS_8))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002790 return 0;
2791 break;
2792 case 0x10:
Takashi Iwai0ba21762007-04-16 11:29:14 +02002793 if (!(val & AC_SUPPCM_BITS_16))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002794 return 0;
2795 break;
2796 case 0x20:
Takashi Iwai0ba21762007-04-16 11:29:14 +02002797 if (!(val & AC_SUPPCM_BITS_20))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002798 return 0;
2799 break;
2800 case 0x30:
Takashi Iwai0ba21762007-04-16 11:29:14 +02002801 if (!(val & AC_SUPPCM_BITS_24))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002802 return 0;
2803 break;
2804 case 0x40:
Takashi Iwai0ba21762007-04-16 11:29:14 +02002805 if (!(val & AC_SUPPCM_BITS_32))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002806 return 0;
2807 break;
2808 default:
2809 return 0;
2810 }
2811 } else {
2812 /* FIXME: check for float32 and AC3? */
2813 }
2814
2815 return 1;
2816}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002817EXPORT_SYMBOL_HDA(snd_hda_is_supported_format);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002818
2819/*
2820 * PCM stuff
2821 */
2822static int hda_pcm_default_open_close(struct hda_pcm_stream *hinfo,
2823 struct hda_codec *codec,
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01002824 struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002825{
2826 return 0;
2827}
2828
2829static int hda_pcm_default_prepare(struct hda_pcm_stream *hinfo,
2830 struct hda_codec *codec,
2831 unsigned int stream_tag,
2832 unsigned int format,
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01002833 struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002834{
2835 snd_hda_codec_setup_stream(codec, hinfo->nid, stream_tag, 0, format);
2836 return 0;
2837}
2838
2839static int hda_pcm_default_cleanup(struct hda_pcm_stream *hinfo,
2840 struct hda_codec *codec,
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01002841 struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002842{
Takashi Iwai888afa12008-03-18 09:57:50 +01002843 snd_hda_codec_cleanup_stream(codec, hinfo->nid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002844 return 0;
2845}
2846
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02002847static int set_pcm_default_values(struct hda_codec *codec,
2848 struct hda_pcm_stream *info)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002849{
Jaroslav Kyselaee504712009-03-17 14:30:31 +01002850 int err;
2851
Takashi Iwai0ba21762007-04-16 11:29:14 +02002852 /* query support PCM information from the given NID */
2853 if (info->nid && (!info->rates || !info->formats)) {
Jaroslav Kyselaee504712009-03-17 14:30:31 +01002854 err = snd_hda_query_supported_pcm(codec, info->nid,
Takashi Iwai0ba21762007-04-16 11:29:14 +02002855 info->rates ? NULL : &info->rates,
2856 info->formats ? NULL : &info->formats,
2857 info->maxbps ? NULL : &info->maxbps);
Jaroslav Kyselaee504712009-03-17 14:30:31 +01002858 if (err < 0)
2859 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002860 }
2861 if (info->ops.open == NULL)
2862 info->ops.open = hda_pcm_default_open_close;
2863 if (info->ops.close == NULL)
2864 info->ops.close = hda_pcm_default_open_close;
2865 if (info->ops.prepare == NULL) {
Takashi Iwaida3cec32008-08-08 17:12:14 +02002866 if (snd_BUG_ON(!info->nid))
2867 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002868 info->ops.prepare = hda_pcm_default_prepare;
2869 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002870 if (info->ops.cleanup == NULL) {
Takashi Iwaida3cec32008-08-08 17:12:14 +02002871 if (snd_BUG_ON(!info->nid))
2872 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002873 info->ops.cleanup = hda_pcm_default_cleanup;
2874 }
2875 return 0;
2876}
2877
Takashi Iwai176d5332008-07-30 15:01:44 +02002878/*
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002879 * get the empty PCM device number to assign
2880 */
2881static int get_empty_pcm_device(struct hda_bus *bus, int type)
2882{
2883 static const char *dev_name[HDA_PCM_NTYPES] = {
2884 "Audio", "SPDIF", "HDMI", "Modem"
2885 };
2886 /* starting device index for each PCM type */
2887 static int dev_idx[HDA_PCM_NTYPES] = {
2888 [HDA_PCM_TYPE_AUDIO] = 0,
2889 [HDA_PCM_TYPE_SPDIF] = 1,
2890 [HDA_PCM_TYPE_HDMI] = 3,
2891 [HDA_PCM_TYPE_MODEM] = 6
2892 };
2893 /* normal audio device indices; not linear to keep compatibility */
2894 static int audio_idx[4] = { 0, 2, 4, 5 };
2895 int i, dev;
2896
2897 switch (type) {
2898 case HDA_PCM_TYPE_AUDIO:
2899 for (i = 0; i < ARRAY_SIZE(audio_idx); i++) {
2900 dev = audio_idx[i];
2901 if (!test_bit(dev, bus->pcm_dev_bits))
Takashi Iwai82ad39f2009-03-03 15:00:35 +01002902 goto ok;
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002903 }
Takashi Iwai82ad39f2009-03-03 15:00:35 +01002904 snd_printk(KERN_WARNING "Too many audio devices\n");
2905 return -EAGAIN;
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002906 case HDA_PCM_TYPE_SPDIF:
2907 case HDA_PCM_TYPE_HDMI:
2908 case HDA_PCM_TYPE_MODEM:
2909 dev = dev_idx[type];
2910 if (test_bit(dev, bus->pcm_dev_bits)) {
2911 snd_printk(KERN_WARNING "%s already defined\n",
2912 dev_name[type]);
2913 return -EAGAIN;
2914 }
2915 break;
2916 default:
2917 snd_printk(KERN_WARNING "Invalid PCM type %d\n", type);
2918 return -EINVAL;
2919 }
Takashi Iwai82ad39f2009-03-03 15:00:35 +01002920 ok:
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002921 set_bit(dev, bus->pcm_dev_bits);
2922 return dev;
2923}
2924
2925/*
Takashi Iwai176d5332008-07-30 15:01:44 +02002926 * attach a new PCM stream
2927 */
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002928static int snd_hda_attach_pcm(struct hda_codec *codec, struct hda_pcm *pcm)
Takashi Iwai176d5332008-07-30 15:01:44 +02002929{
Takashi Iwai33fa35e2008-11-06 16:50:40 +01002930 struct hda_bus *bus = codec->bus;
Takashi Iwai176d5332008-07-30 15:01:44 +02002931 struct hda_pcm_stream *info;
2932 int stream, err;
2933
Takashi Iwaib91f0802008-11-04 08:43:08 +01002934 if (snd_BUG_ON(!pcm->name))
Takashi Iwai176d5332008-07-30 15:01:44 +02002935 return -EINVAL;
2936 for (stream = 0; stream < 2; stream++) {
2937 info = &pcm->stream[stream];
2938 if (info->substreams) {
2939 err = set_pcm_default_values(codec, info);
2940 if (err < 0)
2941 return err;
2942 }
2943 }
Takashi Iwai33fa35e2008-11-06 16:50:40 +01002944 return bus->ops.attach_pcm(bus, codec, pcm);
Takashi Iwai176d5332008-07-30 15:01:44 +02002945}
2946
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002947/* assign all PCMs of the given codec */
2948int snd_hda_codec_build_pcms(struct hda_codec *codec)
2949{
2950 unsigned int pcm;
2951 int err;
2952
2953 if (!codec->num_pcms) {
2954 if (!codec->patch_ops.build_pcms)
2955 return 0;
2956 err = codec->patch_ops.build_pcms(codec);
Takashi Iwai6e655bf2009-03-02 10:46:03 +01002957 if (err < 0) {
2958 printk(KERN_ERR "hda_codec: cannot build PCMs"
2959 "for #%d (error %d)\n", codec->addr, err);
2960 err = snd_hda_codec_reset(codec);
2961 if (err < 0) {
2962 printk(KERN_ERR
2963 "hda_codec: cannot revert codec\n");
2964 return err;
2965 }
2966 }
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002967 }
2968 for (pcm = 0; pcm < codec->num_pcms; pcm++) {
2969 struct hda_pcm *cpcm = &codec->pcm_info[pcm];
2970 int dev;
2971
2972 if (!cpcm->stream[0].substreams && !cpcm->stream[1].substreams)
Takashi Iwai41b5b012009-01-20 18:21:23 +01002973 continue; /* no substreams assigned */
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002974
2975 if (!cpcm->pcm) {
2976 dev = get_empty_pcm_device(codec->bus, cpcm->pcm_type);
2977 if (dev < 0)
Takashi Iwai6e655bf2009-03-02 10:46:03 +01002978 continue; /* no fatal error */
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002979 cpcm->device = dev;
2980 err = snd_hda_attach_pcm(codec, cpcm);
Takashi Iwai6e655bf2009-03-02 10:46:03 +01002981 if (err < 0) {
2982 printk(KERN_ERR "hda_codec: cannot attach "
2983 "PCM stream %d for codec #%d\n",
2984 dev, codec->addr);
2985 continue; /* no fatal error */
2986 }
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002987 }
2988 }
2989 return 0;
2990}
2991
Linus Torvalds1da177e2005-04-16 15:20:36 -07002992/**
2993 * snd_hda_build_pcms - build PCM information
2994 * @bus: the BUS
2995 *
2996 * Create PCM information for each codec included in the bus.
2997 *
2998 * The build_pcms codec patch is requested to set up codec->num_pcms and
2999 * codec->pcm_info properly. The array is referred by the top-level driver
3000 * to create its PCM instances.
3001 * The allocated codec->pcm_info should be released in codec->patch_ops.free
3002 * callback.
3003 *
3004 * At least, substreams, channels_min and channels_max must be filled for
3005 * each stream. substreams = 0 indicates that the stream doesn't exist.
3006 * When rates and/or formats are zero, the supported values are queried
3007 * from the given nid. The nid is used also by the default ops.prepare
3008 * and ops.cleanup callbacks.
3009 *
3010 * The driver needs to call ops.open in its open callback. Similarly,
3011 * ops.close is supposed to be called in the close callback.
3012 * ops.prepare should be called in the prepare or hw_params callback
3013 * with the proper parameters for set up.
3014 * ops.cleanup should be called in hw_free for clean up of streams.
3015 *
3016 * This function returns 0 if successfull, or a negative error code.
3017 */
Takashi Iwai529bd6c2008-11-27 14:17:01 +01003018int __devinit snd_hda_build_pcms(struct hda_bus *bus)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003019{
Takashi Iwai0ba21762007-04-16 11:29:14 +02003020 struct hda_codec *codec;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003021
Takashi Iwai0ba21762007-04-16 11:29:14 +02003022 list_for_each_entry(codec, &bus->codec_list, list) {
Takashi Iwai529bd6c2008-11-27 14:17:01 +01003023 int err = snd_hda_codec_build_pcms(codec);
3024 if (err < 0)
3025 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003026 }
3027 return 0;
3028}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003029EXPORT_SYMBOL_HDA(snd_hda_build_pcms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003030
Linus Torvalds1da177e2005-04-16 15:20:36 -07003031/**
3032 * snd_hda_check_board_config - compare the current codec with the config table
3033 * @codec: the HDA codec
Takashi Iwaif5fcc132006-11-24 17:07:44 +01003034 * @num_configs: number of config enums
3035 * @models: array of model name strings
Linus Torvalds1da177e2005-04-16 15:20:36 -07003036 * @tbl: configuration table, terminated by null entries
3037 *
3038 * Compares the modelname or PCI subsystem id of the current codec with the
3039 * given configuration table. If a matching entry is found, returns its
3040 * config value (supposed to be 0 or positive).
3041 *
3042 * If no entries are matching, the function returns a negative value.
3043 */
Takashi Iwai12f288b2007-08-02 15:51:59 +02003044int snd_hda_check_board_config(struct hda_codec *codec,
3045 int num_configs, const char **models,
3046 const struct snd_pci_quirk *tbl)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003047{
Takashi Iwaif44ac832008-07-30 15:01:45 +02003048 if (codec->modelname && models) {
Takashi Iwaif5fcc132006-11-24 17:07:44 +01003049 int i;
3050 for (i = 0; i < num_configs; i++) {
3051 if (models[i] &&
Takashi Iwaif44ac832008-07-30 15:01:45 +02003052 !strcmp(codec->modelname, models[i])) {
Takashi Iwaif5fcc132006-11-24 17:07:44 +01003053 snd_printd(KERN_INFO "hda_codec: model '%s' is "
3054 "selected\n", models[i]);
3055 return i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003056 }
3057 }
3058 }
3059
Takashi Iwaif5fcc132006-11-24 17:07:44 +01003060 if (!codec->bus->pci || !tbl)
3061 return -1;
3062
3063 tbl = snd_pci_quirk_lookup(codec->bus->pci, tbl);
3064 if (!tbl)
3065 return -1;
3066 if (tbl->value >= 0 && tbl->value < num_configs) {
Takashi Iwai62cf8722008-05-20 12:15:15 +02003067#ifdef CONFIG_SND_DEBUG_VERBOSE
Takashi Iwaif5fcc132006-11-24 17:07:44 +01003068 char tmp[10];
3069 const char *model = NULL;
3070 if (models)
3071 model = models[tbl->value];
3072 if (!model) {
3073 sprintf(tmp, "#%d", tbl->value);
3074 model = tmp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003075 }
Takashi Iwaif5fcc132006-11-24 17:07:44 +01003076 snd_printdd(KERN_INFO "hda_codec: model '%s' is selected "
3077 "for config %x:%x (%s)\n",
3078 model, tbl->subvendor, tbl->subdevice,
3079 (tbl->name ? tbl->name : "Unknown device"));
3080#endif
3081 return tbl->value;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003082 }
3083 return -1;
3084}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003085EXPORT_SYMBOL_HDA(snd_hda_check_board_config);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003086
3087/**
Mauro Carvalho Chehab2eda3442008-08-11 10:18:39 +02003088 * snd_hda_check_board_codec_sid_config - compare the current codec
3089 subsystem ID with the
3090 config table
3091
3092 This is important for Gateway notebooks with SB450 HDA Audio
3093 where the vendor ID of the PCI device is:
3094 ATI Technologies Inc SB450 HDA Audio [1002:437b]
3095 and the vendor/subvendor are found only at the codec.
3096
3097 * @codec: the HDA codec
3098 * @num_configs: number of config enums
3099 * @models: array of model name strings
3100 * @tbl: configuration table, terminated by null entries
3101 *
3102 * Compares the modelname or PCI subsystem id of the current codec with the
3103 * given configuration table. If a matching entry is found, returns its
3104 * config value (supposed to be 0 or positive).
3105 *
3106 * If no entries are matching, the function returns a negative value.
3107 */
3108int snd_hda_check_board_codec_sid_config(struct hda_codec *codec,
3109 int num_configs, const char **models,
3110 const struct snd_pci_quirk *tbl)
3111{
3112 const struct snd_pci_quirk *q;
3113
3114 /* Search for codec ID */
3115 for (q = tbl; q->subvendor; q++) {
3116 unsigned long vendorid = (q->subdevice) | (q->subvendor << 16);
3117
3118 if (vendorid == codec->subsystem_id)
3119 break;
3120 }
3121
3122 if (!q->subvendor)
3123 return -1;
3124
3125 tbl = q;
3126
3127 if (tbl->value >= 0 && tbl->value < num_configs) {
3128#ifdef CONFIG_SND_DEBUG_DETECT
3129 char tmp[10];
3130 const char *model = NULL;
3131 if (models)
3132 model = models[tbl->value];
3133 if (!model) {
3134 sprintf(tmp, "#%d", tbl->value);
3135 model = tmp;
3136 }
3137 snd_printdd(KERN_INFO "hda_codec: model '%s' is selected "
3138 "for config %x:%x (%s)\n",
3139 model, tbl->subvendor, tbl->subdevice,
3140 (tbl->name ? tbl->name : "Unknown device"));
3141#endif
3142 return tbl->value;
3143 }
3144 return -1;
3145}
3146EXPORT_SYMBOL_HDA(snd_hda_check_board_codec_sid_config);
3147
3148/**
Linus Torvalds1da177e2005-04-16 15:20:36 -07003149 * snd_hda_add_new_ctls - create controls from the array
3150 * @codec: the HDA codec
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01003151 * @knew: the array of struct snd_kcontrol_new
Linus Torvalds1da177e2005-04-16 15:20:36 -07003152 *
3153 * This helper function creates and add new controls in the given array.
3154 * The array must be terminated with an empty entry as terminator.
3155 *
3156 * Returns 0 if successful, or a negative error code.
3157 */
Takashi Iwai12f288b2007-08-02 15:51:59 +02003158int snd_hda_add_new_ctls(struct hda_codec *codec, struct snd_kcontrol_new *knew)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003159{
Takashi Iwaicb53c622007-08-10 17:21:45 +02003160 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003161
3162 for (; knew->name; knew++) {
Takashi Iwai54d17402005-11-21 16:33:22 +01003163 struct snd_kcontrol *kctl;
3164 kctl = snd_ctl_new1(knew, codec);
Takashi Iwai0ba21762007-04-16 11:29:14 +02003165 if (!kctl)
Takashi Iwai54d17402005-11-21 16:33:22 +01003166 return -ENOMEM;
Takashi Iwaid13bd412008-07-30 15:01:45 +02003167 err = snd_hda_ctl_add(codec, kctl);
Takashi Iwai54d17402005-11-21 16:33:22 +01003168 if (err < 0) {
Takashi Iwai0ba21762007-04-16 11:29:14 +02003169 if (!codec->addr)
Takashi Iwai54d17402005-11-21 16:33:22 +01003170 return err;
3171 kctl = snd_ctl_new1(knew, codec);
Takashi Iwai0ba21762007-04-16 11:29:14 +02003172 if (!kctl)
Takashi Iwai54d17402005-11-21 16:33:22 +01003173 return -ENOMEM;
3174 kctl->id.device = codec->addr;
Takashi Iwaid13bd412008-07-30 15:01:45 +02003175 err = snd_hda_ctl_add(codec, kctl);
Takashi Iwai0ba21762007-04-16 11:29:14 +02003176 if (err < 0)
Takashi Iwai54d17402005-11-21 16:33:22 +01003177 return err;
3178 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003179 }
3180 return 0;
3181}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003182EXPORT_SYMBOL_HDA(snd_hda_add_new_ctls);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003183
Takashi Iwaicb53c622007-08-10 17:21:45 +02003184#ifdef CONFIG_SND_HDA_POWER_SAVE
3185static void hda_set_power_state(struct hda_codec *codec, hda_nid_t fg,
3186 unsigned int power_state);
3187
3188static void hda_power_work(struct work_struct *work)
3189{
3190 struct hda_codec *codec =
3191 container_of(work, struct hda_codec, power_work.work);
Takashi Iwai33fa35e2008-11-06 16:50:40 +01003192 struct hda_bus *bus = codec->bus;
Takashi Iwaicb53c622007-08-10 17:21:45 +02003193
Maxim Levitsky2e492462007-09-03 15:26:57 +02003194 if (!codec->power_on || codec->power_count) {
3195 codec->power_transition = 0;
Takashi Iwaicb53c622007-08-10 17:21:45 +02003196 return;
Maxim Levitsky2e492462007-09-03 15:26:57 +02003197 }
Takashi Iwaicb53c622007-08-10 17:21:45 +02003198
3199 hda_call_codec_suspend(codec);
Takashi Iwai33fa35e2008-11-06 16:50:40 +01003200 if (bus->ops.pm_notify)
3201 bus->ops.pm_notify(bus);
Takashi Iwaicb53c622007-08-10 17:21:45 +02003202}
3203
3204static void hda_keep_power_on(struct hda_codec *codec)
3205{
3206 codec->power_count++;
3207 codec->power_on = 1;
3208}
3209
3210void snd_hda_power_up(struct hda_codec *codec)
3211{
Takashi Iwai33fa35e2008-11-06 16:50:40 +01003212 struct hda_bus *bus = codec->bus;
3213
Takashi Iwaicb53c622007-08-10 17:21:45 +02003214 codec->power_count++;
Takashi Iwaia221e282007-08-16 16:35:33 +02003215 if (codec->power_on || codec->power_transition)
Takashi Iwaicb53c622007-08-10 17:21:45 +02003216 return;
3217
3218 codec->power_on = 1;
Takashi Iwai33fa35e2008-11-06 16:50:40 +01003219 if (bus->ops.pm_notify)
3220 bus->ops.pm_notify(bus);
Takashi Iwaicb53c622007-08-10 17:21:45 +02003221 hda_call_codec_resume(codec);
3222 cancel_delayed_work(&codec->power_work);
Takashi Iwaia221e282007-08-16 16:35:33 +02003223 codec->power_transition = 0;
Takashi Iwaicb53c622007-08-10 17:21:45 +02003224}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003225EXPORT_SYMBOL_HDA(snd_hda_power_up);
Takashi Iwai1289e9e2008-11-27 15:47:11 +01003226
3227#define power_save(codec) \
3228 ((codec)->bus->power_save ? *(codec)->bus->power_save : 0)
Takashi Iwaicb53c622007-08-10 17:21:45 +02003229
Takashi Iwaifee2fba2008-11-27 12:43:28 +01003230#define power_save(codec) \
3231 ((codec)->bus->power_save ? *(codec)->bus->power_save : 0)
3232
Takashi Iwaicb53c622007-08-10 17:21:45 +02003233void snd_hda_power_down(struct hda_codec *codec)
3234{
3235 --codec->power_count;
Takashi Iwaia221e282007-08-16 16:35:33 +02003236 if (!codec->power_on || codec->power_count || codec->power_transition)
Takashi Iwaicb53c622007-08-10 17:21:45 +02003237 return;
Takashi Iwaifee2fba2008-11-27 12:43:28 +01003238 if (power_save(codec)) {
Takashi Iwaia221e282007-08-16 16:35:33 +02003239 codec->power_transition = 1; /* avoid reentrance */
Takashi Iwaic107b412009-01-13 17:46:37 +01003240 queue_delayed_work(codec->bus->workq, &codec->power_work,
Takashi Iwaifee2fba2008-11-27 12:43:28 +01003241 msecs_to_jiffies(power_save(codec) * 1000));
Takashi Iwaia221e282007-08-16 16:35:33 +02003242 }
Takashi Iwaicb53c622007-08-10 17:21:45 +02003243}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003244EXPORT_SYMBOL_HDA(snd_hda_power_down);
Takashi Iwaicb53c622007-08-10 17:21:45 +02003245
3246int snd_hda_check_amp_list_power(struct hda_codec *codec,
3247 struct hda_loopback_check *check,
3248 hda_nid_t nid)
3249{
3250 struct hda_amp_list *p;
3251 int ch, v;
3252
3253 if (!check->amplist)
3254 return 0;
3255 for (p = check->amplist; p->nid; p++) {
3256 if (p->nid == nid)
3257 break;
3258 }
3259 if (!p->nid)
3260 return 0; /* nothing changed */
3261
3262 for (p = check->amplist; p->nid; p++) {
3263 for (ch = 0; ch < 2; ch++) {
3264 v = snd_hda_codec_amp_read(codec, p->nid, ch, p->dir,
3265 p->idx);
3266 if (!(v & HDA_AMP_MUTE) && v > 0) {
3267 if (!check->power_on) {
3268 check->power_on = 1;
3269 snd_hda_power_up(codec);
3270 }
3271 return 1;
3272 }
3273 }
3274 }
3275 if (check->power_on) {
3276 check->power_on = 0;
3277 snd_hda_power_down(codec);
3278 }
3279 return 0;
3280}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003281EXPORT_SYMBOL_HDA(snd_hda_check_amp_list_power);
Takashi Iwaicb53c622007-08-10 17:21:45 +02003282#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07003283
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01003284/*
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01003285 * Channel mode helper
3286 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003287int snd_hda_ch_mode_info(struct hda_codec *codec,
3288 struct snd_ctl_elem_info *uinfo,
3289 const struct hda_channel_mode *chmode,
3290 int num_chmodes)
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01003291{
3292 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
3293 uinfo->count = 1;
3294 uinfo->value.enumerated.items = num_chmodes;
3295 if (uinfo->value.enumerated.item >= num_chmodes)
3296 uinfo->value.enumerated.item = num_chmodes - 1;
3297 sprintf(uinfo->value.enumerated.name, "%dch",
3298 chmode[uinfo->value.enumerated.item].channels);
3299 return 0;
3300}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003301EXPORT_SYMBOL_HDA(snd_hda_ch_mode_info);
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01003302
Takashi Iwai0ba21762007-04-16 11:29:14 +02003303int snd_hda_ch_mode_get(struct hda_codec *codec,
3304 struct snd_ctl_elem_value *ucontrol,
3305 const struct hda_channel_mode *chmode,
3306 int num_chmodes,
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01003307 int max_channels)
3308{
3309 int i;
3310
3311 for (i = 0; i < num_chmodes; i++) {
3312 if (max_channels == chmode[i].channels) {
3313 ucontrol->value.enumerated.item[0] = i;
3314 break;
3315 }
3316 }
3317 return 0;
3318}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003319EXPORT_SYMBOL_HDA(snd_hda_ch_mode_get);
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01003320
Takashi Iwai0ba21762007-04-16 11:29:14 +02003321int snd_hda_ch_mode_put(struct hda_codec *codec,
3322 struct snd_ctl_elem_value *ucontrol,
3323 const struct hda_channel_mode *chmode,
3324 int num_chmodes,
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01003325 int *max_channelsp)
3326{
3327 unsigned int mode;
3328
3329 mode = ucontrol->value.enumerated.item[0];
Takashi Iwai68ea7b22007-11-15 15:54:38 +01003330 if (mode >= num_chmodes)
3331 return -EINVAL;
Takashi Iwai82beb8f2007-08-10 17:09:26 +02003332 if (*max_channelsp == chmode[mode].channels)
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01003333 return 0;
3334 /* change the current channel setting */
3335 *max_channelsp = chmode[mode].channels;
3336 if (chmode[mode].sequence)
Takashi Iwai82beb8f2007-08-10 17:09:26 +02003337 snd_hda_sequence_write_cache(codec, chmode[mode].sequence);
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01003338 return 1;
3339}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003340EXPORT_SYMBOL_HDA(snd_hda_ch_mode_put);
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01003341
Linus Torvalds1da177e2005-04-16 15:20:36 -07003342/*
3343 * input MUX helper
3344 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003345int snd_hda_input_mux_info(const struct hda_input_mux *imux,
3346 struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003347{
3348 unsigned int index;
3349
3350 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
3351 uinfo->count = 1;
3352 uinfo->value.enumerated.items = imux->num_items;
Takashi Iwai5513b0c2007-10-09 11:58:41 +02003353 if (!imux->num_items)
3354 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003355 index = uinfo->value.enumerated.item;
3356 if (index >= imux->num_items)
3357 index = imux->num_items - 1;
3358 strcpy(uinfo->value.enumerated.name, imux->items[index].label);
3359 return 0;
3360}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003361EXPORT_SYMBOL_HDA(snd_hda_input_mux_info);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003362
Takashi Iwai0ba21762007-04-16 11:29:14 +02003363int snd_hda_input_mux_put(struct hda_codec *codec,
3364 const struct hda_input_mux *imux,
3365 struct snd_ctl_elem_value *ucontrol,
3366 hda_nid_t nid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003367 unsigned int *cur_val)
3368{
3369 unsigned int idx;
3370
Takashi Iwai5513b0c2007-10-09 11:58:41 +02003371 if (!imux->num_items)
3372 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003373 idx = ucontrol->value.enumerated.item[0];
3374 if (idx >= imux->num_items)
3375 idx = imux->num_items - 1;
Takashi Iwai82beb8f2007-08-10 17:09:26 +02003376 if (*cur_val == idx)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003377 return 0;
Takashi Iwai82beb8f2007-08-10 17:09:26 +02003378 snd_hda_codec_write_cache(codec, nid, 0, AC_VERB_SET_CONNECT_SEL,
3379 imux->items[idx].index);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003380 *cur_val = idx;
3381 return 1;
3382}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003383EXPORT_SYMBOL_HDA(snd_hda_input_mux_put);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003384
3385
3386/*
3387 * Multi-channel / digital-out PCM helper functions
3388 */
3389
Takashi Iwai6b97eb42007-04-05 14:51:48 +02003390/* setup SPDIF output stream */
3391static void setup_dig_out_stream(struct hda_codec *codec, hda_nid_t nid,
3392 unsigned int stream_tag, unsigned int format)
3393{
3394 /* turn off SPDIF once; otherwise the IEC958 bits won't be updated */
Takashi Iwai2f728532008-09-25 16:32:41 +02003395 if (codec->spdif_status_reset && (codec->spdif_ctls & AC_DIG1_ENABLE))
3396 set_dig_out_convert(codec, nid,
3397 codec->spdif_ctls & ~AC_DIG1_ENABLE & 0xff,
3398 -1);
Takashi Iwai6b97eb42007-04-05 14:51:48 +02003399 snd_hda_codec_setup_stream(codec, nid, stream_tag, 0, format);
Takashi Iwai2f728532008-09-25 16:32:41 +02003400 if (codec->slave_dig_outs) {
3401 hda_nid_t *d;
3402 for (d = codec->slave_dig_outs; *d; d++)
3403 snd_hda_codec_setup_stream(codec, *d, stream_tag, 0,
3404 format);
Matthew Ranostayde51ca12008-09-07 14:31:40 -04003405 }
Takashi Iwai2f728532008-09-25 16:32:41 +02003406 /* turn on again (if needed) */
3407 if (codec->spdif_status_reset && (codec->spdif_ctls & AC_DIG1_ENABLE))
3408 set_dig_out_convert(codec, nid,
3409 codec->spdif_ctls & 0xff, -1);
3410}
Matthew Ranostayde51ca12008-09-07 14:31:40 -04003411
Takashi Iwai2f728532008-09-25 16:32:41 +02003412static void cleanup_dig_out_stream(struct hda_codec *codec, hda_nid_t nid)
3413{
3414 snd_hda_codec_cleanup_stream(codec, nid);
3415 if (codec->slave_dig_outs) {
3416 hda_nid_t *d;
3417 for (d = codec->slave_dig_outs; *d; d++)
3418 snd_hda_codec_cleanup_stream(codec, *d);
3419 }
Takashi Iwai6b97eb42007-04-05 14:51:48 +02003420}
3421
Linus Torvalds1da177e2005-04-16 15:20:36 -07003422/*
3423 * open the digital out in the exclusive mode
3424 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003425int snd_hda_multi_out_dig_open(struct hda_codec *codec,
3426 struct hda_multi_out *mout)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003427{
Ingo Molnar62932df2006-01-16 16:34:20 +01003428 mutex_lock(&codec->spdif_mutex);
Takashi Iwai5930ca42007-04-16 11:23:56 +02003429 if (mout->dig_out_used == HDA_DIG_ANALOG_DUP)
3430 /* already opened as analog dup; reset it once */
Takashi Iwai2f728532008-09-25 16:32:41 +02003431 cleanup_dig_out_stream(codec, mout->dig_out_nid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003432 mout->dig_out_used = HDA_DIG_EXCLUSIVE;
Ingo Molnar62932df2006-01-16 16:34:20 +01003433 mutex_unlock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003434 return 0;
3435}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003436EXPORT_SYMBOL_HDA(snd_hda_multi_out_dig_open);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003437
Takashi Iwai6b97eb42007-04-05 14:51:48 +02003438int snd_hda_multi_out_dig_prepare(struct hda_codec *codec,
3439 struct hda_multi_out *mout,
3440 unsigned int stream_tag,
3441 unsigned int format,
3442 struct snd_pcm_substream *substream)
3443{
3444 mutex_lock(&codec->spdif_mutex);
3445 setup_dig_out_stream(codec, mout->dig_out_nid, stream_tag, format);
3446 mutex_unlock(&codec->spdif_mutex);
3447 return 0;
3448}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003449EXPORT_SYMBOL_HDA(snd_hda_multi_out_dig_prepare);
Takashi Iwai6b97eb42007-04-05 14:51:48 +02003450
Takashi Iwai9411e212009-02-13 11:32:28 +01003451int snd_hda_multi_out_dig_cleanup(struct hda_codec *codec,
3452 struct hda_multi_out *mout)
3453{
3454 mutex_lock(&codec->spdif_mutex);
3455 cleanup_dig_out_stream(codec, mout->dig_out_nid);
3456 mutex_unlock(&codec->spdif_mutex);
3457 return 0;
3458}
3459EXPORT_SYMBOL_HDA(snd_hda_multi_out_dig_cleanup);
3460
Linus Torvalds1da177e2005-04-16 15:20:36 -07003461/*
3462 * release the digital out
3463 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003464int snd_hda_multi_out_dig_close(struct hda_codec *codec,
3465 struct hda_multi_out *mout)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003466{
Ingo Molnar62932df2006-01-16 16:34:20 +01003467 mutex_lock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003468 mout->dig_out_used = 0;
Ingo Molnar62932df2006-01-16 16:34:20 +01003469 mutex_unlock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003470 return 0;
3471}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003472EXPORT_SYMBOL_HDA(snd_hda_multi_out_dig_close);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003473
3474/*
3475 * set up more restrictions for analog out
3476 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003477int snd_hda_multi_out_analog_open(struct hda_codec *codec,
3478 struct hda_multi_out *mout,
Takashi Iwai9a081602008-02-12 18:37:26 +01003479 struct snd_pcm_substream *substream,
3480 struct hda_pcm_stream *hinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003481{
Takashi Iwai9a081602008-02-12 18:37:26 +01003482 struct snd_pcm_runtime *runtime = substream->runtime;
3483 runtime->hw.channels_max = mout->max_channels;
3484 if (mout->dig_out_nid) {
3485 if (!mout->analog_rates) {
3486 mout->analog_rates = hinfo->rates;
3487 mout->analog_formats = hinfo->formats;
3488 mout->analog_maxbps = hinfo->maxbps;
3489 } else {
3490 runtime->hw.rates = mout->analog_rates;
3491 runtime->hw.formats = mout->analog_formats;
3492 hinfo->maxbps = mout->analog_maxbps;
3493 }
3494 if (!mout->spdif_rates) {
3495 snd_hda_query_supported_pcm(codec, mout->dig_out_nid,
3496 &mout->spdif_rates,
3497 &mout->spdif_formats,
3498 &mout->spdif_maxbps);
3499 }
3500 mutex_lock(&codec->spdif_mutex);
3501 if (mout->share_spdif) {
Takashi Iwai022b4662009-07-03 23:03:30 +02003502 if ((runtime->hw.rates & mout->spdif_rates) &&
3503 (runtime->hw.formats & mout->spdif_formats)) {
3504 runtime->hw.rates &= mout->spdif_rates;
3505 runtime->hw.formats &= mout->spdif_formats;
3506 if (mout->spdif_maxbps < hinfo->maxbps)
3507 hinfo->maxbps = mout->spdif_maxbps;
3508 } else {
3509 mout->share_spdif = 0;
3510 /* FIXME: need notify? */
3511 }
Takashi Iwai9a081602008-02-12 18:37:26 +01003512 }
Frederik Deweerdteaa99852008-04-14 13:11:44 +02003513 mutex_unlock(&codec->spdif_mutex);
Takashi Iwai9a081602008-02-12 18:37:26 +01003514 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003515 return snd_pcm_hw_constraint_step(substream->runtime, 0,
3516 SNDRV_PCM_HW_PARAM_CHANNELS, 2);
3517}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003518EXPORT_SYMBOL_HDA(snd_hda_multi_out_analog_open);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003519
3520/*
3521 * set up the i/o for analog out
3522 * when the digital out is available, copy the front out to digital out, too.
3523 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003524int snd_hda_multi_out_analog_prepare(struct hda_codec *codec,
3525 struct hda_multi_out *mout,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003526 unsigned int stream_tag,
3527 unsigned int format,
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01003528 struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003529{
3530 hda_nid_t *nids = mout->dac_nids;
3531 int chs = substream->runtime->channels;
3532 int i;
3533
Ingo Molnar62932df2006-01-16 16:34:20 +01003534 mutex_lock(&codec->spdif_mutex);
Takashi Iwai9a081602008-02-12 18:37:26 +01003535 if (mout->dig_out_nid && mout->share_spdif &&
3536 mout->dig_out_used != HDA_DIG_EXCLUSIVE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003537 if (chs == 2 &&
Takashi Iwai0ba21762007-04-16 11:29:14 +02003538 snd_hda_is_supported_format(codec, mout->dig_out_nid,
3539 format) &&
3540 !(codec->spdif_status & IEC958_AES0_NONAUDIO)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003541 mout->dig_out_used = HDA_DIG_ANALOG_DUP;
Takashi Iwai6b97eb42007-04-05 14:51:48 +02003542 setup_dig_out_stream(codec, mout->dig_out_nid,
3543 stream_tag, format);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003544 } else {
3545 mout->dig_out_used = 0;
Takashi Iwai2f728532008-09-25 16:32:41 +02003546 cleanup_dig_out_stream(codec, mout->dig_out_nid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003547 }
3548 }
Ingo Molnar62932df2006-01-16 16:34:20 +01003549 mutex_unlock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003550
3551 /* front */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003552 snd_hda_codec_setup_stream(codec, nids[HDA_FRONT], stream_tag,
3553 0, format);
Takashi Iwaid29240c2007-10-26 12:35:56 +02003554 if (!mout->no_share_stream &&
3555 mout->hp_nid && mout->hp_nid != nids[HDA_FRONT])
Linus Torvalds1da177e2005-04-16 15:20:36 -07003556 /* headphone out will just decode front left/right (stereo) */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003557 snd_hda_codec_setup_stream(codec, mout->hp_nid, stream_tag,
3558 0, format);
Takashi Iwai82bc9552006-03-21 11:24:42 +01003559 /* extra outputs copied from front */
3560 for (i = 0; i < ARRAY_SIZE(mout->extra_out_nid); i++)
Takashi Iwaid29240c2007-10-26 12:35:56 +02003561 if (!mout->no_share_stream && mout->extra_out_nid[i])
Takashi Iwai82bc9552006-03-21 11:24:42 +01003562 snd_hda_codec_setup_stream(codec,
3563 mout->extra_out_nid[i],
3564 stream_tag, 0, format);
3565
Linus Torvalds1da177e2005-04-16 15:20:36 -07003566 /* surrounds */
3567 for (i = 1; i < mout->num_dacs; i++) {
Takashi Iwai4b3acaf2005-06-10 19:48:10 +02003568 if (chs >= (i + 1) * 2) /* independent out */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003569 snd_hda_codec_setup_stream(codec, nids[i], stream_tag,
3570 i * 2, format);
Takashi Iwaid29240c2007-10-26 12:35:56 +02003571 else if (!mout->no_share_stream) /* copy front */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003572 snd_hda_codec_setup_stream(codec, nids[i], stream_tag,
3573 0, format);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003574 }
3575 return 0;
3576}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003577EXPORT_SYMBOL_HDA(snd_hda_multi_out_analog_prepare);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003578
3579/*
3580 * clean up the setting for analog out
3581 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003582int snd_hda_multi_out_analog_cleanup(struct hda_codec *codec,
3583 struct hda_multi_out *mout)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003584{
3585 hda_nid_t *nids = mout->dac_nids;
3586 int i;
3587
3588 for (i = 0; i < mout->num_dacs; i++)
Takashi Iwai888afa12008-03-18 09:57:50 +01003589 snd_hda_codec_cleanup_stream(codec, nids[i]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003590 if (mout->hp_nid)
Takashi Iwai888afa12008-03-18 09:57:50 +01003591 snd_hda_codec_cleanup_stream(codec, mout->hp_nid);
Takashi Iwai82bc9552006-03-21 11:24:42 +01003592 for (i = 0; i < ARRAY_SIZE(mout->extra_out_nid); i++)
3593 if (mout->extra_out_nid[i])
Takashi Iwai888afa12008-03-18 09:57:50 +01003594 snd_hda_codec_cleanup_stream(codec,
3595 mout->extra_out_nid[i]);
Ingo Molnar62932df2006-01-16 16:34:20 +01003596 mutex_lock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003597 if (mout->dig_out_nid && mout->dig_out_used == HDA_DIG_ANALOG_DUP) {
Takashi Iwai2f728532008-09-25 16:32:41 +02003598 cleanup_dig_out_stream(codec, mout->dig_out_nid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003599 mout->dig_out_used = 0;
3600 }
Ingo Molnar62932df2006-01-16 16:34:20 +01003601 mutex_unlock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003602 return 0;
3603}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003604EXPORT_SYMBOL_HDA(snd_hda_multi_out_analog_cleanup);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003605
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003606/*
Wu Fengguang6b345002008-10-07 14:21:41 +08003607 * Helper for automatic pin configuration
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003608 */
Kailang Yangdf694da2005-12-05 19:42:22 +01003609
Takashi Iwai12f288b2007-08-02 15:51:59 +02003610static int is_in_nid_list(hda_nid_t nid, hda_nid_t *list)
Kailang Yangdf694da2005-12-05 19:42:22 +01003611{
3612 for (; *list; list++)
3613 if (*list == nid)
3614 return 1;
3615 return 0;
3616}
3617
Steve Longerbeam81937d32007-05-08 15:33:03 +02003618
3619/*
3620 * Sort an associated group of pins according to their sequence numbers.
3621 */
3622static void sort_pins_by_sequence(hda_nid_t * pins, short * sequences,
3623 int num_pins)
3624{
3625 int i, j;
3626 short seq;
3627 hda_nid_t nid;
3628
3629 for (i = 0; i < num_pins; i++) {
3630 for (j = i + 1; j < num_pins; j++) {
3631 if (sequences[i] > sequences[j]) {
3632 seq = sequences[i];
3633 sequences[i] = sequences[j];
3634 sequences[j] = seq;
3635 nid = pins[i];
3636 pins[i] = pins[j];
3637 pins[j] = nid;
3638 }
3639 }
3640 }
3641}
3642
3643
Takashi Iwai82bc9552006-03-21 11:24:42 +01003644/*
3645 * Parse all pin widgets and store the useful pin nids to cfg
3646 *
3647 * The number of line-outs or any primary output is stored in line_outs,
3648 * and the corresponding output pins are assigned to line_out_pins[],
3649 * in the order of front, rear, CLFE, side, ...
3650 *
3651 * If more extra outputs (speaker and headphone) are found, the pins are
Takashi Iwaieb06ed82006-09-20 17:10:27 +02003652 * assisnged to hp_pins[] and speaker_pins[], respectively. If no line-out jack
Takashi Iwai82bc9552006-03-21 11:24:42 +01003653 * is detected, one of speaker of HP pins is assigned as the primary
3654 * output, i.e. to line_out_pins[0]. So, line_outs is always positive
3655 * if any analog output exists.
3656 *
3657 * The analog input pins are assigned to input_pins array.
3658 * The digital input/output pins are assigned to dig_in_pin and dig_out_pin,
3659 * respectively.
3660 */
Takashi Iwai12f288b2007-08-02 15:51:59 +02003661int snd_hda_parse_pin_def_config(struct hda_codec *codec,
3662 struct auto_pin_cfg *cfg,
3663 hda_nid_t *ignore_nids)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003664{
Takashi Iwai0ef6ce72008-01-22 15:35:37 +01003665 hda_nid_t nid, end_nid;
Steve Longerbeam81937d32007-05-08 15:33:03 +02003666 short seq, assoc_line_out, assoc_speaker;
3667 short sequences_line_out[ARRAY_SIZE(cfg->line_out_pins)];
3668 short sequences_speaker[ARRAY_SIZE(cfg->speaker_pins)];
Takashi Iwaif889fa92007-10-31 15:49:32 +01003669 short sequences_hp[ARRAY_SIZE(cfg->hp_pins)];
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003670
3671 memset(cfg, 0, sizeof(*cfg));
3672
Steve Longerbeam81937d32007-05-08 15:33:03 +02003673 memset(sequences_line_out, 0, sizeof(sequences_line_out));
3674 memset(sequences_speaker, 0, sizeof(sequences_speaker));
Takashi Iwaif889fa92007-10-31 15:49:32 +01003675 memset(sequences_hp, 0, sizeof(sequences_hp));
Steve Longerbeam81937d32007-05-08 15:33:03 +02003676 assoc_line_out = assoc_speaker = 0;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003677
Takashi Iwai0ef6ce72008-01-22 15:35:37 +01003678 end_nid = codec->start_nid + codec->num_nodes;
3679 for (nid = codec->start_nid; nid < end_nid; nid++) {
Takashi Iwai54d17402005-11-21 16:33:22 +01003680 unsigned int wid_caps = get_wcaps(codec, nid);
Takashi Iwai0ba21762007-04-16 11:29:14 +02003681 unsigned int wid_type =
3682 (wid_caps & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT;
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");