blob: eea91c3bd420d62e505b2bdd880dc5b2e53d724b [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 Iwaie5f14242009-07-01 18:11:44 +020047 { 0x1013, "Cirrus Logic" },
Takashi Iwaia9226252006-09-17 22:05:54 +020048 { 0x1057, "Motorola" },
Takashi Iwaic8cd1282008-02-13 16:59:29 +010049 { 0x1095, "Silicon Image" },
Takashi Iwai31117b72008-12-16 14:43:21 +010050 { 0x10de, "Nvidia" },
Takashi Iwaic8cd1282008-02-13 16:59:29 +010051 { 0x10ec, "Realtek" },
Takashi Iwai4e01f542009-04-16 08:53:34 +020052 { 0x1102, "Creative" },
Joseph Chanc577b8a2006-11-29 15:29:40 +010053 { 0x1106, "VIA" },
Matthew Ranostay7f168592007-10-18 17:38:17 +020054 { 0x111d, "IDT" },
Takashi Iwaic8cd1282008-02-13 16:59:29 +010055 { 0x11c1, "LSI" },
Takashi Iwai54b903e2005-05-15 14:30:10 +020056 { 0x11d4, "Analog Devices" },
Linus Torvalds1da177e2005-04-16 15:20:36 -070057 { 0x13f6, "C-Media" },
Takashi Iwaia9226252006-09-17 22:05:54 +020058 { 0x14f1, "Conexant" },
Takashi Iwaic8cd1282008-02-13 16:59:29 +010059 { 0x17e8, "Chrontel" },
60 { 0x1854, "LG" },
Mark Brown8199de32008-10-28 14:50:13 +000061 { 0x1aec, "Wolfson Microelectronics" },
Linus Torvalds1da177e2005-04-16 15:20:36 -070062 { 0x434d, "C-Media" },
Takashi Iwai74c61132008-12-18 09:11:33 +010063 { 0x8086, "Intel" },
Matt2f2f4252005-04-13 14:45:30 +020064 { 0x8384, "SigmaTel" },
Linus Torvalds1da177e2005-04-16 15:20:36 -070065 {} /* terminator */
66};
67
Takashi Iwai1289e9e2008-11-27 15:47:11 +010068static DEFINE_MUTEX(preset_mutex);
69static LIST_HEAD(hda_preset_tables);
70
71int snd_hda_add_codec_preset(struct hda_codec_preset_list *preset)
72{
73 mutex_lock(&preset_mutex);
74 list_add_tail(&preset->list, &hda_preset_tables);
75 mutex_unlock(&preset_mutex);
76 return 0;
77}
Takashi Iwaiff7a3262008-11-28 15:17:06 +010078EXPORT_SYMBOL_HDA(snd_hda_add_codec_preset);
Takashi Iwai1289e9e2008-11-27 15:47:11 +010079
80int snd_hda_delete_codec_preset(struct hda_codec_preset_list *preset)
81{
82 mutex_lock(&preset_mutex);
83 list_del(&preset->list);
84 mutex_unlock(&preset_mutex);
85 return 0;
86}
Takashi Iwaiff7a3262008-11-28 15:17:06 +010087EXPORT_SYMBOL_HDA(snd_hda_delete_codec_preset);
Linus Torvalds1da177e2005-04-16 15:20:36 -070088
Takashi Iwaicb53c622007-08-10 17:21:45 +020089#ifdef CONFIG_SND_HDA_POWER_SAVE
90static void hda_power_work(struct work_struct *work);
91static void hda_keep_power_on(struct hda_codec *codec);
92#else
93static inline void hda_keep_power_on(struct hda_codec *codec) {}
94#endif
95
Matthew Ranostay50a9f792008-10-25 01:05:45 -040096const char *snd_hda_get_jack_location(u32 cfg)
97{
98 static char *bases[7] = {
99 "N/A", "Rear", "Front", "Left", "Right", "Top", "Bottom",
100 };
101 static unsigned char specials_idx[] = {
102 0x07, 0x08,
103 0x17, 0x18, 0x19,
104 0x37, 0x38
105 };
106 static char *specials[] = {
107 "Rear Panel", "Drive Bar",
108 "Riser", "HDMI", "ATAPI",
109 "Mobile-In", "Mobile-Out"
110 };
111 int i;
112 cfg = (cfg & AC_DEFCFG_LOCATION) >> AC_DEFCFG_LOCATION_SHIFT;
113 if ((cfg & 0x0f) < 7)
114 return bases[cfg & 0x0f];
115 for (i = 0; i < ARRAY_SIZE(specials_idx); i++) {
116 if (cfg == specials_idx[i])
117 return specials[i];
118 }
119 return "UNKNOWN";
120}
Takashi Iwaiff7a3262008-11-28 15:17:06 +0100121EXPORT_SYMBOL_HDA(snd_hda_get_jack_location);
Matthew Ranostay50a9f792008-10-25 01:05:45 -0400122
123const char *snd_hda_get_jack_connectivity(u32 cfg)
124{
125 static char *jack_locations[4] = { "Ext", "Int", "Sep", "Oth" };
126
127 return jack_locations[(cfg >> (AC_DEFCFG_LOCATION_SHIFT + 4)) & 3];
128}
Takashi Iwaiff7a3262008-11-28 15:17:06 +0100129EXPORT_SYMBOL_HDA(snd_hda_get_jack_connectivity);
Matthew Ranostay50a9f792008-10-25 01:05:45 -0400130
131const char *snd_hda_get_jack_type(u32 cfg)
132{
133 static char *jack_types[16] = {
134 "Line Out", "Speaker", "HP Out", "CD",
135 "SPDIF Out", "Digital Out", "Modem Line", "Modem Hand",
136 "Line In", "Aux", "Mic", "Telephony",
137 "SPDIF In", "Digitial In", "Reserved", "Other"
138 };
139
140 return jack_types[(cfg & AC_DEFCFG_DEVICE)
141 >> AC_DEFCFG_DEVICE_SHIFT];
142}
Takashi Iwaiff7a3262008-11-28 15:17:06 +0100143EXPORT_SYMBOL_HDA(snd_hda_get_jack_type);
Matthew Ranostay50a9f792008-10-25 01:05:45 -0400144
Takashi Iwai33fa35e2008-11-06 16:50:40 +0100145/*
146 * Compose a 32bit command word to be sent to the HD-audio controller
147 */
148static inline unsigned int
149make_codec_cmd(struct hda_codec *codec, hda_nid_t nid, int direct,
150 unsigned int verb, unsigned int parm)
151{
152 u32 val;
153
154 val = (u32)(codec->addr & 0x0f) << 28;
155 val |= (u32)direct << 27;
156 val |= (u32)nid << 20;
157 val |= verb << 8;
158 val |= parm;
159 return val;
160}
161
Takashi Iwaiaa2936f2009-05-26 16:07:57 +0200162/*
163 * Send and receive a verb
164 */
165static int codec_exec_verb(struct hda_codec *codec, unsigned int cmd,
166 unsigned int *res)
167{
168 struct hda_bus *bus = codec->bus;
Takashi Iwai8dd78332009-06-02 01:16:07 +0200169 int err;
Takashi Iwaiaa2936f2009-05-26 16:07:57 +0200170
171 if (res)
172 *res = -1;
Takashi Iwai8dd78332009-06-02 01:16:07 +0200173 again:
Takashi Iwaiaa2936f2009-05-26 16:07:57 +0200174 snd_hda_power_up(codec);
175 mutex_lock(&bus->cmd_mutex);
Takashi Iwaiaa2936f2009-05-26 16:07:57 +0200176 err = bus->ops.command(bus, cmd);
Takashi Iwai8dd78332009-06-02 01:16:07 +0200177 if (!err && res)
178 *res = bus->ops.get_response(bus);
Takashi Iwaiaa2936f2009-05-26 16:07:57 +0200179 mutex_unlock(&bus->cmd_mutex);
180 snd_hda_power_down(codec);
Takashi Iwai8dd78332009-06-02 01:16:07 +0200181 if (res && *res == -1 && bus->rirb_error) {
182 if (bus->response_reset) {
183 snd_printd("hda_codec: resetting BUS due to "
184 "fatal communication error\n");
185 bus->ops.bus_reset(bus);
186 }
187 goto again;
188 }
189 /* clear reset-flag when the communication gets recovered */
190 if (!err)
191 bus->response_reset = 0;
Takashi Iwaiaa2936f2009-05-26 16:07:57 +0200192 return err;
193}
194
Linus Torvalds1da177e2005-04-16 15:20:36 -0700195/**
196 * snd_hda_codec_read - send a command and get the response
197 * @codec: the HDA codec
198 * @nid: NID to send the command
199 * @direct: direct flag
200 * @verb: the verb to send
201 * @parm: the parameter for the verb
202 *
203 * Send a single command and read the corresponding response.
204 *
205 * Returns the obtained response value, or -1 for an error.
206 */
Takashi Iwai0ba21762007-04-16 11:29:14 +0200207unsigned int snd_hda_codec_read(struct hda_codec *codec, hda_nid_t nid,
208 int direct,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700209 unsigned int verb, unsigned int parm)
210{
Takashi Iwaiaa2936f2009-05-26 16:07:57 +0200211 unsigned cmd = make_codec_cmd(codec, nid, direct, verb, parm);
212 unsigned int res;
213 codec_exec_verb(codec, cmd, &res);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700214 return res;
215}
Takashi Iwaiff7a3262008-11-28 15:17:06 +0100216EXPORT_SYMBOL_HDA(snd_hda_codec_read);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700217
218/**
219 * snd_hda_codec_write - send a single command without waiting for response
220 * @codec: the HDA codec
221 * @nid: NID to send the command
222 * @direct: direct flag
223 * @verb: the verb to send
224 * @parm: the parameter for the verb
225 *
226 * Send a single command without waiting for response.
227 *
228 * Returns 0 if successful, or a negative error code.
229 */
230int snd_hda_codec_write(struct hda_codec *codec, hda_nid_t nid, int direct,
231 unsigned int verb, unsigned int parm)
232{
Takashi Iwaiaa2936f2009-05-26 16:07:57 +0200233 unsigned int cmd = make_codec_cmd(codec, nid, direct, verb, parm);
Takashi Iwai33fa35e2008-11-06 16:50:40 +0100234 unsigned int res;
Takashi Iwaib20f3b82009-06-02 01:20:22 +0200235 return codec_exec_verb(codec, cmd,
236 codec->bus->sync_write ? &res : NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700237}
Takashi Iwaiff7a3262008-11-28 15:17:06 +0100238EXPORT_SYMBOL_HDA(snd_hda_codec_write);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700239
240/**
241 * snd_hda_sequence_write - sequence writes
242 * @codec: the HDA codec
243 * @seq: VERB array to send
244 *
245 * Send the commands sequentially from the given array.
246 * The array must be terminated with NID=0.
247 */
248void snd_hda_sequence_write(struct hda_codec *codec, const struct hda_verb *seq)
249{
250 for (; seq->nid; seq++)
251 snd_hda_codec_write(codec, seq->nid, 0, seq->verb, seq->param);
252}
Takashi Iwaiff7a3262008-11-28 15:17:06 +0100253EXPORT_SYMBOL_HDA(snd_hda_sequence_write);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700254
255/**
256 * snd_hda_get_sub_nodes - get the range of sub nodes
257 * @codec: the HDA codec
258 * @nid: NID to parse
259 * @start_id: the pointer to store the start NID
260 *
261 * Parse the NID and store the start NID of its sub-nodes.
262 * Returns the number of sub-nodes.
263 */
Takashi Iwai0ba21762007-04-16 11:29:14 +0200264int snd_hda_get_sub_nodes(struct hda_codec *codec, hda_nid_t nid,
265 hda_nid_t *start_id)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700266{
267 unsigned int parm;
268
269 parm = snd_hda_param_read(codec, nid, AC_PAR_NODE_COUNT);
Danny Tholene8a7f132007-09-11 21:41:56 +0200270 if (parm == -1)
271 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700272 *start_id = (parm >> 16) & 0x7fff;
273 return (int)(parm & 0x7fff);
274}
Takashi Iwaiff7a3262008-11-28 15:17:06 +0100275EXPORT_SYMBOL_HDA(snd_hda_get_sub_nodes);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700276
277/**
278 * snd_hda_get_connections - get connection list
279 * @codec: the HDA codec
280 * @nid: NID to parse
281 * @conn_list: connection list array
282 * @max_conns: max. number of connections to store
283 *
284 * Parses the connection list of the given widget and stores the list
285 * of NIDs.
286 *
287 * Returns the number of connections, or a negative error code.
288 */
289int snd_hda_get_connections(struct hda_codec *codec, hda_nid_t nid,
290 hda_nid_t *conn_list, int max_conns)
291{
292 unsigned int parm;
Takashi Iwai54d17402005-11-21 16:33:22 +0100293 int i, conn_len, conns;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700294 unsigned int shift, num_elems, mask;
Takashi Iwai54d17402005-11-21 16:33:22 +0100295 hda_nid_t prev_nid;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700296
Takashi Iwaida3cec32008-08-08 17:12:14 +0200297 if (snd_BUG_ON(!conn_list || max_conns <= 0))
298 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700299
300 parm = snd_hda_param_read(codec, nid, AC_PAR_CONNLIST_LEN);
301 if (parm & AC_CLIST_LONG) {
302 /* long form */
303 shift = 16;
304 num_elems = 2;
305 } else {
306 /* short form */
307 shift = 8;
308 num_elems = 4;
309 }
310 conn_len = parm & AC_CLIST_LENGTH;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700311 mask = (1 << (shift-1)) - 1;
312
Takashi Iwai0ba21762007-04-16 11:29:14 +0200313 if (!conn_len)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700314 return 0; /* no connection */
315
316 if (conn_len == 1) {
317 /* single connection */
Takashi Iwai0ba21762007-04-16 11:29:14 +0200318 parm = snd_hda_codec_read(codec, nid, 0,
319 AC_VERB_GET_CONNECT_LIST, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700320 conn_list[0] = parm & mask;
321 return 1;
322 }
323
324 /* multi connection */
325 conns = 0;
Takashi Iwai54d17402005-11-21 16:33:22 +0100326 prev_nid = 0;
327 for (i = 0; i < conn_len; i++) {
328 int range_val;
329 hda_nid_t val, n;
330
331 if (i % num_elems == 0)
332 parm = snd_hda_codec_read(codec, nid, 0,
333 AC_VERB_GET_CONNECT_LIST, i);
Takashi Iwai0ba21762007-04-16 11:29:14 +0200334 range_val = !!(parm & (1 << (shift-1))); /* ranges */
Takashi Iwai54d17402005-11-21 16:33:22 +0100335 val = parm & mask;
336 parm >>= shift;
337 if (range_val) {
338 /* ranges between the previous and this one */
Takashi Iwai0ba21762007-04-16 11:29:14 +0200339 if (!prev_nid || prev_nid >= val) {
340 snd_printk(KERN_WARNING "hda_codec: "
341 "invalid dep_range_val %x:%x\n",
342 prev_nid, val);
Takashi Iwai54d17402005-11-21 16:33:22 +0100343 continue;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700344 }
Takashi Iwai54d17402005-11-21 16:33:22 +0100345 for (n = prev_nid + 1; n <= val; n++) {
346 if (conns >= max_conns) {
Takashi Iwai0ba21762007-04-16 11:29:14 +0200347 snd_printk(KERN_ERR
348 "Too many connections\n");
Takashi Iwai54d17402005-11-21 16:33:22 +0100349 return -EINVAL;
350 }
351 conn_list[conns++] = n;
352 }
353 } else {
354 if (conns >= max_conns) {
355 snd_printk(KERN_ERR "Too many connections\n");
356 return -EINVAL;
357 }
358 conn_list[conns++] = val;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700359 }
Takashi Iwai54d17402005-11-21 16:33:22 +0100360 prev_nid = val;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700361 }
362 return conns;
363}
Takashi Iwaiff7a3262008-11-28 15:17:06 +0100364EXPORT_SYMBOL_HDA(snd_hda_get_connections);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700365
366
367/**
368 * snd_hda_queue_unsol_event - add an unsolicited event to queue
369 * @bus: the BUS
370 * @res: unsolicited event (lower 32bit of RIRB entry)
371 * @res_ex: codec addr and flags (upper 32bit or RIRB entry)
372 *
373 * Adds the given event to the queue. The events are processed in
374 * the workqueue asynchronously. Call this function in the interrupt
375 * hanlder when RIRB receives an unsolicited event.
376 *
377 * Returns 0 if successful, or a negative error code.
378 */
379int snd_hda_queue_unsol_event(struct hda_bus *bus, u32 res, u32 res_ex)
380{
381 struct hda_bus_unsolicited *unsol;
382 unsigned int wp;
383
Takashi Iwai0ba21762007-04-16 11:29:14 +0200384 unsol = bus->unsol;
385 if (!unsol)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700386 return 0;
387
388 wp = (unsol->wp + 1) % HDA_UNSOL_QUEUE_SIZE;
389 unsol->wp = wp;
390
391 wp <<= 1;
392 unsol->queue[wp] = res;
393 unsol->queue[wp + 1] = res_ex;
394
Takashi Iwai6acaed32009-01-12 10:09:24 +0100395 queue_work(bus->workq, &unsol->work);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700396
397 return 0;
398}
Takashi Iwaiff7a3262008-11-28 15:17:06 +0100399EXPORT_SYMBOL_HDA(snd_hda_queue_unsol_event);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700400
401/*
Wu Fengguang5c1d1a92008-10-07 14:17:53 +0800402 * process queued unsolicited events
Linus Torvalds1da177e2005-04-16 15:20:36 -0700403 */
David Howellsc4028952006-11-22 14:57:56 +0000404static void process_unsol_events(struct work_struct *work)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700405{
David Howellsc4028952006-11-22 14:57:56 +0000406 struct hda_bus_unsolicited *unsol =
407 container_of(work, struct hda_bus_unsolicited, work);
408 struct hda_bus *bus = unsol->bus;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700409 struct hda_codec *codec;
410 unsigned int rp, caddr, res;
411
412 while (unsol->rp != unsol->wp) {
413 rp = (unsol->rp + 1) % HDA_UNSOL_QUEUE_SIZE;
414 unsol->rp = rp;
415 rp <<= 1;
416 res = unsol->queue[rp];
417 caddr = unsol->queue[rp + 1];
Takashi Iwai0ba21762007-04-16 11:29:14 +0200418 if (!(caddr & (1 << 4))) /* no unsolicited event? */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700419 continue;
420 codec = bus->caddr_tbl[caddr & 0x0f];
421 if (codec && codec->patch_ops.unsol_event)
422 codec->patch_ops.unsol_event(codec, res);
423 }
424}
425
426/*
427 * initialize unsolicited queue
428 */
Takashi Iwai6c1f45e2008-07-30 15:01:45 +0200429static int init_unsol_queue(struct hda_bus *bus)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700430{
431 struct hda_bus_unsolicited *unsol;
432
Takashi Iwai9f146bb2005-11-17 11:07:49 +0100433 if (bus->unsol) /* already initialized */
434 return 0;
435
Takashi Iwaie560d8d2005-09-09 14:21:46 +0200436 unsol = kzalloc(sizeof(*unsol), GFP_KERNEL);
Takashi Iwai0ba21762007-04-16 11:29:14 +0200437 if (!unsol) {
438 snd_printk(KERN_ERR "hda_codec: "
439 "can't allocate unsolicited queue\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700440 return -ENOMEM;
441 }
David Howellsc4028952006-11-22 14:57:56 +0000442 INIT_WORK(&unsol->work, process_unsol_events);
443 unsol->bus = bus;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700444 bus->unsol = unsol;
445 return 0;
446}
447
448/*
449 * destructor
450 */
451static void snd_hda_codec_free(struct hda_codec *codec);
452
453static int snd_hda_bus_free(struct hda_bus *bus)
454{
Takashi Iwai0ba21762007-04-16 11:29:14 +0200455 struct hda_codec *codec, *n;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700456
Takashi Iwai0ba21762007-04-16 11:29:14 +0200457 if (!bus)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700458 return 0;
Takashi Iwai6acaed32009-01-12 10:09:24 +0100459 if (bus->workq)
460 flush_workqueue(bus->workq);
461 if (bus->unsol)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700462 kfree(bus->unsol);
Takashi Iwai0ba21762007-04-16 11:29:14 +0200463 list_for_each_entry_safe(codec, n, &bus->codec_list, list) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700464 snd_hda_codec_free(codec);
465 }
466 if (bus->ops.private_free)
467 bus->ops.private_free(bus);
Takashi Iwai6acaed32009-01-12 10:09:24 +0100468 if (bus->workq)
469 destroy_workqueue(bus->workq);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700470 kfree(bus);
471 return 0;
472}
473
Takashi Iwaic8b6bf92005-11-17 14:57:47 +0100474static int snd_hda_bus_dev_free(struct snd_device *device)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700475{
476 struct hda_bus *bus = device->device_data;
Takashi Iwaib94d35392008-11-21 09:08:06 +0100477 bus->shutdown = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700478 return snd_hda_bus_free(bus);
479}
480
Takashi Iwaid7ffba12008-07-30 15:01:46 +0200481#ifdef CONFIG_SND_HDA_HWDEP
482static int snd_hda_bus_dev_register(struct snd_device *device)
483{
484 struct hda_bus *bus = device->device_data;
485 struct hda_codec *codec;
486 list_for_each_entry(codec, &bus->codec_list, list) {
487 snd_hda_hwdep_add_sysfs(codec);
488 }
489 return 0;
490}
491#else
492#define snd_hda_bus_dev_register NULL
493#endif
494
Linus Torvalds1da177e2005-04-16 15:20:36 -0700495/**
496 * snd_hda_bus_new - create a HDA bus
497 * @card: the card entry
498 * @temp: the template for hda_bus information
499 * @busp: the pointer to store the created bus instance
500 *
501 * Returns 0 if successful, or a negative error code.
502 */
Takashi Iwai1289e9e2008-11-27 15:47:11 +0100503int /*__devinit*/ snd_hda_bus_new(struct snd_card *card,
Takashi Iwai756e2b02007-04-16 11:27:07 +0200504 const struct hda_bus_template *temp,
505 struct hda_bus **busp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700506{
507 struct hda_bus *bus;
508 int err;
Takashi Iwaic8b6bf92005-11-17 14:57:47 +0100509 static struct snd_device_ops dev_ops = {
Takashi Iwaid7ffba12008-07-30 15:01:46 +0200510 .dev_register = snd_hda_bus_dev_register,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700511 .dev_free = snd_hda_bus_dev_free,
512 };
513
Takashi Iwaida3cec32008-08-08 17:12:14 +0200514 if (snd_BUG_ON(!temp))
515 return -EINVAL;
516 if (snd_BUG_ON(!temp->ops.command || !temp->ops.get_response))
517 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700518
519 if (busp)
520 *busp = NULL;
521
Takashi Iwaie560d8d2005-09-09 14:21:46 +0200522 bus = kzalloc(sizeof(*bus), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700523 if (bus == NULL) {
524 snd_printk(KERN_ERR "can't allocate struct hda_bus\n");
525 return -ENOMEM;
526 }
527
528 bus->card = card;
529 bus->private_data = temp->private_data;
530 bus->pci = temp->pci;
531 bus->modelname = temp->modelname;
Takashi Iwaifee2fba2008-11-27 12:43:28 +0100532 bus->power_save = temp->power_save;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700533 bus->ops = temp->ops;
534
Ingo Molnar62932df2006-01-16 16:34:20 +0100535 mutex_init(&bus->cmd_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700536 INIT_LIST_HEAD(&bus->codec_list);
537
Takashi Iwaie8c0ee52009-02-05 07:34:28 +0100538 snprintf(bus->workq_name, sizeof(bus->workq_name),
539 "hd-audio%d", card->number);
540 bus->workq = create_singlethread_workqueue(bus->workq_name);
Takashi Iwai6acaed32009-01-12 10:09:24 +0100541 if (!bus->workq) {
Takashi Iwaie8c0ee52009-02-05 07:34:28 +0100542 snd_printk(KERN_ERR "cannot create workqueue %s\n",
543 bus->workq_name);
Takashi Iwai6acaed32009-01-12 10:09:24 +0100544 kfree(bus);
545 return -ENOMEM;
546 }
547
Takashi Iwai0ba21762007-04-16 11:29:14 +0200548 err = snd_device_new(card, SNDRV_DEV_BUS, bus, &dev_ops);
549 if (err < 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700550 snd_hda_bus_free(bus);
551 return err;
552 }
553 if (busp)
554 *busp = bus;
555 return 0;
556}
Takashi Iwaiff7a3262008-11-28 15:17:06 +0100557EXPORT_SYMBOL_HDA(snd_hda_bus_new);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700558
Takashi Iwai82467612007-07-27 19:15:54 +0200559#ifdef CONFIG_SND_HDA_GENERIC
560#define is_generic_config(codec) \
Takashi Iwaif44ac832008-07-30 15:01:45 +0200561 (codec->modelname && !strcmp(codec->modelname, "generic"))
Takashi Iwai82467612007-07-27 19:15:54 +0200562#else
563#define is_generic_config(codec) 0
564#endif
565
Takashi Iwai645f10c2008-11-28 15:07:37 +0100566#ifdef MODULE
Takashi Iwai1289e9e2008-11-27 15:47:11 +0100567#define HDA_MODREQ_MAX_COUNT 2 /* two request_modules()'s */
568#else
Takashi Iwai645f10c2008-11-28 15:07:37 +0100569#define HDA_MODREQ_MAX_COUNT 0 /* all presets are statically linked */
Takashi Iwai1289e9e2008-11-27 15:47:11 +0100570#endif
571
Linus Torvalds1da177e2005-04-16 15:20:36 -0700572/*
573 * find a matching codec preset
574 */
Takashi Iwai6c1f45e2008-07-30 15:01:45 +0200575static const struct hda_codec_preset *
Takashi Iwai756e2b02007-04-16 11:27:07 +0200576find_codec_preset(struct hda_codec *codec)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700577{
Takashi Iwai1289e9e2008-11-27 15:47:11 +0100578 struct hda_codec_preset_list *tbl;
579 const struct hda_codec_preset *preset;
580 int mod_requested = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700581
Takashi Iwai82467612007-07-27 19:15:54 +0200582 if (is_generic_config(codec))
Takashi Iwaid5ad6302007-03-07 15:55:59 +0100583 return NULL; /* use the generic parser */
584
Takashi Iwai1289e9e2008-11-27 15:47:11 +0100585 again:
586 mutex_lock(&preset_mutex);
587 list_for_each_entry(tbl, &hda_preset_tables, list) {
588 if (!try_module_get(tbl->owner)) {
589 snd_printk(KERN_ERR "hda_codec: cannot module_get\n");
590 continue;
591 }
592 for (preset = tbl->preset; preset->id; preset++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700593 u32 mask = preset->mask;
Marc Boucherca7cfae2008-01-22 15:32:25 +0100594 if (preset->afg && preset->afg != codec->afg)
595 continue;
596 if (preset->mfg && preset->mfg != codec->mfg)
597 continue;
Takashi Iwai0ba21762007-04-16 11:29:14 +0200598 if (!mask)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700599 mask = ~0;
Takashi Iwai9c7f8522006-06-28 15:08:22 +0200600 if (preset->id == (codec->vendor_id & mask) &&
Takashi Iwai0ba21762007-04-16 11:29:14 +0200601 (!preset->rev ||
Takashi Iwai1289e9e2008-11-27 15:47:11 +0100602 preset->rev == codec->revision_id)) {
603 mutex_unlock(&preset_mutex);
604 codec->owner = tbl->owner;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700605 return preset;
Takashi Iwai1289e9e2008-11-27 15:47:11 +0100606 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700607 }
Takashi Iwai1289e9e2008-11-27 15:47:11 +0100608 module_put(tbl->owner);
609 }
610 mutex_unlock(&preset_mutex);
611
612 if (mod_requested < HDA_MODREQ_MAX_COUNT) {
613 char name[32];
614 if (!mod_requested)
615 snprintf(name, sizeof(name), "snd-hda-codec-id:%08x",
616 codec->vendor_id);
617 else
618 snprintf(name, sizeof(name), "snd-hda-codec-id:%04x*",
619 (codec->vendor_id >> 16) & 0xffff);
620 request_module(name);
621 mod_requested++;
622 goto again;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700623 }
624 return NULL;
625}
626
627/*
Takashi Iwaif44ac832008-07-30 15:01:45 +0200628 * get_codec_name - store the codec name
Linus Torvalds1da177e2005-04-16 15:20:36 -0700629 */
Takashi Iwaif44ac832008-07-30 15:01:45 +0200630static int get_codec_name(struct hda_codec *codec)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700631{
632 const struct hda_vendor_id *c;
633 const char *vendor = NULL;
634 u16 vendor_id = codec->vendor_id >> 16;
Takashi Iwai812a2cc2009-05-16 10:00:49 +0200635 char tmp[16];
636
637 if (codec->vendor_name)
638 goto get_chip_name;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700639
640 for (c = hda_vendor_ids; c->id; c++) {
641 if (c->id == vendor_id) {
642 vendor = c->name;
643 break;
644 }
645 }
Takashi Iwai0ba21762007-04-16 11:29:14 +0200646 if (!vendor) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700647 sprintf(tmp, "Generic %04x", vendor_id);
648 vendor = tmp;
649 }
Takashi Iwai812a2cc2009-05-16 10:00:49 +0200650 codec->vendor_name = kstrdup(vendor, GFP_KERNEL);
651 if (!codec->vendor_name)
652 return -ENOMEM;
653
654 get_chip_name:
655 if (codec->chip_name)
656 return 0;
657
Linus Torvalds1da177e2005-04-16 15:20:36 -0700658 if (codec->preset && codec->preset->name)
Takashi Iwai812a2cc2009-05-16 10:00:49 +0200659 codec->chip_name = kstrdup(codec->preset->name, GFP_KERNEL);
660 else {
661 sprintf(tmp, "ID %x", codec->vendor_id & 0xffff);
662 codec->chip_name = kstrdup(tmp, GFP_KERNEL);
663 }
664 if (!codec->chip_name)
Takashi Iwaif44ac832008-07-30 15:01:45 +0200665 return -ENOMEM;
666 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700667}
668
669/*
Sasha Khapyorsky673b6832005-08-11 11:00:16 +0200670 * look for an AFG and MFG nodes
Linus Torvalds1da177e2005-04-16 15:20:36 -0700671 */
Takashi Iwai1289e9e2008-11-27 15:47:11 +0100672static void /*__devinit*/ setup_fg_nodes(struct hda_codec *codec)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700673{
Takashi Iwai93e82ae2009-04-17 18:04:41 +0200674 int i, total_nodes, function_id;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700675 hda_nid_t nid;
676
677 total_nodes = snd_hda_get_sub_nodes(codec, AC_NODE_ROOT, &nid);
678 for (i = 0; i < total_nodes; i++, nid++) {
Takashi Iwai93e82ae2009-04-17 18:04:41 +0200679 function_id = snd_hda_param_read(codec, nid,
Pascal de Bruijn234b4342009-03-23 11:15:59 +0100680 AC_PAR_FUNCTION_TYPE) & 0xff;
Takashi Iwai93e82ae2009-04-17 18:04:41 +0200681 switch (function_id) {
Sasha Khapyorsky673b6832005-08-11 11:00:16 +0200682 case AC_GRP_AUDIO_FUNCTION:
683 codec->afg = nid;
Takashi Iwai93e82ae2009-04-17 18:04:41 +0200684 codec->function_id = function_id;
Sasha Khapyorsky673b6832005-08-11 11:00:16 +0200685 break;
686 case AC_GRP_MODEM_FUNCTION:
687 codec->mfg = nid;
Takashi Iwai93e82ae2009-04-17 18:04:41 +0200688 codec->function_id = function_id;
Sasha Khapyorsky673b6832005-08-11 11:00:16 +0200689 break;
690 default:
691 break;
692 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700693 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700694}
695
696/*
Takashi Iwai54d17402005-11-21 16:33:22 +0100697 * read widget caps for each widget and store in cache
698 */
699static int read_widget_caps(struct hda_codec *codec, hda_nid_t fg_node)
700{
701 int i;
702 hda_nid_t nid;
703
704 codec->num_nodes = snd_hda_get_sub_nodes(codec, fg_node,
705 &codec->start_nid);
706 codec->wcaps = kmalloc(codec->num_nodes * 4, GFP_KERNEL);
Takashi Iwai0ba21762007-04-16 11:29:14 +0200707 if (!codec->wcaps)
Takashi Iwai54d17402005-11-21 16:33:22 +0100708 return -ENOMEM;
709 nid = codec->start_nid;
710 for (i = 0; i < codec->num_nodes; i++, nid++)
711 codec->wcaps[i] = snd_hda_param_read(codec, nid,
712 AC_PAR_AUDIO_WIDGET_CAP);
713 return 0;
714}
715
Takashi Iwai3be14142009-02-20 14:11:16 +0100716/* read all pin default configurations and save codec->init_pins */
717static int read_pin_defaults(struct hda_codec *codec)
718{
719 int i;
720 hda_nid_t nid = codec->start_nid;
721
722 for (i = 0; i < codec->num_nodes; i++, nid++) {
723 struct hda_pincfg *pin;
724 unsigned int wcaps = get_wcaps(codec, nid);
725 unsigned int wid_type = (wcaps & AC_WCAP_TYPE) >>
726 AC_WCAP_TYPE_SHIFT;
727 if (wid_type != AC_WID_PIN)
728 continue;
729 pin = snd_array_new(&codec->init_pins);
730 if (!pin)
731 return -ENOMEM;
732 pin->nid = nid;
733 pin->cfg = snd_hda_codec_read(codec, nid, 0,
734 AC_VERB_GET_CONFIG_DEFAULT, 0);
735 }
736 return 0;
737}
738
739/* look up the given pin config list and return the item matching with NID */
740static struct hda_pincfg *look_up_pincfg(struct hda_codec *codec,
741 struct snd_array *array,
742 hda_nid_t nid)
743{
744 int i;
745 for (i = 0; i < array->used; i++) {
746 struct hda_pincfg *pin = snd_array_elem(array, i);
747 if (pin->nid == nid)
748 return pin;
749 }
750 return NULL;
751}
752
753/* write a config value for the given NID */
754static void set_pincfg(struct hda_codec *codec, hda_nid_t nid,
755 unsigned int cfg)
756{
757 int i;
758 for (i = 0; i < 4; i++) {
759 snd_hda_codec_write(codec, nid, 0,
760 AC_VERB_SET_CONFIG_DEFAULT_BYTES_0 + i,
761 cfg & 0xff);
762 cfg >>= 8;
763 }
764}
765
766/* set the current pin config value for the given NID.
767 * the value is cached, and read via snd_hda_codec_get_pincfg()
768 */
769int snd_hda_add_pincfg(struct hda_codec *codec, struct snd_array *list,
770 hda_nid_t nid, unsigned int cfg)
771{
772 struct hda_pincfg *pin;
Takashi Iwai5e7b8e02009-02-23 09:45:59 +0100773 unsigned int oldcfg;
Takashi Iwai3be14142009-02-20 14:11:16 +0100774
Takashi Iwai5e7b8e02009-02-23 09:45:59 +0100775 oldcfg = snd_hda_codec_get_pincfg(codec, nid);
Takashi Iwai3be14142009-02-20 14:11:16 +0100776 pin = look_up_pincfg(codec, list, nid);
777 if (!pin) {
778 pin = snd_array_new(list);
779 if (!pin)
780 return -ENOMEM;
781 pin->nid = nid;
782 }
783 pin->cfg = cfg;
Takashi Iwai5e7b8e02009-02-23 09:45:59 +0100784
785 /* change only when needed; e.g. if the pincfg is already present
786 * in user_pins[], don't write it
787 */
788 cfg = snd_hda_codec_get_pincfg(codec, nid);
789 if (oldcfg != cfg)
790 set_pincfg(codec, nid, cfg);
Takashi Iwai3be14142009-02-20 14:11:16 +0100791 return 0;
792}
793
794int snd_hda_codec_set_pincfg(struct hda_codec *codec,
795 hda_nid_t nid, unsigned int cfg)
796{
Takashi Iwai346ff702009-02-23 09:42:57 +0100797 return snd_hda_add_pincfg(codec, &codec->driver_pins, nid, cfg);
Takashi Iwai3be14142009-02-20 14:11:16 +0100798}
799EXPORT_SYMBOL_HDA(snd_hda_codec_set_pincfg);
800
801/* get the current pin config value of the given pin NID */
802unsigned int snd_hda_codec_get_pincfg(struct hda_codec *codec, hda_nid_t nid)
803{
804 struct hda_pincfg *pin;
805
Takashi Iwai3be14142009-02-20 14:11:16 +0100806#ifdef CONFIG_SND_HDA_HWDEP
Takashi Iwai346ff702009-02-23 09:42:57 +0100807 pin = look_up_pincfg(codec, &codec->user_pins, nid);
Takashi Iwai3be14142009-02-20 14:11:16 +0100808 if (pin)
809 return pin->cfg;
810#endif
Takashi Iwai5e7b8e02009-02-23 09:45:59 +0100811 pin = look_up_pincfg(codec, &codec->driver_pins, nid);
812 if (pin)
813 return pin->cfg;
Takashi Iwai3be14142009-02-20 14:11:16 +0100814 pin = look_up_pincfg(codec, &codec->init_pins, nid);
815 if (pin)
816 return pin->cfg;
817 return 0;
818}
819EXPORT_SYMBOL_HDA(snd_hda_codec_get_pincfg);
820
821/* restore all current pin configs */
822static void restore_pincfgs(struct hda_codec *codec)
823{
824 int i;
825 for (i = 0; i < codec->init_pins.used; i++) {
826 struct hda_pincfg *pin = snd_array_elem(&codec->init_pins, i);
827 set_pincfg(codec, pin->nid,
828 snd_hda_codec_get_pincfg(codec, pin->nid));
829 }
830}
Takashi Iwai54d17402005-11-21 16:33:22 +0100831
Takashi Iwai01751f52007-08-10 16:59:39 +0200832static void init_hda_cache(struct hda_cache_rec *cache,
833 unsigned int record_size);
Takashi Iwai1fcaee62007-08-23 00:01:09 +0200834static void free_hda_cache(struct hda_cache_rec *cache);
Takashi Iwai01751f52007-08-10 16:59:39 +0200835
Takashi Iwai3be14142009-02-20 14:11:16 +0100836/* restore the initial pin cfgs and release all pincfg lists */
837static void restore_init_pincfgs(struct hda_codec *codec)
838{
Takashi Iwai346ff702009-02-23 09:42:57 +0100839 /* first free driver_pins and user_pins, then call restore_pincfg
Takashi Iwai3be14142009-02-20 14:11:16 +0100840 * so that only the values in init_pins are restored
841 */
Takashi Iwai346ff702009-02-23 09:42:57 +0100842 snd_array_free(&codec->driver_pins);
Takashi Iwai3be14142009-02-20 14:11:16 +0100843#ifdef CONFIG_SND_HDA_HWDEP
Takashi Iwai346ff702009-02-23 09:42:57 +0100844 snd_array_free(&codec->user_pins);
Takashi Iwai3be14142009-02-20 14:11:16 +0100845#endif
846 restore_pincfgs(codec);
847 snd_array_free(&codec->init_pins);
848}
849
Takashi Iwai54d17402005-11-21 16:33:22 +0100850/*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700851 * codec destructor
852 */
853static void snd_hda_codec_free(struct hda_codec *codec)
854{
Takashi Iwai0ba21762007-04-16 11:29:14 +0200855 if (!codec)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700856 return;
Takashi Iwai3be14142009-02-20 14:11:16 +0100857 restore_init_pincfgs(codec);
Takashi Iwaicb53c622007-08-10 17:21:45 +0200858#ifdef CONFIG_SND_HDA_POWER_SAVE
859 cancel_delayed_work(&codec->power_work);
Takashi Iwai6acaed32009-01-12 10:09:24 +0100860 flush_workqueue(codec->bus->workq);
Takashi Iwaicb53c622007-08-10 17:21:45 +0200861#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700862 list_del(&codec->list);
Takashi Iwaid13bd412008-07-30 15:01:45 +0200863 snd_array_free(&codec->mixers);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700864 codec->bus->caddr_tbl[codec->addr] = NULL;
865 if (codec->patch_ops.free)
866 codec->patch_ops.free(codec);
Takashi Iwai1289e9e2008-11-27 15:47:11 +0100867 module_put(codec->owner);
Takashi Iwai01751f52007-08-10 16:59:39 +0200868 free_hda_cache(&codec->amp_cache);
Takashi Iwaib3ac5632007-08-10 17:03:40 +0200869 free_hda_cache(&codec->cmd_cache);
Takashi Iwai812a2cc2009-05-16 10:00:49 +0200870 kfree(codec->vendor_name);
871 kfree(codec->chip_name);
Takashi Iwaif44ac832008-07-30 15:01:45 +0200872 kfree(codec->modelname);
Takashi Iwai54d17402005-11-21 16:33:22 +0100873 kfree(codec->wcaps);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700874 kfree(codec);
875}
876
Takashi Iwaibb6ac722009-03-13 09:02:42 +0100877static void hda_set_power_state(struct hda_codec *codec, hda_nid_t fg,
878 unsigned int power_state);
879
Linus Torvalds1da177e2005-04-16 15:20:36 -0700880/**
881 * snd_hda_codec_new - create a HDA codec
882 * @bus: the bus to assign
883 * @codec_addr: the codec address
884 * @codecp: the pointer to store the generated codec
885 *
886 * Returns 0 if successful, or a negative error code.
887 */
Takashi Iwai1289e9e2008-11-27 15:47:11 +0100888int /*__devinit*/ snd_hda_codec_new(struct hda_bus *bus, unsigned int codec_addr,
Takashi Iwaia1e21c92009-06-17 09:33:52 +0200889 struct hda_codec **codecp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700890{
891 struct hda_codec *codec;
Jaroslav Kyselaba443682008-08-13 20:55:32 +0200892 char component[31];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700893 int err;
894
Takashi Iwaida3cec32008-08-08 17:12:14 +0200895 if (snd_BUG_ON(!bus))
896 return -EINVAL;
897 if (snd_BUG_ON(codec_addr > HDA_MAX_CODEC_ADDRESS))
898 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700899
900 if (bus->caddr_tbl[codec_addr]) {
Takashi Iwai0ba21762007-04-16 11:29:14 +0200901 snd_printk(KERN_ERR "hda_codec: "
902 "address 0x%x is already occupied\n", codec_addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700903 return -EBUSY;
904 }
905
Takashi Iwaie560d8d2005-09-09 14:21:46 +0200906 codec = kzalloc(sizeof(*codec), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700907 if (codec == NULL) {
908 snd_printk(KERN_ERR "can't allocate struct hda_codec\n");
909 return -ENOMEM;
910 }
911
912 codec->bus = bus;
913 codec->addr = codec_addr;
Ingo Molnar62932df2006-01-16 16:34:20 +0100914 mutex_init(&codec->spdif_mutex);
Wu Fengguang5a9e02e2009-01-09 16:45:24 +0800915 mutex_init(&codec->control_mutex);
Takashi Iwai01751f52007-08-10 16:59:39 +0200916 init_hda_cache(&codec->amp_cache, sizeof(struct hda_amp_info));
Takashi Iwaib3ac5632007-08-10 17:03:40 +0200917 init_hda_cache(&codec->cmd_cache, sizeof(struct hda_cache_head));
Takashi Iwaid13bd412008-07-30 15:01:45 +0200918 snd_array_init(&codec->mixers, sizeof(struct snd_kcontrol *), 32);
Takashi Iwai3be14142009-02-20 14:11:16 +0100919 snd_array_init(&codec->init_pins, sizeof(struct hda_pincfg), 16);
Takashi Iwai346ff702009-02-23 09:42:57 +0100920 snd_array_init(&codec->driver_pins, sizeof(struct hda_pincfg), 16);
Takashi Iwai6c1f45e2008-07-30 15:01:45 +0200921 if (codec->bus->modelname) {
922 codec->modelname = kstrdup(codec->bus->modelname, GFP_KERNEL);
923 if (!codec->modelname) {
924 snd_hda_codec_free(codec);
925 return -ENODEV;
926 }
927 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700928
Takashi Iwaicb53c622007-08-10 17:21:45 +0200929#ifdef CONFIG_SND_HDA_POWER_SAVE
930 INIT_DELAYED_WORK(&codec->power_work, hda_power_work);
931 /* snd_hda_codec_new() marks the codec as power-up, and leave it as is.
932 * the caller has to power down appropriatley after initialization
933 * phase.
934 */
935 hda_keep_power_on(codec);
936#endif
937
Linus Torvalds1da177e2005-04-16 15:20:36 -0700938 list_add_tail(&codec->list, &bus->codec_list);
939 bus->caddr_tbl[codec_addr] = codec;
940
Takashi Iwai0ba21762007-04-16 11:29:14 +0200941 codec->vendor_id = snd_hda_param_read(codec, AC_NODE_ROOT,
942 AC_PAR_VENDOR_ID);
Takashi Iwai111d3af2006-02-16 18:17:58 +0100943 if (codec->vendor_id == -1)
944 /* read again, hopefully the access method was corrected
945 * in the last read...
946 */
947 codec->vendor_id = snd_hda_param_read(codec, AC_NODE_ROOT,
948 AC_PAR_VENDOR_ID);
Takashi Iwai0ba21762007-04-16 11:29:14 +0200949 codec->subsystem_id = snd_hda_param_read(codec, AC_NODE_ROOT,
950 AC_PAR_SUBSYSTEM_ID);
951 codec->revision_id = snd_hda_param_read(codec, AC_NODE_ROOT,
952 AC_PAR_REV_ID);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700953
Sasha Khapyorsky673b6832005-08-11 11:00:16 +0200954 setup_fg_nodes(codec);
Takashi Iwai0ba21762007-04-16 11:29:14 +0200955 if (!codec->afg && !codec->mfg) {
Sasha Khapyorsky673b6832005-08-11 11:00:16 +0200956 snd_printdd("hda_codec: no AFG or MFG node found\n");
Takashi Iwai3be14142009-02-20 14:11:16 +0100957 err = -ENODEV;
958 goto error;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700959 }
960
Takashi Iwai3be14142009-02-20 14:11:16 +0100961 err = read_widget_caps(codec, codec->afg ? codec->afg : codec->mfg);
962 if (err < 0) {
Takashi Iwai54d17402005-11-21 16:33:22 +0100963 snd_printk(KERN_ERR "hda_codec: cannot malloc\n");
Takashi Iwai3be14142009-02-20 14:11:16 +0100964 goto error;
Takashi Iwai54d17402005-11-21 16:33:22 +0100965 }
Takashi Iwai3be14142009-02-20 14:11:16 +0100966 err = read_pin_defaults(codec);
967 if (err < 0)
968 goto error;
Takashi Iwai54d17402005-11-21 16:33:22 +0100969
Takashi Iwai0ba21762007-04-16 11:29:14 +0200970 if (!codec->subsystem_id) {
Takashi Iwai86284e42005-10-11 15:05:54 +0200971 hda_nid_t nid = codec->afg ? codec->afg : codec->mfg;
Takashi Iwai0ba21762007-04-16 11:29:14 +0200972 codec->subsystem_id =
973 snd_hda_codec_read(codec, nid, 0,
974 AC_VERB_GET_SUBSYSTEM_ID, 0);
Takashi Iwai86284e42005-10-11 15:05:54 +0200975 }
976
Takashi Iwaibb6ac722009-03-13 09:02:42 +0100977 /* power-up all before initialization */
978 hda_set_power_state(codec,
979 codec->afg ? codec->afg : codec->mfg,
980 AC_PWRST_D0);
981
Takashi Iwai6c1f45e2008-07-30 15:01:45 +0200982 snd_hda_codec_proc_new(codec);
983
Takashi Iwai6c1f45e2008-07-30 15:01:45 +0200984 snd_hda_create_hwdep(codec);
Takashi Iwai6c1f45e2008-07-30 15:01:45 +0200985
986 sprintf(component, "HDA:%08x,%08x,%08x", codec->vendor_id,
987 codec->subsystem_id, codec->revision_id);
988 snd_component_add(codec->bus->card, component);
989
990 if (codecp)
991 *codecp = codec;
992 return 0;
Takashi Iwai3be14142009-02-20 14:11:16 +0100993
994 error:
995 snd_hda_codec_free(codec);
996 return err;
Takashi Iwai6c1f45e2008-07-30 15:01:45 +0200997}
Takashi Iwaiff7a3262008-11-28 15:17:06 +0100998EXPORT_SYMBOL_HDA(snd_hda_codec_new);
Takashi Iwai6c1f45e2008-07-30 15:01:45 +0200999
1000int snd_hda_codec_configure(struct hda_codec *codec)
1001{
1002 int err;
1003
Takashi Iwaid5ad6302007-03-07 15:55:59 +01001004 codec->preset = find_codec_preset(codec);
Takashi Iwai812a2cc2009-05-16 10:00:49 +02001005 if (!codec->vendor_name || !codec->chip_name) {
Takashi Iwaif44ac832008-07-30 15:01:45 +02001006 err = get_codec_name(codec);
1007 if (err < 0)
1008 return err;
1009 }
Takashi Iwai43ea1d42007-04-26 19:12:08 +02001010 /* audio codec should override the mixer name */
Takashi Iwaif44ac832008-07-30 15:01:45 +02001011 if (codec->afg || !*codec->bus->card->mixername)
Takashi Iwai812a2cc2009-05-16 10:00:49 +02001012 snprintf(codec->bus->card->mixername,
1013 sizeof(codec->bus->card->mixername),
1014 "%s %s", codec->vendor_name, codec->chip_name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001015
Takashi Iwai82467612007-07-27 19:15:54 +02001016 if (is_generic_config(codec)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001017 err = snd_hda_parse_generic_codec(codec);
Takashi Iwai82467612007-07-27 19:15:54 +02001018 goto patched;
1019 }
Takashi Iwai82467612007-07-27 19:15:54 +02001020 if (codec->preset && codec->preset->patch) {
1021 err = codec->preset->patch(codec);
1022 goto patched;
1023 }
1024
1025 /* call the default parser */
Takashi Iwai82467612007-07-27 19:15:54 +02001026 err = snd_hda_parse_generic_codec(codec);
Takashi Iwai35a1e0c2007-10-19 08:13:40 +02001027 if (err < 0)
1028 printk(KERN_ERR "hda-codec: No codec parser is available\n");
Takashi Iwai82467612007-07-27 19:15:54 +02001029
1030 patched:
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001031 if (!err && codec->patch_ops.unsol_event)
1032 err = init_unsol_queue(codec->bus);
1033 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001034}
Takashi Iwaia1e21c92009-06-17 09:33:52 +02001035EXPORT_SYMBOL_HDA(snd_hda_codec_configure);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001036
1037/**
1038 * snd_hda_codec_setup_stream - set up the codec for streaming
1039 * @codec: the CODEC to set up
1040 * @nid: the NID to set up
1041 * @stream_tag: stream tag to pass, it's between 0x1 and 0xf.
1042 * @channel_id: channel id to pass, zero based.
1043 * @format: stream format.
1044 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02001045void snd_hda_codec_setup_stream(struct hda_codec *codec, hda_nid_t nid,
1046 u32 stream_tag,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001047 int channel_id, int format)
1048{
Takashi Iwai0ba21762007-04-16 11:29:14 +02001049 if (!nid)
Takashi Iwaid21b37e2005-04-20 13:45:55 +02001050 return;
1051
Takashi Iwai0ba21762007-04-16 11:29:14 +02001052 snd_printdd("hda_codec_setup_stream: "
1053 "NID=0x%x, stream=0x%x, channel=%d, format=0x%x\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07001054 nid, stream_tag, channel_id, format);
1055 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CHANNEL_STREAMID,
1056 (stream_tag << 4) | channel_id);
1057 msleep(1);
1058 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_STREAM_FORMAT, format);
1059}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001060EXPORT_SYMBOL_HDA(snd_hda_codec_setup_stream);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001061
Takashi Iwai888afa12008-03-18 09:57:50 +01001062void snd_hda_codec_cleanup_stream(struct hda_codec *codec, hda_nid_t nid)
1063{
1064 if (!nid)
1065 return;
1066
1067 snd_printdd("hda_codec_cleanup_stream: NID=0x%x\n", nid);
1068 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CHANNEL_STREAMID, 0);
1069#if 0 /* keep the format */
1070 msleep(1);
1071 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_STREAM_FORMAT, 0);
1072#endif
1073}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001074EXPORT_SYMBOL_HDA(snd_hda_codec_cleanup_stream);
Takashi Iwai888afa12008-03-18 09:57:50 +01001075
Linus Torvalds1da177e2005-04-16 15:20:36 -07001076/*
1077 * amp access functions
1078 */
1079
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001080/* FIXME: more better hash key? */
1081#define HDA_HASH_KEY(nid,dir,idx) (u32)((nid) + ((idx) << 16) + ((dir) << 24))
Takashi Iwai1327a322009-03-23 13:07:47 +01001082#define HDA_HASH_PINCAP_KEY(nid) (u32)((nid) + (0x02 << 24))
Takashi Iwai92c7c8a2009-03-24 07:32:14 +01001083#define HDA_HASH_PARPCM_KEY(nid) (u32)((nid) + (0x03 << 24))
1084#define HDA_HASH_PARSTR_KEY(nid) (u32)((nid) + (0x04 << 24))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001085#define INFO_AMP_CAPS (1<<0)
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001086#define INFO_AMP_VOL(ch) (1 << (1 + (ch)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001087
1088/* initialize the hash table */
Takashi Iwai1289e9e2008-11-27 15:47:11 +01001089static void /*__devinit*/ init_hda_cache(struct hda_cache_rec *cache,
Takashi Iwai01751f52007-08-10 16:59:39 +02001090 unsigned int record_size)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001091{
Takashi Iwai01751f52007-08-10 16:59:39 +02001092 memset(cache, 0, sizeof(*cache));
1093 memset(cache->hash, 0xff, sizeof(cache->hash));
Takashi Iwai603c4012008-07-30 15:01:44 +02001094 snd_array_init(&cache->buf, record_size, 64);
Takashi Iwai01751f52007-08-10 16:59:39 +02001095}
1096
Takashi Iwai1fcaee62007-08-23 00:01:09 +02001097static void free_hda_cache(struct hda_cache_rec *cache)
Takashi Iwai01751f52007-08-10 16:59:39 +02001098{
Takashi Iwai603c4012008-07-30 15:01:44 +02001099 snd_array_free(&cache->buf);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001100}
1101
1102/* query the hash. allocate an entry if not found. */
Takashi Iwai01751f52007-08-10 16:59:39 +02001103static struct hda_cache_head *get_alloc_hash(struct hda_cache_rec *cache,
1104 u32 key)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001105{
Takashi Iwai01751f52007-08-10 16:59:39 +02001106 u16 idx = key % (u16)ARRAY_SIZE(cache->hash);
1107 u16 cur = cache->hash[idx];
1108 struct hda_cache_head *info;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001109
1110 while (cur != 0xffff) {
Takashi Iwaif43aa022008-11-10 16:24:26 +01001111 info = snd_array_elem(&cache->buf, cur);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001112 if (info->key == key)
1113 return info;
1114 cur = info->next;
1115 }
1116
1117 /* add a new hash entry */
Takashi Iwai603c4012008-07-30 15:01:44 +02001118 info = snd_array_new(&cache->buf);
Takashi Iwaic2174292008-11-07 00:23:30 +01001119 if (!info)
1120 return NULL;
Takashi Iwaif43aa022008-11-10 16:24:26 +01001121 cur = snd_array_index(&cache->buf, info);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001122 info->key = key;
Takashi Iwai01751f52007-08-10 16:59:39 +02001123 info->val = 0;
1124 info->next = cache->hash[idx];
1125 cache->hash[idx] = cur;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001126
1127 return info;
1128}
1129
Takashi Iwai01751f52007-08-10 16:59:39 +02001130/* query and allocate an amp hash entry */
1131static inline struct hda_amp_info *
1132get_alloc_amp_hash(struct hda_codec *codec, u32 key)
1133{
1134 return (struct hda_amp_info *)get_alloc_hash(&codec->amp_cache, key);
1135}
1136
Linus Torvalds1da177e2005-04-16 15:20:36 -07001137/*
1138 * query AMP capabilities for the given widget and direction
1139 */
Matthew Ranostay09a99952008-01-24 11:49:21 +01001140u32 query_amp_caps(struct hda_codec *codec, hda_nid_t nid, int direction)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001141{
Takashi Iwai0ba21762007-04-16 11:29:14 +02001142 struct hda_amp_info *info;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001143
Takashi Iwai0ba21762007-04-16 11:29:14 +02001144 info = get_alloc_amp_hash(codec, HDA_HASH_KEY(nid, direction, 0));
1145 if (!info)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001146 return 0;
Takashi Iwai01751f52007-08-10 16:59:39 +02001147 if (!(info->head.val & INFO_AMP_CAPS)) {
Takashi Iwai0ba21762007-04-16 11:29:14 +02001148 if (!(get_wcaps(codec, nid) & AC_WCAP_AMP_OVRD))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001149 nid = codec->afg;
Takashi Iwai0ba21762007-04-16 11:29:14 +02001150 info->amp_caps = snd_hda_param_read(codec, nid,
1151 direction == HDA_OUTPUT ?
1152 AC_PAR_AMP_OUT_CAP :
1153 AC_PAR_AMP_IN_CAP);
Takashi Iwaib75e53f2007-05-10 16:56:09 +02001154 if (info->amp_caps)
Takashi Iwai01751f52007-08-10 16:59:39 +02001155 info->head.val |= INFO_AMP_CAPS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001156 }
1157 return info->amp_caps;
1158}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001159EXPORT_SYMBOL_HDA(query_amp_caps);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001160
Takashi Iwai897cc182007-05-29 19:01:37 +02001161int snd_hda_override_amp_caps(struct hda_codec *codec, hda_nid_t nid, int dir,
1162 unsigned int caps)
1163{
1164 struct hda_amp_info *info;
1165
1166 info = get_alloc_amp_hash(codec, HDA_HASH_KEY(nid, dir, 0));
1167 if (!info)
1168 return -EINVAL;
1169 info->amp_caps = caps;
Takashi Iwai01751f52007-08-10 16:59:39 +02001170 info->head.val |= INFO_AMP_CAPS;
Takashi Iwai897cc182007-05-29 19:01:37 +02001171 return 0;
1172}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001173EXPORT_SYMBOL_HDA(snd_hda_override_amp_caps);
Takashi Iwai897cc182007-05-29 19:01:37 +02001174
Takashi Iwai92c7c8a2009-03-24 07:32:14 +01001175static unsigned int
1176query_caps_hash(struct hda_codec *codec, hda_nid_t nid, u32 key,
1177 unsigned int (*func)(struct hda_codec *, hda_nid_t))
Takashi Iwai1327a322009-03-23 13:07:47 +01001178{
1179 struct hda_amp_info *info;
1180
Takashi Iwai92c7c8a2009-03-24 07:32:14 +01001181 info = get_alloc_amp_hash(codec, key);
Takashi Iwai1327a322009-03-23 13:07:47 +01001182 if (!info)
1183 return 0;
1184 if (!info->head.val) {
Takashi Iwai1327a322009-03-23 13:07:47 +01001185 info->head.val |= INFO_AMP_CAPS;
Takashi Iwai92c7c8a2009-03-24 07:32:14 +01001186 info->amp_caps = func(codec, nid);
Takashi Iwai1327a322009-03-23 13:07:47 +01001187 }
1188 return info->amp_caps;
1189}
Takashi Iwai92c7c8a2009-03-24 07:32:14 +01001190
1191static unsigned int read_pin_cap(struct hda_codec *codec, hda_nid_t nid)
1192{
1193 return snd_hda_param_read(codec, nid, AC_PAR_PIN_CAP);
1194}
1195
1196u32 snd_hda_query_pin_caps(struct hda_codec *codec, hda_nid_t nid)
1197{
1198 return query_caps_hash(codec, nid, HDA_HASH_PINCAP_KEY(nid),
1199 read_pin_cap);
1200}
Takashi Iwai1327a322009-03-23 13:07:47 +01001201EXPORT_SYMBOL_HDA(snd_hda_query_pin_caps);
1202
Linus Torvalds1da177e2005-04-16 15:20:36 -07001203/*
1204 * read the current volume to info
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001205 * if the cache exists, read the cache value.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001206 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02001207static unsigned int get_vol_mute(struct hda_codec *codec,
1208 struct hda_amp_info *info, hda_nid_t nid,
1209 int ch, int direction, int index)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001210{
1211 u32 val, parm;
1212
Takashi Iwai01751f52007-08-10 16:59:39 +02001213 if (info->head.val & INFO_AMP_VOL(ch))
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001214 return info->vol[ch];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001215
1216 parm = ch ? AC_AMP_GET_RIGHT : AC_AMP_GET_LEFT;
1217 parm |= direction == HDA_OUTPUT ? AC_AMP_GET_OUTPUT : AC_AMP_GET_INPUT;
1218 parm |= index;
Takashi Iwai0ba21762007-04-16 11:29:14 +02001219 val = snd_hda_codec_read(codec, nid, 0,
1220 AC_VERB_GET_AMP_GAIN_MUTE, parm);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001221 info->vol[ch] = val & 0xff;
Takashi Iwai01751f52007-08-10 16:59:39 +02001222 info->head.val |= INFO_AMP_VOL(ch);
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001223 return info->vol[ch];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001224}
1225
1226/*
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001227 * write the current volume in info to the h/w and update the cache
Linus Torvalds1da177e2005-04-16 15:20:36 -07001228 */
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001229static void put_vol_mute(struct hda_codec *codec, struct hda_amp_info *info,
Takashi Iwai0ba21762007-04-16 11:29:14 +02001230 hda_nid_t nid, int ch, int direction, int index,
1231 int val)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001232{
1233 u32 parm;
1234
1235 parm = ch ? AC_AMP_SET_RIGHT : AC_AMP_SET_LEFT;
1236 parm |= direction == HDA_OUTPUT ? AC_AMP_SET_OUTPUT : AC_AMP_SET_INPUT;
1237 parm |= index << AC_AMP_SET_INDEX_SHIFT;
1238 parm |= val;
1239 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, parm);
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001240 info->vol[ch] = val;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001241}
1242
1243/*
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001244 * read AMP value. The volume is between 0 to 0x7f, 0x80 = mute bit.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001245 */
Takashi Iwai834be882006-03-01 14:16:17 +01001246int snd_hda_codec_amp_read(struct hda_codec *codec, hda_nid_t nid, int ch,
1247 int direction, int index)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001248{
Takashi Iwai0ba21762007-04-16 11:29:14 +02001249 struct hda_amp_info *info;
1250 info = get_alloc_amp_hash(codec, HDA_HASH_KEY(nid, direction, index));
1251 if (!info)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001252 return 0;
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001253 return get_vol_mute(codec, info, nid, ch, direction, index);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001254}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001255EXPORT_SYMBOL_HDA(snd_hda_codec_amp_read);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001256
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001257/*
1258 * update the AMP value, mask = bit mask to set, val = the value
1259 */
Takashi Iwai834be882006-03-01 14:16:17 +01001260int snd_hda_codec_amp_update(struct hda_codec *codec, hda_nid_t nid, int ch,
1261 int direction, int idx, int mask, int val)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001262{
Takashi Iwai0ba21762007-04-16 11:29:14 +02001263 struct hda_amp_info *info;
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001264
Takashi Iwai0ba21762007-04-16 11:29:14 +02001265 info = get_alloc_amp_hash(codec, HDA_HASH_KEY(nid, direction, idx));
1266 if (!info)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001267 return 0;
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001268 val &= mask;
1269 val |= get_vol_mute(codec, info, nid, ch, direction, idx) & ~mask;
Takashi Iwai82beb8f2007-08-10 17:09:26 +02001270 if (info->vol[ch] == val)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001271 return 0;
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001272 put_vol_mute(codec, info, nid, ch, direction, idx, val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001273 return 1;
1274}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001275EXPORT_SYMBOL_HDA(snd_hda_codec_amp_update);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001276
Takashi Iwai47fd8302007-08-10 17:11:07 +02001277/*
1278 * update the AMP stereo with the same mask and value
1279 */
1280int snd_hda_codec_amp_stereo(struct hda_codec *codec, hda_nid_t nid,
1281 int direction, int idx, int mask, int val)
1282{
1283 int ch, ret = 0;
1284 for (ch = 0; ch < 2; ch++)
1285 ret |= snd_hda_codec_amp_update(codec, nid, ch, direction,
1286 idx, mask, val);
1287 return ret;
1288}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001289EXPORT_SYMBOL_HDA(snd_hda_codec_amp_stereo);
Takashi Iwai47fd8302007-08-10 17:11:07 +02001290
Takashi Iwaicb53c622007-08-10 17:21:45 +02001291#ifdef SND_HDA_NEEDS_RESUME
Takashi Iwaib3ac5632007-08-10 17:03:40 +02001292/* resume the all amp commands from the cache */
1293void snd_hda_codec_resume_amp(struct hda_codec *codec)
1294{
Takashi Iwai603c4012008-07-30 15:01:44 +02001295 struct hda_amp_info *buffer = codec->amp_cache.buf.list;
Takashi Iwaib3ac5632007-08-10 17:03:40 +02001296 int i;
1297
Takashi Iwai603c4012008-07-30 15:01:44 +02001298 for (i = 0; i < codec->amp_cache.buf.used; i++, buffer++) {
Takashi Iwaib3ac5632007-08-10 17:03:40 +02001299 u32 key = buffer->head.key;
1300 hda_nid_t nid;
1301 unsigned int idx, dir, ch;
1302 if (!key)
1303 continue;
1304 nid = key & 0xff;
1305 idx = (key >> 16) & 0xff;
1306 dir = (key >> 24) & 0xff;
1307 for (ch = 0; ch < 2; ch++) {
1308 if (!(buffer->head.val & INFO_AMP_VOL(ch)))
1309 continue;
1310 put_vol_mute(codec, buffer, nid, ch, dir, idx,
1311 buffer->vol[ch]);
1312 }
1313 }
1314}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001315EXPORT_SYMBOL_HDA(snd_hda_codec_resume_amp);
Takashi Iwaicb53c622007-08-10 17:21:45 +02001316#endif /* SND_HDA_NEEDS_RESUME */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001317
Linus Torvalds1da177e2005-04-16 15:20:36 -07001318/* volume */
Takashi Iwai0ba21762007-04-16 11:29:14 +02001319int snd_hda_mixer_amp_volume_info(struct snd_kcontrol *kcontrol,
1320 struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001321{
1322 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1323 u16 nid = get_amp_nid(kcontrol);
1324 u8 chs = get_amp_channels(kcontrol);
1325 int dir = get_amp_direction(kcontrol);
Takashi Iwai29fdbec2009-01-20 13:07:55 +01001326 unsigned int ofs = get_amp_offset(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001327 u32 caps;
1328
1329 caps = query_amp_caps(codec, nid, dir);
Takashi Iwai0ba21762007-04-16 11:29:14 +02001330 /* num steps */
1331 caps = (caps & AC_AMPCAP_NUM_STEPS) >> AC_AMPCAP_NUM_STEPS_SHIFT;
1332 if (!caps) {
1333 printk(KERN_WARNING "hda_codec: "
Takashi Iwai9c8f2ab2008-01-11 16:12:23 +01001334 "num_steps = 0 for NID=0x%x (ctl = %s)\n", nid,
1335 kcontrol->id.name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001336 return -EINVAL;
1337 }
Takashi Iwai29fdbec2009-01-20 13:07:55 +01001338 if (ofs < caps)
1339 caps -= ofs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001340 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
1341 uinfo->count = chs == 3 ? 2 : 1;
1342 uinfo->value.integer.min = 0;
1343 uinfo->value.integer.max = caps;
1344 return 0;
1345}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001346EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_volume_info);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001347
Takashi Iwai29fdbec2009-01-20 13:07:55 +01001348
1349static inline unsigned int
1350read_amp_value(struct hda_codec *codec, hda_nid_t nid,
1351 int ch, int dir, int idx, unsigned int ofs)
1352{
1353 unsigned int val;
1354 val = snd_hda_codec_amp_read(codec, nid, ch, dir, idx);
1355 val &= HDA_AMP_VOLMASK;
1356 if (val >= ofs)
1357 val -= ofs;
1358 else
1359 val = 0;
1360 return val;
1361}
1362
1363static inline int
1364update_amp_value(struct hda_codec *codec, hda_nid_t nid,
1365 int ch, int dir, int idx, unsigned int ofs,
1366 unsigned int val)
1367{
1368 if (val > 0)
1369 val += ofs;
1370 return snd_hda_codec_amp_update(codec, nid, ch, dir, idx,
1371 HDA_AMP_VOLMASK, val);
1372}
1373
Takashi Iwai0ba21762007-04-16 11:29:14 +02001374int snd_hda_mixer_amp_volume_get(struct snd_kcontrol *kcontrol,
1375 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001376{
1377 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1378 hda_nid_t nid = get_amp_nid(kcontrol);
1379 int chs = get_amp_channels(kcontrol);
1380 int dir = get_amp_direction(kcontrol);
1381 int idx = get_amp_index(kcontrol);
Takashi Iwai29fdbec2009-01-20 13:07:55 +01001382 unsigned int ofs = get_amp_offset(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001383 long *valp = ucontrol->value.integer.value;
1384
1385 if (chs & 1)
Takashi Iwai29fdbec2009-01-20 13:07:55 +01001386 *valp++ = read_amp_value(codec, nid, 0, dir, idx, ofs);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001387 if (chs & 2)
Takashi Iwai29fdbec2009-01-20 13:07:55 +01001388 *valp = read_amp_value(codec, nid, 1, dir, idx, ofs);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001389 return 0;
1390}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001391EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_volume_get);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001392
Takashi Iwai0ba21762007-04-16 11:29:14 +02001393int snd_hda_mixer_amp_volume_put(struct snd_kcontrol *kcontrol,
1394 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001395{
1396 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1397 hda_nid_t nid = get_amp_nid(kcontrol);
1398 int chs = get_amp_channels(kcontrol);
1399 int dir = get_amp_direction(kcontrol);
1400 int idx = get_amp_index(kcontrol);
Takashi Iwai29fdbec2009-01-20 13:07:55 +01001401 unsigned int ofs = get_amp_offset(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001402 long *valp = ucontrol->value.integer.value;
1403 int change = 0;
1404
Takashi Iwaicb53c622007-08-10 17:21:45 +02001405 snd_hda_power_up(codec);
Nicolas Grazianob9f5a892005-07-29 12:17:20 +02001406 if (chs & 1) {
Takashi Iwai29fdbec2009-01-20 13:07:55 +01001407 change = update_amp_value(codec, nid, 0, dir, idx, ofs, *valp);
Nicolas Grazianob9f5a892005-07-29 12:17:20 +02001408 valp++;
1409 }
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001410 if (chs & 2)
Takashi Iwai29fdbec2009-01-20 13:07:55 +01001411 change |= update_amp_value(codec, nid, 1, dir, idx, ofs, *valp);
Takashi Iwaicb53c622007-08-10 17:21:45 +02001412 snd_hda_power_down(codec);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001413 return change;
1414}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001415EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_volume_put);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001416
Jaroslav Kysela302e9c52006-07-05 17:39:49 +02001417int snd_hda_mixer_amp_tlv(struct snd_kcontrol *kcontrol, int op_flag,
1418 unsigned int size, unsigned int __user *_tlv)
1419{
1420 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1421 hda_nid_t nid = get_amp_nid(kcontrol);
1422 int dir = get_amp_direction(kcontrol);
Takashi Iwai29fdbec2009-01-20 13:07:55 +01001423 unsigned int ofs = get_amp_offset(kcontrol);
Jaroslav Kysela302e9c52006-07-05 17:39:49 +02001424 u32 caps, val1, val2;
1425
1426 if (size < 4 * sizeof(unsigned int))
1427 return -ENOMEM;
1428 caps = query_amp_caps(codec, nid, dir);
Takashi Iwai0ba21762007-04-16 11:29:14 +02001429 val2 = (caps & AC_AMPCAP_STEP_SIZE) >> AC_AMPCAP_STEP_SIZE_SHIFT;
1430 val2 = (val2 + 1) * 25;
Jaroslav Kysela302e9c52006-07-05 17:39:49 +02001431 val1 = -((caps & AC_AMPCAP_OFFSET) >> AC_AMPCAP_OFFSET_SHIFT);
Takashi Iwai29fdbec2009-01-20 13:07:55 +01001432 val1 += ofs;
Jaroslav Kysela302e9c52006-07-05 17:39:49 +02001433 val1 = ((int)val1) * ((int)val2);
Jaroslav Kysela302e9c52006-07-05 17:39:49 +02001434 if (put_user(SNDRV_CTL_TLVT_DB_SCALE, _tlv))
1435 return -EFAULT;
1436 if (put_user(2 * sizeof(unsigned int), _tlv + 1))
1437 return -EFAULT;
1438 if (put_user(val1, _tlv + 2))
1439 return -EFAULT;
1440 if (put_user(val2, _tlv + 3))
1441 return -EFAULT;
1442 return 0;
1443}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001444EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_tlv);
Jaroslav Kysela302e9c52006-07-05 17:39:49 +02001445
Takashi Iwai2134ea42008-01-10 16:53:55 +01001446/*
1447 * set (static) TLV for virtual master volume; recalculated as max 0dB
1448 */
1449void snd_hda_set_vmaster_tlv(struct hda_codec *codec, hda_nid_t nid, int dir,
1450 unsigned int *tlv)
1451{
1452 u32 caps;
1453 int nums, step;
1454
1455 caps = query_amp_caps(codec, nid, dir);
1456 nums = (caps & AC_AMPCAP_NUM_STEPS) >> AC_AMPCAP_NUM_STEPS_SHIFT;
1457 step = (caps & AC_AMPCAP_STEP_SIZE) >> AC_AMPCAP_STEP_SIZE_SHIFT;
1458 step = (step + 1) * 25;
1459 tlv[0] = SNDRV_CTL_TLVT_DB_SCALE;
1460 tlv[1] = 2 * sizeof(unsigned int);
1461 tlv[2] = -nums * step;
1462 tlv[3] = step;
1463}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001464EXPORT_SYMBOL_HDA(snd_hda_set_vmaster_tlv);
Takashi Iwai2134ea42008-01-10 16:53:55 +01001465
1466/* find a mixer control element with the given name */
Takashi Iwai09f99702008-02-04 12:31:13 +01001467static struct snd_kcontrol *
1468_snd_hda_find_mixer_ctl(struct hda_codec *codec,
1469 const char *name, int idx)
Takashi Iwai2134ea42008-01-10 16:53:55 +01001470{
1471 struct snd_ctl_elem_id id;
1472 memset(&id, 0, sizeof(id));
1473 id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
Takashi Iwai09f99702008-02-04 12:31:13 +01001474 id.index = idx;
Takashi Iwai18cb7102009-04-16 10:22:24 +02001475 if (snd_BUG_ON(strlen(name) >= sizeof(id.name)))
1476 return NULL;
Takashi Iwai2134ea42008-01-10 16:53:55 +01001477 strcpy(id.name, name);
1478 return snd_ctl_find_id(codec->bus->card, &id);
1479}
1480
Takashi Iwai09f99702008-02-04 12:31:13 +01001481struct snd_kcontrol *snd_hda_find_mixer_ctl(struct hda_codec *codec,
1482 const char *name)
1483{
1484 return _snd_hda_find_mixer_ctl(codec, name, 0);
1485}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001486EXPORT_SYMBOL_HDA(snd_hda_find_mixer_ctl);
Takashi Iwai09f99702008-02-04 12:31:13 +01001487
Takashi Iwaid13bd412008-07-30 15:01:45 +02001488/* Add a control element and assign to the codec */
1489int snd_hda_ctl_add(struct hda_codec *codec, struct snd_kcontrol *kctl)
1490{
1491 int err;
1492 struct snd_kcontrol **knewp;
1493
1494 err = snd_ctl_add(codec->bus->card, kctl);
1495 if (err < 0)
1496 return err;
1497 knewp = snd_array_new(&codec->mixers);
1498 if (!knewp)
1499 return -ENOMEM;
1500 *knewp = kctl;
1501 return 0;
1502}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001503EXPORT_SYMBOL_HDA(snd_hda_ctl_add);
Takashi Iwaid13bd412008-07-30 15:01:45 +02001504
1505/* Clear all controls assigned to the given codec */
1506void snd_hda_ctls_clear(struct hda_codec *codec)
1507{
1508 int i;
1509 struct snd_kcontrol **kctls = codec->mixers.list;
1510 for (i = 0; i < codec->mixers.used; i++)
1511 snd_ctl_remove(codec->bus->card, kctls[i]);
1512 snd_array_free(&codec->mixers);
1513}
1514
Takashi Iwaia65d6292009-02-23 16:57:04 +01001515/* pseudo device locking
1516 * toggle card->shutdown to allow/disallow the device access (as a hack)
1517 */
1518static int hda_lock_devices(struct snd_card *card)
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001519{
Takashi Iwaia65d6292009-02-23 16:57:04 +01001520 spin_lock(&card->files_lock);
1521 if (card->shutdown) {
1522 spin_unlock(&card->files_lock);
1523 return -EINVAL;
1524 }
1525 card->shutdown = 1;
1526 spin_unlock(&card->files_lock);
1527 return 0;
1528}
1529
1530static void hda_unlock_devices(struct snd_card *card)
1531{
1532 spin_lock(&card->files_lock);
1533 card->shutdown = 0;
1534 spin_unlock(&card->files_lock);
1535}
1536
1537int snd_hda_codec_reset(struct hda_codec *codec)
1538{
1539 struct snd_card *card = codec->bus->card;
1540 int i, pcm;
1541
1542 if (hda_lock_devices(card) < 0)
1543 return -EBUSY;
1544 /* check whether the codec isn't used by any mixer or PCM streams */
1545 if (!list_empty(&card->ctl_files)) {
1546 hda_unlock_devices(card);
1547 return -EBUSY;
1548 }
1549 for (pcm = 0; pcm < codec->num_pcms; pcm++) {
1550 struct hda_pcm *cpcm = &codec->pcm_info[pcm];
1551 if (!cpcm->pcm)
1552 continue;
1553 if (cpcm->pcm->streams[0].substream_opened ||
1554 cpcm->pcm->streams[1].substream_opened) {
1555 hda_unlock_devices(card);
1556 return -EBUSY;
1557 }
1558 }
1559
1560 /* OK, let it free */
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001561
1562#ifdef CONFIG_SND_HDA_POWER_SAVE
1563 cancel_delayed_work(&codec->power_work);
Takashi Iwai6acaed32009-01-12 10:09:24 +01001564 flush_workqueue(codec->bus->workq);
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001565#endif
1566 snd_hda_ctls_clear(codec);
1567 /* relase PCMs */
1568 for (i = 0; i < codec->num_pcms; i++) {
Takashi Iwai529bd6c2008-11-27 14:17:01 +01001569 if (codec->pcm_info[i].pcm) {
Takashi Iwaia65d6292009-02-23 16:57:04 +01001570 snd_device_free(card, codec->pcm_info[i].pcm);
Takashi Iwai529bd6c2008-11-27 14:17:01 +01001571 clear_bit(codec->pcm_info[i].device,
1572 codec->bus->pcm_dev_bits);
1573 }
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001574 }
1575 if (codec->patch_ops.free)
1576 codec->patch_ops.free(codec);
Takashi Iwai56d17712008-11-28 14:36:23 +01001577 codec->proc_widget_hook = NULL;
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001578 codec->spec = NULL;
1579 free_hda_cache(&codec->amp_cache);
1580 free_hda_cache(&codec->cmd_cache);
Takashi Iwai827057f2008-12-19 10:12:02 +01001581 init_hda_cache(&codec->amp_cache, sizeof(struct hda_amp_info));
1582 init_hda_cache(&codec->cmd_cache, sizeof(struct hda_cache_head));
Takashi Iwai346ff702009-02-23 09:42:57 +01001583 /* free only driver_pins so that init_pins + user_pins are restored */
1584 snd_array_free(&codec->driver_pins);
Takashi Iwai3be14142009-02-20 14:11:16 +01001585 restore_pincfgs(codec);
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001586 codec->num_pcms = 0;
1587 codec->pcm_info = NULL;
1588 codec->preset = NULL;
Takashi Iwaid1f1af22009-03-02 10:35:29 +01001589 memset(&codec->patch_ops, 0, sizeof(codec->patch_ops));
1590 codec->slave_dig_outs = NULL;
1591 codec->spdif_status_reset = 0;
Takashi Iwai1289e9e2008-11-27 15:47:11 +01001592 module_put(codec->owner);
1593 codec->owner = NULL;
Takashi Iwaia65d6292009-02-23 16:57:04 +01001594
1595 /* allow device access again */
1596 hda_unlock_devices(card);
1597 return 0;
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001598}
1599
Takashi Iwai2134ea42008-01-10 16:53:55 +01001600/* create a virtual master control and add slaves */
1601int snd_hda_add_vmaster(struct hda_codec *codec, char *name,
1602 unsigned int *tlv, const char **slaves)
1603{
1604 struct snd_kcontrol *kctl;
1605 const char **s;
1606 int err;
1607
Takashi Iwai2f085542008-02-22 18:43:50 +01001608 for (s = slaves; *s && !snd_hda_find_mixer_ctl(codec, *s); s++)
1609 ;
1610 if (!*s) {
1611 snd_printdd("No slave found for %s\n", name);
1612 return 0;
1613 }
Takashi Iwai2134ea42008-01-10 16:53:55 +01001614 kctl = snd_ctl_make_virtual_master(name, tlv);
1615 if (!kctl)
1616 return -ENOMEM;
Takashi Iwaid13bd412008-07-30 15:01:45 +02001617 err = snd_hda_ctl_add(codec, kctl);
Takashi Iwai2134ea42008-01-10 16:53:55 +01001618 if (err < 0)
1619 return err;
1620
1621 for (s = slaves; *s; s++) {
1622 struct snd_kcontrol *sctl;
Takashi Iwai7a411ee2009-03-06 10:08:14 +01001623 int i = 0;
1624 for (;;) {
1625 sctl = _snd_hda_find_mixer_ctl(codec, *s, i);
1626 if (!sctl) {
1627 if (!i)
1628 snd_printdd("Cannot find slave %s, "
1629 "skipped\n", *s);
1630 break;
1631 }
1632 err = snd_ctl_add_slave(kctl, sctl);
1633 if (err < 0)
1634 return err;
1635 i++;
Takashi Iwai2134ea42008-01-10 16:53:55 +01001636 }
Takashi Iwai2134ea42008-01-10 16:53:55 +01001637 }
1638 return 0;
1639}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001640EXPORT_SYMBOL_HDA(snd_hda_add_vmaster);
Takashi Iwai2134ea42008-01-10 16:53:55 +01001641
Linus Torvalds1da177e2005-04-16 15:20:36 -07001642/* switch */
Takashi Iwai0ba21762007-04-16 11:29:14 +02001643int snd_hda_mixer_amp_switch_info(struct snd_kcontrol *kcontrol,
1644 struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001645{
1646 int chs = get_amp_channels(kcontrol);
1647
1648 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
1649 uinfo->count = chs == 3 ? 2 : 1;
1650 uinfo->value.integer.min = 0;
1651 uinfo->value.integer.max = 1;
1652 return 0;
1653}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001654EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_switch_info);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001655
Takashi Iwai0ba21762007-04-16 11:29:14 +02001656int snd_hda_mixer_amp_switch_get(struct snd_kcontrol *kcontrol,
1657 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001658{
1659 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1660 hda_nid_t nid = get_amp_nid(kcontrol);
1661 int chs = get_amp_channels(kcontrol);
1662 int dir = get_amp_direction(kcontrol);
1663 int idx = get_amp_index(kcontrol);
1664 long *valp = ucontrol->value.integer.value;
1665
1666 if (chs & 1)
Takashi Iwai0ba21762007-04-16 11:29:14 +02001667 *valp++ = (snd_hda_codec_amp_read(codec, nid, 0, dir, idx) &
Takashi Iwai47fd8302007-08-10 17:11:07 +02001668 HDA_AMP_MUTE) ? 0 : 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001669 if (chs & 2)
Takashi Iwai0ba21762007-04-16 11:29:14 +02001670 *valp = (snd_hda_codec_amp_read(codec, nid, 1, dir, idx) &
Takashi Iwai47fd8302007-08-10 17:11:07 +02001671 HDA_AMP_MUTE) ? 0 : 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001672 return 0;
1673}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001674EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_switch_get);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001675
Takashi Iwai0ba21762007-04-16 11:29:14 +02001676int snd_hda_mixer_amp_switch_put(struct snd_kcontrol *kcontrol,
1677 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001678{
1679 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1680 hda_nid_t nid = get_amp_nid(kcontrol);
1681 int chs = get_amp_channels(kcontrol);
1682 int dir = get_amp_direction(kcontrol);
1683 int idx = get_amp_index(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001684 long *valp = ucontrol->value.integer.value;
1685 int change = 0;
1686
Takashi Iwaicb53c622007-08-10 17:21:45 +02001687 snd_hda_power_up(codec);
Nicolas Grazianob9f5a892005-07-29 12:17:20 +02001688 if (chs & 1) {
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001689 change = snd_hda_codec_amp_update(codec, nid, 0, dir, idx,
Takashi Iwai47fd8302007-08-10 17:11:07 +02001690 HDA_AMP_MUTE,
1691 *valp ? 0 : HDA_AMP_MUTE);
Nicolas Grazianob9f5a892005-07-29 12:17:20 +02001692 valp++;
1693 }
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001694 if (chs & 2)
1695 change |= snd_hda_codec_amp_update(codec, nid, 1, dir, idx,
Takashi Iwai47fd8302007-08-10 17:11:07 +02001696 HDA_AMP_MUTE,
1697 *valp ? 0 : HDA_AMP_MUTE);
Takashi Iwaicb53c622007-08-10 17:21:45 +02001698#ifdef CONFIG_SND_HDA_POWER_SAVE
1699 if (codec->patch_ops.check_power_status)
1700 codec->patch_ops.check_power_status(codec, nid);
1701#endif
1702 snd_hda_power_down(codec);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001703 return change;
1704}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001705EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_switch_put);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001706
1707/*
Takashi Iwai985be542005-11-02 18:26:49 +01001708 * bound volume controls
1709 *
1710 * bind multiple volumes (# indices, from 0)
1711 */
1712
1713#define AMP_VAL_IDX_SHIFT 19
1714#define AMP_VAL_IDX_MASK (0x0f<<19)
1715
Takashi Iwai0ba21762007-04-16 11:29:14 +02001716int snd_hda_mixer_bind_switch_get(struct snd_kcontrol *kcontrol,
1717 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai985be542005-11-02 18:26:49 +01001718{
1719 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1720 unsigned long pval;
1721 int err;
1722
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001723 mutex_lock(&codec->control_mutex);
Takashi Iwai985be542005-11-02 18:26:49 +01001724 pval = kcontrol->private_value;
1725 kcontrol->private_value = pval & ~AMP_VAL_IDX_MASK; /* index 0 */
1726 err = snd_hda_mixer_amp_switch_get(kcontrol, ucontrol);
1727 kcontrol->private_value = pval;
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001728 mutex_unlock(&codec->control_mutex);
Takashi Iwai985be542005-11-02 18:26:49 +01001729 return err;
1730}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001731EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_switch_get);
Takashi Iwai985be542005-11-02 18:26:49 +01001732
Takashi Iwai0ba21762007-04-16 11:29:14 +02001733int snd_hda_mixer_bind_switch_put(struct snd_kcontrol *kcontrol,
1734 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai985be542005-11-02 18:26:49 +01001735{
1736 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1737 unsigned long pval;
1738 int i, indices, err = 0, change = 0;
1739
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001740 mutex_lock(&codec->control_mutex);
Takashi Iwai985be542005-11-02 18:26:49 +01001741 pval = kcontrol->private_value;
1742 indices = (pval & AMP_VAL_IDX_MASK) >> AMP_VAL_IDX_SHIFT;
1743 for (i = 0; i < indices; i++) {
Takashi Iwai0ba21762007-04-16 11:29:14 +02001744 kcontrol->private_value = (pval & ~AMP_VAL_IDX_MASK) |
1745 (i << AMP_VAL_IDX_SHIFT);
Takashi Iwai985be542005-11-02 18:26:49 +01001746 err = snd_hda_mixer_amp_switch_put(kcontrol, ucontrol);
1747 if (err < 0)
1748 break;
1749 change |= err;
1750 }
1751 kcontrol->private_value = pval;
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001752 mutex_unlock(&codec->control_mutex);
Takashi Iwai985be542005-11-02 18:26:49 +01001753 return err < 0 ? err : change;
1754}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001755EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_switch_put);
Takashi Iwai985be542005-11-02 18:26:49 +01001756
1757/*
Takashi Iwai532d5382007-07-27 19:02:40 +02001758 * generic bound volume/swtich controls
1759 */
1760int snd_hda_mixer_bind_ctls_info(struct snd_kcontrol *kcontrol,
1761 struct snd_ctl_elem_info *uinfo)
1762{
1763 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1764 struct hda_bind_ctls *c;
1765 int err;
1766
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001767 mutex_lock(&codec->control_mutex);
Serge A. Suchkov14c65f92008-02-22 18:43:16 +01001768 c = (struct hda_bind_ctls *)kcontrol->private_value;
Takashi Iwai532d5382007-07-27 19:02:40 +02001769 kcontrol->private_value = *c->values;
1770 err = c->ops->info(kcontrol, uinfo);
1771 kcontrol->private_value = (long)c;
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001772 mutex_unlock(&codec->control_mutex);
Takashi Iwai532d5382007-07-27 19:02:40 +02001773 return err;
1774}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001775EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_ctls_info);
Takashi Iwai532d5382007-07-27 19:02:40 +02001776
1777int snd_hda_mixer_bind_ctls_get(struct snd_kcontrol *kcontrol,
1778 struct snd_ctl_elem_value *ucontrol)
1779{
1780 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1781 struct hda_bind_ctls *c;
1782 int err;
1783
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001784 mutex_lock(&codec->control_mutex);
Serge A. Suchkov14c65f92008-02-22 18:43:16 +01001785 c = (struct hda_bind_ctls *)kcontrol->private_value;
Takashi Iwai532d5382007-07-27 19:02:40 +02001786 kcontrol->private_value = *c->values;
1787 err = c->ops->get(kcontrol, ucontrol);
1788 kcontrol->private_value = (long)c;
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001789 mutex_unlock(&codec->control_mutex);
Takashi Iwai532d5382007-07-27 19:02:40 +02001790 return err;
1791}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001792EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_ctls_get);
Takashi Iwai532d5382007-07-27 19:02:40 +02001793
1794int snd_hda_mixer_bind_ctls_put(struct snd_kcontrol *kcontrol,
1795 struct snd_ctl_elem_value *ucontrol)
1796{
1797 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1798 struct hda_bind_ctls *c;
1799 unsigned long *vals;
1800 int err = 0, change = 0;
1801
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001802 mutex_lock(&codec->control_mutex);
Serge A. Suchkov14c65f92008-02-22 18:43:16 +01001803 c = (struct hda_bind_ctls *)kcontrol->private_value;
Takashi Iwai532d5382007-07-27 19:02:40 +02001804 for (vals = c->values; *vals; vals++) {
1805 kcontrol->private_value = *vals;
1806 err = c->ops->put(kcontrol, ucontrol);
1807 if (err < 0)
1808 break;
1809 change |= err;
1810 }
1811 kcontrol->private_value = (long)c;
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001812 mutex_unlock(&codec->control_mutex);
Takashi Iwai532d5382007-07-27 19:02:40 +02001813 return err < 0 ? err : change;
1814}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001815EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_ctls_put);
Takashi Iwai532d5382007-07-27 19:02:40 +02001816
1817int snd_hda_mixer_bind_tlv(struct snd_kcontrol *kcontrol, int op_flag,
1818 unsigned int size, unsigned int __user *tlv)
1819{
1820 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1821 struct hda_bind_ctls *c;
1822 int err;
1823
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001824 mutex_lock(&codec->control_mutex);
Serge A. Suchkov14c65f92008-02-22 18:43:16 +01001825 c = (struct hda_bind_ctls *)kcontrol->private_value;
Takashi Iwai532d5382007-07-27 19:02:40 +02001826 kcontrol->private_value = *c->values;
1827 err = c->ops->tlv(kcontrol, op_flag, size, tlv);
1828 kcontrol->private_value = (long)c;
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001829 mutex_unlock(&codec->control_mutex);
Takashi Iwai532d5382007-07-27 19:02:40 +02001830 return err;
1831}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001832EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_tlv);
Takashi Iwai532d5382007-07-27 19:02:40 +02001833
1834struct hda_ctl_ops snd_hda_bind_vol = {
1835 .info = snd_hda_mixer_amp_volume_info,
1836 .get = snd_hda_mixer_amp_volume_get,
1837 .put = snd_hda_mixer_amp_volume_put,
1838 .tlv = snd_hda_mixer_amp_tlv
1839};
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001840EXPORT_SYMBOL_HDA(snd_hda_bind_vol);
Takashi Iwai532d5382007-07-27 19:02:40 +02001841
1842struct hda_ctl_ops snd_hda_bind_sw = {
1843 .info = snd_hda_mixer_amp_switch_info,
1844 .get = snd_hda_mixer_amp_switch_get,
1845 .put = snd_hda_mixer_amp_switch_put,
1846 .tlv = snd_hda_mixer_amp_tlv
1847};
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001848EXPORT_SYMBOL_HDA(snd_hda_bind_sw);
Takashi Iwai532d5382007-07-27 19:02:40 +02001849
1850/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07001851 * SPDIF out controls
1852 */
1853
Takashi Iwai0ba21762007-04-16 11:29:14 +02001854static int snd_hda_spdif_mask_info(struct snd_kcontrol *kcontrol,
1855 struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001856{
1857 uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
1858 uinfo->count = 1;
1859 return 0;
1860}
1861
Takashi Iwai0ba21762007-04-16 11:29:14 +02001862static int snd_hda_spdif_cmask_get(struct snd_kcontrol *kcontrol,
1863 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001864{
1865 ucontrol->value.iec958.status[0] = IEC958_AES0_PROFESSIONAL |
1866 IEC958_AES0_NONAUDIO |
1867 IEC958_AES0_CON_EMPHASIS_5015 |
1868 IEC958_AES0_CON_NOT_COPYRIGHT;
1869 ucontrol->value.iec958.status[1] = IEC958_AES1_CON_CATEGORY |
1870 IEC958_AES1_CON_ORIGINAL;
1871 return 0;
1872}
1873
Takashi Iwai0ba21762007-04-16 11:29:14 +02001874static int snd_hda_spdif_pmask_get(struct snd_kcontrol *kcontrol,
1875 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001876{
1877 ucontrol->value.iec958.status[0] = IEC958_AES0_PROFESSIONAL |
1878 IEC958_AES0_NONAUDIO |
1879 IEC958_AES0_PRO_EMPHASIS_5015;
1880 return 0;
1881}
1882
Takashi Iwai0ba21762007-04-16 11:29:14 +02001883static int snd_hda_spdif_default_get(struct snd_kcontrol *kcontrol,
1884 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001885{
1886 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1887
1888 ucontrol->value.iec958.status[0] = codec->spdif_status & 0xff;
1889 ucontrol->value.iec958.status[1] = (codec->spdif_status >> 8) & 0xff;
1890 ucontrol->value.iec958.status[2] = (codec->spdif_status >> 16) & 0xff;
1891 ucontrol->value.iec958.status[3] = (codec->spdif_status >> 24) & 0xff;
1892
1893 return 0;
1894}
1895
1896/* convert from SPDIF status bits to HDA SPDIF bits
1897 * bit 0 (DigEn) is always set zero (to be filled later)
1898 */
1899static unsigned short convert_from_spdif_status(unsigned int sbits)
1900{
1901 unsigned short val = 0;
1902
1903 if (sbits & IEC958_AES0_PROFESSIONAL)
Takashi Iwai0ba21762007-04-16 11:29:14 +02001904 val |= AC_DIG1_PROFESSIONAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001905 if (sbits & IEC958_AES0_NONAUDIO)
Takashi Iwai0ba21762007-04-16 11:29:14 +02001906 val |= AC_DIG1_NONAUDIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001907 if (sbits & IEC958_AES0_PROFESSIONAL) {
Takashi Iwai0ba21762007-04-16 11:29:14 +02001908 if ((sbits & IEC958_AES0_PRO_EMPHASIS) ==
1909 IEC958_AES0_PRO_EMPHASIS_5015)
1910 val |= AC_DIG1_EMPHASIS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001911 } else {
Takashi Iwai0ba21762007-04-16 11:29:14 +02001912 if ((sbits & IEC958_AES0_CON_EMPHASIS) ==
1913 IEC958_AES0_CON_EMPHASIS_5015)
1914 val |= AC_DIG1_EMPHASIS;
1915 if (!(sbits & IEC958_AES0_CON_NOT_COPYRIGHT))
1916 val |= AC_DIG1_COPYRIGHT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001917 if (sbits & (IEC958_AES1_CON_ORIGINAL << 8))
Takashi Iwai0ba21762007-04-16 11:29:14 +02001918 val |= AC_DIG1_LEVEL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001919 val |= sbits & (IEC958_AES1_CON_CATEGORY << 8);
1920 }
1921 return val;
1922}
1923
1924/* convert to SPDIF status bits from HDA SPDIF bits
1925 */
1926static unsigned int convert_to_spdif_status(unsigned short val)
1927{
1928 unsigned int sbits = 0;
1929
Takashi Iwai0ba21762007-04-16 11:29:14 +02001930 if (val & AC_DIG1_NONAUDIO)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001931 sbits |= IEC958_AES0_NONAUDIO;
Takashi Iwai0ba21762007-04-16 11:29:14 +02001932 if (val & AC_DIG1_PROFESSIONAL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001933 sbits |= IEC958_AES0_PROFESSIONAL;
1934 if (sbits & IEC958_AES0_PROFESSIONAL) {
Takashi Iwai0ba21762007-04-16 11:29:14 +02001935 if (sbits & AC_DIG1_EMPHASIS)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001936 sbits |= IEC958_AES0_PRO_EMPHASIS_5015;
1937 } else {
Takashi Iwai0ba21762007-04-16 11:29:14 +02001938 if (val & AC_DIG1_EMPHASIS)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001939 sbits |= IEC958_AES0_CON_EMPHASIS_5015;
Takashi Iwai0ba21762007-04-16 11:29:14 +02001940 if (!(val & AC_DIG1_COPYRIGHT))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001941 sbits |= IEC958_AES0_CON_NOT_COPYRIGHT;
Takashi Iwai0ba21762007-04-16 11:29:14 +02001942 if (val & AC_DIG1_LEVEL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001943 sbits |= (IEC958_AES1_CON_ORIGINAL << 8);
1944 sbits |= val & (0x7f << 8);
1945 }
1946 return sbits;
1947}
1948
Takashi Iwai2f728532008-09-25 16:32:41 +02001949/* set digital convert verbs both for the given NID and its slaves */
1950static void set_dig_out(struct hda_codec *codec, hda_nid_t nid,
1951 int verb, int val)
1952{
1953 hda_nid_t *d;
1954
Takashi Iwai9e976972008-11-25 08:17:20 +01001955 snd_hda_codec_write_cache(codec, nid, 0, verb, val);
Takashi Iwai2f728532008-09-25 16:32:41 +02001956 d = codec->slave_dig_outs;
1957 if (!d)
1958 return;
1959 for (; *d; d++)
Takashi Iwai9e976972008-11-25 08:17:20 +01001960 snd_hda_codec_write_cache(codec, *d, 0, verb, val);
Takashi Iwai2f728532008-09-25 16:32:41 +02001961}
1962
1963static inline void set_dig_out_convert(struct hda_codec *codec, hda_nid_t nid,
1964 int dig1, int dig2)
1965{
1966 if (dig1 != -1)
1967 set_dig_out(codec, nid, AC_VERB_SET_DIGI_CONVERT_1, dig1);
1968 if (dig2 != -1)
1969 set_dig_out(codec, nid, AC_VERB_SET_DIGI_CONVERT_2, dig2);
1970}
1971
Takashi Iwai0ba21762007-04-16 11:29:14 +02001972static int snd_hda_spdif_default_put(struct snd_kcontrol *kcontrol,
1973 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001974{
1975 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1976 hda_nid_t nid = kcontrol->private_value;
1977 unsigned short val;
1978 int change;
1979
Ingo Molnar62932df2006-01-16 16:34:20 +01001980 mutex_lock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001981 codec->spdif_status = ucontrol->value.iec958.status[0] |
1982 ((unsigned int)ucontrol->value.iec958.status[1] << 8) |
1983 ((unsigned int)ucontrol->value.iec958.status[2] << 16) |
1984 ((unsigned int)ucontrol->value.iec958.status[3] << 24);
1985 val = convert_from_spdif_status(codec->spdif_status);
1986 val |= codec->spdif_ctls & 1;
1987 change = codec->spdif_ctls != val;
1988 codec->spdif_ctls = val;
1989
Takashi Iwai2f728532008-09-25 16:32:41 +02001990 if (change)
1991 set_dig_out_convert(codec, nid, val & 0xff, (val >> 8) & 0xff);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001992
Ingo Molnar62932df2006-01-16 16:34:20 +01001993 mutex_unlock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001994 return change;
1995}
1996
Takashi Iwaia5ce8892007-07-23 15:42:26 +02001997#define snd_hda_spdif_out_switch_info snd_ctl_boolean_mono_info
Linus Torvalds1da177e2005-04-16 15:20:36 -07001998
Takashi Iwai0ba21762007-04-16 11:29:14 +02001999static int snd_hda_spdif_out_switch_get(struct snd_kcontrol *kcontrol,
2000 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002001{
2002 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2003
Takashi Iwai0ba21762007-04-16 11:29:14 +02002004 ucontrol->value.integer.value[0] = codec->spdif_ctls & AC_DIG1_ENABLE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002005 return 0;
2006}
2007
Takashi Iwai0ba21762007-04-16 11:29:14 +02002008static int snd_hda_spdif_out_switch_put(struct snd_kcontrol *kcontrol,
2009 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002010{
2011 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2012 hda_nid_t nid = kcontrol->private_value;
2013 unsigned short val;
2014 int change;
2015
Ingo Molnar62932df2006-01-16 16:34:20 +01002016 mutex_lock(&codec->spdif_mutex);
Takashi Iwai0ba21762007-04-16 11:29:14 +02002017 val = codec->spdif_ctls & ~AC_DIG1_ENABLE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002018 if (ucontrol->value.integer.value[0])
Takashi Iwai0ba21762007-04-16 11:29:14 +02002019 val |= AC_DIG1_ENABLE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002020 change = codec->spdif_ctls != val;
Takashi Iwai82beb8f2007-08-10 17:09:26 +02002021 if (change) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002022 codec->spdif_ctls = val;
Takashi Iwai2f728532008-09-25 16:32:41 +02002023 set_dig_out_convert(codec, nid, val & 0xff, -1);
Takashi Iwai0ba21762007-04-16 11:29:14 +02002024 /* unmute amp switch (if any) */
2025 if ((get_wcaps(codec, nid) & AC_WCAP_OUT_AMP) &&
Takashi Iwai47fd8302007-08-10 17:11:07 +02002026 (val & AC_DIG1_ENABLE))
2027 snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0,
2028 HDA_AMP_MUTE, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002029 }
Ingo Molnar62932df2006-01-16 16:34:20 +01002030 mutex_unlock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002031 return change;
2032}
2033
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01002034static struct snd_kcontrol_new dig_mixes[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002035 {
2036 .access = SNDRV_CTL_ELEM_ACCESS_READ,
2037 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2038 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,CON_MASK),
2039 .info = snd_hda_spdif_mask_info,
2040 .get = snd_hda_spdif_cmask_get,
2041 },
2042 {
2043 .access = SNDRV_CTL_ELEM_ACCESS_READ,
2044 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2045 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,PRO_MASK),
2046 .info = snd_hda_spdif_mask_info,
2047 .get = snd_hda_spdif_pmask_get,
2048 },
2049 {
2050 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2051 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT),
2052 .info = snd_hda_spdif_mask_info,
2053 .get = snd_hda_spdif_default_get,
2054 .put = snd_hda_spdif_default_put,
2055 },
2056 {
2057 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2058 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,SWITCH),
2059 .info = snd_hda_spdif_out_switch_info,
2060 .get = snd_hda_spdif_out_switch_get,
2061 .put = snd_hda_spdif_out_switch_put,
2062 },
2063 { } /* end */
2064};
2065
Takashi Iwai09f99702008-02-04 12:31:13 +01002066#define SPDIF_MAX_IDX 4 /* 4 instances should be enough to probe */
2067
Linus Torvalds1da177e2005-04-16 15:20:36 -07002068/**
2069 * snd_hda_create_spdif_out_ctls - create Output SPDIF-related controls
2070 * @codec: the HDA codec
2071 * @nid: audio out widget NID
2072 *
2073 * Creates controls related with the SPDIF output.
2074 * Called from each patch supporting the SPDIF out.
2075 *
2076 * Returns 0 if successful, or a negative error code.
2077 */
Takashi Iwai12f288b2007-08-02 15:51:59 +02002078int snd_hda_create_spdif_out_ctls(struct hda_codec *codec, hda_nid_t nid)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002079{
2080 int err;
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01002081 struct snd_kcontrol *kctl;
2082 struct snd_kcontrol_new *dig_mix;
Takashi Iwai09f99702008-02-04 12:31:13 +01002083 int idx;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002084
Takashi Iwai09f99702008-02-04 12:31:13 +01002085 for (idx = 0; idx < SPDIF_MAX_IDX; idx++) {
2086 if (!_snd_hda_find_mixer_ctl(codec, "IEC958 Playback Switch",
2087 idx))
2088 break;
2089 }
2090 if (idx >= SPDIF_MAX_IDX) {
2091 printk(KERN_ERR "hda_codec: too many IEC958 outputs\n");
2092 return -EBUSY;
2093 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002094 for (dig_mix = dig_mixes; dig_mix->name; dig_mix++) {
2095 kctl = snd_ctl_new1(dig_mix, codec);
Takashi Iwaib91f0802008-11-04 08:43:08 +01002096 if (!kctl)
2097 return -ENOMEM;
Takashi Iwai09f99702008-02-04 12:31:13 +01002098 kctl->id.index = idx;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002099 kctl->private_value = nid;
Takashi Iwaid13bd412008-07-30 15:01:45 +02002100 err = snd_hda_ctl_add(codec, kctl);
Takashi Iwai0ba21762007-04-16 11:29:14 +02002101 if (err < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002102 return err;
2103 }
Takashi Iwai0ba21762007-04-16 11:29:14 +02002104 codec->spdif_ctls =
Andrew Paprocki3982d172007-12-19 12:13:44 +01002105 snd_hda_codec_read(codec, nid, 0,
2106 AC_VERB_GET_DIGI_CONVERT_1, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002107 codec->spdif_status = convert_to_spdif_status(codec->spdif_ctls);
2108 return 0;
2109}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002110EXPORT_SYMBOL_HDA(snd_hda_create_spdif_out_ctls);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002111
2112/*
Takashi Iwai9a081602008-02-12 18:37:26 +01002113 * SPDIF sharing with analog output
2114 */
2115static int spdif_share_sw_get(struct snd_kcontrol *kcontrol,
2116 struct snd_ctl_elem_value *ucontrol)
2117{
2118 struct hda_multi_out *mout = snd_kcontrol_chip(kcontrol);
2119 ucontrol->value.integer.value[0] = mout->share_spdif;
2120 return 0;
2121}
2122
2123static int spdif_share_sw_put(struct snd_kcontrol *kcontrol,
2124 struct snd_ctl_elem_value *ucontrol)
2125{
2126 struct hda_multi_out *mout = snd_kcontrol_chip(kcontrol);
2127 mout->share_spdif = !!ucontrol->value.integer.value[0];
2128 return 0;
2129}
2130
2131static struct snd_kcontrol_new spdif_share_sw = {
2132 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2133 .name = "IEC958 Default PCM Playback Switch",
2134 .info = snd_ctl_boolean_mono_info,
2135 .get = spdif_share_sw_get,
2136 .put = spdif_share_sw_put,
2137};
2138
2139int snd_hda_create_spdif_share_sw(struct hda_codec *codec,
2140 struct hda_multi_out *mout)
2141{
2142 if (!mout->dig_out_nid)
2143 return 0;
2144 /* ATTENTION: here mout is passed as private_data, instead of codec */
Takashi Iwaid13bd412008-07-30 15:01:45 +02002145 return snd_hda_ctl_add(codec,
Takashi Iwai9a081602008-02-12 18:37:26 +01002146 snd_ctl_new1(&spdif_share_sw, mout));
2147}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002148EXPORT_SYMBOL_HDA(snd_hda_create_spdif_share_sw);
Takashi Iwai9a081602008-02-12 18:37:26 +01002149
2150/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002151 * SPDIF input
2152 */
2153
2154#define snd_hda_spdif_in_switch_info snd_hda_spdif_out_switch_info
2155
Takashi Iwai0ba21762007-04-16 11:29:14 +02002156static int snd_hda_spdif_in_switch_get(struct snd_kcontrol *kcontrol,
2157 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002158{
2159 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2160
2161 ucontrol->value.integer.value[0] = codec->spdif_in_enable;
2162 return 0;
2163}
2164
Takashi Iwai0ba21762007-04-16 11:29:14 +02002165static int snd_hda_spdif_in_switch_put(struct snd_kcontrol *kcontrol,
2166 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002167{
2168 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2169 hda_nid_t nid = kcontrol->private_value;
2170 unsigned int val = !!ucontrol->value.integer.value[0];
2171 int change;
2172
Ingo Molnar62932df2006-01-16 16:34:20 +01002173 mutex_lock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002174 change = codec->spdif_in_enable != val;
Takashi Iwai82beb8f2007-08-10 17:09:26 +02002175 if (change) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002176 codec->spdif_in_enable = val;
Takashi Iwai82beb8f2007-08-10 17:09:26 +02002177 snd_hda_codec_write_cache(codec, nid, 0,
2178 AC_VERB_SET_DIGI_CONVERT_1, val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002179 }
Ingo Molnar62932df2006-01-16 16:34:20 +01002180 mutex_unlock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002181 return change;
2182}
2183
Takashi Iwai0ba21762007-04-16 11:29:14 +02002184static int snd_hda_spdif_in_status_get(struct snd_kcontrol *kcontrol,
2185 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002186{
2187 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2188 hda_nid_t nid = kcontrol->private_value;
2189 unsigned short val;
2190 unsigned int sbits;
2191
Andrew Paprocki3982d172007-12-19 12:13:44 +01002192 val = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_DIGI_CONVERT_1, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002193 sbits = convert_to_spdif_status(val);
2194 ucontrol->value.iec958.status[0] = sbits;
2195 ucontrol->value.iec958.status[1] = sbits >> 8;
2196 ucontrol->value.iec958.status[2] = sbits >> 16;
2197 ucontrol->value.iec958.status[3] = sbits >> 24;
2198 return 0;
2199}
2200
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01002201static struct snd_kcontrol_new dig_in_ctls[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002202 {
2203 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2204 .name = SNDRV_CTL_NAME_IEC958("",CAPTURE,SWITCH),
2205 .info = snd_hda_spdif_in_switch_info,
2206 .get = snd_hda_spdif_in_switch_get,
2207 .put = snd_hda_spdif_in_switch_put,
2208 },
2209 {
2210 .access = SNDRV_CTL_ELEM_ACCESS_READ,
2211 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2212 .name = SNDRV_CTL_NAME_IEC958("",CAPTURE,DEFAULT),
2213 .info = snd_hda_spdif_mask_info,
2214 .get = snd_hda_spdif_in_status_get,
2215 },
2216 { } /* end */
2217};
2218
2219/**
2220 * snd_hda_create_spdif_in_ctls - create Input SPDIF-related controls
2221 * @codec: the HDA codec
2222 * @nid: audio in widget NID
2223 *
2224 * Creates controls related with the SPDIF input.
2225 * Called from each patch supporting the SPDIF in.
2226 *
2227 * Returns 0 if successful, or a negative error code.
2228 */
Takashi Iwai12f288b2007-08-02 15:51:59 +02002229int snd_hda_create_spdif_in_ctls(struct hda_codec *codec, hda_nid_t nid)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002230{
2231 int err;
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01002232 struct snd_kcontrol *kctl;
2233 struct snd_kcontrol_new *dig_mix;
Takashi Iwai09f99702008-02-04 12:31:13 +01002234 int idx;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002235
Takashi Iwai09f99702008-02-04 12:31:13 +01002236 for (idx = 0; idx < SPDIF_MAX_IDX; idx++) {
2237 if (!_snd_hda_find_mixer_ctl(codec, "IEC958 Capture Switch",
2238 idx))
2239 break;
2240 }
2241 if (idx >= SPDIF_MAX_IDX) {
2242 printk(KERN_ERR "hda_codec: too many IEC958 inputs\n");
2243 return -EBUSY;
2244 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002245 for (dig_mix = dig_in_ctls; dig_mix->name; dig_mix++) {
2246 kctl = snd_ctl_new1(dig_mix, codec);
Takashi Iwaic8dcdf82009-02-06 16:21:20 +01002247 if (!kctl)
2248 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002249 kctl->private_value = nid;
Takashi Iwaid13bd412008-07-30 15:01:45 +02002250 err = snd_hda_ctl_add(codec, kctl);
Takashi Iwai0ba21762007-04-16 11:29:14 +02002251 if (err < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002252 return err;
2253 }
Takashi Iwai0ba21762007-04-16 11:29:14 +02002254 codec->spdif_in_enable =
Andrew Paprocki3982d172007-12-19 12:13:44 +01002255 snd_hda_codec_read(codec, nid, 0,
2256 AC_VERB_GET_DIGI_CONVERT_1, 0) &
Takashi Iwai0ba21762007-04-16 11:29:14 +02002257 AC_DIG1_ENABLE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002258 return 0;
2259}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002260EXPORT_SYMBOL_HDA(snd_hda_create_spdif_in_ctls);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002261
Takashi Iwaicb53c622007-08-10 17:21:45 +02002262#ifdef SND_HDA_NEEDS_RESUME
Takashi Iwai82beb8f2007-08-10 17:09:26 +02002263/*
2264 * command cache
2265 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002266
Takashi Iwaib3ac5632007-08-10 17:03:40 +02002267/* build a 32bit cache key with the widget id and the command parameter */
2268#define build_cmd_cache_key(nid, verb) ((verb << 8) | nid)
2269#define get_cmd_cache_nid(key) ((key) & 0xff)
2270#define get_cmd_cache_cmd(key) (((key) >> 8) & 0xffff)
2271
2272/**
2273 * snd_hda_codec_write_cache - send a single command with caching
2274 * @codec: the HDA codec
2275 * @nid: NID to send the command
2276 * @direct: direct flag
2277 * @verb: the verb to send
2278 * @parm: the parameter for the verb
2279 *
2280 * Send a single command without waiting for response.
2281 *
2282 * Returns 0 if successful, or a negative error code.
2283 */
2284int snd_hda_codec_write_cache(struct hda_codec *codec, hda_nid_t nid,
2285 int direct, unsigned int verb, unsigned int parm)
2286{
Takashi Iwaiaa2936f2009-05-26 16:07:57 +02002287 int err = snd_hda_codec_write(codec, nid, direct, verb, parm);
2288 struct hda_cache_head *c;
2289 u32 key;
Takashi Iwai33fa35e2008-11-06 16:50:40 +01002290
Takashi Iwaiaa2936f2009-05-26 16:07:57 +02002291 if (err < 0)
2292 return err;
2293 /* parm may contain the verb stuff for get/set amp */
2294 verb = verb | (parm >> 8);
2295 parm &= 0xff;
2296 key = build_cmd_cache_key(nid, verb);
2297 mutex_lock(&codec->bus->cmd_mutex);
2298 c = get_alloc_hash(&codec->cmd_cache, key);
2299 if (c)
2300 c->val = parm;
2301 mutex_unlock(&codec->bus->cmd_mutex);
2302 return 0;
Takashi Iwaib3ac5632007-08-10 17:03:40 +02002303}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002304EXPORT_SYMBOL_HDA(snd_hda_codec_write_cache);
Takashi Iwaib3ac5632007-08-10 17:03:40 +02002305
2306/* resume the all commands from the cache */
2307void snd_hda_codec_resume_cache(struct hda_codec *codec)
2308{
Takashi Iwai603c4012008-07-30 15:01:44 +02002309 struct hda_cache_head *buffer = codec->cmd_cache.buf.list;
Takashi Iwaib3ac5632007-08-10 17:03:40 +02002310 int i;
2311
Takashi Iwai603c4012008-07-30 15:01:44 +02002312 for (i = 0; i < codec->cmd_cache.buf.used; i++, buffer++) {
Takashi Iwaib3ac5632007-08-10 17:03:40 +02002313 u32 key = buffer->key;
2314 if (!key)
2315 continue;
2316 snd_hda_codec_write(codec, get_cmd_cache_nid(key), 0,
2317 get_cmd_cache_cmd(key), buffer->val);
2318 }
2319}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002320EXPORT_SYMBOL_HDA(snd_hda_codec_resume_cache);
Takashi Iwaib3ac5632007-08-10 17:03:40 +02002321
2322/**
2323 * snd_hda_sequence_write_cache - sequence writes with caching
2324 * @codec: the HDA codec
2325 * @seq: VERB array to send
2326 *
2327 * Send the commands sequentially from the given array.
2328 * Thte commands are recorded on cache for power-save and resume.
2329 * The array must be terminated with NID=0.
2330 */
2331void snd_hda_sequence_write_cache(struct hda_codec *codec,
2332 const struct hda_verb *seq)
2333{
2334 for (; seq->nid; seq++)
2335 snd_hda_codec_write_cache(codec, seq->nid, 0, seq->verb,
2336 seq->param);
2337}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002338EXPORT_SYMBOL_HDA(snd_hda_sequence_write_cache);
Takashi Iwaicb53c622007-08-10 17:21:45 +02002339#endif /* SND_HDA_NEEDS_RESUME */
Takashi Iwaib3ac5632007-08-10 17:03:40 +02002340
Takashi Iwai54d17402005-11-21 16:33:22 +01002341/*
2342 * set power state of the codec
2343 */
2344static void hda_set_power_state(struct hda_codec *codec, hda_nid_t fg,
2345 unsigned int power_state)
2346{
Takashi Iwaicb53c622007-08-10 17:21:45 +02002347 hda_nid_t nid;
2348 int i;
Takashi Iwai54d17402005-11-21 16:33:22 +01002349
2350 snd_hda_codec_write(codec, fg, 0, AC_VERB_SET_POWER_STATE,
2351 power_state);
Marc Boucherd2595d82008-01-22 15:23:30 +01002352 msleep(10); /* partial workaround for "azx_get_response timeout" */
Takashi Iwai54d17402005-11-21 16:33:22 +01002353
Takashi Iwaicb53c622007-08-10 17:21:45 +02002354 nid = codec->start_nid;
2355 for (i = 0; i < codec->num_nodes; i++, nid++) {
Takashi Iwai7eba5c92007-11-14 14:53:42 +01002356 unsigned int wcaps = get_wcaps(codec, nid);
2357 if (wcaps & AC_WCAP_POWER) {
2358 unsigned int wid_type = (wcaps & AC_WCAP_TYPE) >>
2359 AC_WCAP_TYPE_SHIFT;
Takashi Iwaia3b48c82009-04-21 13:37:29 +02002360 if (power_state == AC_PWRST_D3 &&
2361 wid_type == AC_WID_PIN) {
Takashi Iwai7eba5c92007-11-14 14:53:42 +01002362 unsigned int pincap;
2363 /*
2364 * don't power down the widget if it controls
2365 * eapd and EAPD_BTLENABLE is set.
2366 */
Takashi Iwai14bafe32009-03-23 16:35:39 +01002367 pincap = snd_hda_query_pin_caps(codec, nid);
Takashi Iwai7eba5c92007-11-14 14:53:42 +01002368 if (pincap & AC_PINCAP_EAPD) {
2369 int eapd = snd_hda_codec_read(codec,
2370 nid, 0,
2371 AC_VERB_GET_EAPD_BTLENABLE, 0);
2372 eapd &= 0x02;
Takashi Iwaia3b48c82009-04-21 13:37:29 +02002373 if (eapd)
Takashi Iwai7eba5c92007-11-14 14:53:42 +01002374 continue;
2375 }
Takashi Iwai1194b5b2007-10-10 10:04:26 +02002376 }
Takashi Iwai54d17402005-11-21 16:33:22 +01002377 snd_hda_codec_write(codec, nid, 0,
2378 AC_VERB_SET_POWER_STATE,
2379 power_state);
Takashi Iwai1194b5b2007-10-10 10:04:26 +02002380 }
Takashi Iwai54d17402005-11-21 16:33:22 +01002381 }
2382
Takashi Iwaicb53c622007-08-10 17:21:45 +02002383 if (power_state == AC_PWRST_D0) {
2384 unsigned long end_time;
2385 int state;
Takashi Iwai54d17402005-11-21 16:33:22 +01002386 msleep(10);
Takashi Iwaicb53c622007-08-10 17:21:45 +02002387 /* wait until the codec reachs to D0 */
2388 end_time = jiffies + msecs_to_jiffies(500);
2389 do {
2390 state = snd_hda_codec_read(codec, fg, 0,
2391 AC_VERB_GET_POWER_STATE, 0);
2392 if (state == power_state)
2393 break;
2394 msleep(1);
2395 } while (time_after_eq(end_time, jiffies));
2396 }
Takashi Iwai54d17402005-11-21 16:33:22 +01002397}
2398
Takashi Iwai11aeff02008-07-30 15:01:46 +02002399#ifdef CONFIG_SND_HDA_HWDEP
2400/* execute additional init verbs */
2401static void hda_exec_init_verbs(struct hda_codec *codec)
2402{
2403 if (codec->init_verbs.list)
2404 snd_hda_sequence_write(codec, codec->init_verbs.list);
2405}
2406#else
2407static inline void hda_exec_init_verbs(struct hda_codec *codec) {}
2408#endif
2409
Takashi Iwaicb53c622007-08-10 17:21:45 +02002410#ifdef SND_HDA_NEEDS_RESUME
2411/*
2412 * call suspend and power-down; used both from PM and power-save
2413 */
2414static void hda_call_codec_suspend(struct hda_codec *codec)
2415{
2416 if (codec->patch_ops.suspend)
2417 codec->patch_ops.suspend(codec, PMSG_SUSPEND);
2418 hda_set_power_state(codec,
2419 codec->afg ? codec->afg : codec->mfg,
2420 AC_PWRST_D3);
2421#ifdef CONFIG_SND_HDA_POWER_SAVE
2422 cancel_delayed_work(&codec->power_work);
Takashi Iwai95e99fd2007-08-13 15:29:04 +02002423 codec->power_on = 0;
Takashi Iwaia221e282007-08-16 16:35:33 +02002424 codec->power_transition = 0;
Takashi Iwaicb53c622007-08-10 17:21:45 +02002425#endif
2426}
2427
2428/*
2429 * kick up codec; used both from PM and power-save
2430 */
2431static void hda_call_codec_resume(struct hda_codec *codec)
2432{
2433 hda_set_power_state(codec,
2434 codec->afg ? codec->afg : codec->mfg,
2435 AC_PWRST_D0);
Takashi Iwai3be14142009-02-20 14:11:16 +01002436 restore_pincfgs(codec); /* restore all current pin configs */
Takashi Iwai11aeff02008-07-30 15:01:46 +02002437 hda_exec_init_verbs(codec);
Takashi Iwaicb53c622007-08-10 17:21:45 +02002438 if (codec->patch_ops.resume)
2439 codec->patch_ops.resume(codec);
2440 else {
Takashi Iwai9d99f312007-08-14 15:15:52 +02002441 if (codec->patch_ops.init)
2442 codec->patch_ops.init(codec);
Takashi Iwaicb53c622007-08-10 17:21:45 +02002443 snd_hda_codec_resume_amp(codec);
2444 snd_hda_codec_resume_cache(codec);
2445 }
2446}
2447#endif /* SND_HDA_NEEDS_RESUME */
2448
Takashi Iwai54d17402005-11-21 16:33:22 +01002449
Linus Torvalds1da177e2005-04-16 15:20:36 -07002450/**
2451 * snd_hda_build_controls - build mixer controls
2452 * @bus: the BUS
2453 *
2454 * Creates mixer controls for each codec included in the bus.
2455 *
2456 * Returns 0 if successful, otherwise a negative error code.
2457 */
Takashi Iwai1289e9e2008-11-27 15:47:11 +01002458int /*__devinit*/ snd_hda_build_controls(struct hda_bus *bus)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002459{
Takashi Iwai0ba21762007-04-16 11:29:14 +02002460 struct hda_codec *codec;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002461
Takashi Iwai0ba21762007-04-16 11:29:14 +02002462 list_for_each_entry(codec, &bus->codec_list, list) {
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02002463 int err = snd_hda_codec_build_controls(codec);
Takashi Iwaif93d4612009-03-02 10:44:15 +01002464 if (err < 0) {
2465 printk(KERN_ERR "hda_codec: cannot build controls"
2466 "for #%d (error %d)\n", codec->addr, err);
2467 err = snd_hda_codec_reset(codec);
2468 if (err < 0) {
2469 printk(KERN_ERR
2470 "hda_codec: cannot revert codec\n");
2471 return err;
2472 }
2473 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002474 }
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02002475 return 0;
2476}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002477EXPORT_SYMBOL_HDA(snd_hda_build_controls);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002478
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02002479int snd_hda_codec_build_controls(struct hda_codec *codec)
2480{
2481 int err = 0;
Takashi Iwai11aeff02008-07-30 15:01:46 +02002482 hda_exec_init_verbs(codec);
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02002483 /* continue to initialize... */
2484 if (codec->patch_ops.init)
2485 err = codec->patch_ops.init(codec);
2486 if (!err && codec->patch_ops.build_controls)
2487 err = codec->patch_ops.build_controls(codec);
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02002488 if (err < 0)
2489 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002490 return 0;
2491}
2492
Linus Torvalds1da177e2005-04-16 15:20:36 -07002493/*
2494 * stream formats
2495 */
Takashi Iwaibefdf312005-08-22 13:57:55 +02002496struct hda_rate_tbl {
2497 unsigned int hz;
2498 unsigned int alsa_bits;
2499 unsigned int hda_fmt;
2500};
2501
2502static struct hda_rate_tbl rate_bits[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002503 /* rate in Hz, ALSA rate bitmask, HDA format value */
Nicolas Graziano9d8f53f2005-08-22 13:47:16 +02002504
2505 /* autodetected value used in snd_hda_query_supported_pcm */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002506 { 8000, SNDRV_PCM_RATE_8000, 0x0500 }, /* 1/6 x 48 */
2507 { 11025, SNDRV_PCM_RATE_11025, 0x4300 }, /* 1/4 x 44 */
2508 { 16000, SNDRV_PCM_RATE_16000, 0x0200 }, /* 1/3 x 48 */
2509 { 22050, SNDRV_PCM_RATE_22050, 0x4100 }, /* 1/2 x 44 */
2510 { 32000, SNDRV_PCM_RATE_32000, 0x0a00 }, /* 2/3 x 48 */
2511 { 44100, SNDRV_PCM_RATE_44100, 0x4000 }, /* 44 */
2512 { 48000, SNDRV_PCM_RATE_48000, 0x0000 }, /* 48 */
2513 { 88200, SNDRV_PCM_RATE_88200, 0x4800 }, /* 2 x 44 */
2514 { 96000, SNDRV_PCM_RATE_96000, 0x0800 }, /* 2 x 48 */
2515 { 176400, SNDRV_PCM_RATE_176400, 0x5800 },/* 4 x 44 */
2516 { 192000, SNDRV_PCM_RATE_192000, 0x1800 }, /* 4 x 48 */
Takashi Iwaia961f9f2007-04-12 13:08:09 +02002517#define AC_PAR_PCM_RATE_BITS 11
2518 /* up to bits 10, 384kHZ isn't supported properly */
2519
2520 /* not autodetected value */
2521 { 9600, SNDRV_PCM_RATE_KNOT, 0x0400 }, /* 1/5 x 48 */
Nicolas Graziano9d8f53f2005-08-22 13:47:16 +02002522
Takashi Iwaibefdf312005-08-22 13:57:55 +02002523 { 0 } /* terminator */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002524};
2525
2526/**
2527 * snd_hda_calc_stream_format - calculate format bitset
2528 * @rate: the sample rate
2529 * @channels: the number of channels
2530 * @format: the PCM format (SNDRV_PCM_FORMAT_XXX)
2531 * @maxbps: the max. bps
2532 *
2533 * Calculate the format bitset from the given rate, channels and th PCM format.
2534 *
2535 * Return zero if invalid.
2536 */
2537unsigned int snd_hda_calc_stream_format(unsigned int rate,
2538 unsigned int channels,
2539 unsigned int format,
2540 unsigned int maxbps)
2541{
2542 int i;
2543 unsigned int val = 0;
2544
Takashi Iwaibefdf312005-08-22 13:57:55 +02002545 for (i = 0; rate_bits[i].hz; i++)
2546 if (rate_bits[i].hz == rate) {
2547 val = rate_bits[i].hda_fmt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002548 break;
2549 }
Takashi Iwai0ba21762007-04-16 11:29:14 +02002550 if (!rate_bits[i].hz) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002551 snd_printdd("invalid rate %d\n", rate);
2552 return 0;
2553 }
2554
2555 if (channels == 0 || channels > 8) {
2556 snd_printdd("invalid channels %d\n", channels);
2557 return 0;
2558 }
2559 val |= channels - 1;
2560
2561 switch (snd_pcm_format_width(format)) {
2562 case 8: val |= 0x00; break;
2563 case 16: val |= 0x10; break;
2564 case 20:
2565 case 24:
2566 case 32:
2567 if (maxbps >= 32)
2568 val |= 0x40;
2569 else if (maxbps >= 24)
2570 val |= 0x30;
2571 else
2572 val |= 0x20;
2573 break;
2574 default:
Takashi Iwai0ba21762007-04-16 11:29:14 +02002575 snd_printdd("invalid format width %d\n",
2576 snd_pcm_format_width(format));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002577 return 0;
2578 }
2579
2580 return val;
2581}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002582EXPORT_SYMBOL_HDA(snd_hda_calc_stream_format);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002583
Takashi Iwai92c7c8a2009-03-24 07:32:14 +01002584static unsigned int get_pcm_param(struct hda_codec *codec, hda_nid_t nid)
2585{
2586 unsigned int val = 0;
2587 if (nid != codec->afg &&
2588 (get_wcaps(codec, nid) & AC_WCAP_FORMAT_OVRD))
2589 val = snd_hda_param_read(codec, nid, AC_PAR_PCM);
2590 if (!val || val == -1)
2591 val = snd_hda_param_read(codec, codec->afg, AC_PAR_PCM);
2592 if (!val || val == -1)
2593 return 0;
2594 return val;
2595}
2596
2597static unsigned int query_pcm_param(struct hda_codec *codec, hda_nid_t nid)
2598{
2599 return query_caps_hash(codec, nid, HDA_HASH_PARPCM_KEY(nid),
2600 get_pcm_param);
2601}
2602
2603static unsigned int get_stream_param(struct hda_codec *codec, hda_nid_t nid)
2604{
2605 unsigned int streams = snd_hda_param_read(codec, nid, AC_PAR_STREAM);
2606 if (!streams || streams == -1)
2607 streams = snd_hda_param_read(codec, codec->afg, AC_PAR_STREAM);
2608 if (!streams || streams == -1)
2609 return 0;
2610 return streams;
2611}
2612
2613static unsigned int query_stream_param(struct hda_codec *codec, hda_nid_t nid)
2614{
2615 return query_caps_hash(codec, nid, HDA_HASH_PARSTR_KEY(nid),
2616 get_stream_param);
2617}
2618
Linus Torvalds1da177e2005-04-16 15:20:36 -07002619/**
2620 * snd_hda_query_supported_pcm - query the supported PCM rates and formats
2621 * @codec: the HDA codec
2622 * @nid: NID to query
2623 * @ratesp: the pointer to store the detected rate bitflags
2624 * @formatsp: the pointer to store the detected formats
2625 * @bpsp: the pointer to store the detected format widths
2626 *
2627 * Queries the supported PCM rates and formats. The NULL @ratesp, @formatsp
2628 * or @bsps argument is ignored.
2629 *
2630 * Returns 0 if successful, otherwise a negative error code.
2631 */
Takashi Iwai986862bd2008-11-27 12:40:13 +01002632static int snd_hda_query_supported_pcm(struct hda_codec *codec, hda_nid_t nid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002633 u32 *ratesp, u64 *formatsp, unsigned int *bpsp)
2634{
Jaroslav Kyselaee504712009-03-17 14:30:31 +01002635 unsigned int i, val, wcaps;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002636
Jaroslav Kyselaee504712009-03-17 14:30:31 +01002637 wcaps = get_wcaps(codec, nid);
Takashi Iwai92c7c8a2009-03-24 07:32:14 +01002638 val = query_pcm_param(codec, nid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002639
2640 if (ratesp) {
2641 u32 rates = 0;
Takashi Iwaia961f9f2007-04-12 13:08:09 +02002642 for (i = 0; i < AC_PAR_PCM_RATE_BITS; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002643 if (val & (1 << i))
Takashi Iwaibefdf312005-08-22 13:57:55 +02002644 rates |= rate_bits[i].alsa_bits;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002645 }
Jaroslav Kyselaee504712009-03-17 14:30:31 +01002646 if (rates == 0) {
2647 snd_printk(KERN_ERR "hda_codec: rates == 0 "
2648 "(nid=0x%x, val=0x%x, ovrd=%i)\n",
2649 nid, val,
2650 (wcaps & AC_WCAP_FORMAT_OVRD) ? 1 : 0);
2651 return -EIO;
2652 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002653 *ratesp = rates;
2654 }
2655
2656 if (formatsp || bpsp) {
2657 u64 formats = 0;
Jaroslav Kyselaee504712009-03-17 14:30:31 +01002658 unsigned int streams, bps;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002659
Takashi Iwai92c7c8a2009-03-24 07:32:14 +01002660 streams = query_stream_param(codec, nid);
2661 if (!streams)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002662 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002663
2664 bps = 0;
2665 if (streams & AC_SUPFMT_PCM) {
2666 if (val & AC_SUPPCM_BITS_8) {
2667 formats |= SNDRV_PCM_FMTBIT_U8;
2668 bps = 8;
2669 }
2670 if (val & AC_SUPPCM_BITS_16) {
2671 formats |= SNDRV_PCM_FMTBIT_S16_LE;
2672 bps = 16;
2673 }
2674 if (wcaps & AC_WCAP_DIGITAL) {
2675 if (val & AC_SUPPCM_BITS_32)
2676 formats |= SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_LE;
2677 if (val & (AC_SUPPCM_BITS_20|AC_SUPPCM_BITS_24))
2678 formats |= SNDRV_PCM_FMTBIT_S32_LE;
2679 if (val & AC_SUPPCM_BITS_24)
2680 bps = 24;
2681 else if (val & AC_SUPPCM_BITS_20)
2682 bps = 20;
Takashi Iwai0ba21762007-04-16 11:29:14 +02002683 } else if (val & (AC_SUPPCM_BITS_20|AC_SUPPCM_BITS_24|
2684 AC_SUPPCM_BITS_32)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002685 formats |= SNDRV_PCM_FMTBIT_S32_LE;
2686 if (val & AC_SUPPCM_BITS_32)
2687 bps = 32;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002688 else if (val & AC_SUPPCM_BITS_24)
2689 bps = 24;
Nicolas Graziano33ef76512006-09-19 14:23:14 +02002690 else if (val & AC_SUPPCM_BITS_20)
2691 bps = 20;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002692 }
2693 }
Takashi Iwaib5025c52009-07-01 18:05:27 +02002694 if (streams & AC_SUPFMT_FLOAT32) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002695 formats |= SNDRV_PCM_FMTBIT_FLOAT_LE;
2696 bps = 32;
Takashi Iwaib5025c52009-07-01 18:05:27 +02002697 }
2698 if (streams == AC_SUPFMT_AC3) {
Takashi Iwai0ba21762007-04-16 11:29:14 +02002699 /* should be exclusive */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002700 /* temporary hack: we have still no proper support
2701 * for the direct AC3 stream...
2702 */
2703 formats |= SNDRV_PCM_FMTBIT_U8;
2704 bps = 8;
2705 }
Jaroslav Kyselaee504712009-03-17 14:30:31 +01002706 if (formats == 0) {
2707 snd_printk(KERN_ERR "hda_codec: formats == 0 "
2708 "(nid=0x%x, val=0x%x, ovrd=%i, "
2709 "streams=0x%x)\n",
2710 nid, val,
2711 (wcaps & AC_WCAP_FORMAT_OVRD) ? 1 : 0,
2712 streams);
2713 return -EIO;
2714 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002715 if (formatsp)
2716 *formatsp = formats;
2717 if (bpsp)
2718 *bpsp = bps;
2719 }
2720
2721 return 0;
2722}
2723
2724/**
Takashi Iwai0ba21762007-04-16 11:29:14 +02002725 * snd_hda_is_supported_format - check whether the given node supports
2726 * the format val
Linus Torvalds1da177e2005-04-16 15:20:36 -07002727 *
2728 * Returns 1 if supported, 0 if not.
2729 */
2730int snd_hda_is_supported_format(struct hda_codec *codec, hda_nid_t nid,
2731 unsigned int format)
2732{
2733 int i;
2734 unsigned int val = 0, rate, stream;
2735
Takashi Iwai92c7c8a2009-03-24 07:32:14 +01002736 val = query_pcm_param(codec, nid);
2737 if (!val)
2738 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002739
2740 rate = format & 0xff00;
Takashi Iwaia961f9f2007-04-12 13:08:09 +02002741 for (i = 0; i < AC_PAR_PCM_RATE_BITS; i++)
Takashi Iwaibefdf312005-08-22 13:57:55 +02002742 if (rate_bits[i].hda_fmt == rate) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002743 if (val & (1 << i))
2744 break;
2745 return 0;
2746 }
Takashi Iwaia961f9f2007-04-12 13:08:09 +02002747 if (i >= AC_PAR_PCM_RATE_BITS)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002748 return 0;
2749
Takashi Iwai92c7c8a2009-03-24 07:32:14 +01002750 stream = query_stream_param(codec, nid);
2751 if (!stream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002752 return 0;
2753
2754 if (stream & AC_SUPFMT_PCM) {
2755 switch (format & 0xf0) {
2756 case 0x00:
Takashi Iwai0ba21762007-04-16 11:29:14 +02002757 if (!(val & AC_SUPPCM_BITS_8))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002758 return 0;
2759 break;
2760 case 0x10:
Takashi Iwai0ba21762007-04-16 11:29:14 +02002761 if (!(val & AC_SUPPCM_BITS_16))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002762 return 0;
2763 break;
2764 case 0x20:
Takashi Iwai0ba21762007-04-16 11:29:14 +02002765 if (!(val & AC_SUPPCM_BITS_20))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002766 return 0;
2767 break;
2768 case 0x30:
Takashi Iwai0ba21762007-04-16 11:29:14 +02002769 if (!(val & AC_SUPPCM_BITS_24))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002770 return 0;
2771 break;
2772 case 0x40:
Takashi Iwai0ba21762007-04-16 11:29:14 +02002773 if (!(val & AC_SUPPCM_BITS_32))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002774 return 0;
2775 break;
2776 default:
2777 return 0;
2778 }
2779 } else {
2780 /* FIXME: check for float32 and AC3? */
2781 }
2782
2783 return 1;
2784}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002785EXPORT_SYMBOL_HDA(snd_hda_is_supported_format);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002786
2787/*
2788 * PCM stuff
2789 */
2790static int hda_pcm_default_open_close(struct hda_pcm_stream *hinfo,
2791 struct hda_codec *codec,
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01002792 struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002793{
2794 return 0;
2795}
2796
2797static int hda_pcm_default_prepare(struct hda_pcm_stream *hinfo,
2798 struct hda_codec *codec,
2799 unsigned int stream_tag,
2800 unsigned int format,
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01002801 struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002802{
2803 snd_hda_codec_setup_stream(codec, hinfo->nid, stream_tag, 0, format);
2804 return 0;
2805}
2806
2807static int hda_pcm_default_cleanup(struct hda_pcm_stream *hinfo,
2808 struct hda_codec *codec,
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01002809 struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002810{
Takashi Iwai888afa12008-03-18 09:57:50 +01002811 snd_hda_codec_cleanup_stream(codec, hinfo->nid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002812 return 0;
2813}
2814
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02002815static int set_pcm_default_values(struct hda_codec *codec,
2816 struct hda_pcm_stream *info)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002817{
Jaroslav Kyselaee504712009-03-17 14:30:31 +01002818 int err;
2819
Takashi Iwai0ba21762007-04-16 11:29:14 +02002820 /* query support PCM information from the given NID */
2821 if (info->nid && (!info->rates || !info->formats)) {
Jaroslav Kyselaee504712009-03-17 14:30:31 +01002822 err = snd_hda_query_supported_pcm(codec, info->nid,
Takashi Iwai0ba21762007-04-16 11:29:14 +02002823 info->rates ? NULL : &info->rates,
2824 info->formats ? NULL : &info->formats,
2825 info->maxbps ? NULL : &info->maxbps);
Jaroslav Kyselaee504712009-03-17 14:30:31 +01002826 if (err < 0)
2827 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002828 }
2829 if (info->ops.open == NULL)
2830 info->ops.open = hda_pcm_default_open_close;
2831 if (info->ops.close == NULL)
2832 info->ops.close = hda_pcm_default_open_close;
2833 if (info->ops.prepare == NULL) {
Takashi Iwaida3cec32008-08-08 17:12:14 +02002834 if (snd_BUG_ON(!info->nid))
2835 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002836 info->ops.prepare = hda_pcm_default_prepare;
2837 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002838 if (info->ops.cleanup == NULL) {
Takashi Iwaida3cec32008-08-08 17:12:14 +02002839 if (snd_BUG_ON(!info->nid))
2840 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002841 info->ops.cleanup = hda_pcm_default_cleanup;
2842 }
2843 return 0;
2844}
2845
Takashi Iwai176d5332008-07-30 15:01:44 +02002846/*
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002847 * get the empty PCM device number to assign
2848 */
2849static int get_empty_pcm_device(struct hda_bus *bus, int type)
2850{
2851 static const char *dev_name[HDA_PCM_NTYPES] = {
2852 "Audio", "SPDIF", "HDMI", "Modem"
2853 };
2854 /* starting device index for each PCM type */
2855 static int dev_idx[HDA_PCM_NTYPES] = {
2856 [HDA_PCM_TYPE_AUDIO] = 0,
2857 [HDA_PCM_TYPE_SPDIF] = 1,
2858 [HDA_PCM_TYPE_HDMI] = 3,
2859 [HDA_PCM_TYPE_MODEM] = 6
2860 };
2861 /* normal audio device indices; not linear to keep compatibility */
2862 static int audio_idx[4] = { 0, 2, 4, 5 };
2863 int i, dev;
2864
2865 switch (type) {
2866 case HDA_PCM_TYPE_AUDIO:
2867 for (i = 0; i < ARRAY_SIZE(audio_idx); i++) {
2868 dev = audio_idx[i];
2869 if (!test_bit(dev, bus->pcm_dev_bits))
Takashi Iwai82ad39f2009-03-03 15:00:35 +01002870 goto ok;
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002871 }
Takashi Iwai82ad39f2009-03-03 15:00:35 +01002872 snd_printk(KERN_WARNING "Too many audio devices\n");
2873 return -EAGAIN;
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002874 case HDA_PCM_TYPE_SPDIF:
2875 case HDA_PCM_TYPE_HDMI:
2876 case HDA_PCM_TYPE_MODEM:
2877 dev = dev_idx[type];
2878 if (test_bit(dev, bus->pcm_dev_bits)) {
2879 snd_printk(KERN_WARNING "%s already defined\n",
2880 dev_name[type]);
2881 return -EAGAIN;
2882 }
2883 break;
2884 default:
2885 snd_printk(KERN_WARNING "Invalid PCM type %d\n", type);
2886 return -EINVAL;
2887 }
Takashi Iwai82ad39f2009-03-03 15:00:35 +01002888 ok:
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002889 set_bit(dev, bus->pcm_dev_bits);
2890 return dev;
2891}
2892
2893/*
Takashi Iwai176d5332008-07-30 15:01:44 +02002894 * attach a new PCM stream
2895 */
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002896static int snd_hda_attach_pcm(struct hda_codec *codec, struct hda_pcm *pcm)
Takashi Iwai176d5332008-07-30 15:01:44 +02002897{
Takashi Iwai33fa35e2008-11-06 16:50:40 +01002898 struct hda_bus *bus = codec->bus;
Takashi Iwai176d5332008-07-30 15:01:44 +02002899 struct hda_pcm_stream *info;
2900 int stream, err;
2901
Takashi Iwaib91f0802008-11-04 08:43:08 +01002902 if (snd_BUG_ON(!pcm->name))
Takashi Iwai176d5332008-07-30 15:01:44 +02002903 return -EINVAL;
2904 for (stream = 0; stream < 2; stream++) {
2905 info = &pcm->stream[stream];
2906 if (info->substreams) {
2907 err = set_pcm_default_values(codec, info);
2908 if (err < 0)
2909 return err;
2910 }
2911 }
Takashi Iwai33fa35e2008-11-06 16:50:40 +01002912 return bus->ops.attach_pcm(bus, codec, pcm);
Takashi Iwai176d5332008-07-30 15:01:44 +02002913}
2914
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002915/* assign all PCMs of the given codec */
2916int snd_hda_codec_build_pcms(struct hda_codec *codec)
2917{
2918 unsigned int pcm;
2919 int err;
2920
2921 if (!codec->num_pcms) {
2922 if (!codec->patch_ops.build_pcms)
2923 return 0;
2924 err = codec->patch_ops.build_pcms(codec);
Takashi Iwai6e655bf2009-03-02 10:46:03 +01002925 if (err < 0) {
2926 printk(KERN_ERR "hda_codec: cannot build PCMs"
2927 "for #%d (error %d)\n", codec->addr, err);
2928 err = snd_hda_codec_reset(codec);
2929 if (err < 0) {
2930 printk(KERN_ERR
2931 "hda_codec: cannot revert codec\n");
2932 return err;
2933 }
2934 }
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002935 }
2936 for (pcm = 0; pcm < codec->num_pcms; pcm++) {
2937 struct hda_pcm *cpcm = &codec->pcm_info[pcm];
2938 int dev;
2939
2940 if (!cpcm->stream[0].substreams && !cpcm->stream[1].substreams)
Takashi Iwai41b5b012009-01-20 18:21:23 +01002941 continue; /* no substreams assigned */
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002942
2943 if (!cpcm->pcm) {
2944 dev = get_empty_pcm_device(codec->bus, cpcm->pcm_type);
2945 if (dev < 0)
Takashi Iwai6e655bf2009-03-02 10:46:03 +01002946 continue; /* no fatal error */
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002947 cpcm->device = dev;
2948 err = snd_hda_attach_pcm(codec, cpcm);
Takashi Iwai6e655bf2009-03-02 10:46:03 +01002949 if (err < 0) {
2950 printk(KERN_ERR "hda_codec: cannot attach "
2951 "PCM stream %d for codec #%d\n",
2952 dev, codec->addr);
2953 continue; /* no fatal error */
2954 }
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002955 }
2956 }
2957 return 0;
2958}
2959
Linus Torvalds1da177e2005-04-16 15:20:36 -07002960/**
2961 * snd_hda_build_pcms - build PCM information
2962 * @bus: the BUS
2963 *
2964 * Create PCM information for each codec included in the bus.
2965 *
2966 * The build_pcms codec patch is requested to set up codec->num_pcms and
2967 * codec->pcm_info properly. The array is referred by the top-level driver
2968 * to create its PCM instances.
2969 * The allocated codec->pcm_info should be released in codec->patch_ops.free
2970 * callback.
2971 *
2972 * At least, substreams, channels_min and channels_max must be filled for
2973 * each stream. substreams = 0 indicates that the stream doesn't exist.
2974 * When rates and/or formats are zero, the supported values are queried
2975 * from the given nid. The nid is used also by the default ops.prepare
2976 * and ops.cleanup callbacks.
2977 *
2978 * The driver needs to call ops.open in its open callback. Similarly,
2979 * ops.close is supposed to be called in the close callback.
2980 * ops.prepare should be called in the prepare or hw_params callback
2981 * with the proper parameters for set up.
2982 * ops.cleanup should be called in hw_free for clean up of streams.
2983 *
2984 * This function returns 0 if successfull, or a negative error code.
2985 */
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002986int __devinit snd_hda_build_pcms(struct hda_bus *bus)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002987{
Takashi Iwai0ba21762007-04-16 11:29:14 +02002988 struct hda_codec *codec;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002989
Takashi Iwai0ba21762007-04-16 11:29:14 +02002990 list_for_each_entry(codec, &bus->codec_list, list) {
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002991 int err = snd_hda_codec_build_pcms(codec);
2992 if (err < 0)
2993 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002994 }
2995 return 0;
2996}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002997EXPORT_SYMBOL_HDA(snd_hda_build_pcms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002998
Linus Torvalds1da177e2005-04-16 15:20:36 -07002999/**
3000 * snd_hda_check_board_config - compare the current codec with the config table
3001 * @codec: the HDA codec
Takashi Iwaif5fcc132006-11-24 17:07:44 +01003002 * @num_configs: number of config enums
3003 * @models: array of model name strings
Linus Torvalds1da177e2005-04-16 15:20:36 -07003004 * @tbl: configuration table, terminated by null entries
3005 *
3006 * Compares the modelname or PCI subsystem id of the current codec with the
3007 * given configuration table. If a matching entry is found, returns its
3008 * config value (supposed to be 0 or positive).
3009 *
3010 * If no entries are matching, the function returns a negative value.
3011 */
Takashi Iwai12f288b2007-08-02 15:51:59 +02003012int snd_hda_check_board_config(struct hda_codec *codec,
3013 int num_configs, const char **models,
3014 const struct snd_pci_quirk *tbl)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003015{
Takashi Iwaif44ac832008-07-30 15:01:45 +02003016 if (codec->modelname && models) {
Takashi Iwaif5fcc132006-11-24 17:07:44 +01003017 int i;
3018 for (i = 0; i < num_configs; i++) {
3019 if (models[i] &&
Takashi Iwaif44ac832008-07-30 15:01:45 +02003020 !strcmp(codec->modelname, models[i])) {
Takashi Iwaif5fcc132006-11-24 17:07:44 +01003021 snd_printd(KERN_INFO "hda_codec: model '%s' is "
3022 "selected\n", models[i]);
3023 return i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003024 }
3025 }
3026 }
3027
Takashi Iwaif5fcc132006-11-24 17:07:44 +01003028 if (!codec->bus->pci || !tbl)
3029 return -1;
3030
3031 tbl = snd_pci_quirk_lookup(codec->bus->pci, tbl);
3032 if (!tbl)
3033 return -1;
3034 if (tbl->value >= 0 && tbl->value < num_configs) {
Takashi Iwai62cf8722008-05-20 12:15:15 +02003035#ifdef CONFIG_SND_DEBUG_VERBOSE
Takashi Iwaif5fcc132006-11-24 17:07:44 +01003036 char tmp[10];
3037 const char *model = NULL;
3038 if (models)
3039 model = models[tbl->value];
3040 if (!model) {
3041 sprintf(tmp, "#%d", tbl->value);
3042 model = tmp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003043 }
Takashi Iwaif5fcc132006-11-24 17:07:44 +01003044 snd_printdd(KERN_INFO "hda_codec: model '%s' is selected "
3045 "for config %x:%x (%s)\n",
3046 model, tbl->subvendor, tbl->subdevice,
3047 (tbl->name ? tbl->name : "Unknown device"));
3048#endif
3049 return tbl->value;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003050 }
3051 return -1;
3052}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003053EXPORT_SYMBOL_HDA(snd_hda_check_board_config);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003054
3055/**
Mauro Carvalho Chehab2eda3442008-08-11 10:18:39 +02003056 * snd_hda_check_board_codec_sid_config - compare the current codec
3057 subsystem ID with the
3058 config table
3059
3060 This is important for Gateway notebooks with SB450 HDA Audio
3061 where the vendor ID of the PCI device is:
3062 ATI Technologies Inc SB450 HDA Audio [1002:437b]
3063 and the vendor/subvendor are found only at the codec.
3064
3065 * @codec: the HDA codec
3066 * @num_configs: number of config enums
3067 * @models: array of model name strings
3068 * @tbl: configuration table, terminated by null entries
3069 *
3070 * Compares the modelname or PCI subsystem id of the current codec with the
3071 * given configuration table. If a matching entry is found, returns its
3072 * config value (supposed to be 0 or positive).
3073 *
3074 * If no entries are matching, the function returns a negative value.
3075 */
3076int snd_hda_check_board_codec_sid_config(struct hda_codec *codec,
3077 int num_configs, const char **models,
3078 const struct snd_pci_quirk *tbl)
3079{
3080 const struct snd_pci_quirk *q;
3081
3082 /* Search for codec ID */
3083 for (q = tbl; q->subvendor; q++) {
3084 unsigned long vendorid = (q->subdevice) | (q->subvendor << 16);
3085
3086 if (vendorid == codec->subsystem_id)
3087 break;
3088 }
3089
3090 if (!q->subvendor)
3091 return -1;
3092
3093 tbl = q;
3094
3095 if (tbl->value >= 0 && tbl->value < num_configs) {
3096#ifdef CONFIG_SND_DEBUG_DETECT
3097 char tmp[10];
3098 const char *model = NULL;
3099 if (models)
3100 model = models[tbl->value];
3101 if (!model) {
3102 sprintf(tmp, "#%d", tbl->value);
3103 model = tmp;
3104 }
3105 snd_printdd(KERN_INFO "hda_codec: model '%s' is selected "
3106 "for config %x:%x (%s)\n",
3107 model, tbl->subvendor, tbl->subdevice,
3108 (tbl->name ? tbl->name : "Unknown device"));
3109#endif
3110 return tbl->value;
3111 }
3112 return -1;
3113}
3114EXPORT_SYMBOL_HDA(snd_hda_check_board_codec_sid_config);
3115
3116/**
Linus Torvalds1da177e2005-04-16 15:20:36 -07003117 * snd_hda_add_new_ctls - create controls from the array
3118 * @codec: the HDA codec
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01003119 * @knew: the array of struct snd_kcontrol_new
Linus Torvalds1da177e2005-04-16 15:20:36 -07003120 *
3121 * This helper function creates and add new controls in the given array.
3122 * The array must be terminated with an empty entry as terminator.
3123 *
3124 * Returns 0 if successful, or a negative error code.
3125 */
Takashi Iwai12f288b2007-08-02 15:51:59 +02003126int snd_hda_add_new_ctls(struct hda_codec *codec, struct snd_kcontrol_new *knew)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003127{
Takashi Iwaicb53c622007-08-10 17:21:45 +02003128 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003129
3130 for (; knew->name; knew++) {
Takashi Iwai54d17402005-11-21 16:33:22 +01003131 struct snd_kcontrol *kctl;
3132 kctl = snd_ctl_new1(knew, codec);
Takashi Iwai0ba21762007-04-16 11:29:14 +02003133 if (!kctl)
Takashi Iwai54d17402005-11-21 16:33:22 +01003134 return -ENOMEM;
Takashi Iwaid13bd412008-07-30 15:01:45 +02003135 err = snd_hda_ctl_add(codec, kctl);
Takashi Iwai54d17402005-11-21 16:33:22 +01003136 if (err < 0) {
Takashi Iwai0ba21762007-04-16 11:29:14 +02003137 if (!codec->addr)
Takashi Iwai54d17402005-11-21 16:33:22 +01003138 return err;
3139 kctl = snd_ctl_new1(knew, codec);
Takashi Iwai0ba21762007-04-16 11:29:14 +02003140 if (!kctl)
Takashi Iwai54d17402005-11-21 16:33:22 +01003141 return -ENOMEM;
3142 kctl->id.device = codec->addr;
Takashi Iwaid13bd412008-07-30 15:01:45 +02003143 err = snd_hda_ctl_add(codec, kctl);
Takashi Iwai0ba21762007-04-16 11:29:14 +02003144 if (err < 0)
Takashi Iwai54d17402005-11-21 16:33:22 +01003145 return err;
3146 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003147 }
3148 return 0;
3149}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003150EXPORT_SYMBOL_HDA(snd_hda_add_new_ctls);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003151
Takashi Iwaicb53c622007-08-10 17:21:45 +02003152#ifdef CONFIG_SND_HDA_POWER_SAVE
3153static void hda_set_power_state(struct hda_codec *codec, hda_nid_t fg,
3154 unsigned int power_state);
3155
3156static void hda_power_work(struct work_struct *work)
3157{
3158 struct hda_codec *codec =
3159 container_of(work, struct hda_codec, power_work.work);
Takashi Iwai33fa35e2008-11-06 16:50:40 +01003160 struct hda_bus *bus = codec->bus;
Takashi Iwaicb53c622007-08-10 17:21:45 +02003161
Maxim Levitsky2e492462007-09-03 15:26:57 +02003162 if (!codec->power_on || codec->power_count) {
3163 codec->power_transition = 0;
Takashi Iwaicb53c622007-08-10 17:21:45 +02003164 return;
Maxim Levitsky2e492462007-09-03 15:26:57 +02003165 }
Takashi Iwaicb53c622007-08-10 17:21:45 +02003166
3167 hda_call_codec_suspend(codec);
Takashi Iwai33fa35e2008-11-06 16:50:40 +01003168 if (bus->ops.pm_notify)
3169 bus->ops.pm_notify(bus);
Takashi Iwaicb53c622007-08-10 17:21:45 +02003170}
3171
3172static void hda_keep_power_on(struct hda_codec *codec)
3173{
3174 codec->power_count++;
3175 codec->power_on = 1;
3176}
3177
3178void snd_hda_power_up(struct hda_codec *codec)
3179{
Takashi Iwai33fa35e2008-11-06 16:50:40 +01003180 struct hda_bus *bus = codec->bus;
3181
Takashi Iwaicb53c622007-08-10 17:21:45 +02003182 codec->power_count++;
Takashi Iwaia221e282007-08-16 16:35:33 +02003183 if (codec->power_on || codec->power_transition)
Takashi Iwaicb53c622007-08-10 17:21:45 +02003184 return;
3185
3186 codec->power_on = 1;
Takashi Iwai33fa35e2008-11-06 16:50:40 +01003187 if (bus->ops.pm_notify)
3188 bus->ops.pm_notify(bus);
Takashi Iwaicb53c622007-08-10 17:21:45 +02003189 hda_call_codec_resume(codec);
3190 cancel_delayed_work(&codec->power_work);
Takashi Iwaia221e282007-08-16 16:35:33 +02003191 codec->power_transition = 0;
Takashi Iwaicb53c622007-08-10 17:21:45 +02003192}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003193EXPORT_SYMBOL_HDA(snd_hda_power_up);
Takashi Iwai1289e9e2008-11-27 15:47:11 +01003194
3195#define power_save(codec) \
3196 ((codec)->bus->power_save ? *(codec)->bus->power_save : 0)
Takashi Iwaicb53c622007-08-10 17:21:45 +02003197
Takashi Iwaifee2fba2008-11-27 12:43:28 +01003198#define power_save(codec) \
3199 ((codec)->bus->power_save ? *(codec)->bus->power_save : 0)
3200
Takashi Iwaicb53c622007-08-10 17:21:45 +02003201void snd_hda_power_down(struct hda_codec *codec)
3202{
3203 --codec->power_count;
Takashi Iwaia221e282007-08-16 16:35:33 +02003204 if (!codec->power_on || codec->power_count || codec->power_transition)
Takashi Iwaicb53c622007-08-10 17:21:45 +02003205 return;
Takashi Iwaifee2fba2008-11-27 12:43:28 +01003206 if (power_save(codec)) {
Takashi Iwaia221e282007-08-16 16:35:33 +02003207 codec->power_transition = 1; /* avoid reentrance */
Takashi Iwaic107b412009-01-13 17:46:37 +01003208 queue_delayed_work(codec->bus->workq, &codec->power_work,
Takashi Iwaifee2fba2008-11-27 12:43:28 +01003209 msecs_to_jiffies(power_save(codec) * 1000));
Takashi Iwaia221e282007-08-16 16:35:33 +02003210 }
Takashi Iwaicb53c622007-08-10 17:21:45 +02003211}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003212EXPORT_SYMBOL_HDA(snd_hda_power_down);
Takashi Iwaicb53c622007-08-10 17:21:45 +02003213
3214int snd_hda_check_amp_list_power(struct hda_codec *codec,
3215 struct hda_loopback_check *check,
3216 hda_nid_t nid)
3217{
3218 struct hda_amp_list *p;
3219 int ch, v;
3220
3221 if (!check->amplist)
3222 return 0;
3223 for (p = check->amplist; p->nid; p++) {
3224 if (p->nid == nid)
3225 break;
3226 }
3227 if (!p->nid)
3228 return 0; /* nothing changed */
3229
3230 for (p = check->amplist; p->nid; p++) {
3231 for (ch = 0; ch < 2; ch++) {
3232 v = snd_hda_codec_amp_read(codec, p->nid, ch, p->dir,
3233 p->idx);
3234 if (!(v & HDA_AMP_MUTE) && v > 0) {
3235 if (!check->power_on) {
3236 check->power_on = 1;
3237 snd_hda_power_up(codec);
3238 }
3239 return 1;
3240 }
3241 }
3242 }
3243 if (check->power_on) {
3244 check->power_on = 0;
3245 snd_hda_power_down(codec);
3246 }
3247 return 0;
3248}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003249EXPORT_SYMBOL_HDA(snd_hda_check_amp_list_power);
Takashi Iwaicb53c622007-08-10 17:21:45 +02003250#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07003251
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01003252/*
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01003253 * Channel mode helper
3254 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003255int snd_hda_ch_mode_info(struct hda_codec *codec,
3256 struct snd_ctl_elem_info *uinfo,
3257 const struct hda_channel_mode *chmode,
3258 int num_chmodes)
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01003259{
3260 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
3261 uinfo->count = 1;
3262 uinfo->value.enumerated.items = num_chmodes;
3263 if (uinfo->value.enumerated.item >= num_chmodes)
3264 uinfo->value.enumerated.item = num_chmodes - 1;
3265 sprintf(uinfo->value.enumerated.name, "%dch",
3266 chmode[uinfo->value.enumerated.item].channels);
3267 return 0;
3268}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003269EXPORT_SYMBOL_HDA(snd_hda_ch_mode_info);
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01003270
Takashi Iwai0ba21762007-04-16 11:29:14 +02003271int snd_hda_ch_mode_get(struct hda_codec *codec,
3272 struct snd_ctl_elem_value *ucontrol,
3273 const struct hda_channel_mode *chmode,
3274 int num_chmodes,
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01003275 int max_channels)
3276{
3277 int i;
3278
3279 for (i = 0; i < num_chmodes; i++) {
3280 if (max_channels == chmode[i].channels) {
3281 ucontrol->value.enumerated.item[0] = i;
3282 break;
3283 }
3284 }
3285 return 0;
3286}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003287EXPORT_SYMBOL_HDA(snd_hda_ch_mode_get);
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01003288
Takashi Iwai0ba21762007-04-16 11:29:14 +02003289int snd_hda_ch_mode_put(struct hda_codec *codec,
3290 struct snd_ctl_elem_value *ucontrol,
3291 const struct hda_channel_mode *chmode,
3292 int num_chmodes,
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01003293 int *max_channelsp)
3294{
3295 unsigned int mode;
3296
3297 mode = ucontrol->value.enumerated.item[0];
Takashi Iwai68ea7b22007-11-15 15:54:38 +01003298 if (mode >= num_chmodes)
3299 return -EINVAL;
Takashi Iwai82beb8f2007-08-10 17:09:26 +02003300 if (*max_channelsp == chmode[mode].channels)
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01003301 return 0;
3302 /* change the current channel setting */
3303 *max_channelsp = chmode[mode].channels;
3304 if (chmode[mode].sequence)
Takashi Iwai82beb8f2007-08-10 17:09:26 +02003305 snd_hda_sequence_write_cache(codec, chmode[mode].sequence);
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01003306 return 1;
3307}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003308EXPORT_SYMBOL_HDA(snd_hda_ch_mode_put);
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01003309
Linus Torvalds1da177e2005-04-16 15:20:36 -07003310/*
3311 * input MUX helper
3312 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003313int snd_hda_input_mux_info(const struct hda_input_mux *imux,
3314 struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003315{
3316 unsigned int index;
3317
3318 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
3319 uinfo->count = 1;
3320 uinfo->value.enumerated.items = imux->num_items;
Takashi Iwai5513b0c2007-10-09 11:58:41 +02003321 if (!imux->num_items)
3322 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003323 index = uinfo->value.enumerated.item;
3324 if (index >= imux->num_items)
3325 index = imux->num_items - 1;
3326 strcpy(uinfo->value.enumerated.name, imux->items[index].label);
3327 return 0;
3328}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003329EXPORT_SYMBOL_HDA(snd_hda_input_mux_info);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003330
Takashi Iwai0ba21762007-04-16 11:29:14 +02003331int snd_hda_input_mux_put(struct hda_codec *codec,
3332 const struct hda_input_mux *imux,
3333 struct snd_ctl_elem_value *ucontrol,
3334 hda_nid_t nid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003335 unsigned int *cur_val)
3336{
3337 unsigned int idx;
3338
Takashi Iwai5513b0c2007-10-09 11:58:41 +02003339 if (!imux->num_items)
3340 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003341 idx = ucontrol->value.enumerated.item[0];
3342 if (idx >= imux->num_items)
3343 idx = imux->num_items - 1;
Takashi Iwai82beb8f2007-08-10 17:09:26 +02003344 if (*cur_val == idx)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003345 return 0;
Takashi Iwai82beb8f2007-08-10 17:09:26 +02003346 snd_hda_codec_write_cache(codec, nid, 0, AC_VERB_SET_CONNECT_SEL,
3347 imux->items[idx].index);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003348 *cur_val = idx;
3349 return 1;
3350}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003351EXPORT_SYMBOL_HDA(snd_hda_input_mux_put);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003352
3353
3354/*
3355 * Multi-channel / digital-out PCM helper functions
3356 */
3357
Takashi Iwai6b97eb42007-04-05 14:51:48 +02003358/* setup SPDIF output stream */
3359static void setup_dig_out_stream(struct hda_codec *codec, hda_nid_t nid,
3360 unsigned int stream_tag, unsigned int format)
3361{
3362 /* turn off SPDIF once; otherwise the IEC958 bits won't be updated */
Takashi Iwai2f728532008-09-25 16:32:41 +02003363 if (codec->spdif_status_reset && (codec->spdif_ctls & AC_DIG1_ENABLE))
3364 set_dig_out_convert(codec, nid,
3365 codec->spdif_ctls & ~AC_DIG1_ENABLE & 0xff,
3366 -1);
Takashi Iwai6b97eb42007-04-05 14:51:48 +02003367 snd_hda_codec_setup_stream(codec, nid, stream_tag, 0, format);
Takashi Iwai2f728532008-09-25 16:32:41 +02003368 if (codec->slave_dig_outs) {
3369 hda_nid_t *d;
3370 for (d = codec->slave_dig_outs; *d; d++)
3371 snd_hda_codec_setup_stream(codec, *d, stream_tag, 0,
3372 format);
Matthew Ranostayde51ca12008-09-07 14:31:40 -04003373 }
Takashi Iwai2f728532008-09-25 16:32:41 +02003374 /* turn on again (if needed) */
3375 if (codec->spdif_status_reset && (codec->spdif_ctls & AC_DIG1_ENABLE))
3376 set_dig_out_convert(codec, nid,
3377 codec->spdif_ctls & 0xff, -1);
3378}
Matthew Ranostayde51ca12008-09-07 14:31:40 -04003379
Takashi Iwai2f728532008-09-25 16:32:41 +02003380static void cleanup_dig_out_stream(struct hda_codec *codec, hda_nid_t nid)
3381{
3382 snd_hda_codec_cleanup_stream(codec, nid);
3383 if (codec->slave_dig_outs) {
3384 hda_nid_t *d;
3385 for (d = codec->slave_dig_outs; *d; d++)
3386 snd_hda_codec_cleanup_stream(codec, *d);
3387 }
Takashi Iwai6b97eb42007-04-05 14:51:48 +02003388}
3389
Linus Torvalds1da177e2005-04-16 15:20:36 -07003390/*
3391 * open the digital out in the exclusive mode
3392 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003393int snd_hda_multi_out_dig_open(struct hda_codec *codec,
3394 struct hda_multi_out *mout)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003395{
Ingo Molnar62932df2006-01-16 16:34:20 +01003396 mutex_lock(&codec->spdif_mutex);
Takashi Iwai5930ca42007-04-16 11:23:56 +02003397 if (mout->dig_out_used == HDA_DIG_ANALOG_DUP)
3398 /* already opened as analog dup; reset it once */
Takashi Iwai2f728532008-09-25 16:32:41 +02003399 cleanup_dig_out_stream(codec, mout->dig_out_nid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003400 mout->dig_out_used = HDA_DIG_EXCLUSIVE;
Ingo Molnar62932df2006-01-16 16:34:20 +01003401 mutex_unlock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003402 return 0;
3403}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003404EXPORT_SYMBOL_HDA(snd_hda_multi_out_dig_open);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003405
Takashi Iwai6b97eb42007-04-05 14:51:48 +02003406int snd_hda_multi_out_dig_prepare(struct hda_codec *codec,
3407 struct hda_multi_out *mout,
3408 unsigned int stream_tag,
3409 unsigned int format,
3410 struct snd_pcm_substream *substream)
3411{
3412 mutex_lock(&codec->spdif_mutex);
3413 setup_dig_out_stream(codec, mout->dig_out_nid, stream_tag, format);
3414 mutex_unlock(&codec->spdif_mutex);
3415 return 0;
3416}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003417EXPORT_SYMBOL_HDA(snd_hda_multi_out_dig_prepare);
Takashi Iwai6b97eb42007-04-05 14:51:48 +02003418
Takashi Iwai9411e212009-02-13 11:32:28 +01003419int snd_hda_multi_out_dig_cleanup(struct hda_codec *codec,
3420 struct hda_multi_out *mout)
3421{
3422 mutex_lock(&codec->spdif_mutex);
3423 cleanup_dig_out_stream(codec, mout->dig_out_nid);
3424 mutex_unlock(&codec->spdif_mutex);
3425 return 0;
3426}
3427EXPORT_SYMBOL_HDA(snd_hda_multi_out_dig_cleanup);
3428
Linus Torvalds1da177e2005-04-16 15:20:36 -07003429/*
3430 * release the digital out
3431 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003432int snd_hda_multi_out_dig_close(struct hda_codec *codec,
3433 struct hda_multi_out *mout)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003434{
Ingo Molnar62932df2006-01-16 16:34:20 +01003435 mutex_lock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003436 mout->dig_out_used = 0;
Ingo Molnar62932df2006-01-16 16:34:20 +01003437 mutex_unlock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003438 return 0;
3439}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003440EXPORT_SYMBOL_HDA(snd_hda_multi_out_dig_close);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003441
3442/*
3443 * set up more restrictions for analog out
3444 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003445int snd_hda_multi_out_analog_open(struct hda_codec *codec,
3446 struct hda_multi_out *mout,
Takashi Iwai9a081602008-02-12 18:37:26 +01003447 struct snd_pcm_substream *substream,
3448 struct hda_pcm_stream *hinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003449{
Takashi Iwai9a081602008-02-12 18:37:26 +01003450 struct snd_pcm_runtime *runtime = substream->runtime;
3451 runtime->hw.channels_max = mout->max_channels;
3452 if (mout->dig_out_nid) {
3453 if (!mout->analog_rates) {
3454 mout->analog_rates = hinfo->rates;
3455 mout->analog_formats = hinfo->formats;
3456 mout->analog_maxbps = hinfo->maxbps;
3457 } else {
3458 runtime->hw.rates = mout->analog_rates;
3459 runtime->hw.formats = mout->analog_formats;
3460 hinfo->maxbps = mout->analog_maxbps;
3461 }
3462 if (!mout->spdif_rates) {
3463 snd_hda_query_supported_pcm(codec, mout->dig_out_nid,
3464 &mout->spdif_rates,
3465 &mout->spdif_formats,
3466 &mout->spdif_maxbps);
3467 }
3468 mutex_lock(&codec->spdif_mutex);
3469 if (mout->share_spdif) {
3470 runtime->hw.rates &= mout->spdif_rates;
3471 runtime->hw.formats &= mout->spdif_formats;
3472 if (mout->spdif_maxbps < hinfo->maxbps)
3473 hinfo->maxbps = mout->spdif_maxbps;
3474 }
Frederik Deweerdteaa99852008-04-14 13:11:44 +02003475 mutex_unlock(&codec->spdif_mutex);
Takashi Iwai9a081602008-02-12 18:37:26 +01003476 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003477 return snd_pcm_hw_constraint_step(substream->runtime, 0,
3478 SNDRV_PCM_HW_PARAM_CHANNELS, 2);
3479}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003480EXPORT_SYMBOL_HDA(snd_hda_multi_out_analog_open);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003481
3482/*
3483 * set up the i/o for analog out
3484 * when the digital out is available, copy the front out to digital out, too.
3485 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003486int snd_hda_multi_out_analog_prepare(struct hda_codec *codec,
3487 struct hda_multi_out *mout,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003488 unsigned int stream_tag,
3489 unsigned int format,
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01003490 struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003491{
3492 hda_nid_t *nids = mout->dac_nids;
3493 int chs = substream->runtime->channels;
3494 int i;
3495
Ingo Molnar62932df2006-01-16 16:34:20 +01003496 mutex_lock(&codec->spdif_mutex);
Takashi Iwai9a081602008-02-12 18:37:26 +01003497 if (mout->dig_out_nid && mout->share_spdif &&
3498 mout->dig_out_used != HDA_DIG_EXCLUSIVE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003499 if (chs == 2 &&
Takashi Iwai0ba21762007-04-16 11:29:14 +02003500 snd_hda_is_supported_format(codec, mout->dig_out_nid,
3501 format) &&
3502 !(codec->spdif_status & IEC958_AES0_NONAUDIO)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003503 mout->dig_out_used = HDA_DIG_ANALOG_DUP;
Takashi Iwai6b97eb42007-04-05 14:51:48 +02003504 setup_dig_out_stream(codec, mout->dig_out_nid,
3505 stream_tag, format);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003506 } else {
3507 mout->dig_out_used = 0;
Takashi Iwai2f728532008-09-25 16:32:41 +02003508 cleanup_dig_out_stream(codec, mout->dig_out_nid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003509 }
3510 }
Ingo Molnar62932df2006-01-16 16:34:20 +01003511 mutex_unlock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003512
3513 /* front */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003514 snd_hda_codec_setup_stream(codec, nids[HDA_FRONT], stream_tag,
3515 0, format);
Takashi Iwaid29240c2007-10-26 12:35:56 +02003516 if (!mout->no_share_stream &&
3517 mout->hp_nid && mout->hp_nid != nids[HDA_FRONT])
Linus Torvalds1da177e2005-04-16 15:20:36 -07003518 /* headphone out will just decode front left/right (stereo) */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003519 snd_hda_codec_setup_stream(codec, mout->hp_nid, stream_tag,
3520 0, format);
Takashi Iwai82bc9552006-03-21 11:24:42 +01003521 /* extra outputs copied from front */
3522 for (i = 0; i < ARRAY_SIZE(mout->extra_out_nid); i++)
Takashi Iwaid29240c2007-10-26 12:35:56 +02003523 if (!mout->no_share_stream && mout->extra_out_nid[i])
Takashi Iwai82bc9552006-03-21 11:24:42 +01003524 snd_hda_codec_setup_stream(codec,
3525 mout->extra_out_nid[i],
3526 stream_tag, 0, format);
3527
Linus Torvalds1da177e2005-04-16 15:20:36 -07003528 /* surrounds */
3529 for (i = 1; i < mout->num_dacs; i++) {
Takashi Iwai4b3acaf2005-06-10 19:48:10 +02003530 if (chs >= (i + 1) * 2) /* independent out */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003531 snd_hda_codec_setup_stream(codec, nids[i], stream_tag,
3532 i * 2, format);
Takashi Iwaid29240c2007-10-26 12:35:56 +02003533 else if (!mout->no_share_stream) /* copy front */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003534 snd_hda_codec_setup_stream(codec, nids[i], stream_tag,
3535 0, format);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003536 }
3537 return 0;
3538}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003539EXPORT_SYMBOL_HDA(snd_hda_multi_out_analog_prepare);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003540
3541/*
3542 * clean up the setting for analog out
3543 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003544int snd_hda_multi_out_analog_cleanup(struct hda_codec *codec,
3545 struct hda_multi_out *mout)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003546{
3547 hda_nid_t *nids = mout->dac_nids;
3548 int i;
3549
3550 for (i = 0; i < mout->num_dacs; i++)
Takashi Iwai888afa12008-03-18 09:57:50 +01003551 snd_hda_codec_cleanup_stream(codec, nids[i]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003552 if (mout->hp_nid)
Takashi Iwai888afa12008-03-18 09:57:50 +01003553 snd_hda_codec_cleanup_stream(codec, mout->hp_nid);
Takashi Iwai82bc9552006-03-21 11:24:42 +01003554 for (i = 0; i < ARRAY_SIZE(mout->extra_out_nid); i++)
3555 if (mout->extra_out_nid[i])
Takashi Iwai888afa12008-03-18 09:57:50 +01003556 snd_hda_codec_cleanup_stream(codec,
3557 mout->extra_out_nid[i]);
Ingo Molnar62932df2006-01-16 16:34:20 +01003558 mutex_lock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003559 if (mout->dig_out_nid && mout->dig_out_used == HDA_DIG_ANALOG_DUP) {
Takashi Iwai2f728532008-09-25 16:32:41 +02003560 cleanup_dig_out_stream(codec, mout->dig_out_nid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003561 mout->dig_out_used = 0;
3562 }
Ingo Molnar62932df2006-01-16 16:34:20 +01003563 mutex_unlock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003564 return 0;
3565}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003566EXPORT_SYMBOL_HDA(snd_hda_multi_out_analog_cleanup);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003567
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003568/*
Wu Fengguang6b345002008-10-07 14:21:41 +08003569 * Helper for automatic pin configuration
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003570 */
Kailang Yangdf694da2005-12-05 19:42:22 +01003571
Takashi Iwai12f288b2007-08-02 15:51:59 +02003572static int is_in_nid_list(hda_nid_t nid, hda_nid_t *list)
Kailang Yangdf694da2005-12-05 19:42:22 +01003573{
3574 for (; *list; list++)
3575 if (*list == nid)
3576 return 1;
3577 return 0;
3578}
3579
Steve Longerbeam81937d32007-05-08 15:33:03 +02003580
3581/*
3582 * Sort an associated group of pins according to their sequence numbers.
3583 */
3584static void sort_pins_by_sequence(hda_nid_t * pins, short * sequences,
3585 int num_pins)
3586{
3587 int i, j;
3588 short seq;
3589 hda_nid_t nid;
3590
3591 for (i = 0; i < num_pins; i++) {
3592 for (j = i + 1; j < num_pins; j++) {
3593 if (sequences[i] > sequences[j]) {
3594 seq = sequences[i];
3595 sequences[i] = sequences[j];
3596 sequences[j] = seq;
3597 nid = pins[i];
3598 pins[i] = pins[j];
3599 pins[j] = nid;
3600 }
3601 }
3602 }
3603}
3604
3605
Takashi Iwai82bc9552006-03-21 11:24:42 +01003606/*
3607 * Parse all pin widgets and store the useful pin nids to cfg
3608 *
3609 * The number of line-outs or any primary output is stored in line_outs,
3610 * and the corresponding output pins are assigned to line_out_pins[],
3611 * in the order of front, rear, CLFE, side, ...
3612 *
3613 * If more extra outputs (speaker and headphone) are found, the pins are
Takashi Iwaieb06ed82006-09-20 17:10:27 +02003614 * assisnged to hp_pins[] and speaker_pins[], respectively. If no line-out jack
Takashi Iwai82bc9552006-03-21 11:24:42 +01003615 * is detected, one of speaker of HP pins is assigned as the primary
3616 * output, i.e. to line_out_pins[0]. So, line_outs is always positive
3617 * if any analog output exists.
3618 *
3619 * The analog input pins are assigned to input_pins array.
3620 * The digital input/output pins are assigned to dig_in_pin and dig_out_pin,
3621 * respectively.
3622 */
Takashi Iwai12f288b2007-08-02 15:51:59 +02003623int snd_hda_parse_pin_def_config(struct hda_codec *codec,
3624 struct auto_pin_cfg *cfg,
3625 hda_nid_t *ignore_nids)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003626{
Takashi Iwai0ef6ce72008-01-22 15:35:37 +01003627 hda_nid_t nid, end_nid;
Steve Longerbeam81937d32007-05-08 15:33:03 +02003628 short seq, assoc_line_out, assoc_speaker;
3629 short sequences_line_out[ARRAY_SIZE(cfg->line_out_pins)];
3630 short sequences_speaker[ARRAY_SIZE(cfg->speaker_pins)];
Takashi Iwaif889fa92007-10-31 15:49:32 +01003631 short sequences_hp[ARRAY_SIZE(cfg->hp_pins)];
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003632
3633 memset(cfg, 0, sizeof(*cfg));
3634
Steve Longerbeam81937d32007-05-08 15:33:03 +02003635 memset(sequences_line_out, 0, sizeof(sequences_line_out));
3636 memset(sequences_speaker, 0, sizeof(sequences_speaker));
Takashi Iwaif889fa92007-10-31 15:49:32 +01003637 memset(sequences_hp, 0, sizeof(sequences_hp));
Steve Longerbeam81937d32007-05-08 15:33:03 +02003638 assoc_line_out = assoc_speaker = 0;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003639
Takashi Iwai0ef6ce72008-01-22 15:35:37 +01003640 end_nid = codec->start_nid + codec->num_nodes;
3641 for (nid = codec->start_nid; nid < end_nid; nid++) {
Takashi Iwai54d17402005-11-21 16:33:22 +01003642 unsigned int wid_caps = get_wcaps(codec, nid);
Takashi Iwai0ba21762007-04-16 11:29:14 +02003643 unsigned int wid_type =
3644 (wid_caps & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003645 unsigned int def_conf;
3646 short assoc, loc;
3647
3648 /* read all default configuration for pin complex */
3649 if (wid_type != AC_WID_PIN)
3650 continue;
Kailang Yangdf694da2005-12-05 19:42:22 +01003651 /* ignore the given nids (e.g. pc-beep returns error) */
3652 if (ignore_nids && is_in_nid_list(nid, ignore_nids))
3653 continue;
3654
Takashi Iwaic17a1ab2009-02-23 09:28:12 +01003655 def_conf = snd_hda_codec_get_pincfg(codec, nid);
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003656 if (get_defcfg_connect(def_conf) == AC_JACK_PORT_NONE)
3657 continue;
3658 loc = get_defcfg_location(def_conf);
3659 switch (get_defcfg_device(def_conf)) {
3660 case AC_JACK_LINE_OUT:
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003661 seq = get_defcfg_sequence(def_conf);
3662 assoc = get_defcfg_association(def_conf);
Matthew Ranostay90da78b2008-01-24 11:48:01 +01003663
3664 if (!(wid_caps & AC_WCAP_STEREO))
3665 if (!cfg->mono_out_pin)
3666 cfg->mono_out_pin = nid;
Takashi Iwai0ba21762007-04-16 11:29:14 +02003667 if (!assoc)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003668 continue;
Takashi Iwai0ba21762007-04-16 11:29:14 +02003669 if (!assoc_line_out)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003670 assoc_line_out = assoc;
3671 else if (assoc_line_out != assoc)
3672 continue;
3673 if (cfg->line_outs >= ARRAY_SIZE(cfg->line_out_pins))
3674 continue;
3675 cfg->line_out_pins[cfg->line_outs] = nid;
Steve Longerbeam81937d32007-05-08 15:33:03 +02003676 sequences_line_out[cfg->line_outs] = seq;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003677 cfg->line_outs++;
3678 break;
Takashi Iwai8d88bc32005-11-17 11:09:23 +01003679 case AC_JACK_SPEAKER:
Steve Longerbeam81937d32007-05-08 15:33:03 +02003680 seq = get_defcfg_sequence(def_conf);
3681 assoc = get_defcfg_association(def_conf);
3682 if (! assoc)
3683 continue;
3684 if (! assoc_speaker)
3685 assoc_speaker = assoc;
3686 else if (assoc_speaker != assoc)
3687 continue;
Takashi Iwai82bc9552006-03-21 11:24:42 +01003688 if (cfg->speaker_outs >= ARRAY_SIZE(cfg->speaker_pins))
3689 continue;
3690 cfg->speaker_pins[cfg->speaker_outs] = nid;
Steve Longerbeam81937d32007-05-08 15:33:03 +02003691 sequences_speaker[cfg->speaker_outs] = seq;
Takashi Iwai82bc9552006-03-21 11:24:42 +01003692 cfg->speaker_outs++;
Takashi Iwai8d88bc32005-11-17 11:09:23 +01003693 break;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003694 case AC_JACK_HP_OUT:
Takashi Iwaif889fa92007-10-31 15:49:32 +01003695 seq = get_defcfg_sequence(def_conf);
3696 assoc = get_defcfg_association(def_conf);
Takashi Iwaieb06ed82006-09-20 17:10:27 +02003697 if (cfg->hp_outs >= ARRAY_SIZE(cfg->hp_pins))
3698 continue;
3699 cfg->hp_pins[cfg->hp_outs] = nid;
Takashi Iwaif889fa92007-10-31 15:49:32 +01003700 sequences_hp[cfg->hp_outs] = (assoc << 4) | seq;
Takashi Iwaieb06ed82006-09-20 17:10:27 +02003701 cfg->hp_outs++;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003702 break;
Takashi Iwai314634b2006-09-21 11:56:18 +02003703 case AC_JACK_MIC_IN: {
3704 int preferred, alt;
3705 if (loc == AC_JACK_LOC_FRONT) {
3706 preferred = AUTO_PIN_FRONT_MIC;
3707 alt = AUTO_PIN_MIC;
3708 } else {
3709 preferred = AUTO_PIN_MIC;
3710 alt = AUTO_PIN_FRONT_MIC;
3711 }
3712 if (!cfg->input_pins[preferred])
3713 cfg->input_pins[preferred] = nid;
3714 else if (!cfg->input_pins[alt])
3715 cfg->input_pins[alt] = nid;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003716 break;
Takashi Iwai314634b2006-09-21 11:56:18 +02003717 }
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003718 case AC_JACK_LINE_IN:
3719 if (loc == AC_JACK_LOC_FRONT)
3720 cfg->input_pins[AUTO_PIN_FRONT_LINE] = nid;
3721 else
3722 cfg->input_pins[AUTO_PIN_LINE] = nid;
3723 break;
3724 case AC_JACK_CD:
3725 cfg->input_pins[AUTO_PIN_CD] = nid;
3726 break;
3727 case AC_JACK_AUX:
3728 cfg->input_pins[AUTO_PIN_AUX] = nid;
3729 break;
3730 case AC_JACK_SPDIF_OUT:
Takashi Iwai1b52ae72009-01-20 17:17:29 +01003731 case AC_JACK_DIG_OTHER_OUT:
Takashi Iwai0852d7a2009-02-11 11:35:15 +01003732 if (cfg->dig_outs >= ARRAY_SIZE(cfg->dig_out_pins))
3733 continue;
3734 cfg->dig_out_pins[cfg->dig_outs] = nid;
3735 cfg->dig_out_type[cfg->dig_outs] =
3736 (loc == AC_JACK_LOC_HDMI) ?
3737 HDA_PCM_TYPE_HDMI : HDA_PCM_TYPE_SPDIF;
3738 cfg->dig_outs++;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003739 break;
3740 case AC_JACK_SPDIF_IN:
Takashi Iwai1b52ae72009-01-20 17:17:29 +01003741 case AC_JACK_DIG_OTHER_IN:
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003742 cfg->dig_in_pin = nid;
Takashi Iwai2297bd62009-01-20 18:24:13 +01003743 if (loc == AC_JACK_LOC_HDMI)
3744 cfg->dig_in_type = HDA_PCM_TYPE_HDMI;
3745 else
3746 cfg->dig_in_type = HDA_PCM_TYPE_SPDIF;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003747 break;
3748 }
3749 }
3750
Takashi Iwai5832fcf2008-02-12 18:30:12 +01003751 /* FIX-UP:
3752 * If no line-out is defined but multiple HPs are found,
3753 * some of them might be the real line-outs.
3754 */
3755 if (!cfg->line_outs && cfg->hp_outs > 1) {
3756 int i = 0;
3757 while (i < cfg->hp_outs) {
3758 /* The real HPs should have the sequence 0x0f */
3759 if ((sequences_hp[i] & 0x0f) == 0x0f) {
3760 i++;
3761 continue;
3762 }
3763 /* Move it to the line-out table */
3764 cfg->line_out_pins[cfg->line_outs] = cfg->hp_pins[i];
3765 sequences_line_out[cfg->line_outs] = sequences_hp[i];
3766 cfg->line_outs++;
3767 cfg->hp_outs--;
3768 memmove(cfg->hp_pins + i, cfg->hp_pins + i + 1,
3769 sizeof(cfg->hp_pins[0]) * (cfg->hp_outs - i));
3770 memmove(sequences_hp + i - 1, sequences_hp + i,
3771 sizeof(sequences_hp[0]) * (cfg->hp_outs - i));
3772 }
3773 }
3774
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003775 /* sort by sequence */
Steve Longerbeam81937d32007-05-08 15:33:03 +02003776 sort_pins_by_sequence(cfg->line_out_pins, sequences_line_out,
3777 cfg->line_outs);
3778 sort_pins_by_sequence(cfg->speaker_pins, sequences_speaker,
3779 cfg->speaker_outs);
Takashi Iwaif889fa92007-10-31 15:49:32 +01003780 sort_pins_by_sequence(cfg->hp_pins, sequences_hp,
3781 cfg->hp_outs);
Steve Longerbeam81937d32007-05-08 15:33:03 +02003782
Takashi Iwaif889fa92007-10-31 15:49:32 +01003783 /* if we have only one mic, make it AUTO_PIN_MIC */
3784 if (!cfg->input_pins[AUTO_PIN_MIC] &&
3785 cfg->input_pins[AUTO_PIN_FRONT_MIC]) {
3786 cfg->input_pins[AUTO_PIN_MIC] =
3787 cfg->input_pins[AUTO_PIN_FRONT_MIC];
3788 cfg->input_pins[AUTO_PIN_FRONT_MIC] = 0;
3789 }
3790 /* ditto for line-in */
3791 if (!cfg->input_pins[AUTO_PIN_LINE] &&
3792 cfg->input_pins[AUTO_PIN_FRONT_LINE]) {
3793 cfg->input_pins[AUTO_PIN_LINE] =
3794 cfg->input_pins[AUTO_PIN_FRONT_LINE];
3795 cfg->input_pins[AUTO_PIN_FRONT_LINE] = 0;
3796 }
3797
Steve Longerbeam81937d32007-05-08 15:33:03 +02003798 /*
3799 * FIX-UP: if no line-outs are detected, try to use speaker or HP pin
3800 * as a primary output
3801 */
3802 if (!cfg->line_outs) {
3803 if (cfg->speaker_outs) {
3804 cfg->line_outs = cfg->speaker_outs;
3805 memcpy(cfg->line_out_pins, cfg->speaker_pins,
3806 sizeof(cfg->speaker_pins));
3807 cfg->speaker_outs = 0;
3808 memset(cfg->speaker_pins, 0, sizeof(cfg->speaker_pins));
3809 cfg->line_out_type = AUTO_PIN_SPEAKER_OUT;
3810 } else if (cfg->hp_outs) {
3811 cfg->line_outs = cfg->hp_outs;
3812 memcpy(cfg->line_out_pins, cfg->hp_pins,
3813 sizeof(cfg->hp_pins));
3814 cfg->hp_outs = 0;
3815 memset(cfg->hp_pins, 0, sizeof(cfg->hp_pins));
3816 cfg->line_out_type = AUTO_PIN_HP_OUT;
3817 }
3818 }
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003819
Takashi Iwaicb8e2f82005-07-29 11:54:32 +02003820 /* Reorder the surround channels
3821 * ALSA sequence is front/surr/clfe/side
3822 * HDA sequence is:
3823 * 4-ch: front/surr => OK as it is
3824 * 6-ch: front/clfe/surr
Takashi Iwai9422db42007-04-20 16:11:43 +02003825 * 8-ch: front/clfe/rear/side|fc
Takashi Iwaicb8e2f82005-07-29 11:54:32 +02003826 */
3827 switch (cfg->line_outs) {
3828 case 3:
Takashi Iwaicb8e2f82005-07-29 11:54:32 +02003829 case 4:
3830 nid = cfg->line_out_pins[1];
Takashi Iwai9422db42007-04-20 16:11:43 +02003831 cfg->line_out_pins[1] = cfg->line_out_pins[2];
Takashi Iwaicb8e2f82005-07-29 11:54:32 +02003832 cfg->line_out_pins[2] = nid;
3833 break;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003834 }
3835
Takashi Iwai82bc9552006-03-21 11:24:42 +01003836 /*
3837 * debug prints of the parsed results
3838 */
3839 snd_printd("autoconfig: line_outs=%d (0x%x/0x%x/0x%x/0x%x/0x%x)\n",
3840 cfg->line_outs, cfg->line_out_pins[0], cfg->line_out_pins[1],
3841 cfg->line_out_pins[2], cfg->line_out_pins[3],
3842 cfg->line_out_pins[4]);
3843 snd_printd(" speaker_outs=%d (0x%x/0x%x/0x%x/0x%x/0x%x)\n",
3844 cfg->speaker_outs, cfg->speaker_pins[0],
3845 cfg->speaker_pins[1], cfg->speaker_pins[2],
3846 cfg->speaker_pins[3], cfg->speaker_pins[4]);
Takashi Iwaieb06ed82006-09-20 17:10:27 +02003847 snd_printd(" hp_outs=%d (0x%x/0x%x/0x%x/0x%x/0x%x)\n",
3848 cfg->hp_outs, cfg->hp_pins[0],
3849 cfg->hp_pins[1], cfg->hp_pins[2],
3850 cfg->hp_pins[3], cfg->hp_pins[4]);
Matthew Ranostay90da78b2008-01-24 11:48:01 +01003851 snd_printd(" mono: mono_out=0x%x\n", cfg->mono_out_pin);
Takashi Iwai0852d7a2009-02-11 11:35:15 +01003852 if (cfg->dig_outs)
3853 snd_printd(" dig-out=0x%x/0x%x\n",
3854 cfg->dig_out_pins[0], cfg->dig_out_pins[1]);
Takashi Iwai82bc9552006-03-21 11:24:42 +01003855 snd_printd(" inputs: mic=0x%x, fmic=0x%x, line=0x%x, fline=0x%x,"
3856 " cd=0x%x, aux=0x%x\n",
3857 cfg->input_pins[AUTO_PIN_MIC],
3858 cfg->input_pins[AUTO_PIN_FRONT_MIC],
3859 cfg->input_pins[AUTO_PIN_LINE],
3860 cfg->input_pins[AUTO_PIN_FRONT_LINE],
3861 cfg->input_pins[AUTO_PIN_CD],
3862 cfg->input_pins[AUTO_PIN_AUX]);
Takashi Iwai32d2c7f2009-02-11 11:33:13 +01003863 if (cfg->dig_in_pin)
Takashi Iwai89ce9e82009-01-20 17:15:57 +01003864 snd_printd(" dig-in=0x%x\n", cfg->dig_in_pin);
Takashi Iwai82bc9552006-03-21 11:24:42 +01003865
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003866 return 0;
3867}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003868EXPORT_SYMBOL_HDA(snd_hda_parse_pin_def_config);
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003869
Takashi Iwai4a471b72005-12-07 13:56:29 +01003870/* labels for input pins */
3871const char *auto_pin_cfg_labels[AUTO_PIN_LAST] = {
3872 "Mic", "Front Mic", "Line", "Front Line", "CD", "Aux"
3873};
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003874EXPORT_SYMBOL_HDA(auto_pin_cfg_labels);
Takashi Iwai4a471b72005-12-07 13:56:29 +01003875
3876
Linus Torvalds1da177e2005-04-16 15:20:36 -07003877#ifdef CONFIG_PM
3878/*
3879 * power management
3880 */
3881
3882/**
3883 * snd_hda_suspend - suspend the codecs
3884 * @bus: the HDA bus
Linus Torvalds1da177e2005-04-16 15:20:36 -07003885 *
3886 * Returns 0 if successful.
3887 */
Takashi Iwai8dd78332009-06-02 01:16:07 +02003888int snd_hda_suspend(struct hda_bus *bus)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003889{
Takashi Iwai0ba21762007-04-16 11:29:14 +02003890 struct hda_codec *codec;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003891
Takashi Iwai0ba21762007-04-16 11:29:14 +02003892 list_for_each_entry(codec, &bus->codec_list, list) {
Takashi Iwai0b7a2e92007-08-14 15:18:26 +02003893#ifdef CONFIG_SND_HDA_POWER_SAVE
3894 if (!codec->power_on)
3895 continue;
3896#endif
Takashi Iwaicb53c622007-08-10 17:21:45 +02003897 hda_call_codec_suspend(codec);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003898 }
3899 return 0;
3900}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003901EXPORT_SYMBOL_HDA(snd_hda_suspend);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003902
3903/**
3904 * snd_hda_resume - resume the codecs
3905 * @bus: the HDA bus
Linus Torvalds1da177e2005-04-16 15:20:36 -07003906 *
3907 * Returns 0 if successful.
Takashi Iwaicb53c622007-08-10 17:21:45 +02003908 *
3909 * This fucntion is defined only when POWER_SAVE isn't set.
3910 * In the power-save mode, the codec is resumed dynamically.
Linus Torvalds1da177e2005-04-16 15:20:36 -07003911 */
3912int snd_hda_resume(struct hda_bus *bus)
3913{
Takashi Iwai0ba21762007-04-16 11:29:14 +02003914 struct hda_codec *codec;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003915
Takashi Iwai0ba21762007-04-16 11:29:14 +02003916 list_for_each_entry(codec, &bus->codec_list, list) {
Maxim Levitskyd804ad92007-09-03 15:28:04 +02003917 if (snd_hda_codec_needs_resume(codec))
3918 hda_call_codec_resume(codec);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003919 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003920 return 0;
3921}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003922EXPORT_SYMBOL_HDA(snd_hda_resume);
Takashi Iwai1289e9e2008-11-27 15:47:11 +01003923#endif /* CONFIG_PM */
Takashi Iwaib2e18592008-07-30 15:01:44 +02003924
3925/*
3926 * generic arrays
3927 */
3928
3929/* get a new element from the given array
3930 * if it exceeds the pre-allocated array size, re-allocate the array
3931 */
3932void *snd_array_new(struct snd_array *array)
3933{
3934 if (array->used >= array->alloced) {
3935 int num = array->alloced + array->alloc_align;
Takashi Iwaib910d9a2008-11-07 00:26:52 +01003936 void *nlist;
3937 if (snd_BUG_ON(num >= 4096))
3938 return NULL;
3939 nlist = kcalloc(num + 1, array->elem_size, GFP_KERNEL);
Takashi Iwaib2e18592008-07-30 15:01:44 +02003940 if (!nlist)
3941 return NULL;
3942 if (array->list) {
3943 memcpy(nlist, array->list,
3944 array->elem_size * array->alloced);
3945 kfree(array->list);
3946 }
3947 array->list = nlist;
3948 array->alloced = num;
3949 }
Takashi Iwaif43aa022008-11-10 16:24:26 +01003950 return snd_array_elem(array, array->used++);
Takashi Iwaib2e18592008-07-30 15:01:44 +02003951}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003952EXPORT_SYMBOL_HDA(snd_array_new);
Takashi Iwaib2e18592008-07-30 15:01:44 +02003953
3954/* free the given array elements */
3955void snd_array_free(struct snd_array *array)
3956{
3957 kfree(array->list);
3958 array->used = 0;
3959 array->alloced = 0;
3960 array->list = NULL;
3961}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003962EXPORT_SYMBOL_HDA(snd_array_free);
Takashi Iwaib2022262008-11-21 21:24:03 +01003963
3964/*
3965 * used by hda_proc.c and hda_eld.c
3966 */
3967void snd_print_pcm_rates(int pcm, char *buf, int buflen)
3968{
3969 static unsigned int rates[] = {
3970 8000, 11025, 16000, 22050, 32000, 44100, 48000, 88200,
3971 96000, 176400, 192000, 384000
3972 };
3973 int i, j;
3974
3975 for (i = 0, j = 0; i < ARRAY_SIZE(rates); i++)
3976 if (pcm & (1 << i))
3977 j += snprintf(buf + j, buflen - j, " %d", rates[i]);
3978
3979 buf[j] = '\0'; /* necessary when j == 0 */
3980}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003981EXPORT_SYMBOL_HDA(snd_print_pcm_rates);
Takashi Iwaib2022262008-11-21 21:24:03 +01003982
3983void snd_print_pcm_bits(int pcm, char *buf, int buflen)
3984{
3985 static unsigned int bits[] = { 8, 16, 20, 24, 32 };
3986 int i, j;
3987
3988 for (i = 0, j = 0; i < ARRAY_SIZE(bits); i++)
3989 if (pcm & (AC_SUPPCM_BITS_8 << i))
3990 j += snprintf(buf + j, buflen - j, " %d", bits[i]);
3991
3992 buf[j] = '\0'; /* necessary when j == 0 */
3993}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003994EXPORT_SYMBOL_HDA(snd_print_pcm_bits);
Takashi Iwai1289e9e2008-11-27 15:47:11 +01003995
3996MODULE_DESCRIPTION("HDA codec core");
3997MODULE_LICENSE("GPL");