blob: d9d326297834ed6346b8b129d63b4e2e66b84a16 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * Universal Interface for Intel High Definition Audio Codec
3 *
4 * Copyright (c) 2004 Takashi Iwai <tiwai@suse.de>
5 *
6 *
7 * This driver is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This driver is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21
Linus Torvalds1da177e2005-04-16 15:20:36 -070022#include <linux/init.h>
23#include <linux/delay.h>
24#include <linux/slab.h>
25#include <linux/pci.h>
Ingo Molnar62932df2006-01-16 16:34:20 +010026#include <linux/mutex.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070027#include <sound/core.h>
28#include "hda_codec.h"
29#include <sound/asoundef.h>
Jaroslav Kysela302e9c52006-07-05 17:39:49 +020030#include <sound/tlv.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070031#include <sound/initval.h>
32#include "hda_local.h"
Takashi Iwai28073142007-07-27 18:58:06 +020033#include <sound/hda_hwdep.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070034
Linus Torvalds1da177e2005-04-16 15:20:36 -070035/*
36 * vendor / preset table
37 */
38
39struct hda_vendor_id {
40 unsigned int id;
41 const char *name;
42};
43
44/* codec vendor labels */
45static struct hda_vendor_id hda_vendor_ids[] = {
Takashi Iwaic8cd1282008-02-13 16:59:29 +010046 { 0x1002, "ATI" },
Takashi Iwaia9226252006-09-17 22:05:54 +020047 { 0x1057, "Motorola" },
Takashi Iwaic8cd1282008-02-13 16:59:29 +010048 { 0x1095, "Silicon Image" },
Takashi Iwai31117b72008-12-16 14:43:21 +010049 { 0x10de, "Nvidia" },
Takashi Iwaic8cd1282008-02-13 16:59:29 +010050 { 0x10ec, "Realtek" },
Takashi Iwai4e01f542009-04-16 08:53:34 +020051 { 0x1102, "Creative" },
Joseph Chanc577b8a2006-11-29 15:29:40 +010052 { 0x1106, "VIA" },
Matthew Ranostay7f168592007-10-18 17:38:17 +020053 { 0x111d, "IDT" },
Takashi Iwaic8cd1282008-02-13 16:59:29 +010054 { 0x11c1, "LSI" },
Takashi Iwai54b903e2005-05-15 14:30:10 +020055 { 0x11d4, "Analog Devices" },
Linus Torvalds1da177e2005-04-16 15:20:36 -070056 { 0x13f6, "C-Media" },
Takashi Iwaia9226252006-09-17 22:05:54 +020057 { 0x14f1, "Conexant" },
Takashi Iwaic8cd1282008-02-13 16:59:29 +010058 { 0x17e8, "Chrontel" },
59 { 0x1854, "LG" },
Mark Brown8199de32008-10-28 14:50:13 +000060 { 0x1aec, "Wolfson Microelectronics" },
Linus Torvalds1da177e2005-04-16 15:20:36 -070061 { 0x434d, "C-Media" },
Takashi Iwai74c61132008-12-18 09:11:33 +010062 { 0x8086, "Intel" },
Matt2f2f4252005-04-13 14:45:30 +020063 { 0x8384, "SigmaTel" },
Linus Torvalds1da177e2005-04-16 15:20:36 -070064 {} /* terminator */
65};
66
Takashi Iwai1289e9e2008-11-27 15:47:11 +010067static DEFINE_MUTEX(preset_mutex);
68static LIST_HEAD(hda_preset_tables);
69
70int snd_hda_add_codec_preset(struct hda_codec_preset_list *preset)
71{
72 mutex_lock(&preset_mutex);
73 list_add_tail(&preset->list, &hda_preset_tables);
74 mutex_unlock(&preset_mutex);
75 return 0;
76}
Takashi Iwaiff7a3262008-11-28 15:17:06 +010077EXPORT_SYMBOL_HDA(snd_hda_add_codec_preset);
Takashi Iwai1289e9e2008-11-27 15:47:11 +010078
79int snd_hda_delete_codec_preset(struct hda_codec_preset_list *preset)
80{
81 mutex_lock(&preset_mutex);
82 list_del(&preset->list);
83 mutex_unlock(&preset_mutex);
84 return 0;
85}
Takashi Iwaiff7a3262008-11-28 15:17:06 +010086EXPORT_SYMBOL_HDA(snd_hda_delete_codec_preset);
Linus Torvalds1da177e2005-04-16 15:20:36 -070087
Takashi Iwaicb53c622007-08-10 17:21:45 +020088#ifdef CONFIG_SND_HDA_POWER_SAVE
89static void hda_power_work(struct work_struct *work);
90static void hda_keep_power_on(struct hda_codec *codec);
91#else
92static inline void hda_keep_power_on(struct hda_codec *codec) {}
93#endif
94
Matthew Ranostay50a9f792008-10-25 01:05:45 -040095const char *snd_hda_get_jack_location(u32 cfg)
96{
97 static char *bases[7] = {
98 "N/A", "Rear", "Front", "Left", "Right", "Top", "Bottom",
99 };
100 static unsigned char specials_idx[] = {
101 0x07, 0x08,
102 0x17, 0x18, 0x19,
103 0x37, 0x38
104 };
105 static char *specials[] = {
106 "Rear Panel", "Drive Bar",
107 "Riser", "HDMI", "ATAPI",
108 "Mobile-In", "Mobile-Out"
109 };
110 int i;
111 cfg = (cfg & AC_DEFCFG_LOCATION) >> AC_DEFCFG_LOCATION_SHIFT;
112 if ((cfg & 0x0f) < 7)
113 return bases[cfg & 0x0f];
114 for (i = 0; i < ARRAY_SIZE(specials_idx); i++) {
115 if (cfg == specials_idx[i])
116 return specials[i];
117 }
118 return "UNKNOWN";
119}
Takashi Iwaiff7a3262008-11-28 15:17:06 +0100120EXPORT_SYMBOL_HDA(snd_hda_get_jack_location);
Matthew Ranostay50a9f792008-10-25 01:05:45 -0400121
122const char *snd_hda_get_jack_connectivity(u32 cfg)
123{
124 static char *jack_locations[4] = { "Ext", "Int", "Sep", "Oth" };
125
126 return jack_locations[(cfg >> (AC_DEFCFG_LOCATION_SHIFT + 4)) & 3];
127}
Takashi Iwaiff7a3262008-11-28 15:17:06 +0100128EXPORT_SYMBOL_HDA(snd_hda_get_jack_connectivity);
Matthew Ranostay50a9f792008-10-25 01:05:45 -0400129
130const char *snd_hda_get_jack_type(u32 cfg)
131{
132 static char *jack_types[16] = {
133 "Line Out", "Speaker", "HP Out", "CD",
134 "SPDIF Out", "Digital Out", "Modem Line", "Modem Hand",
135 "Line In", "Aux", "Mic", "Telephony",
136 "SPDIF In", "Digitial In", "Reserved", "Other"
137 };
138
139 return jack_types[(cfg & AC_DEFCFG_DEVICE)
140 >> AC_DEFCFG_DEVICE_SHIFT];
141}
Takashi Iwaiff7a3262008-11-28 15:17:06 +0100142EXPORT_SYMBOL_HDA(snd_hda_get_jack_type);
Matthew Ranostay50a9f792008-10-25 01:05:45 -0400143
Takashi Iwai33fa35e2008-11-06 16:50:40 +0100144/*
145 * Compose a 32bit command word to be sent to the HD-audio controller
146 */
147static inline unsigned int
148make_codec_cmd(struct hda_codec *codec, hda_nid_t nid, int direct,
149 unsigned int verb, unsigned int parm)
150{
151 u32 val;
152
Wu Fengguang6430aee2009-07-17 16:49:19 +0800153 if ((codec->addr & ~0xf) | (direct & ~1) | (nid & ~0x7f) |
154 (verb & ~0xfff) | (parm & ~0xff)) {
155 printk(KERN_ERR "hda-codec: out of range cmd %x:%x:%x:%x:%x\n",
156 codec->addr, direct, nid, verb, parm);
157 return ~0;
158 }
159
160 val = (u32)codec->addr << 28;
Takashi Iwai33fa35e2008-11-06 16:50:40 +0100161 val |= (u32)direct << 27;
162 val |= (u32)nid << 20;
163 val |= verb << 8;
164 val |= parm;
165 return val;
166}
167
Takashi Iwaiaa2936f2009-05-26 16:07:57 +0200168/*
169 * Send and receive a verb
170 */
171static int codec_exec_verb(struct hda_codec *codec, unsigned int cmd,
172 unsigned int *res)
173{
174 struct hda_bus *bus = codec->bus;
Takashi Iwai8dd78332009-06-02 01:16:07 +0200175 int err;
Takashi Iwaiaa2936f2009-05-26 16:07:57 +0200176
Wu Fengguang6430aee2009-07-17 16:49:19 +0800177 if (cmd == ~0)
178 return -1;
179
Takashi Iwaiaa2936f2009-05-26 16:07:57 +0200180 if (res)
181 *res = -1;
Takashi Iwai8dd78332009-06-02 01:16:07 +0200182 again:
Takashi Iwaiaa2936f2009-05-26 16:07:57 +0200183 snd_hda_power_up(codec);
184 mutex_lock(&bus->cmd_mutex);
Takashi Iwaiaa2936f2009-05-26 16:07:57 +0200185 err = bus->ops.command(bus, cmd);
Takashi Iwai8dd78332009-06-02 01:16:07 +0200186 if (!err && res)
187 *res = bus->ops.get_response(bus);
Takashi Iwaiaa2936f2009-05-26 16:07:57 +0200188 mutex_unlock(&bus->cmd_mutex);
189 snd_hda_power_down(codec);
Takashi Iwai8dd78332009-06-02 01:16:07 +0200190 if (res && *res == -1 && bus->rirb_error) {
191 if (bus->response_reset) {
192 snd_printd("hda_codec: resetting BUS due to "
193 "fatal communication error\n");
194 bus->ops.bus_reset(bus);
195 }
196 goto again;
197 }
198 /* clear reset-flag when the communication gets recovered */
199 if (!err)
200 bus->response_reset = 0;
Takashi Iwaiaa2936f2009-05-26 16:07:57 +0200201 return err;
202}
203
Linus Torvalds1da177e2005-04-16 15:20:36 -0700204/**
205 * snd_hda_codec_read - send a command and get the response
206 * @codec: the HDA codec
207 * @nid: NID to send the command
208 * @direct: direct flag
209 * @verb: the verb to send
210 * @parm: the parameter for the verb
211 *
212 * Send a single command and read the corresponding response.
213 *
214 * Returns the obtained response value, or -1 for an error.
215 */
Takashi Iwai0ba21762007-04-16 11:29:14 +0200216unsigned int snd_hda_codec_read(struct hda_codec *codec, hda_nid_t nid,
217 int direct,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700218 unsigned int verb, unsigned int parm)
219{
Takashi Iwaiaa2936f2009-05-26 16:07:57 +0200220 unsigned cmd = make_codec_cmd(codec, nid, direct, verb, parm);
221 unsigned int res;
222 codec_exec_verb(codec, cmd, &res);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700223 return res;
224}
Takashi Iwaiff7a3262008-11-28 15:17:06 +0100225EXPORT_SYMBOL_HDA(snd_hda_codec_read);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700226
227/**
228 * snd_hda_codec_write - send a single command without waiting for response
229 * @codec: the HDA codec
230 * @nid: NID to send the command
231 * @direct: direct flag
232 * @verb: the verb to send
233 * @parm: the parameter for the verb
234 *
235 * Send a single command without waiting for response.
236 *
237 * Returns 0 if successful, or a negative error code.
238 */
239int snd_hda_codec_write(struct hda_codec *codec, hda_nid_t nid, int direct,
240 unsigned int verb, unsigned int parm)
241{
Takashi Iwaiaa2936f2009-05-26 16:07:57 +0200242 unsigned int cmd = make_codec_cmd(codec, nid, direct, verb, parm);
Takashi Iwai33fa35e2008-11-06 16:50:40 +0100243 unsigned int res;
Takashi Iwaib20f3b82009-06-02 01:20:22 +0200244 return codec_exec_verb(codec, cmd,
245 codec->bus->sync_write ? &res : NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700246}
Takashi Iwaiff7a3262008-11-28 15:17:06 +0100247EXPORT_SYMBOL_HDA(snd_hda_codec_write);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700248
249/**
250 * snd_hda_sequence_write - sequence writes
251 * @codec: the HDA codec
252 * @seq: VERB array to send
253 *
254 * Send the commands sequentially from the given array.
255 * The array must be terminated with NID=0.
256 */
257void snd_hda_sequence_write(struct hda_codec *codec, const struct hda_verb *seq)
258{
259 for (; seq->nid; seq++)
260 snd_hda_codec_write(codec, seq->nid, 0, seq->verb, seq->param);
261}
Takashi Iwaiff7a3262008-11-28 15:17:06 +0100262EXPORT_SYMBOL_HDA(snd_hda_sequence_write);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700263
264/**
265 * snd_hda_get_sub_nodes - get the range of sub nodes
266 * @codec: the HDA codec
267 * @nid: NID to parse
268 * @start_id: the pointer to store the start NID
269 *
270 * Parse the NID and store the start NID of its sub-nodes.
271 * Returns the number of sub-nodes.
272 */
Takashi Iwai0ba21762007-04-16 11:29:14 +0200273int snd_hda_get_sub_nodes(struct hda_codec *codec, hda_nid_t nid,
274 hda_nid_t *start_id)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700275{
276 unsigned int parm;
277
278 parm = snd_hda_param_read(codec, nid, AC_PAR_NODE_COUNT);
Danny Tholene8a7f132007-09-11 21:41:56 +0200279 if (parm == -1)
280 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700281 *start_id = (parm >> 16) & 0x7fff;
282 return (int)(parm & 0x7fff);
283}
Takashi Iwaiff7a3262008-11-28 15:17:06 +0100284EXPORT_SYMBOL_HDA(snd_hda_get_sub_nodes);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700285
286/**
287 * snd_hda_get_connections - get connection list
288 * @codec: the HDA codec
289 * @nid: NID to parse
290 * @conn_list: connection list array
291 * @max_conns: max. number of connections to store
292 *
293 * Parses the connection list of the given widget and stores the list
294 * of NIDs.
295 *
296 * Returns the number of connections, or a negative error code.
297 */
298int snd_hda_get_connections(struct hda_codec *codec, hda_nid_t nid,
299 hda_nid_t *conn_list, int max_conns)
300{
301 unsigned int parm;
Takashi Iwai54d17402005-11-21 16:33:22 +0100302 int i, conn_len, conns;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700303 unsigned int shift, num_elems, mask;
Takashi Iwai54d17402005-11-21 16:33:22 +0100304 hda_nid_t prev_nid;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700305
Takashi Iwaida3cec32008-08-08 17:12:14 +0200306 if (snd_BUG_ON(!conn_list || max_conns <= 0))
307 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700308
309 parm = snd_hda_param_read(codec, nid, AC_PAR_CONNLIST_LEN);
310 if (parm & AC_CLIST_LONG) {
311 /* long form */
312 shift = 16;
313 num_elems = 2;
314 } else {
315 /* short form */
316 shift = 8;
317 num_elems = 4;
318 }
319 conn_len = parm & AC_CLIST_LENGTH;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700320 mask = (1 << (shift-1)) - 1;
321
Takashi Iwai0ba21762007-04-16 11:29:14 +0200322 if (!conn_len)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700323 return 0; /* no connection */
324
325 if (conn_len == 1) {
326 /* single connection */
Takashi Iwai0ba21762007-04-16 11:29:14 +0200327 parm = snd_hda_codec_read(codec, nid, 0,
328 AC_VERB_GET_CONNECT_LIST, 0);
Takashi Iwai3c6aae42009-07-10 12:52:27 +0200329 if (parm == -1 && codec->bus->rirb_error)
330 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700331 conn_list[0] = parm & mask;
332 return 1;
333 }
334
335 /* multi connection */
336 conns = 0;
Takashi Iwai54d17402005-11-21 16:33:22 +0100337 prev_nid = 0;
338 for (i = 0; i < conn_len; i++) {
339 int range_val;
340 hda_nid_t val, n;
341
Takashi Iwai3c6aae42009-07-10 12:52:27 +0200342 if (i % num_elems == 0) {
Takashi Iwai54d17402005-11-21 16:33:22 +0100343 parm = snd_hda_codec_read(codec, nid, 0,
344 AC_VERB_GET_CONNECT_LIST, i);
Takashi Iwai3c6aae42009-07-10 12:52:27 +0200345 if (parm == -1 && codec->bus->rirb_error)
346 return -EIO;
347 }
Takashi Iwai0ba21762007-04-16 11:29:14 +0200348 range_val = !!(parm & (1 << (shift-1))); /* ranges */
Takashi Iwai54d17402005-11-21 16:33:22 +0100349 val = parm & mask;
350 parm >>= shift;
351 if (range_val) {
352 /* ranges between the previous and this one */
Takashi Iwai0ba21762007-04-16 11:29:14 +0200353 if (!prev_nid || prev_nid >= val) {
354 snd_printk(KERN_WARNING "hda_codec: "
355 "invalid dep_range_val %x:%x\n",
356 prev_nid, val);
Takashi Iwai54d17402005-11-21 16:33:22 +0100357 continue;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700358 }
Takashi Iwai54d17402005-11-21 16:33:22 +0100359 for (n = prev_nid + 1; n <= val; n++) {
360 if (conns >= max_conns) {
Takashi Iwai0ba21762007-04-16 11:29:14 +0200361 snd_printk(KERN_ERR
362 "Too many connections\n");
Takashi Iwai54d17402005-11-21 16:33:22 +0100363 return -EINVAL;
364 }
365 conn_list[conns++] = n;
366 }
367 } else {
368 if (conns >= max_conns) {
369 snd_printk(KERN_ERR "Too many connections\n");
370 return -EINVAL;
371 }
372 conn_list[conns++] = val;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700373 }
Takashi Iwai54d17402005-11-21 16:33:22 +0100374 prev_nid = val;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700375 }
376 return conns;
377}
Takashi Iwaiff7a3262008-11-28 15:17:06 +0100378EXPORT_SYMBOL_HDA(snd_hda_get_connections);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700379
380
381/**
382 * snd_hda_queue_unsol_event - add an unsolicited event to queue
383 * @bus: the BUS
384 * @res: unsolicited event (lower 32bit of RIRB entry)
385 * @res_ex: codec addr and flags (upper 32bit or RIRB entry)
386 *
387 * Adds the given event to the queue. The events are processed in
388 * the workqueue asynchronously. Call this function in the interrupt
389 * hanlder when RIRB receives an unsolicited event.
390 *
391 * Returns 0 if successful, or a negative error code.
392 */
393int snd_hda_queue_unsol_event(struct hda_bus *bus, u32 res, u32 res_ex)
394{
395 struct hda_bus_unsolicited *unsol;
396 unsigned int wp;
397
Takashi Iwai0ba21762007-04-16 11:29:14 +0200398 unsol = bus->unsol;
399 if (!unsol)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700400 return 0;
401
402 wp = (unsol->wp + 1) % HDA_UNSOL_QUEUE_SIZE;
403 unsol->wp = wp;
404
405 wp <<= 1;
406 unsol->queue[wp] = res;
407 unsol->queue[wp + 1] = res_ex;
408
Takashi Iwai6acaed32009-01-12 10:09:24 +0100409 queue_work(bus->workq, &unsol->work);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700410
411 return 0;
412}
Takashi Iwaiff7a3262008-11-28 15:17:06 +0100413EXPORT_SYMBOL_HDA(snd_hda_queue_unsol_event);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700414
415/*
Wu Fengguang5c1d1a92008-10-07 14:17:53 +0800416 * process queued unsolicited events
Linus Torvalds1da177e2005-04-16 15:20:36 -0700417 */
David Howellsc4028952006-11-22 14:57:56 +0000418static void process_unsol_events(struct work_struct *work)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700419{
David Howellsc4028952006-11-22 14:57:56 +0000420 struct hda_bus_unsolicited *unsol =
421 container_of(work, struct hda_bus_unsolicited, work);
422 struct hda_bus *bus = unsol->bus;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700423 struct hda_codec *codec;
424 unsigned int rp, caddr, res;
425
426 while (unsol->rp != unsol->wp) {
427 rp = (unsol->rp + 1) % HDA_UNSOL_QUEUE_SIZE;
428 unsol->rp = rp;
429 rp <<= 1;
430 res = unsol->queue[rp];
431 caddr = unsol->queue[rp + 1];
Takashi Iwai0ba21762007-04-16 11:29:14 +0200432 if (!(caddr & (1 << 4))) /* no unsolicited event? */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700433 continue;
434 codec = bus->caddr_tbl[caddr & 0x0f];
435 if (codec && codec->patch_ops.unsol_event)
436 codec->patch_ops.unsol_event(codec, res);
437 }
438}
439
440/*
441 * initialize unsolicited queue
442 */
Takashi Iwai6c1f45e2008-07-30 15:01:45 +0200443static int init_unsol_queue(struct hda_bus *bus)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700444{
445 struct hda_bus_unsolicited *unsol;
446
Takashi Iwai9f146bb2005-11-17 11:07:49 +0100447 if (bus->unsol) /* already initialized */
448 return 0;
449
Takashi Iwaie560d8d2005-09-09 14:21:46 +0200450 unsol = kzalloc(sizeof(*unsol), GFP_KERNEL);
Takashi Iwai0ba21762007-04-16 11:29:14 +0200451 if (!unsol) {
452 snd_printk(KERN_ERR "hda_codec: "
453 "can't allocate unsolicited queue\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700454 return -ENOMEM;
455 }
David Howellsc4028952006-11-22 14:57:56 +0000456 INIT_WORK(&unsol->work, process_unsol_events);
457 unsol->bus = bus;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700458 bus->unsol = unsol;
459 return 0;
460}
461
462/*
463 * destructor
464 */
465static void snd_hda_codec_free(struct hda_codec *codec);
466
467static int snd_hda_bus_free(struct hda_bus *bus)
468{
Takashi Iwai0ba21762007-04-16 11:29:14 +0200469 struct hda_codec *codec, *n;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700470
Takashi Iwai0ba21762007-04-16 11:29:14 +0200471 if (!bus)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700472 return 0;
Takashi Iwai6acaed32009-01-12 10:09:24 +0100473 if (bus->workq)
474 flush_workqueue(bus->workq);
475 if (bus->unsol)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700476 kfree(bus->unsol);
Takashi Iwai0ba21762007-04-16 11:29:14 +0200477 list_for_each_entry_safe(codec, n, &bus->codec_list, list) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700478 snd_hda_codec_free(codec);
479 }
480 if (bus->ops.private_free)
481 bus->ops.private_free(bus);
Takashi Iwai6acaed32009-01-12 10:09:24 +0100482 if (bus->workq)
483 destroy_workqueue(bus->workq);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700484 kfree(bus);
485 return 0;
486}
487
Takashi Iwaic8b6bf92005-11-17 14:57:47 +0100488static int snd_hda_bus_dev_free(struct snd_device *device)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700489{
490 struct hda_bus *bus = device->device_data;
Takashi Iwaib94d35392008-11-21 09:08:06 +0100491 bus->shutdown = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700492 return snd_hda_bus_free(bus);
493}
494
Takashi Iwaid7ffba12008-07-30 15:01:46 +0200495#ifdef CONFIG_SND_HDA_HWDEP
496static int snd_hda_bus_dev_register(struct snd_device *device)
497{
498 struct hda_bus *bus = device->device_data;
499 struct hda_codec *codec;
500 list_for_each_entry(codec, &bus->codec_list, list) {
501 snd_hda_hwdep_add_sysfs(codec);
502 }
503 return 0;
504}
505#else
506#define snd_hda_bus_dev_register NULL
507#endif
508
Linus Torvalds1da177e2005-04-16 15:20:36 -0700509/**
510 * snd_hda_bus_new - create a HDA bus
511 * @card: the card entry
512 * @temp: the template for hda_bus information
513 * @busp: the pointer to store the created bus instance
514 *
515 * Returns 0 if successful, or a negative error code.
516 */
Takashi Iwai1289e9e2008-11-27 15:47:11 +0100517int /*__devinit*/ snd_hda_bus_new(struct snd_card *card,
Takashi Iwai756e2b02007-04-16 11:27:07 +0200518 const struct hda_bus_template *temp,
519 struct hda_bus **busp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700520{
521 struct hda_bus *bus;
522 int err;
Takashi Iwaic8b6bf92005-11-17 14:57:47 +0100523 static struct snd_device_ops dev_ops = {
Takashi Iwaid7ffba12008-07-30 15:01:46 +0200524 .dev_register = snd_hda_bus_dev_register,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700525 .dev_free = snd_hda_bus_dev_free,
526 };
527
Takashi Iwaida3cec32008-08-08 17:12:14 +0200528 if (snd_BUG_ON(!temp))
529 return -EINVAL;
530 if (snd_BUG_ON(!temp->ops.command || !temp->ops.get_response))
531 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700532
533 if (busp)
534 *busp = NULL;
535
Takashi Iwaie560d8d2005-09-09 14:21:46 +0200536 bus = kzalloc(sizeof(*bus), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700537 if (bus == NULL) {
538 snd_printk(KERN_ERR "can't allocate struct hda_bus\n");
539 return -ENOMEM;
540 }
541
542 bus->card = card;
543 bus->private_data = temp->private_data;
544 bus->pci = temp->pci;
545 bus->modelname = temp->modelname;
Takashi Iwaifee2fba2008-11-27 12:43:28 +0100546 bus->power_save = temp->power_save;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700547 bus->ops = temp->ops;
548
Ingo Molnar62932df2006-01-16 16:34:20 +0100549 mutex_init(&bus->cmd_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700550 INIT_LIST_HEAD(&bus->codec_list);
551
Takashi Iwaie8c0ee52009-02-05 07:34:28 +0100552 snprintf(bus->workq_name, sizeof(bus->workq_name),
553 "hd-audio%d", card->number);
554 bus->workq = create_singlethread_workqueue(bus->workq_name);
Takashi Iwai6acaed32009-01-12 10:09:24 +0100555 if (!bus->workq) {
Takashi Iwaie8c0ee52009-02-05 07:34:28 +0100556 snd_printk(KERN_ERR "cannot create workqueue %s\n",
557 bus->workq_name);
Takashi Iwai6acaed32009-01-12 10:09:24 +0100558 kfree(bus);
559 return -ENOMEM;
560 }
561
Takashi Iwai0ba21762007-04-16 11:29:14 +0200562 err = snd_device_new(card, SNDRV_DEV_BUS, bus, &dev_ops);
563 if (err < 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700564 snd_hda_bus_free(bus);
565 return err;
566 }
567 if (busp)
568 *busp = bus;
569 return 0;
570}
Takashi Iwaiff7a3262008-11-28 15:17:06 +0100571EXPORT_SYMBOL_HDA(snd_hda_bus_new);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700572
Takashi Iwai82467612007-07-27 19:15:54 +0200573#ifdef CONFIG_SND_HDA_GENERIC
574#define is_generic_config(codec) \
Takashi Iwaif44ac832008-07-30 15:01:45 +0200575 (codec->modelname && !strcmp(codec->modelname, "generic"))
Takashi Iwai82467612007-07-27 19:15:54 +0200576#else
577#define is_generic_config(codec) 0
578#endif
579
Takashi Iwai645f10c2008-11-28 15:07:37 +0100580#ifdef MODULE
Takashi Iwai1289e9e2008-11-27 15:47:11 +0100581#define HDA_MODREQ_MAX_COUNT 2 /* two request_modules()'s */
582#else
Takashi Iwai645f10c2008-11-28 15:07:37 +0100583#define HDA_MODREQ_MAX_COUNT 0 /* all presets are statically linked */
Takashi Iwai1289e9e2008-11-27 15:47:11 +0100584#endif
585
Linus Torvalds1da177e2005-04-16 15:20:36 -0700586/*
587 * find a matching codec preset
588 */
Takashi Iwai6c1f45e2008-07-30 15:01:45 +0200589static const struct hda_codec_preset *
Takashi Iwai756e2b02007-04-16 11:27:07 +0200590find_codec_preset(struct hda_codec *codec)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700591{
Takashi Iwai1289e9e2008-11-27 15:47:11 +0100592 struct hda_codec_preset_list *tbl;
593 const struct hda_codec_preset *preset;
594 int mod_requested = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700595
Takashi Iwai82467612007-07-27 19:15:54 +0200596 if (is_generic_config(codec))
Takashi Iwaid5ad6302007-03-07 15:55:59 +0100597 return NULL; /* use the generic parser */
598
Takashi Iwai1289e9e2008-11-27 15:47:11 +0100599 again:
600 mutex_lock(&preset_mutex);
601 list_for_each_entry(tbl, &hda_preset_tables, list) {
602 if (!try_module_get(tbl->owner)) {
603 snd_printk(KERN_ERR "hda_codec: cannot module_get\n");
604 continue;
605 }
606 for (preset = tbl->preset; preset->id; preset++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700607 u32 mask = preset->mask;
Marc Boucherca7cfae2008-01-22 15:32:25 +0100608 if (preset->afg && preset->afg != codec->afg)
609 continue;
610 if (preset->mfg && preset->mfg != codec->mfg)
611 continue;
Takashi Iwai0ba21762007-04-16 11:29:14 +0200612 if (!mask)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700613 mask = ~0;
Takashi Iwai9c7f8522006-06-28 15:08:22 +0200614 if (preset->id == (codec->vendor_id & mask) &&
Takashi Iwai0ba21762007-04-16 11:29:14 +0200615 (!preset->rev ||
Takashi Iwai1289e9e2008-11-27 15:47:11 +0100616 preset->rev == codec->revision_id)) {
617 mutex_unlock(&preset_mutex);
618 codec->owner = tbl->owner;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700619 return preset;
Takashi Iwai1289e9e2008-11-27 15:47:11 +0100620 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700621 }
Takashi Iwai1289e9e2008-11-27 15:47:11 +0100622 module_put(tbl->owner);
623 }
624 mutex_unlock(&preset_mutex);
625
626 if (mod_requested < HDA_MODREQ_MAX_COUNT) {
627 char name[32];
628 if (!mod_requested)
629 snprintf(name, sizeof(name), "snd-hda-codec-id:%08x",
630 codec->vendor_id);
631 else
632 snprintf(name, sizeof(name), "snd-hda-codec-id:%04x*",
633 (codec->vendor_id >> 16) & 0xffff);
634 request_module(name);
635 mod_requested++;
636 goto again;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700637 }
638 return NULL;
639}
640
641/*
Takashi Iwaif44ac832008-07-30 15:01:45 +0200642 * get_codec_name - store the codec name
Linus Torvalds1da177e2005-04-16 15:20:36 -0700643 */
Takashi Iwaif44ac832008-07-30 15:01:45 +0200644static int get_codec_name(struct hda_codec *codec)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700645{
646 const struct hda_vendor_id *c;
647 const char *vendor = NULL;
648 u16 vendor_id = codec->vendor_id >> 16;
Takashi Iwai812a2cc2009-05-16 10:00:49 +0200649 char tmp[16];
650
651 if (codec->vendor_name)
652 goto get_chip_name;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700653
654 for (c = hda_vendor_ids; c->id; c++) {
655 if (c->id == vendor_id) {
656 vendor = c->name;
657 break;
658 }
659 }
Takashi Iwai0ba21762007-04-16 11:29:14 +0200660 if (!vendor) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700661 sprintf(tmp, "Generic %04x", vendor_id);
662 vendor = tmp;
663 }
Takashi Iwai812a2cc2009-05-16 10:00:49 +0200664 codec->vendor_name = kstrdup(vendor, GFP_KERNEL);
665 if (!codec->vendor_name)
666 return -ENOMEM;
667
668 get_chip_name:
669 if (codec->chip_name)
670 return 0;
671
Linus Torvalds1da177e2005-04-16 15:20:36 -0700672 if (codec->preset && codec->preset->name)
Takashi Iwai812a2cc2009-05-16 10:00:49 +0200673 codec->chip_name = kstrdup(codec->preset->name, GFP_KERNEL);
674 else {
675 sprintf(tmp, "ID %x", codec->vendor_id & 0xffff);
676 codec->chip_name = kstrdup(tmp, GFP_KERNEL);
677 }
678 if (!codec->chip_name)
Takashi Iwaif44ac832008-07-30 15:01:45 +0200679 return -ENOMEM;
680 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700681}
682
683/*
Sasha Khapyorsky673b6832005-08-11 11:00:16 +0200684 * look for an AFG and MFG nodes
Linus Torvalds1da177e2005-04-16 15:20:36 -0700685 */
Takashi Iwai1289e9e2008-11-27 15:47:11 +0100686static void /*__devinit*/ setup_fg_nodes(struct hda_codec *codec)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700687{
Takashi Iwai93e82ae2009-04-17 18:04:41 +0200688 int i, total_nodes, function_id;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700689 hda_nid_t nid;
690
691 total_nodes = snd_hda_get_sub_nodes(codec, AC_NODE_ROOT, &nid);
692 for (i = 0; i < total_nodes; i++, nid++) {
Takashi Iwai93e82ae2009-04-17 18:04:41 +0200693 function_id = snd_hda_param_read(codec, nid,
Pascal de Bruijn234b4342009-03-23 11:15:59 +0100694 AC_PAR_FUNCTION_TYPE) & 0xff;
Takashi Iwai93e82ae2009-04-17 18:04:41 +0200695 switch (function_id) {
Sasha Khapyorsky673b6832005-08-11 11:00:16 +0200696 case AC_GRP_AUDIO_FUNCTION:
697 codec->afg = nid;
Takashi Iwai93e82ae2009-04-17 18:04:41 +0200698 codec->function_id = function_id;
Sasha Khapyorsky673b6832005-08-11 11:00:16 +0200699 break;
700 case AC_GRP_MODEM_FUNCTION:
701 codec->mfg = nid;
Takashi Iwai93e82ae2009-04-17 18:04:41 +0200702 codec->function_id = function_id;
Sasha Khapyorsky673b6832005-08-11 11:00:16 +0200703 break;
704 default:
705 break;
706 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700707 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700708}
709
710/*
Takashi Iwai54d17402005-11-21 16:33:22 +0100711 * read widget caps for each widget and store in cache
712 */
713static int read_widget_caps(struct hda_codec *codec, hda_nid_t fg_node)
714{
715 int i;
716 hda_nid_t nid;
717
718 codec->num_nodes = snd_hda_get_sub_nodes(codec, fg_node,
719 &codec->start_nid);
720 codec->wcaps = kmalloc(codec->num_nodes * 4, GFP_KERNEL);
Takashi Iwai0ba21762007-04-16 11:29:14 +0200721 if (!codec->wcaps)
Takashi Iwai54d17402005-11-21 16:33:22 +0100722 return -ENOMEM;
723 nid = codec->start_nid;
724 for (i = 0; i < codec->num_nodes; i++, nid++)
725 codec->wcaps[i] = snd_hda_param_read(codec, nid,
726 AC_PAR_AUDIO_WIDGET_CAP);
727 return 0;
728}
729
Takashi Iwai3be14142009-02-20 14:11:16 +0100730/* read all pin default configurations and save codec->init_pins */
731static int read_pin_defaults(struct hda_codec *codec)
732{
733 int i;
734 hda_nid_t nid = codec->start_nid;
735
736 for (i = 0; i < codec->num_nodes; i++, nid++) {
737 struct hda_pincfg *pin;
738 unsigned int wcaps = get_wcaps(codec, nid);
739 unsigned int wid_type = (wcaps & AC_WCAP_TYPE) >>
740 AC_WCAP_TYPE_SHIFT;
741 if (wid_type != AC_WID_PIN)
742 continue;
743 pin = snd_array_new(&codec->init_pins);
744 if (!pin)
745 return -ENOMEM;
746 pin->nid = nid;
747 pin->cfg = snd_hda_codec_read(codec, nid, 0,
748 AC_VERB_GET_CONFIG_DEFAULT, 0);
749 }
750 return 0;
751}
752
753/* look up the given pin config list and return the item matching with NID */
754static struct hda_pincfg *look_up_pincfg(struct hda_codec *codec,
755 struct snd_array *array,
756 hda_nid_t nid)
757{
758 int i;
759 for (i = 0; i < array->used; i++) {
760 struct hda_pincfg *pin = snd_array_elem(array, i);
761 if (pin->nid == nid)
762 return pin;
763 }
764 return NULL;
765}
766
767/* write a config value for the given NID */
768static void set_pincfg(struct hda_codec *codec, hda_nid_t nid,
769 unsigned int cfg)
770{
771 int i;
772 for (i = 0; i < 4; i++) {
773 snd_hda_codec_write(codec, nid, 0,
774 AC_VERB_SET_CONFIG_DEFAULT_BYTES_0 + i,
775 cfg & 0xff);
776 cfg >>= 8;
777 }
778}
779
780/* set the current pin config value for the given NID.
781 * the value is cached, and read via snd_hda_codec_get_pincfg()
782 */
783int snd_hda_add_pincfg(struct hda_codec *codec, struct snd_array *list,
784 hda_nid_t nid, unsigned int cfg)
785{
786 struct hda_pincfg *pin;
Takashi Iwai5e7b8e02009-02-23 09:45:59 +0100787 unsigned int oldcfg;
Takashi Iwai3be14142009-02-20 14:11:16 +0100788
Takashi Iwai5e7b8e02009-02-23 09:45:59 +0100789 oldcfg = snd_hda_codec_get_pincfg(codec, nid);
Takashi Iwai3be14142009-02-20 14:11:16 +0100790 pin = look_up_pincfg(codec, list, nid);
791 if (!pin) {
792 pin = snd_array_new(list);
793 if (!pin)
794 return -ENOMEM;
795 pin->nid = nid;
796 }
797 pin->cfg = cfg;
Takashi Iwai5e7b8e02009-02-23 09:45:59 +0100798
799 /* change only when needed; e.g. if the pincfg is already present
800 * in user_pins[], don't write it
801 */
802 cfg = snd_hda_codec_get_pincfg(codec, nid);
803 if (oldcfg != cfg)
804 set_pincfg(codec, nid, cfg);
Takashi Iwai3be14142009-02-20 14:11:16 +0100805 return 0;
806}
807
808int snd_hda_codec_set_pincfg(struct hda_codec *codec,
809 hda_nid_t nid, unsigned int cfg)
810{
Takashi Iwai346ff702009-02-23 09:42:57 +0100811 return snd_hda_add_pincfg(codec, &codec->driver_pins, nid, cfg);
Takashi Iwai3be14142009-02-20 14:11:16 +0100812}
813EXPORT_SYMBOL_HDA(snd_hda_codec_set_pincfg);
814
815/* get the current pin config value of the given pin NID */
816unsigned int snd_hda_codec_get_pincfg(struct hda_codec *codec, hda_nid_t nid)
817{
818 struct hda_pincfg *pin;
819
Takashi Iwai3be14142009-02-20 14:11:16 +0100820#ifdef CONFIG_SND_HDA_HWDEP
Takashi Iwai346ff702009-02-23 09:42:57 +0100821 pin = look_up_pincfg(codec, &codec->user_pins, nid);
Takashi Iwai3be14142009-02-20 14:11:16 +0100822 if (pin)
823 return pin->cfg;
824#endif
Takashi Iwai5e7b8e02009-02-23 09:45:59 +0100825 pin = look_up_pincfg(codec, &codec->driver_pins, nid);
826 if (pin)
827 return pin->cfg;
Takashi Iwai3be14142009-02-20 14:11:16 +0100828 pin = look_up_pincfg(codec, &codec->init_pins, nid);
829 if (pin)
830 return pin->cfg;
831 return 0;
832}
833EXPORT_SYMBOL_HDA(snd_hda_codec_get_pincfg);
834
835/* restore all current pin configs */
836static void restore_pincfgs(struct hda_codec *codec)
837{
838 int i;
839 for (i = 0; i < codec->init_pins.used; i++) {
840 struct hda_pincfg *pin = snd_array_elem(&codec->init_pins, i);
841 set_pincfg(codec, pin->nid,
842 snd_hda_codec_get_pincfg(codec, pin->nid));
843 }
844}
Takashi Iwai54d17402005-11-21 16:33:22 +0100845
Takashi Iwai01751f52007-08-10 16:59:39 +0200846static void init_hda_cache(struct hda_cache_rec *cache,
847 unsigned int record_size);
Takashi Iwai1fcaee62007-08-23 00:01:09 +0200848static void free_hda_cache(struct hda_cache_rec *cache);
Takashi Iwai01751f52007-08-10 16:59:39 +0200849
Takashi Iwai3be14142009-02-20 14:11:16 +0100850/* restore the initial pin cfgs and release all pincfg lists */
851static void restore_init_pincfgs(struct hda_codec *codec)
852{
Takashi Iwai346ff702009-02-23 09:42:57 +0100853 /* first free driver_pins and user_pins, then call restore_pincfg
Takashi Iwai3be14142009-02-20 14:11:16 +0100854 * so that only the values in init_pins are restored
855 */
Takashi Iwai346ff702009-02-23 09:42:57 +0100856 snd_array_free(&codec->driver_pins);
Takashi Iwai3be14142009-02-20 14:11:16 +0100857#ifdef CONFIG_SND_HDA_HWDEP
Takashi Iwai346ff702009-02-23 09:42:57 +0100858 snd_array_free(&codec->user_pins);
Takashi Iwai3be14142009-02-20 14:11:16 +0100859#endif
860 restore_pincfgs(codec);
861 snd_array_free(&codec->init_pins);
862}
863
Takashi Iwai54d17402005-11-21 16:33:22 +0100864/*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700865 * codec destructor
866 */
867static void snd_hda_codec_free(struct hda_codec *codec)
868{
Takashi Iwai0ba21762007-04-16 11:29:14 +0200869 if (!codec)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700870 return;
Takashi Iwai3be14142009-02-20 14:11:16 +0100871 restore_init_pincfgs(codec);
Takashi Iwaicb53c622007-08-10 17:21:45 +0200872#ifdef CONFIG_SND_HDA_POWER_SAVE
873 cancel_delayed_work(&codec->power_work);
Takashi Iwai6acaed32009-01-12 10:09:24 +0100874 flush_workqueue(codec->bus->workq);
Takashi Iwaicb53c622007-08-10 17:21:45 +0200875#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700876 list_del(&codec->list);
Takashi Iwaid13bd412008-07-30 15:01:45 +0200877 snd_array_free(&codec->mixers);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700878 codec->bus->caddr_tbl[codec->addr] = NULL;
879 if (codec->patch_ops.free)
880 codec->patch_ops.free(codec);
Takashi Iwai1289e9e2008-11-27 15:47:11 +0100881 module_put(codec->owner);
Takashi Iwai01751f52007-08-10 16:59:39 +0200882 free_hda_cache(&codec->amp_cache);
Takashi Iwaib3ac5632007-08-10 17:03:40 +0200883 free_hda_cache(&codec->cmd_cache);
Takashi Iwai812a2cc2009-05-16 10:00:49 +0200884 kfree(codec->vendor_name);
885 kfree(codec->chip_name);
Takashi Iwaif44ac832008-07-30 15:01:45 +0200886 kfree(codec->modelname);
Takashi Iwai54d17402005-11-21 16:33:22 +0100887 kfree(codec->wcaps);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700888 kfree(codec);
889}
890
Takashi Iwaibb6ac722009-03-13 09:02:42 +0100891static void hda_set_power_state(struct hda_codec *codec, hda_nid_t fg,
892 unsigned int power_state);
893
Linus Torvalds1da177e2005-04-16 15:20:36 -0700894/**
895 * snd_hda_codec_new - create a HDA codec
896 * @bus: the bus to assign
897 * @codec_addr: the codec address
898 * @codecp: the pointer to store the generated codec
899 *
900 * Returns 0 if successful, or a negative error code.
901 */
Takashi Iwai1289e9e2008-11-27 15:47:11 +0100902int /*__devinit*/ snd_hda_codec_new(struct hda_bus *bus, unsigned int codec_addr,
Takashi Iwaia1e21c92009-06-17 09:33:52 +0200903 struct hda_codec **codecp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700904{
905 struct hda_codec *codec;
Jaroslav Kyselaba443682008-08-13 20:55:32 +0200906 char component[31];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700907 int err;
908
Takashi Iwaida3cec32008-08-08 17:12:14 +0200909 if (snd_BUG_ON(!bus))
910 return -EINVAL;
911 if (snd_BUG_ON(codec_addr > HDA_MAX_CODEC_ADDRESS))
912 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700913
914 if (bus->caddr_tbl[codec_addr]) {
Takashi Iwai0ba21762007-04-16 11:29:14 +0200915 snd_printk(KERN_ERR "hda_codec: "
916 "address 0x%x is already occupied\n", codec_addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700917 return -EBUSY;
918 }
919
Takashi Iwaie560d8d2005-09-09 14:21:46 +0200920 codec = kzalloc(sizeof(*codec), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700921 if (codec == NULL) {
922 snd_printk(KERN_ERR "can't allocate struct hda_codec\n");
923 return -ENOMEM;
924 }
925
926 codec->bus = bus;
927 codec->addr = codec_addr;
Ingo Molnar62932df2006-01-16 16:34:20 +0100928 mutex_init(&codec->spdif_mutex);
Wu Fengguang5a9e02e2009-01-09 16:45:24 +0800929 mutex_init(&codec->control_mutex);
Takashi Iwai01751f52007-08-10 16:59:39 +0200930 init_hda_cache(&codec->amp_cache, sizeof(struct hda_amp_info));
Takashi Iwaib3ac5632007-08-10 17:03:40 +0200931 init_hda_cache(&codec->cmd_cache, sizeof(struct hda_cache_head));
Takashi Iwaid13bd412008-07-30 15:01:45 +0200932 snd_array_init(&codec->mixers, sizeof(struct snd_kcontrol *), 32);
Takashi Iwai3be14142009-02-20 14:11:16 +0100933 snd_array_init(&codec->init_pins, sizeof(struct hda_pincfg), 16);
Takashi Iwai346ff702009-02-23 09:42:57 +0100934 snd_array_init(&codec->driver_pins, sizeof(struct hda_pincfg), 16);
Takashi Iwai6c1f45e2008-07-30 15:01:45 +0200935 if (codec->bus->modelname) {
936 codec->modelname = kstrdup(codec->bus->modelname, GFP_KERNEL);
937 if (!codec->modelname) {
938 snd_hda_codec_free(codec);
939 return -ENODEV;
940 }
941 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700942
Takashi Iwaicb53c622007-08-10 17:21:45 +0200943#ifdef CONFIG_SND_HDA_POWER_SAVE
944 INIT_DELAYED_WORK(&codec->power_work, hda_power_work);
945 /* snd_hda_codec_new() marks the codec as power-up, and leave it as is.
946 * the caller has to power down appropriatley after initialization
947 * phase.
948 */
949 hda_keep_power_on(codec);
950#endif
951
Linus Torvalds1da177e2005-04-16 15:20:36 -0700952 list_add_tail(&codec->list, &bus->codec_list);
953 bus->caddr_tbl[codec_addr] = codec;
954
Takashi Iwai0ba21762007-04-16 11:29:14 +0200955 codec->vendor_id = snd_hda_param_read(codec, AC_NODE_ROOT,
956 AC_PAR_VENDOR_ID);
Takashi Iwai111d3af2006-02-16 18:17:58 +0100957 if (codec->vendor_id == -1)
958 /* read again, hopefully the access method was corrected
959 * in the last read...
960 */
961 codec->vendor_id = snd_hda_param_read(codec, AC_NODE_ROOT,
962 AC_PAR_VENDOR_ID);
Takashi Iwai0ba21762007-04-16 11:29:14 +0200963 codec->subsystem_id = snd_hda_param_read(codec, AC_NODE_ROOT,
964 AC_PAR_SUBSYSTEM_ID);
965 codec->revision_id = snd_hda_param_read(codec, AC_NODE_ROOT,
966 AC_PAR_REV_ID);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700967
Sasha Khapyorsky673b6832005-08-11 11:00:16 +0200968 setup_fg_nodes(codec);
Takashi Iwai0ba21762007-04-16 11:29:14 +0200969 if (!codec->afg && !codec->mfg) {
Sasha Khapyorsky673b6832005-08-11 11:00:16 +0200970 snd_printdd("hda_codec: no AFG or MFG node found\n");
Takashi Iwai3be14142009-02-20 14:11:16 +0100971 err = -ENODEV;
972 goto error;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700973 }
974
Takashi Iwai3be14142009-02-20 14:11:16 +0100975 err = read_widget_caps(codec, codec->afg ? codec->afg : codec->mfg);
976 if (err < 0) {
Takashi Iwai54d17402005-11-21 16:33:22 +0100977 snd_printk(KERN_ERR "hda_codec: cannot malloc\n");
Takashi Iwai3be14142009-02-20 14:11:16 +0100978 goto error;
Takashi Iwai54d17402005-11-21 16:33:22 +0100979 }
Takashi Iwai3be14142009-02-20 14:11:16 +0100980 err = read_pin_defaults(codec);
981 if (err < 0)
982 goto error;
Takashi Iwai54d17402005-11-21 16:33:22 +0100983
Takashi Iwai0ba21762007-04-16 11:29:14 +0200984 if (!codec->subsystem_id) {
Takashi Iwai86284e42005-10-11 15:05:54 +0200985 hda_nid_t nid = codec->afg ? codec->afg : codec->mfg;
Takashi Iwai0ba21762007-04-16 11:29:14 +0200986 codec->subsystem_id =
987 snd_hda_codec_read(codec, nid, 0,
988 AC_VERB_GET_SUBSYSTEM_ID, 0);
Takashi Iwai86284e42005-10-11 15:05:54 +0200989 }
990
Takashi Iwaibb6ac722009-03-13 09:02:42 +0100991 /* power-up all before initialization */
992 hda_set_power_state(codec,
993 codec->afg ? codec->afg : codec->mfg,
994 AC_PWRST_D0);
995
Takashi Iwai6c1f45e2008-07-30 15:01:45 +0200996 snd_hda_codec_proc_new(codec);
997
Takashi Iwai6c1f45e2008-07-30 15:01:45 +0200998 snd_hda_create_hwdep(codec);
Takashi Iwai6c1f45e2008-07-30 15:01:45 +0200999
1000 sprintf(component, "HDA:%08x,%08x,%08x", codec->vendor_id,
1001 codec->subsystem_id, codec->revision_id);
1002 snd_component_add(codec->bus->card, component);
1003
1004 if (codecp)
1005 *codecp = codec;
1006 return 0;
Takashi Iwai3be14142009-02-20 14:11:16 +01001007
1008 error:
1009 snd_hda_codec_free(codec);
1010 return err;
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001011}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001012EXPORT_SYMBOL_HDA(snd_hda_codec_new);
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001013
1014int snd_hda_codec_configure(struct hda_codec *codec)
1015{
1016 int err;
1017
Takashi Iwaid5ad6302007-03-07 15:55:59 +01001018 codec->preset = find_codec_preset(codec);
Takashi Iwai812a2cc2009-05-16 10:00:49 +02001019 if (!codec->vendor_name || !codec->chip_name) {
Takashi Iwaif44ac832008-07-30 15:01:45 +02001020 err = get_codec_name(codec);
1021 if (err < 0)
1022 return err;
1023 }
Takashi Iwai43ea1d42007-04-26 19:12:08 +02001024 /* audio codec should override the mixer name */
Takashi Iwaif44ac832008-07-30 15:01:45 +02001025 if (codec->afg || !*codec->bus->card->mixername)
Takashi Iwai812a2cc2009-05-16 10:00:49 +02001026 snprintf(codec->bus->card->mixername,
1027 sizeof(codec->bus->card->mixername),
1028 "%s %s", codec->vendor_name, codec->chip_name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001029
Takashi Iwai82467612007-07-27 19:15:54 +02001030 if (is_generic_config(codec)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001031 err = snd_hda_parse_generic_codec(codec);
Takashi Iwai82467612007-07-27 19:15:54 +02001032 goto patched;
1033 }
Takashi Iwai82467612007-07-27 19:15:54 +02001034 if (codec->preset && codec->preset->patch) {
1035 err = codec->preset->patch(codec);
1036 goto patched;
1037 }
1038
1039 /* call the default parser */
Takashi Iwai82467612007-07-27 19:15:54 +02001040 err = snd_hda_parse_generic_codec(codec);
Takashi Iwai35a1e0c2007-10-19 08:13:40 +02001041 if (err < 0)
1042 printk(KERN_ERR "hda-codec: No codec parser is available\n");
Takashi Iwai82467612007-07-27 19:15:54 +02001043
1044 patched:
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001045 if (!err && codec->patch_ops.unsol_event)
1046 err = init_unsol_queue(codec->bus);
1047 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001048}
Takashi Iwaia1e21c92009-06-17 09:33:52 +02001049EXPORT_SYMBOL_HDA(snd_hda_codec_configure);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001050
1051/**
1052 * snd_hda_codec_setup_stream - set up the codec for streaming
1053 * @codec: the CODEC to set up
1054 * @nid: the NID to set up
1055 * @stream_tag: stream tag to pass, it's between 0x1 and 0xf.
1056 * @channel_id: channel id to pass, zero based.
1057 * @format: stream format.
1058 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02001059void snd_hda_codec_setup_stream(struct hda_codec *codec, hda_nid_t nid,
1060 u32 stream_tag,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001061 int channel_id, int format)
1062{
Takashi Iwai0ba21762007-04-16 11:29:14 +02001063 if (!nid)
Takashi Iwaid21b37e2005-04-20 13:45:55 +02001064 return;
1065
Takashi Iwai0ba21762007-04-16 11:29:14 +02001066 snd_printdd("hda_codec_setup_stream: "
1067 "NID=0x%x, stream=0x%x, channel=%d, format=0x%x\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07001068 nid, stream_tag, channel_id, format);
1069 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CHANNEL_STREAMID,
1070 (stream_tag << 4) | channel_id);
1071 msleep(1);
1072 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_STREAM_FORMAT, format);
1073}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001074EXPORT_SYMBOL_HDA(snd_hda_codec_setup_stream);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001075
Takashi Iwai888afa12008-03-18 09:57:50 +01001076void snd_hda_codec_cleanup_stream(struct hda_codec *codec, hda_nid_t nid)
1077{
1078 if (!nid)
1079 return;
1080
1081 snd_printdd("hda_codec_cleanup_stream: NID=0x%x\n", nid);
1082 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CHANNEL_STREAMID, 0);
1083#if 0 /* keep the format */
1084 msleep(1);
1085 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_STREAM_FORMAT, 0);
1086#endif
1087}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001088EXPORT_SYMBOL_HDA(snd_hda_codec_cleanup_stream);
Takashi Iwai888afa12008-03-18 09:57:50 +01001089
Linus Torvalds1da177e2005-04-16 15:20:36 -07001090/*
1091 * amp access functions
1092 */
1093
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001094/* FIXME: more better hash key? */
1095#define HDA_HASH_KEY(nid,dir,idx) (u32)((nid) + ((idx) << 16) + ((dir) << 24))
Takashi Iwai1327a322009-03-23 13:07:47 +01001096#define HDA_HASH_PINCAP_KEY(nid) (u32)((nid) + (0x02 << 24))
Takashi Iwai92c7c8a2009-03-24 07:32:14 +01001097#define HDA_HASH_PARPCM_KEY(nid) (u32)((nid) + (0x03 << 24))
1098#define HDA_HASH_PARSTR_KEY(nid) (u32)((nid) + (0x04 << 24))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001099#define INFO_AMP_CAPS (1<<0)
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001100#define INFO_AMP_VOL(ch) (1 << (1 + (ch)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001101
1102/* initialize the hash table */
Takashi Iwai1289e9e2008-11-27 15:47:11 +01001103static void /*__devinit*/ init_hda_cache(struct hda_cache_rec *cache,
Takashi Iwai01751f52007-08-10 16:59:39 +02001104 unsigned int record_size)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001105{
Takashi Iwai01751f52007-08-10 16:59:39 +02001106 memset(cache, 0, sizeof(*cache));
1107 memset(cache->hash, 0xff, sizeof(cache->hash));
Takashi Iwai603c4012008-07-30 15:01:44 +02001108 snd_array_init(&cache->buf, record_size, 64);
Takashi Iwai01751f52007-08-10 16:59:39 +02001109}
1110
Takashi Iwai1fcaee62007-08-23 00:01:09 +02001111static void free_hda_cache(struct hda_cache_rec *cache)
Takashi Iwai01751f52007-08-10 16:59:39 +02001112{
Takashi Iwai603c4012008-07-30 15:01:44 +02001113 snd_array_free(&cache->buf);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001114}
1115
1116/* query the hash. allocate an entry if not found. */
Takashi Iwai01751f52007-08-10 16:59:39 +02001117static struct hda_cache_head *get_alloc_hash(struct hda_cache_rec *cache,
1118 u32 key)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001119{
Takashi Iwai01751f52007-08-10 16:59:39 +02001120 u16 idx = key % (u16)ARRAY_SIZE(cache->hash);
1121 u16 cur = cache->hash[idx];
1122 struct hda_cache_head *info;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001123
1124 while (cur != 0xffff) {
Takashi Iwaif43aa022008-11-10 16:24:26 +01001125 info = snd_array_elem(&cache->buf, cur);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001126 if (info->key == key)
1127 return info;
1128 cur = info->next;
1129 }
1130
1131 /* add a new hash entry */
Takashi Iwai603c4012008-07-30 15:01:44 +02001132 info = snd_array_new(&cache->buf);
Takashi Iwaic2174292008-11-07 00:23:30 +01001133 if (!info)
1134 return NULL;
Takashi Iwaif43aa022008-11-10 16:24:26 +01001135 cur = snd_array_index(&cache->buf, info);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001136 info->key = key;
Takashi Iwai01751f52007-08-10 16:59:39 +02001137 info->val = 0;
1138 info->next = cache->hash[idx];
1139 cache->hash[idx] = cur;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001140
1141 return info;
1142}
1143
Takashi Iwai01751f52007-08-10 16:59:39 +02001144/* query and allocate an amp hash entry */
1145static inline struct hda_amp_info *
1146get_alloc_amp_hash(struct hda_codec *codec, u32 key)
1147{
1148 return (struct hda_amp_info *)get_alloc_hash(&codec->amp_cache, key);
1149}
1150
Linus Torvalds1da177e2005-04-16 15:20:36 -07001151/*
1152 * query AMP capabilities for the given widget and direction
1153 */
Matthew Ranostay09a99952008-01-24 11:49:21 +01001154u32 query_amp_caps(struct hda_codec *codec, hda_nid_t nid, int direction)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001155{
Takashi Iwai0ba21762007-04-16 11:29:14 +02001156 struct hda_amp_info *info;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001157
Takashi Iwai0ba21762007-04-16 11:29:14 +02001158 info = get_alloc_amp_hash(codec, HDA_HASH_KEY(nid, direction, 0));
1159 if (!info)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001160 return 0;
Takashi Iwai01751f52007-08-10 16:59:39 +02001161 if (!(info->head.val & INFO_AMP_CAPS)) {
Takashi Iwai0ba21762007-04-16 11:29:14 +02001162 if (!(get_wcaps(codec, nid) & AC_WCAP_AMP_OVRD))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001163 nid = codec->afg;
Takashi Iwai0ba21762007-04-16 11:29:14 +02001164 info->amp_caps = snd_hda_param_read(codec, nid,
1165 direction == HDA_OUTPUT ?
1166 AC_PAR_AMP_OUT_CAP :
1167 AC_PAR_AMP_IN_CAP);
Takashi Iwaib75e53f2007-05-10 16:56:09 +02001168 if (info->amp_caps)
Takashi Iwai01751f52007-08-10 16:59:39 +02001169 info->head.val |= INFO_AMP_CAPS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001170 }
1171 return info->amp_caps;
1172}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001173EXPORT_SYMBOL_HDA(query_amp_caps);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001174
Takashi Iwai897cc182007-05-29 19:01:37 +02001175int snd_hda_override_amp_caps(struct hda_codec *codec, hda_nid_t nid, int dir,
1176 unsigned int caps)
1177{
1178 struct hda_amp_info *info;
1179
1180 info = get_alloc_amp_hash(codec, HDA_HASH_KEY(nid, dir, 0));
1181 if (!info)
1182 return -EINVAL;
1183 info->amp_caps = caps;
Takashi Iwai01751f52007-08-10 16:59:39 +02001184 info->head.val |= INFO_AMP_CAPS;
Takashi Iwai897cc182007-05-29 19:01:37 +02001185 return 0;
1186}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001187EXPORT_SYMBOL_HDA(snd_hda_override_amp_caps);
Takashi Iwai897cc182007-05-29 19:01:37 +02001188
Takashi Iwai92c7c8a2009-03-24 07:32:14 +01001189static unsigned int
1190query_caps_hash(struct hda_codec *codec, hda_nid_t nid, u32 key,
1191 unsigned int (*func)(struct hda_codec *, hda_nid_t))
Takashi Iwai1327a322009-03-23 13:07:47 +01001192{
1193 struct hda_amp_info *info;
1194
Takashi Iwai92c7c8a2009-03-24 07:32:14 +01001195 info = get_alloc_amp_hash(codec, key);
Takashi Iwai1327a322009-03-23 13:07:47 +01001196 if (!info)
1197 return 0;
1198 if (!info->head.val) {
Takashi Iwai1327a322009-03-23 13:07:47 +01001199 info->head.val |= INFO_AMP_CAPS;
Takashi Iwai92c7c8a2009-03-24 07:32:14 +01001200 info->amp_caps = func(codec, nid);
Takashi Iwai1327a322009-03-23 13:07:47 +01001201 }
1202 return info->amp_caps;
1203}
Takashi Iwai92c7c8a2009-03-24 07:32:14 +01001204
1205static unsigned int read_pin_cap(struct hda_codec *codec, hda_nid_t nid)
1206{
1207 return snd_hda_param_read(codec, nid, AC_PAR_PIN_CAP);
1208}
1209
1210u32 snd_hda_query_pin_caps(struct hda_codec *codec, hda_nid_t nid)
1211{
1212 return query_caps_hash(codec, nid, HDA_HASH_PINCAP_KEY(nid),
1213 read_pin_cap);
1214}
Takashi Iwai1327a322009-03-23 13:07:47 +01001215EXPORT_SYMBOL_HDA(snd_hda_query_pin_caps);
1216
Linus Torvalds1da177e2005-04-16 15:20:36 -07001217/*
1218 * read the current volume to info
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001219 * if the cache exists, read the cache value.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001220 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02001221static unsigned int get_vol_mute(struct hda_codec *codec,
1222 struct hda_amp_info *info, hda_nid_t nid,
1223 int ch, int direction, int index)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001224{
1225 u32 val, parm;
1226
Takashi Iwai01751f52007-08-10 16:59:39 +02001227 if (info->head.val & INFO_AMP_VOL(ch))
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001228 return info->vol[ch];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001229
1230 parm = ch ? AC_AMP_GET_RIGHT : AC_AMP_GET_LEFT;
1231 parm |= direction == HDA_OUTPUT ? AC_AMP_GET_OUTPUT : AC_AMP_GET_INPUT;
1232 parm |= index;
Takashi Iwai0ba21762007-04-16 11:29:14 +02001233 val = snd_hda_codec_read(codec, nid, 0,
1234 AC_VERB_GET_AMP_GAIN_MUTE, parm);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001235 info->vol[ch] = val & 0xff;
Takashi Iwai01751f52007-08-10 16:59:39 +02001236 info->head.val |= INFO_AMP_VOL(ch);
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001237 return info->vol[ch];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001238}
1239
1240/*
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001241 * write the current volume in info to the h/w and update the cache
Linus Torvalds1da177e2005-04-16 15:20:36 -07001242 */
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001243static void put_vol_mute(struct hda_codec *codec, struct hda_amp_info *info,
Takashi Iwai0ba21762007-04-16 11:29:14 +02001244 hda_nid_t nid, int ch, int direction, int index,
1245 int val)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001246{
1247 u32 parm;
1248
1249 parm = ch ? AC_AMP_SET_RIGHT : AC_AMP_SET_LEFT;
1250 parm |= direction == HDA_OUTPUT ? AC_AMP_SET_OUTPUT : AC_AMP_SET_INPUT;
1251 parm |= index << AC_AMP_SET_INDEX_SHIFT;
1252 parm |= val;
1253 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, parm);
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001254 info->vol[ch] = val;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001255}
1256
1257/*
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001258 * read AMP value. The volume is between 0 to 0x7f, 0x80 = mute bit.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001259 */
Takashi Iwai834be882006-03-01 14:16:17 +01001260int snd_hda_codec_amp_read(struct hda_codec *codec, hda_nid_t nid, int ch,
1261 int direction, int index)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001262{
Takashi Iwai0ba21762007-04-16 11:29:14 +02001263 struct hda_amp_info *info;
1264 info = get_alloc_amp_hash(codec, HDA_HASH_KEY(nid, direction, index));
1265 if (!info)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001266 return 0;
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001267 return get_vol_mute(codec, info, nid, ch, direction, index);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001268}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001269EXPORT_SYMBOL_HDA(snd_hda_codec_amp_read);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001270
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001271/*
1272 * update the AMP value, mask = bit mask to set, val = the value
1273 */
Takashi Iwai834be882006-03-01 14:16:17 +01001274int snd_hda_codec_amp_update(struct hda_codec *codec, hda_nid_t nid, int ch,
1275 int direction, int idx, int mask, int val)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001276{
Takashi Iwai0ba21762007-04-16 11:29:14 +02001277 struct hda_amp_info *info;
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001278
Takashi Iwai0ba21762007-04-16 11:29:14 +02001279 info = get_alloc_amp_hash(codec, HDA_HASH_KEY(nid, direction, idx));
1280 if (!info)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001281 return 0;
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001282 val &= mask;
1283 val |= get_vol_mute(codec, info, nid, ch, direction, idx) & ~mask;
Takashi Iwai82beb8f2007-08-10 17:09:26 +02001284 if (info->vol[ch] == val)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001285 return 0;
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001286 put_vol_mute(codec, info, nid, ch, direction, idx, val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001287 return 1;
1288}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001289EXPORT_SYMBOL_HDA(snd_hda_codec_amp_update);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001290
Takashi Iwai47fd8302007-08-10 17:11:07 +02001291/*
1292 * update the AMP stereo with the same mask and value
1293 */
1294int snd_hda_codec_amp_stereo(struct hda_codec *codec, hda_nid_t nid,
1295 int direction, int idx, int mask, int val)
1296{
1297 int ch, ret = 0;
1298 for (ch = 0; ch < 2; ch++)
1299 ret |= snd_hda_codec_amp_update(codec, nid, ch, direction,
1300 idx, mask, val);
1301 return ret;
1302}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001303EXPORT_SYMBOL_HDA(snd_hda_codec_amp_stereo);
Takashi Iwai47fd8302007-08-10 17:11:07 +02001304
Takashi Iwaicb53c622007-08-10 17:21:45 +02001305#ifdef SND_HDA_NEEDS_RESUME
Takashi Iwaib3ac5632007-08-10 17:03:40 +02001306/* resume the all amp commands from the cache */
1307void snd_hda_codec_resume_amp(struct hda_codec *codec)
1308{
Takashi Iwai603c4012008-07-30 15:01:44 +02001309 struct hda_amp_info *buffer = codec->amp_cache.buf.list;
Takashi Iwaib3ac5632007-08-10 17:03:40 +02001310 int i;
1311
Takashi Iwai603c4012008-07-30 15:01:44 +02001312 for (i = 0; i < codec->amp_cache.buf.used; i++, buffer++) {
Takashi Iwaib3ac5632007-08-10 17:03:40 +02001313 u32 key = buffer->head.key;
1314 hda_nid_t nid;
1315 unsigned int idx, dir, ch;
1316 if (!key)
1317 continue;
1318 nid = key & 0xff;
1319 idx = (key >> 16) & 0xff;
1320 dir = (key >> 24) & 0xff;
1321 for (ch = 0; ch < 2; ch++) {
1322 if (!(buffer->head.val & INFO_AMP_VOL(ch)))
1323 continue;
1324 put_vol_mute(codec, buffer, nid, ch, dir, idx,
1325 buffer->vol[ch]);
1326 }
1327 }
1328}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001329EXPORT_SYMBOL_HDA(snd_hda_codec_resume_amp);
Takashi Iwaicb53c622007-08-10 17:21:45 +02001330#endif /* SND_HDA_NEEDS_RESUME */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001331
Linus Torvalds1da177e2005-04-16 15:20:36 -07001332/* volume */
Takashi Iwai0ba21762007-04-16 11:29:14 +02001333int snd_hda_mixer_amp_volume_info(struct snd_kcontrol *kcontrol,
1334 struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001335{
1336 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1337 u16 nid = get_amp_nid(kcontrol);
1338 u8 chs = get_amp_channels(kcontrol);
1339 int dir = get_amp_direction(kcontrol);
Takashi Iwai29fdbec2009-01-20 13:07:55 +01001340 unsigned int ofs = get_amp_offset(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001341 u32 caps;
1342
1343 caps = query_amp_caps(codec, nid, dir);
Takashi Iwai0ba21762007-04-16 11:29:14 +02001344 /* num steps */
1345 caps = (caps & AC_AMPCAP_NUM_STEPS) >> AC_AMPCAP_NUM_STEPS_SHIFT;
1346 if (!caps) {
1347 printk(KERN_WARNING "hda_codec: "
Takashi Iwai9c8f2ab2008-01-11 16:12:23 +01001348 "num_steps = 0 for NID=0x%x (ctl = %s)\n", nid,
1349 kcontrol->id.name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001350 return -EINVAL;
1351 }
Takashi Iwai29fdbec2009-01-20 13:07:55 +01001352 if (ofs < caps)
1353 caps -= ofs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001354 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
1355 uinfo->count = chs == 3 ? 2 : 1;
1356 uinfo->value.integer.min = 0;
1357 uinfo->value.integer.max = caps;
1358 return 0;
1359}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001360EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_volume_info);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001361
Takashi Iwai29fdbec2009-01-20 13:07:55 +01001362
1363static inline unsigned int
1364read_amp_value(struct hda_codec *codec, hda_nid_t nid,
1365 int ch, int dir, int idx, unsigned int ofs)
1366{
1367 unsigned int val;
1368 val = snd_hda_codec_amp_read(codec, nid, ch, dir, idx);
1369 val &= HDA_AMP_VOLMASK;
1370 if (val >= ofs)
1371 val -= ofs;
1372 else
1373 val = 0;
1374 return val;
1375}
1376
1377static inline int
1378update_amp_value(struct hda_codec *codec, hda_nid_t nid,
1379 int ch, int dir, int idx, unsigned int ofs,
1380 unsigned int val)
1381{
1382 if (val > 0)
1383 val += ofs;
1384 return snd_hda_codec_amp_update(codec, nid, ch, dir, idx,
1385 HDA_AMP_VOLMASK, val);
1386}
1387
Takashi Iwai0ba21762007-04-16 11:29:14 +02001388int snd_hda_mixer_amp_volume_get(struct snd_kcontrol *kcontrol,
1389 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001390{
1391 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1392 hda_nid_t nid = get_amp_nid(kcontrol);
1393 int chs = get_amp_channels(kcontrol);
1394 int dir = get_amp_direction(kcontrol);
1395 int idx = get_amp_index(kcontrol);
Takashi Iwai29fdbec2009-01-20 13:07:55 +01001396 unsigned int ofs = get_amp_offset(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001397 long *valp = ucontrol->value.integer.value;
1398
1399 if (chs & 1)
Takashi Iwai29fdbec2009-01-20 13:07:55 +01001400 *valp++ = read_amp_value(codec, nid, 0, dir, idx, ofs);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001401 if (chs & 2)
Takashi Iwai29fdbec2009-01-20 13:07:55 +01001402 *valp = read_amp_value(codec, nid, 1, dir, idx, ofs);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001403 return 0;
1404}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001405EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_volume_get);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001406
Takashi Iwai0ba21762007-04-16 11:29:14 +02001407int snd_hda_mixer_amp_volume_put(struct snd_kcontrol *kcontrol,
1408 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001409{
1410 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1411 hda_nid_t nid = get_amp_nid(kcontrol);
1412 int chs = get_amp_channels(kcontrol);
1413 int dir = get_amp_direction(kcontrol);
1414 int idx = get_amp_index(kcontrol);
Takashi Iwai29fdbec2009-01-20 13:07:55 +01001415 unsigned int ofs = get_amp_offset(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001416 long *valp = ucontrol->value.integer.value;
1417 int change = 0;
1418
Takashi Iwaicb53c622007-08-10 17:21:45 +02001419 snd_hda_power_up(codec);
Nicolas Grazianob9f5a892005-07-29 12:17:20 +02001420 if (chs & 1) {
Takashi Iwai29fdbec2009-01-20 13:07:55 +01001421 change = update_amp_value(codec, nid, 0, dir, idx, ofs, *valp);
Nicolas Grazianob9f5a892005-07-29 12:17:20 +02001422 valp++;
1423 }
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001424 if (chs & 2)
Takashi Iwai29fdbec2009-01-20 13:07:55 +01001425 change |= update_amp_value(codec, nid, 1, dir, idx, ofs, *valp);
Takashi Iwaicb53c622007-08-10 17:21:45 +02001426 snd_hda_power_down(codec);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001427 return change;
1428}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001429EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_volume_put);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001430
Jaroslav Kysela302e9c52006-07-05 17:39:49 +02001431int snd_hda_mixer_amp_tlv(struct snd_kcontrol *kcontrol, int op_flag,
1432 unsigned int size, unsigned int __user *_tlv)
1433{
1434 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1435 hda_nid_t nid = get_amp_nid(kcontrol);
1436 int dir = get_amp_direction(kcontrol);
Takashi Iwai29fdbec2009-01-20 13:07:55 +01001437 unsigned int ofs = get_amp_offset(kcontrol);
Jaroslav Kysela302e9c52006-07-05 17:39:49 +02001438 u32 caps, val1, val2;
1439
1440 if (size < 4 * sizeof(unsigned int))
1441 return -ENOMEM;
1442 caps = query_amp_caps(codec, nid, dir);
Takashi Iwai0ba21762007-04-16 11:29:14 +02001443 val2 = (caps & AC_AMPCAP_STEP_SIZE) >> AC_AMPCAP_STEP_SIZE_SHIFT;
1444 val2 = (val2 + 1) * 25;
Jaroslav Kysela302e9c52006-07-05 17:39:49 +02001445 val1 = -((caps & AC_AMPCAP_OFFSET) >> AC_AMPCAP_OFFSET_SHIFT);
Takashi Iwai29fdbec2009-01-20 13:07:55 +01001446 val1 += ofs;
Jaroslav Kysela302e9c52006-07-05 17:39:49 +02001447 val1 = ((int)val1) * ((int)val2);
Jaroslav Kysela302e9c52006-07-05 17:39:49 +02001448 if (put_user(SNDRV_CTL_TLVT_DB_SCALE, _tlv))
1449 return -EFAULT;
1450 if (put_user(2 * sizeof(unsigned int), _tlv + 1))
1451 return -EFAULT;
1452 if (put_user(val1, _tlv + 2))
1453 return -EFAULT;
1454 if (put_user(val2, _tlv + 3))
1455 return -EFAULT;
1456 return 0;
1457}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001458EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_tlv);
Jaroslav Kysela302e9c52006-07-05 17:39:49 +02001459
Takashi Iwai2134ea42008-01-10 16:53:55 +01001460/*
1461 * set (static) TLV for virtual master volume; recalculated as max 0dB
1462 */
1463void snd_hda_set_vmaster_tlv(struct hda_codec *codec, hda_nid_t nid, int dir,
1464 unsigned int *tlv)
1465{
1466 u32 caps;
1467 int nums, step;
1468
1469 caps = query_amp_caps(codec, nid, dir);
1470 nums = (caps & AC_AMPCAP_NUM_STEPS) >> AC_AMPCAP_NUM_STEPS_SHIFT;
1471 step = (caps & AC_AMPCAP_STEP_SIZE) >> AC_AMPCAP_STEP_SIZE_SHIFT;
1472 step = (step + 1) * 25;
1473 tlv[0] = SNDRV_CTL_TLVT_DB_SCALE;
1474 tlv[1] = 2 * sizeof(unsigned int);
1475 tlv[2] = -nums * step;
1476 tlv[3] = step;
1477}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001478EXPORT_SYMBOL_HDA(snd_hda_set_vmaster_tlv);
Takashi Iwai2134ea42008-01-10 16:53:55 +01001479
1480/* find a mixer control element with the given name */
Takashi Iwai09f99702008-02-04 12:31:13 +01001481static struct snd_kcontrol *
1482_snd_hda_find_mixer_ctl(struct hda_codec *codec,
1483 const char *name, int idx)
Takashi Iwai2134ea42008-01-10 16:53:55 +01001484{
1485 struct snd_ctl_elem_id id;
1486 memset(&id, 0, sizeof(id));
1487 id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
Takashi Iwai09f99702008-02-04 12:31:13 +01001488 id.index = idx;
Takashi Iwai18cb7102009-04-16 10:22:24 +02001489 if (snd_BUG_ON(strlen(name) >= sizeof(id.name)))
1490 return NULL;
Takashi Iwai2134ea42008-01-10 16:53:55 +01001491 strcpy(id.name, name);
1492 return snd_ctl_find_id(codec->bus->card, &id);
1493}
1494
Takashi Iwai09f99702008-02-04 12:31:13 +01001495struct snd_kcontrol *snd_hda_find_mixer_ctl(struct hda_codec *codec,
1496 const char *name)
1497{
1498 return _snd_hda_find_mixer_ctl(codec, name, 0);
1499}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001500EXPORT_SYMBOL_HDA(snd_hda_find_mixer_ctl);
Takashi Iwai09f99702008-02-04 12:31:13 +01001501
Takashi Iwaid13bd412008-07-30 15:01:45 +02001502/* Add a control element and assign to the codec */
1503int snd_hda_ctl_add(struct hda_codec *codec, struct snd_kcontrol *kctl)
1504{
1505 int err;
1506 struct snd_kcontrol **knewp;
1507
1508 err = snd_ctl_add(codec->bus->card, kctl);
1509 if (err < 0)
1510 return err;
1511 knewp = snd_array_new(&codec->mixers);
1512 if (!knewp)
1513 return -ENOMEM;
1514 *knewp = kctl;
1515 return 0;
1516}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001517EXPORT_SYMBOL_HDA(snd_hda_ctl_add);
Takashi Iwaid13bd412008-07-30 15:01:45 +02001518
1519/* Clear all controls assigned to the given codec */
1520void snd_hda_ctls_clear(struct hda_codec *codec)
1521{
1522 int i;
1523 struct snd_kcontrol **kctls = codec->mixers.list;
1524 for (i = 0; i < codec->mixers.used; i++)
1525 snd_ctl_remove(codec->bus->card, kctls[i]);
1526 snd_array_free(&codec->mixers);
1527}
1528
Takashi Iwaia65d6292009-02-23 16:57:04 +01001529/* pseudo device locking
1530 * toggle card->shutdown to allow/disallow the device access (as a hack)
1531 */
1532static int hda_lock_devices(struct snd_card *card)
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001533{
Takashi Iwaia65d6292009-02-23 16:57:04 +01001534 spin_lock(&card->files_lock);
1535 if (card->shutdown) {
1536 spin_unlock(&card->files_lock);
1537 return -EINVAL;
1538 }
1539 card->shutdown = 1;
1540 spin_unlock(&card->files_lock);
1541 return 0;
1542}
1543
1544static void hda_unlock_devices(struct snd_card *card)
1545{
1546 spin_lock(&card->files_lock);
1547 card->shutdown = 0;
1548 spin_unlock(&card->files_lock);
1549}
1550
1551int snd_hda_codec_reset(struct hda_codec *codec)
1552{
1553 struct snd_card *card = codec->bus->card;
1554 int i, pcm;
1555
1556 if (hda_lock_devices(card) < 0)
1557 return -EBUSY;
1558 /* check whether the codec isn't used by any mixer or PCM streams */
1559 if (!list_empty(&card->ctl_files)) {
1560 hda_unlock_devices(card);
1561 return -EBUSY;
1562 }
1563 for (pcm = 0; pcm < codec->num_pcms; pcm++) {
1564 struct hda_pcm *cpcm = &codec->pcm_info[pcm];
1565 if (!cpcm->pcm)
1566 continue;
1567 if (cpcm->pcm->streams[0].substream_opened ||
1568 cpcm->pcm->streams[1].substream_opened) {
1569 hda_unlock_devices(card);
1570 return -EBUSY;
1571 }
1572 }
1573
1574 /* OK, let it free */
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001575
1576#ifdef CONFIG_SND_HDA_POWER_SAVE
1577 cancel_delayed_work(&codec->power_work);
Takashi Iwai6acaed32009-01-12 10:09:24 +01001578 flush_workqueue(codec->bus->workq);
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001579#endif
1580 snd_hda_ctls_clear(codec);
1581 /* relase PCMs */
1582 for (i = 0; i < codec->num_pcms; i++) {
Takashi Iwai529bd6c2008-11-27 14:17:01 +01001583 if (codec->pcm_info[i].pcm) {
Takashi Iwaia65d6292009-02-23 16:57:04 +01001584 snd_device_free(card, codec->pcm_info[i].pcm);
Takashi Iwai529bd6c2008-11-27 14:17:01 +01001585 clear_bit(codec->pcm_info[i].device,
1586 codec->bus->pcm_dev_bits);
1587 }
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001588 }
1589 if (codec->patch_ops.free)
1590 codec->patch_ops.free(codec);
Takashi Iwai56d17712008-11-28 14:36:23 +01001591 codec->proc_widget_hook = NULL;
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001592 codec->spec = NULL;
1593 free_hda_cache(&codec->amp_cache);
1594 free_hda_cache(&codec->cmd_cache);
Takashi Iwai827057f2008-12-19 10:12:02 +01001595 init_hda_cache(&codec->amp_cache, sizeof(struct hda_amp_info));
1596 init_hda_cache(&codec->cmd_cache, sizeof(struct hda_cache_head));
Takashi Iwai346ff702009-02-23 09:42:57 +01001597 /* free only driver_pins so that init_pins + user_pins are restored */
1598 snd_array_free(&codec->driver_pins);
Takashi Iwai3be14142009-02-20 14:11:16 +01001599 restore_pincfgs(codec);
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001600 codec->num_pcms = 0;
1601 codec->pcm_info = NULL;
1602 codec->preset = NULL;
Takashi Iwaid1f1af22009-03-02 10:35:29 +01001603 memset(&codec->patch_ops, 0, sizeof(codec->patch_ops));
1604 codec->slave_dig_outs = NULL;
1605 codec->spdif_status_reset = 0;
Takashi Iwai1289e9e2008-11-27 15:47:11 +01001606 module_put(codec->owner);
1607 codec->owner = NULL;
Takashi Iwaia65d6292009-02-23 16:57:04 +01001608
1609 /* allow device access again */
1610 hda_unlock_devices(card);
1611 return 0;
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001612}
1613
Takashi Iwai2134ea42008-01-10 16:53:55 +01001614/* create a virtual master control and add slaves */
1615int snd_hda_add_vmaster(struct hda_codec *codec, char *name,
1616 unsigned int *tlv, const char **slaves)
1617{
1618 struct snd_kcontrol *kctl;
1619 const char **s;
1620 int err;
1621
Takashi Iwai2f085542008-02-22 18:43:50 +01001622 for (s = slaves; *s && !snd_hda_find_mixer_ctl(codec, *s); s++)
1623 ;
1624 if (!*s) {
1625 snd_printdd("No slave found for %s\n", name);
1626 return 0;
1627 }
Takashi Iwai2134ea42008-01-10 16:53:55 +01001628 kctl = snd_ctl_make_virtual_master(name, tlv);
1629 if (!kctl)
1630 return -ENOMEM;
Takashi Iwaid13bd412008-07-30 15:01:45 +02001631 err = snd_hda_ctl_add(codec, kctl);
Takashi Iwai2134ea42008-01-10 16:53:55 +01001632 if (err < 0)
1633 return err;
1634
1635 for (s = slaves; *s; s++) {
1636 struct snd_kcontrol *sctl;
Takashi Iwai7a411ee2009-03-06 10:08:14 +01001637 int i = 0;
1638 for (;;) {
1639 sctl = _snd_hda_find_mixer_ctl(codec, *s, i);
1640 if (!sctl) {
1641 if (!i)
1642 snd_printdd("Cannot find slave %s, "
1643 "skipped\n", *s);
1644 break;
1645 }
1646 err = snd_ctl_add_slave(kctl, sctl);
1647 if (err < 0)
1648 return err;
1649 i++;
Takashi Iwai2134ea42008-01-10 16:53:55 +01001650 }
Takashi Iwai2134ea42008-01-10 16:53:55 +01001651 }
1652 return 0;
1653}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001654EXPORT_SYMBOL_HDA(snd_hda_add_vmaster);
Takashi Iwai2134ea42008-01-10 16:53:55 +01001655
Linus Torvalds1da177e2005-04-16 15:20:36 -07001656/* switch */
Takashi Iwai0ba21762007-04-16 11:29:14 +02001657int snd_hda_mixer_amp_switch_info(struct snd_kcontrol *kcontrol,
1658 struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001659{
1660 int chs = get_amp_channels(kcontrol);
1661
1662 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
1663 uinfo->count = chs == 3 ? 2 : 1;
1664 uinfo->value.integer.min = 0;
1665 uinfo->value.integer.max = 1;
1666 return 0;
1667}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001668EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_switch_info);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001669
Takashi Iwai0ba21762007-04-16 11:29:14 +02001670int snd_hda_mixer_amp_switch_get(struct snd_kcontrol *kcontrol,
1671 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001672{
1673 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1674 hda_nid_t nid = get_amp_nid(kcontrol);
1675 int chs = get_amp_channels(kcontrol);
1676 int dir = get_amp_direction(kcontrol);
1677 int idx = get_amp_index(kcontrol);
1678 long *valp = ucontrol->value.integer.value;
1679
1680 if (chs & 1)
Takashi Iwai0ba21762007-04-16 11:29:14 +02001681 *valp++ = (snd_hda_codec_amp_read(codec, nid, 0, dir, idx) &
Takashi Iwai47fd8302007-08-10 17:11:07 +02001682 HDA_AMP_MUTE) ? 0 : 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001683 if (chs & 2)
Takashi Iwai0ba21762007-04-16 11:29:14 +02001684 *valp = (snd_hda_codec_amp_read(codec, nid, 1, dir, idx) &
Takashi Iwai47fd8302007-08-10 17:11:07 +02001685 HDA_AMP_MUTE) ? 0 : 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001686 return 0;
1687}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001688EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_switch_get);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001689
Takashi Iwai0ba21762007-04-16 11:29:14 +02001690int snd_hda_mixer_amp_switch_put(struct snd_kcontrol *kcontrol,
1691 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001692{
1693 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1694 hda_nid_t nid = get_amp_nid(kcontrol);
1695 int chs = get_amp_channels(kcontrol);
1696 int dir = get_amp_direction(kcontrol);
1697 int idx = get_amp_index(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001698 long *valp = ucontrol->value.integer.value;
1699 int change = 0;
1700
Takashi Iwaicb53c622007-08-10 17:21:45 +02001701 snd_hda_power_up(codec);
Nicolas Grazianob9f5a892005-07-29 12:17:20 +02001702 if (chs & 1) {
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001703 change = snd_hda_codec_amp_update(codec, nid, 0, dir, idx,
Takashi Iwai47fd8302007-08-10 17:11:07 +02001704 HDA_AMP_MUTE,
1705 *valp ? 0 : HDA_AMP_MUTE);
Nicolas Grazianob9f5a892005-07-29 12:17:20 +02001706 valp++;
1707 }
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001708 if (chs & 2)
1709 change |= snd_hda_codec_amp_update(codec, nid, 1, dir, idx,
Takashi Iwai47fd8302007-08-10 17:11:07 +02001710 HDA_AMP_MUTE,
1711 *valp ? 0 : HDA_AMP_MUTE);
Takashi Iwaicb53c622007-08-10 17:21:45 +02001712#ifdef CONFIG_SND_HDA_POWER_SAVE
1713 if (codec->patch_ops.check_power_status)
1714 codec->patch_ops.check_power_status(codec, nid);
1715#endif
1716 snd_hda_power_down(codec);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001717 return change;
1718}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001719EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_switch_put);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001720
1721/*
Takashi Iwai985be542005-11-02 18:26:49 +01001722 * bound volume controls
1723 *
1724 * bind multiple volumes (# indices, from 0)
1725 */
1726
1727#define AMP_VAL_IDX_SHIFT 19
1728#define AMP_VAL_IDX_MASK (0x0f<<19)
1729
Takashi Iwai0ba21762007-04-16 11:29:14 +02001730int snd_hda_mixer_bind_switch_get(struct snd_kcontrol *kcontrol,
1731 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai985be542005-11-02 18:26:49 +01001732{
1733 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1734 unsigned long pval;
1735 int err;
1736
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001737 mutex_lock(&codec->control_mutex);
Takashi Iwai985be542005-11-02 18:26:49 +01001738 pval = kcontrol->private_value;
1739 kcontrol->private_value = pval & ~AMP_VAL_IDX_MASK; /* index 0 */
1740 err = snd_hda_mixer_amp_switch_get(kcontrol, ucontrol);
1741 kcontrol->private_value = pval;
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001742 mutex_unlock(&codec->control_mutex);
Takashi Iwai985be542005-11-02 18:26:49 +01001743 return err;
1744}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001745EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_switch_get);
Takashi Iwai985be542005-11-02 18:26:49 +01001746
Takashi Iwai0ba21762007-04-16 11:29:14 +02001747int snd_hda_mixer_bind_switch_put(struct snd_kcontrol *kcontrol,
1748 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai985be542005-11-02 18:26:49 +01001749{
1750 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1751 unsigned long pval;
1752 int i, indices, err = 0, change = 0;
1753
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001754 mutex_lock(&codec->control_mutex);
Takashi Iwai985be542005-11-02 18:26:49 +01001755 pval = kcontrol->private_value;
1756 indices = (pval & AMP_VAL_IDX_MASK) >> AMP_VAL_IDX_SHIFT;
1757 for (i = 0; i < indices; i++) {
Takashi Iwai0ba21762007-04-16 11:29:14 +02001758 kcontrol->private_value = (pval & ~AMP_VAL_IDX_MASK) |
1759 (i << AMP_VAL_IDX_SHIFT);
Takashi Iwai985be542005-11-02 18:26:49 +01001760 err = snd_hda_mixer_amp_switch_put(kcontrol, ucontrol);
1761 if (err < 0)
1762 break;
1763 change |= err;
1764 }
1765 kcontrol->private_value = pval;
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001766 mutex_unlock(&codec->control_mutex);
Takashi Iwai985be542005-11-02 18:26:49 +01001767 return err < 0 ? err : change;
1768}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001769EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_switch_put);
Takashi Iwai985be542005-11-02 18:26:49 +01001770
1771/*
Takashi Iwai532d5382007-07-27 19:02:40 +02001772 * generic bound volume/swtich controls
1773 */
1774int snd_hda_mixer_bind_ctls_info(struct snd_kcontrol *kcontrol,
1775 struct snd_ctl_elem_info *uinfo)
1776{
1777 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1778 struct hda_bind_ctls *c;
1779 int err;
1780
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001781 mutex_lock(&codec->control_mutex);
Serge A. Suchkov14c65f92008-02-22 18:43:16 +01001782 c = (struct hda_bind_ctls *)kcontrol->private_value;
Takashi Iwai532d5382007-07-27 19:02:40 +02001783 kcontrol->private_value = *c->values;
1784 err = c->ops->info(kcontrol, uinfo);
1785 kcontrol->private_value = (long)c;
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001786 mutex_unlock(&codec->control_mutex);
Takashi Iwai532d5382007-07-27 19:02:40 +02001787 return err;
1788}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001789EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_ctls_info);
Takashi Iwai532d5382007-07-27 19:02:40 +02001790
1791int snd_hda_mixer_bind_ctls_get(struct snd_kcontrol *kcontrol,
1792 struct snd_ctl_elem_value *ucontrol)
1793{
1794 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1795 struct hda_bind_ctls *c;
1796 int err;
1797
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001798 mutex_lock(&codec->control_mutex);
Serge A. Suchkov14c65f92008-02-22 18:43:16 +01001799 c = (struct hda_bind_ctls *)kcontrol->private_value;
Takashi Iwai532d5382007-07-27 19:02:40 +02001800 kcontrol->private_value = *c->values;
1801 err = c->ops->get(kcontrol, ucontrol);
1802 kcontrol->private_value = (long)c;
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001803 mutex_unlock(&codec->control_mutex);
Takashi Iwai532d5382007-07-27 19:02:40 +02001804 return err;
1805}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001806EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_ctls_get);
Takashi Iwai532d5382007-07-27 19:02:40 +02001807
1808int snd_hda_mixer_bind_ctls_put(struct snd_kcontrol *kcontrol,
1809 struct snd_ctl_elem_value *ucontrol)
1810{
1811 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1812 struct hda_bind_ctls *c;
1813 unsigned long *vals;
1814 int err = 0, change = 0;
1815
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001816 mutex_lock(&codec->control_mutex);
Serge A. Suchkov14c65f92008-02-22 18:43:16 +01001817 c = (struct hda_bind_ctls *)kcontrol->private_value;
Takashi Iwai532d5382007-07-27 19:02:40 +02001818 for (vals = c->values; *vals; vals++) {
1819 kcontrol->private_value = *vals;
1820 err = c->ops->put(kcontrol, ucontrol);
1821 if (err < 0)
1822 break;
1823 change |= err;
1824 }
1825 kcontrol->private_value = (long)c;
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001826 mutex_unlock(&codec->control_mutex);
Takashi Iwai532d5382007-07-27 19:02:40 +02001827 return err < 0 ? err : change;
1828}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001829EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_ctls_put);
Takashi Iwai532d5382007-07-27 19:02:40 +02001830
1831int snd_hda_mixer_bind_tlv(struct snd_kcontrol *kcontrol, int op_flag,
1832 unsigned int size, unsigned int __user *tlv)
1833{
1834 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1835 struct hda_bind_ctls *c;
1836 int err;
1837
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001838 mutex_lock(&codec->control_mutex);
Serge A. Suchkov14c65f92008-02-22 18:43:16 +01001839 c = (struct hda_bind_ctls *)kcontrol->private_value;
Takashi Iwai532d5382007-07-27 19:02:40 +02001840 kcontrol->private_value = *c->values;
1841 err = c->ops->tlv(kcontrol, op_flag, size, tlv);
1842 kcontrol->private_value = (long)c;
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001843 mutex_unlock(&codec->control_mutex);
Takashi Iwai532d5382007-07-27 19:02:40 +02001844 return err;
1845}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001846EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_tlv);
Takashi Iwai532d5382007-07-27 19:02:40 +02001847
1848struct hda_ctl_ops snd_hda_bind_vol = {
1849 .info = snd_hda_mixer_amp_volume_info,
1850 .get = snd_hda_mixer_amp_volume_get,
1851 .put = snd_hda_mixer_amp_volume_put,
1852 .tlv = snd_hda_mixer_amp_tlv
1853};
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001854EXPORT_SYMBOL_HDA(snd_hda_bind_vol);
Takashi Iwai532d5382007-07-27 19:02:40 +02001855
1856struct hda_ctl_ops snd_hda_bind_sw = {
1857 .info = snd_hda_mixer_amp_switch_info,
1858 .get = snd_hda_mixer_amp_switch_get,
1859 .put = snd_hda_mixer_amp_switch_put,
1860 .tlv = snd_hda_mixer_amp_tlv
1861};
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001862EXPORT_SYMBOL_HDA(snd_hda_bind_sw);
Takashi Iwai532d5382007-07-27 19:02:40 +02001863
1864/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07001865 * SPDIF out controls
1866 */
1867
Takashi Iwai0ba21762007-04-16 11:29:14 +02001868static int snd_hda_spdif_mask_info(struct snd_kcontrol *kcontrol,
1869 struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001870{
1871 uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
1872 uinfo->count = 1;
1873 return 0;
1874}
1875
Takashi Iwai0ba21762007-04-16 11:29:14 +02001876static int snd_hda_spdif_cmask_get(struct snd_kcontrol *kcontrol,
1877 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001878{
1879 ucontrol->value.iec958.status[0] = IEC958_AES0_PROFESSIONAL |
1880 IEC958_AES0_NONAUDIO |
1881 IEC958_AES0_CON_EMPHASIS_5015 |
1882 IEC958_AES0_CON_NOT_COPYRIGHT;
1883 ucontrol->value.iec958.status[1] = IEC958_AES1_CON_CATEGORY |
1884 IEC958_AES1_CON_ORIGINAL;
1885 return 0;
1886}
1887
Takashi Iwai0ba21762007-04-16 11:29:14 +02001888static int snd_hda_spdif_pmask_get(struct snd_kcontrol *kcontrol,
1889 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001890{
1891 ucontrol->value.iec958.status[0] = IEC958_AES0_PROFESSIONAL |
1892 IEC958_AES0_NONAUDIO |
1893 IEC958_AES0_PRO_EMPHASIS_5015;
1894 return 0;
1895}
1896
Takashi Iwai0ba21762007-04-16 11:29:14 +02001897static int snd_hda_spdif_default_get(struct snd_kcontrol *kcontrol,
1898 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001899{
1900 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1901
1902 ucontrol->value.iec958.status[0] = codec->spdif_status & 0xff;
1903 ucontrol->value.iec958.status[1] = (codec->spdif_status >> 8) & 0xff;
1904 ucontrol->value.iec958.status[2] = (codec->spdif_status >> 16) & 0xff;
1905 ucontrol->value.iec958.status[3] = (codec->spdif_status >> 24) & 0xff;
1906
1907 return 0;
1908}
1909
1910/* convert from SPDIF status bits to HDA SPDIF bits
1911 * bit 0 (DigEn) is always set zero (to be filled later)
1912 */
1913static unsigned short convert_from_spdif_status(unsigned int sbits)
1914{
1915 unsigned short val = 0;
1916
1917 if (sbits & IEC958_AES0_PROFESSIONAL)
Takashi Iwai0ba21762007-04-16 11:29:14 +02001918 val |= AC_DIG1_PROFESSIONAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001919 if (sbits & IEC958_AES0_NONAUDIO)
Takashi Iwai0ba21762007-04-16 11:29:14 +02001920 val |= AC_DIG1_NONAUDIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001921 if (sbits & IEC958_AES0_PROFESSIONAL) {
Takashi Iwai0ba21762007-04-16 11:29:14 +02001922 if ((sbits & IEC958_AES0_PRO_EMPHASIS) ==
1923 IEC958_AES0_PRO_EMPHASIS_5015)
1924 val |= AC_DIG1_EMPHASIS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001925 } else {
Takashi Iwai0ba21762007-04-16 11:29:14 +02001926 if ((sbits & IEC958_AES0_CON_EMPHASIS) ==
1927 IEC958_AES0_CON_EMPHASIS_5015)
1928 val |= AC_DIG1_EMPHASIS;
1929 if (!(sbits & IEC958_AES0_CON_NOT_COPYRIGHT))
1930 val |= AC_DIG1_COPYRIGHT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001931 if (sbits & (IEC958_AES1_CON_ORIGINAL << 8))
Takashi Iwai0ba21762007-04-16 11:29:14 +02001932 val |= AC_DIG1_LEVEL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001933 val |= sbits & (IEC958_AES1_CON_CATEGORY << 8);
1934 }
1935 return val;
1936}
1937
1938/* convert to SPDIF status bits from HDA SPDIF bits
1939 */
1940static unsigned int convert_to_spdif_status(unsigned short val)
1941{
1942 unsigned int sbits = 0;
1943
Takashi Iwai0ba21762007-04-16 11:29:14 +02001944 if (val & AC_DIG1_NONAUDIO)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001945 sbits |= IEC958_AES0_NONAUDIO;
Takashi Iwai0ba21762007-04-16 11:29:14 +02001946 if (val & AC_DIG1_PROFESSIONAL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001947 sbits |= IEC958_AES0_PROFESSIONAL;
1948 if (sbits & IEC958_AES0_PROFESSIONAL) {
Takashi Iwai0ba21762007-04-16 11:29:14 +02001949 if (sbits & AC_DIG1_EMPHASIS)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001950 sbits |= IEC958_AES0_PRO_EMPHASIS_5015;
1951 } else {
Takashi Iwai0ba21762007-04-16 11:29:14 +02001952 if (val & AC_DIG1_EMPHASIS)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001953 sbits |= IEC958_AES0_CON_EMPHASIS_5015;
Takashi Iwai0ba21762007-04-16 11:29:14 +02001954 if (!(val & AC_DIG1_COPYRIGHT))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001955 sbits |= IEC958_AES0_CON_NOT_COPYRIGHT;
Takashi Iwai0ba21762007-04-16 11:29:14 +02001956 if (val & AC_DIG1_LEVEL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001957 sbits |= (IEC958_AES1_CON_ORIGINAL << 8);
1958 sbits |= val & (0x7f << 8);
1959 }
1960 return sbits;
1961}
1962
Takashi Iwai2f728532008-09-25 16:32:41 +02001963/* set digital convert verbs both for the given NID and its slaves */
1964static void set_dig_out(struct hda_codec *codec, hda_nid_t nid,
1965 int verb, int val)
1966{
1967 hda_nid_t *d;
1968
Takashi Iwai9e976972008-11-25 08:17:20 +01001969 snd_hda_codec_write_cache(codec, nid, 0, verb, val);
Takashi Iwai2f728532008-09-25 16:32:41 +02001970 d = codec->slave_dig_outs;
1971 if (!d)
1972 return;
1973 for (; *d; d++)
Takashi Iwai9e976972008-11-25 08:17:20 +01001974 snd_hda_codec_write_cache(codec, *d, 0, verb, val);
Takashi Iwai2f728532008-09-25 16:32:41 +02001975}
1976
1977static inline void set_dig_out_convert(struct hda_codec *codec, hda_nid_t nid,
1978 int dig1, int dig2)
1979{
1980 if (dig1 != -1)
1981 set_dig_out(codec, nid, AC_VERB_SET_DIGI_CONVERT_1, dig1);
1982 if (dig2 != -1)
1983 set_dig_out(codec, nid, AC_VERB_SET_DIGI_CONVERT_2, dig2);
1984}
1985
Takashi Iwai0ba21762007-04-16 11:29:14 +02001986static int snd_hda_spdif_default_put(struct snd_kcontrol *kcontrol,
1987 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001988{
1989 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1990 hda_nid_t nid = kcontrol->private_value;
1991 unsigned short val;
1992 int change;
1993
Ingo Molnar62932df2006-01-16 16:34:20 +01001994 mutex_lock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001995 codec->spdif_status = ucontrol->value.iec958.status[0] |
1996 ((unsigned int)ucontrol->value.iec958.status[1] << 8) |
1997 ((unsigned int)ucontrol->value.iec958.status[2] << 16) |
1998 ((unsigned int)ucontrol->value.iec958.status[3] << 24);
1999 val = convert_from_spdif_status(codec->spdif_status);
2000 val |= codec->spdif_ctls & 1;
2001 change = codec->spdif_ctls != val;
2002 codec->spdif_ctls = val;
2003
Takashi Iwai2f728532008-09-25 16:32:41 +02002004 if (change)
2005 set_dig_out_convert(codec, nid, val & 0xff, (val >> 8) & 0xff);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002006
Ingo Molnar62932df2006-01-16 16:34:20 +01002007 mutex_unlock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002008 return change;
2009}
2010
Takashi Iwaia5ce8892007-07-23 15:42:26 +02002011#define snd_hda_spdif_out_switch_info snd_ctl_boolean_mono_info
Linus Torvalds1da177e2005-04-16 15:20:36 -07002012
Takashi Iwai0ba21762007-04-16 11:29:14 +02002013static int snd_hda_spdif_out_switch_get(struct snd_kcontrol *kcontrol,
2014 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002015{
2016 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2017
Takashi Iwai0ba21762007-04-16 11:29:14 +02002018 ucontrol->value.integer.value[0] = codec->spdif_ctls & AC_DIG1_ENABLE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002019 return 0;
2020}
2021
Takashi Iwai0ba21762007-04-16 11:29:14 +02002022static int snd_hda_spdif_out_switch_put(struct snd_kcontrol *kcontrol,
2023 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002024{
2025 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2026 hda_nid_t nid = kcontrol->private_value;
2027 unsigned short val;
2028 int change;
2029
Ingo Molnar62932df2006-01-16 16:34:20 +01002030 mutex_lock(&codec->spdif_mutex);
Takashi Iwai0ba21762007-04-16 11:29:14 +02002031 val = codec->spdif_ctls & ~AC_DIG1_ENABLE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002032 if (ucontrol->value.integer.value[0])
Takashi Iwai0ba21762007-04-16 11:29:14 +02002033 val |= AC_DIG1_ENABLE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002034 change = codec->spdif_ctls != val;
Takashi Iwai82beb8f2007-08-10 17:09:26 +02002035 if (change) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002036 codec->spdif_ctls = val;
Takashi Iwai2f728532008-09-25 16:32:41 +02002037 set_dig_out_convert(codec, nid, val & 0xff, -1);
Takashi Iwai0ba21762007-04-16 11:29:14 +02002038 /* unmute amp switch (if any) */
2039 if ((get_wcaps(codec, nid) & AC_WCAP_OUT_AMP) &&
Takashi Iwai47fd8302007-08-10 17:11:07 +02002040 (val & AC_DIG1_ENABLE))
2041 snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0,
2042 HDA_AMP_MUTE, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002043 }
Ingo Molnar62932df2006-01-16 16:34:20 +01002044 mutex_unlock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002045 return change;
2046}
2047
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01002048static struct snd_kcontrol_new dig_mixes[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002049 {
2050 .access = SNDRV_CTL_ELEM_ACCESS_READ,
2051 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2052 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,CON_MASK),
2053 .info = snd_hda_spdif_mask_info,
2054 .get = snd_hda_spdif_cmask_get,
2055 },
2056 {
2057 .access = SNDRV_CTL_ELEM_ACCESS_READ,
2058 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2059 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,PRO_MASK),
2060 .info = snd_hda_spdif_mask_info,
2061 .get = snd_hda_spdif_pmask_get,
2062 },
2063 {
2064 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2065 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT),
2066 .info = snd_hda_spdif_mask_info,
2067 .get = snd_hda_spdif_default_get,
2068 .put = snd_hda_spdif_default_put,
2069 },
2070 {
2071 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2072 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,SWITCH),
2073 .info = snd_hda_spdif_out_switch_info,
2074 .get = snd_hda_spdif_out_switch_get,
2075 .put = snd_hda_spdif_out_switch_put,
2076 },
2077 { } /* end */
2078};
2079
Takashi Iwai09f99702008-02-04 12:31:13 +01002080#define SPDIF_MAX_IDX 4 /* 4 instances should be enough to probe */
2081
Linus Torvalds1da177e2005-04-16 15:20:36 -07002082/**
2083 * snd_hda_create_spdif_out_ctls - create Output SPDIF-related controls
2084 * @codec: the HDA codec
2085 * @nid: audio out widget NID
2086 *
2087 * Creates controls related with the SPDIF output.
2088 * Called from each patch supporting the SPDIF out.
2089 *
2090 * Returns 0 if successful, or a negative error code.
2091 */
Takashi Iwai12f288b2007-08-02 15:51:59 +02002092int snd_hda_create_spdif_out_ctls(struct hda_codec *codec, hda_nid_t nid)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002093{
2094 int err;
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01002095 struct snd_kcontrol *kctl;
2096 struct snd_kcontrol_new *dig_mix;
Takashi Iwai09f99702008-02-04 12:31:13 +01002097 int idx;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002098
Takashi Iwai09f99702008-02-04 12:31:13 +01002099 for (idx = 0; idx < SPDIF_MAX_IDX; idx++) {
2100 if (!_snd_hda_find_mixer_ctl(codec, "IEC958 Playback Switch",
2101 idx))
2102 break;
2103 }
2104 if (idx >= SPDIF_MAX_IDX) {
2105 printk(KERN_ERR "hda_codec: too many IEC958 outputs\n");
2106 return -EBUSY;
2107 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002108 for (dig_mix = dig_mixes; dig_mix->name; dig_mix++) {
2109 kctl = snd_ctl_new1(dig_mix, codec);
Takashi Iwaib91f0802008-11-04 08:43:08 +01002110 if (!kctl)
2111 return -ENOMEM;
Takashi Iwai09f99702008-02-04 12:31:13 +01002112 kctl->id.index = idx;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002113 kctl->private_value = nid;
Takashi Iwaid13bd412008-07-30 15:01:45 +02002114 err = snd_hda_ctl_add(codec, kctl);
Takashi Iwai0ba21762007-04-16 11:29:14 +02002115 if (err < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002116 return err;
2117 }
Takashi Iwai0ba21762007-04-16 11:29:14 +02002118 codec->spdif_ctls =
Andrew Paprocki3982d172007-12-19 12:13:44 +01002119 snd_hda_codec_read(codec, nid, 0,
2120 AC_VERB_GET_DIGI_CONVERT_1, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002121 codec->spdif_status = convert_to_spdif_status(codec->spdif_ctls);
2122 return 0;
2123}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002124EXPORT_SYMBOL_HDA(snd_hda_create_spdif_out_ctls);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002125
2126/*
Takashi Iwai9a081602008-02-12 18:37:26 +01002127 * SPDIF sharing with analog output
2128 */
2129static int spdif_share_sw_get(struct snd_kcontrol *kcontrol,
2130 struct snd_ctl_elem_value *ucontrol)
2131{
2132 struct hda_multi_out *mout = snd_kcontrol_chip(kcontrol);
2133 ucontrol->value.integer.value[0] = mout->share_spdif;
2134 return 0;
2135}
2136
2137static int spdif_share_sw_put(struct snd_kcontrol *kcontrol,
2138 struct snd_ctl_elem_value *ucontrol)
2139{
2140 struct hda_multi_out *mout = snd_kcontrol_chip(kcontrol);
2141 mout->share_spdif = !!ucontrol->value.integer.value[0];
2142 return 0;
2143}
2144
2145static struct snd_kcontrol_new spdif_share_sw = {
2146 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2147 .name = "IEC958 Default PCM Playback Switch",
2148 .info = snd_ctl_boolean_mono_info,
2149 .get = spdif_share_sw_get,
2150 .put = spdif_share_sw_put,
2151};
2152
2153int snd_hda_create_spdif_share_sw(struct hda_codec *codec,
2154 struct hda_multi_out *mout)
2155{
2156 if (!mout->dig_out_nid)
2157 return 0;
2158 /* ATTENTION: here mout is passed as private_data, instead of codec */
Takashi Iwaid13bd412008-07-30 15:01:45 +02002159 return snd_hda_ctl_add(codec,
Takashi Iwai9a081602008-02-12 18:37:26 +01002160 snd_ctl_new1(&spdif_share_sw, mout));
2161}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002162EXPORT_SYMBOL_HDA(snd_hda_create_spdif_share_sw);
Takashi Iwai9a081602008-02-12 18:37:26 +01002163
2164/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002165 * SPDIF input
2166 */
2167
2168#define snd_hda_spdif_in_switch_info snd_hda_spdif_out_switch_info
2169
Takashi Iwai0ba21762007-04-16 11:29:14 +02002170static int snd_hda_spdif_in_switch_get(struct snd_kcontrol *kcontrol,
2171 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002172{
2173 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2174
2175 ucontrol->value.integer.value[0] = codec->spdif_in_enable;
2176 return 0;
2177}
2178
Takashi Iwai0ba21762007-04-16 11:29:14 +02002179static int snd_hda_spdif_in_switch_put(struct snd_kcontrol *kcontrol,
2180 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002181{
2182 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2183 hda_nid_t nid = kcontrol->private_value;
2184 unsigned int val = !!ucontrol->value.integer.value[0];
2185 int change;
2186
Ingo Molnar62932df2006-01-16 16:34:20 +01002187 mutex_lock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002188 change = codec->spdif_in_enable != val;
Takashi Iwai82beb8f2007-08-10 17:09:26 +02002189 if (change) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002190 codec->spdif_in_enable = val;
Takashi Iwai82beb8f2007-08-10 17:09:26 +02002191 snd_hda_codec_write_cache(codec, nid, 0,
2192 AC_VERB_SET_DIGI_CONVERT_1, val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002193 }
Ingo Molnar62932df2006-01-16 16:34:20 +01002194 mutex_unlock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002195 return change;
2196}
2197
Takashi Iwai0ba21762007-04-16 11:29:14 +02002198static int snd_hda_spdif_in_status_get(struct snd_kcontrol *kcontrol,
2199 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002200{
2201 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2202 hda_nid_t nid = kcontrol->private_value;
2203 unsigned short val;
2204 unsigned int sbits;
2205
Andrew Paprocki3982d172007-12-19 12:13:44 +01002206 val = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_DIGI_CONVERT_1, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002207 sbits = convert_to_spdif_status(val);
2208 ucontrol->value.iec958.status[0] = sbits;
2209 ucontrol->value.iec958.status[1] = sbits >> 8;
2210 ucontrol->value.iec958.status[2] = sbits >> 16;
2211 ucontrol->value.iec958.status[3] = sbits >> 24;
2212 return 0;
2213}
2214
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01002215static struct snd_kcontrol_new dig_in_ctls[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002216 {
2217 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2218 .name = SNDRV_CTL_NAME_IEC958("",CAPTURE,SWITCH),
2219 .info = snd_hda_spdif_in_switch_info,
2220 .get = snd_hda_spdif_in_switch_get,
2221 .put = snd_hda_spdif_in_switch_put,
2222 },
2223 {
2224 .access = SNDRV_CTL_ELEM_ACCESS_READ,
2225 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2226 .name = SNDRV_CTL_NAME_IEC958("",CAPTURE,DEFAULT),
2227 .info = snd_hda_spdif_mask_info,
2228 .get = snd_hda_spdif_in_status_get,
2229 },
2230 { } /* end */
2231};
2232
2233/**
2234 * snd_hda_create_spdif_in_ctls - create Input SPDIF-related controls
2235 * @codec: the HDA codec
2236 * @nid: audio in widget NID
2237 *
2238 * Creates controls related with the SPDIF input.
2239 * Called from each patch supporting the SPDIF in.
2240 *
2241 * Returns 0 if successful, or a negative error code.
2242 */
Takashi Iwai12f288b2007-08-02 15:51:59 +02002243int snd_hda_create_spdif_in_ctls(struct hda_codec *codec, hda_nid_t nid)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002244{
2245 int err;
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01002246 struct snd_kcontrol *kctl;
2247 struct snd_kcontrol_new *dig_mix;
Takashi Iwai09f99702008-02-04 12:31:13 +01002248 int idx;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002249
Takashi Iwai09f99702008-02-04 12:31:13 +01002250 for (idx = 0; idx < SPDIF_MAX_IDX; idx++) {
2251 if (!_snd_hda_find_mixer_ctl(codec, "IEC958 Capture Switch",
2252 idx))
2253 break;
2254 }
2255 if (idx >= SPDIF_MAX_IDX) {
2256 printk(KERN_ERR "hda_codec: too many IEC958 inputs\n");
2257 return -EBUSY;
2258 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002259 for (dig_mix = dig_in_ctls; dig_mix->name; dig_mix++) {
2260 kctl = snd_ctl_new1(dig_mix, codec);
Takashi Iwaic8dcdf82009-02-06 16:21:20 +01002261 if (!kctl)
2262 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002263 kctl->private_value = nid;
Takashi Iwaid13bd412008-07-30 15:01:45 +02002264 err = snd_hda_ctl_add(codec, kctl);
Takashi Iwai0ba21762007-04-16 11:29:14 +02002265 if (err < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002266 return err;
2267 }
Takashi Iwai0ba21762007-04-16 11:29:14 +02002268 codec->spdif_in_enable =
Andrew Paprocki3982d172007-12-19 12:13:44 +01002269 snd_hda_codec_read(codec, nid, 0,
2270 AC_VERB_GET_DIGI_CONVERT_1, 0) &
Takashi Iwai0ba21762007-04-16 11:29:14 +02002271 AC_DIG1_ENABLE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002272 return 0;
2273}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002274EXPORT_SYMBOL_HDA(snd_hda_create_spdif_in_ctls);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002275
Takashi Iwaicb53c622007-08-10 17:21:45 +02002276#ifdef SND_HDA_NEEDS_RESUME
Takashi Iwai82beb8f2007-08-10 17:09:26 +02002277/*
2278 * command cache
2279 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002280
Takashi Iwaib3ac5632007-08-10 17:03:40 +02002281/* build a 32bit cache key with the widget id and the command parameter */
2282#define build_cmd_cache_key(nid, verb) ((verb << 8) | nid)
2283#define get_cmd_cache_nid(key) ((key) & 0xff)
2284#define get_cmd_cache_cmd(key) (((key) >> 8) & 0xffff)
2285
2286/**
2287 * snd_hda_codec_write_cache - send a single command with caching
2288 * @codec: the HDA codec
2289 * @nid: NID to send the command
2290 * @direct: direct flag
2291 * @verb: the verb to send
2292 * @parm: the parameter for the verb
2293 *
2294 * Send a single command without waiting for response.
2295 *
2296 * Returns 0 if successful, or a negative error code.
2297 */
2298int snd_hda_codec_write_cache(struct hda_codec *codec, hda_nid_t nid,
2299 int direct, unsigned int verb, unsigned int parm)
2300{
Takashi Iwaiaa2936f2009-05-26 16:07:57 +02002301 int err = snd_hda_codec_write(codec, nid, direct, verb, parm);
2302 struct hda_cache_head *c;
2303 u32 key;
Takashi Iwai33fa35e2008-11-06 16:50:40 +01002304
Takashi Iwaiaa2936f2009-05-26 16:07:57 +02002305 if (err < 0)
2306 return err;
2307 /* parm may contain the verb stuff for get/set amp */
2308 verb = verb | (parm >> 8);
2309 parm &= 0xff;
2310 key = build_cmd_cache_key(nid, verb);
2311 mutex_lock(&codec->bus->cmd_mutex);
2312 c = get_alloc_hash(&codec->cmd_cache, key);
2313 if (c)
2314 c->val = parm;
2315 mutex_unlock(&codec->bus->cmd_mutex);
2316 return 0;
Takashi Iwaib3ac5632007-08-10 17:03:40 +02002317}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002318EXPORT_SYMBOL_HDA(snd_hda_codec_write_cache);
Takashi Iwaib3ac5632007-08-10 17:03:40 +02002319
2320/* resume the all commands from the cache */
2321void snd_hda_codec_resume_cache(struct hda_codec *codec)
2322{
Takashi Iwai603c4012008-07-30 15:01:44 +02002323 struct hda_cache_head *buffer = codec->cmd_cache.buf.list;
Takashi Iwaib3ac5632007-08-10 17:03:40 +02002324 int i;
2325
Takashi Iwai603c4012008-07-30 15:01:44 +02002326 for (i = 0; i < codec->cmd_cache.buf.used; i++, buffer++) {
Takashi Iwaib3ac5632007-08-10 17:03:40 +02002327 u32 key = buffer->key;
2328 if (!key)
2329 continue;
2330 snd_hda_codec_write(codec, get_cmd_cache_nid(key), 0,
2331 get_cmd_cache_cmd(key), buffer->val);
2332 }
2333}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002334EXPORT_SYMBOL_HDA(snd_hda_codec_resume_cache);
Takashi Iwaib3ac5632007-08-10 17:03:40 +02002335
2336/**
2337 * snd_hda_sequence_write_cache - sequence writes with caching
2338 * @codec: the HDA codec
2339 * @seq: VERB array to send
2340 *
2341 * Send the commands sequentially from the given array.
2342 * Thte commands are recorded on cache for power-save and resume.
2343 * The array must be terminated with NID=0.
2344 */
2345void snd_hda_sequence_write_cache(struct hda_codec *codec,
2346 const struct hda_verb *seq)
2347{
2348 for (; seq->nid; seq++)
2349 snd_hda_codec_write_cache(codec, seq->nid, 0, seq->verb,
2350 seq->param);
2351}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002352EXPORT_SYMBOL_HDA(snd_hda_sequence_write_cache);
Takashi Iwaicb53c622007-08-10 17:21:45 +02002353#endif /* SND_HDA_NEEDS_RESUME */
Takashi Iwaib3ac5632007-08-10 17:03:40 +02002354
Takashi Iwai54d17402005-11-21 16:33:22 +01002355/*
2356 * set power state of the codec
2357 */
2358static void hda_set_power_state(struct hda_codec *codec, hda_nid_t fg,
2359 unsigned int power_state)
2360{
Takashi Iwaicb53c622007-08-10 17:21:45 +02002361 hda_nid_t nid;
2362 int i;
Takashi Iwai54d17402005-11-21 16:33:22 +01002363
2364 snd_hda_codec_write(codec, fg, 0, AC_VERB_SET_POWER_STATE,
2365 power_state);
Marc Boucherd2595d82008-01-22 15:23:30 +01002366 msleep(10); /* partial workaround for "azx_get_response timeout" */
Takashi Iwai54d17402005-11-21 16:33:22 +01002367
Takashi Iwaicb53c622007-08-10 17:21:45 +02002368 nid = codec->start_nid;
2369 for (i = 0; i < codec->num_nodes; i++, nid++) {
Takashi Iwai7eba5c92007-11-14 14:53:42 +01002370 unsigned int wcaps = get_wcaps(codec, nid);
2371 if (wcaps & AC_WCAP_POWER) {
2372 unsigned int wid_type = (wcaps & AC_WCAP_TYPE) >>
2373 AC_WCAP_TYPE_SHIFT;
Takashi Iwaia3b48c82009-04-21 13:37:29 +02002374 if (power_state == AC_PWRST_D3 &&
2375 wid_type == AC_WID_PIN) {
Takashi Iwai7eba5c92007-11-14 14:53:42 +01002376 unsigned int pincap;
2377 /*
2378 * don't power down the widget if it controls
2379 * eapd and EAPD_BTLENABLE is set.
2380 */
Takashi Iwai14bafe32009-03-23 16:35:39 +01002381 pincap = snd_hda_query_pin_caps(codec, nid);
Takashi Iwai7eba5c92007-11-14 14:53:42 +01002382 if (pincap & AC_PINCAP_EAPD) {
2383 int eapd = snd_hda_codec_read(codec,
2384 nid, 0,
2385 AC_VERB_GET_EAPD_BTLENABLE, 0);
2386 eapd &= 0x02;
Takashi Iwaia3b48c82009-04-21 13:37:29 +02002387 if (eapd)
Takashi Iwai7eba5c92007-11-14 14:53:42 +01002388 continue;
2389 }
Takashi Iwai1194b5b2007-10-10 10:04:26 +02002390 }
Takashi Iwai54d17402005-11-21 16:33:22 +01002391 snd_hda_codec_write(codec, nid, 0,
2392 AC_VERB_SET_POWER_STATE,
2393 power_state);
Takashi Iwai1194b5b2007-10-10 10:04:26 +02002394 }
Takashi Iwai54d17402005-11-21 16:33:22 +01002395 }
2396
Takashi Iwaicb53c622007-08-10 17:21:45 +02002397 if (power_state == AC_PWRST_D0) {
2398 unsigned long end_time;
2399 int state;
Takashi Iwai54d17402005-11-21 16:33:22 +01002400 msleep(10);
Takashi Iwaicb53c622007-08-10 17:21:45 +02002401 /* wait until the codec reachs to D0 */
2402 end_time = jiffies + msecs_to_jiffies(500);
2403 do {
2404 state = snd_hda_codec_read(codec, fg, 0,
2405 AC_VERB_GET_POWER_STATE, 0);
2406 if (state == power_state)
2407 break;
2408 msleep(1);
2409 } while (time_after_eq(end_time, jiffies));
2410 }
Takashi Iwai54d17402005-11-21 16:33:22 +01002411}
2412
Takashi Iwai11aeff02008-07-30 15:01:46 +02002413#ifdef CONFIG_SND_HDA_HWDEP
2414/* execute additional init verbs */
2415static void hda_exec_init_verbs(struct hda_codec *codec)
2416{
2417 if (codec->init_verbs.list)
2418 snd_hda_sequence_write(codec, codec->init_verbs.list);
2419}
2420#else
2421static inline void hda_exec_init_verbs(struct hda_codec *codec) {}
2422#endif
2423
Takashi Iwaicb53c622007-08-10 17:21:45 +02002424#ifdef SND_HDA_NEEDS_RESUME
2425/*
2426 * call suspend and power-down; used both from PM and power-save
2427 */
2428static void hda_call_codec_suspend(struct hda_codec *codec)
2429{
2430 if (codec->patch_ops.suspend)
2431 codec->patch_ops.suspend(codec, PMSG_SUSPEND);
2432 hda_set_power_state(codec,
2433 codec->afg ? codec->afg : codec->mfg,
2434 AC_PWRST_D3);
2435#ifdef CONFIG_SND_HDA_POWER_SAVE
2436 cancel_delayed_work(&codec->power_work);
Takashi Iwai95e99fd2007-08-13 15:29:04 +02002437 codec->power_on = 0;
Takashi Iwaia221e282007-08-16 16:35:33 +02002438 codec->power_transition = 0;
Takashi Iwaicb53c622007-08-10 17:21:45 +02002439#endif
2440}
2441
2442/*
2443 * kick up codec; used both from PM and power-save
2444 */
2445static void hda_call_codec_resume(struct hda_codec *codec)
2446{
2447 hda_set_power_state(codec,
2448 codec->afg ? codec->afg : codec->mfg,
2449 AC_PWRST_D0);
Takashi Iwai3be14142009-02-20 14:11:16 +01002450 restore_pincfgs(codec); /* restore all current pin configs */
Takashi Iwai11aeff02008-07-30 15:01:46 +02002451 hda_exec_init_verbs(codec);
Takashi Iwaicb53c622007-08-10 17:21:45 +02002452 if (codec->patch_ops.resume)
2453 codec->patch_ops.resume(codec);
2454 else {
Takashi Iwai9d99f312007-08-14 15:15:52 +02002455 if (codec->patch_ops.init)
2456 codec->patch_ops.init(codec);
Takashi Iwaicb53c622007-08-10 17:21:45 +02002457 snd_hda_codec_resume_amp(codec);
2458 snd_hda_codec_resume_cache(codec);
2459 }
2460}
2461#endif /* SND_HDA_NEEDS_RESUME */
2462
Takashi Iwai54d17402005-11-21 16:33:22 +01002463
Linus Torvalds1da177e2005-04-16 15:20:36 -07002464/**
2465 * snd_hda_build_controls - build mixer controls
2466 * @bus: the BUS
2467 *
2468 * Creates mixer controls for each codec included in the bus.
2469 *
2470 * Returns 0 if successful, otherwise a negative error code.
2471 */
Takashi Iwai1289e9e2008-11-27 15:47:11 +01002472int /*__devinit*/ snd_hda_build_controls(struct hda_bus *bus)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002473{
Takashi Iwai0ba21762007-04-16 11:29:14 +02002474 struct hda_codec *codec;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002475
Takashi Iwai0ba21762007-04-16 11:29:14 +02002476 list_for_each_entry(codec, &bus->codec_list, list) {
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02002477 int err = snd_hda_codec_build_controls(codec);
Takashi Iwaif93d4612009-03-02 10:44:15 +01002478 if (err < 0) {
2479 printk(KERN_ERR "hda_codec: cannot build controls"
2480 "for #%d (error %d)\n", codec->addr, err);
2481 err = snd_hda_codec_reset(codec);
2482 if (err < 0) {
2483 printk(KERN_ERR
2484 "hda_codec: cannot revert codec\n");
2485 return err;
2486 }
2487 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002488 }
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02002489 return 0;
2490}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002491EXPORT_SYMBOL_HDA(snd_hda_build_controls);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002492
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02002493int snd_hda_codec_build_controls(struct hda_codec *codec)
2494{
2495 int err = 0;
Takashi Iwai11aeff02008-07-30 15:01:46 +02002496 hda_exec_init_verbs(codec);
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02002497 /* continue to initialize... */
2498 if (codec->patch_ops.init)
2499 err = codec->patch_ops.init(codec);
2500 if (!err && codec->patch_ops.build_controls)
2501 err = codec->patch_ops.build_controls(codec);
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02002502 if (err < 0)
2503 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002504 return 0;
2505}
2506
Linus Torvalds1da177e2005-04-16 15:20:36 -07002507/*
2508 * stream formats
2509 */
Takashi Iwaibefdf312005-08-22 13:57:55 +02002510struct hda_rate_tbl {
2511 unsigned int hz;
2512 unsigned int alsa_bits;
2513 unsigned int hda_fmt;
2514};
2515
2516static struct hda_rate_tbl rate_bits[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002517 /* rate in Hz, ALSA rate bitmask, HDA format value */
Nicolas Graziano9d8f53f2005-08-22 13:47:16 +02002518
2519 /* autodetected value used in snd_hda_query_supported_pcm */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002520 { 8000, SNDRV_PCM_RATE_8000, 0x0500 }, /* 1/6 x 48 */
2521 { 11025, SNDRV_PCM_RATE_11025, 0x4300 }, /* 1/4 x 44 */
2522 { 16000, SNDRV_PCM_RATE_16000, 0x0200 }, /* 1/3 x 48 */
2523 { 22050, SNDRV_PCM_RATE_22050, 0x4100 }, /* 1/2 x 44 */
2524 { 32000, SNDRV_PCM_RATE_32000, 0x0a00 }, /* 2/3 x 48 */
2525 { 44100, SNDRV_PCM_RATE_44100, 0x4000 }, /* 44 */
2526 { 48000, SNDRV_PCM_RATE_48000, 0x0000 }, /* 48 */
2527 { 88200, SNDRV_PCM_RATE_88200, 0x4800 }, /* 2 x 44 */
2528 { 96000, SNDRV_PCM_RATE_96000, 0x0800 }, /* 2 x 48 */
2529 { 176400, SNDRV_PCM_RATE_176400, 0x5800 },/* 4 x 44 */
2530 { 192000, SNDRV_PCM_RATE_192000, 0x1800 }, /* 4 x 48 */
Takashi Iwaia961f9f2007-04-12 13:08:09 +02002531#define AC_PAR_PCM_RATE_BITS 11
2532 /* up to bits 10, 384kHZ isn't supported properly */
2533
2534 /* not autodetected value */
2535 { 9600, SNDRV_PCM_RATE_KNOT, 0x0400 }, /* 1/5 x 48 */
Nicolas Graziano9d8f53f2005-08-22 13:47:16 +02002536
Takashi Iwaibefdf312005-08-22 13:57:55 +02002537 { 0 } /* terminator */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002538};
2539
2540/**
2541 * snd_hda_calc_stream_format - calculate format bitset
2542 * @rate: the sample rate
2543 * @channels: the number of channels
2544 * @format: the PCM format (SNDRV_PCM_FORMAT_XXX)
2545 * @maxbps: the max. bps
2546 *
2547 * Calculate the format bitset from the given rate, channels and th PCM format.
2548 *
2549 * Return zero if invalid.
2550 */
2551unsigned int snd_hda_calc_stream_format(unsigned int rate,
2552 unsigned int channels,
2553 unsigned int format,
2554 unsigned int maxbps)
2555{
2556 int i;
2557 unsigned int val = 0;
2558
Takashi Iwaibefdf312005-08-22 13:57:55 +02002559 for (i = 0; rate_bits[i].hz; i++)
2560 if (rate_bits[i].hz == rate) {
2561 val = rate_bits[i].hda_fmt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002562 break;
2563 }
Takashi Iwai0ba21762007-04-16 11:29:14 +02002564 if (!rate_bits[i].hz) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002565 snd_printdd("invalid rate %d\n", rate);
2566 return 0;
2567 }
2568
2569 if (channels == 0 || channels > 8) {
2570 snd_printdd("invalid channels %d\n", channels);
2571 return 0;
2572 }
2573 val |= channels - 1;
2574
2575 switch (snd_pcm_format_width(format)) {
2576 case 8: val |= 0x00; break;
2577 case 16: val |= 0x10; break;
2578 case 20:
2579 case 24:
2580 case 32:
Takashi Iwaib0bb3aa2009-07-03 23:25:37 +02002581 if (maxbps >= 32 || format == SNDRV_PCM_FORMAT_FLOAT_LE)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002582 val |= 0x40;
2583 else if (maxbps >= 24)
2584 val |= 0x30;
2585 else
2586 val |= 0x20;
2587 break;
2588 default:
Takashi Iwai0ba21762007-04-16 11:29:14 +02002589 snd_printdd("invalid format width %d\n",
2590 snd_pcm_format_width(format));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002591 return 0;
2592 }
2593
2594 return val;
2595}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002596EXPORT_SYMBOL_HDA(snd_hda_calc_stream_format);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002597
Takashi Iwai92c7c8a2009-03-24 07:32:14 +01002598static unsigned int get_pcm_param(struct hda_codec *codec, hda_nid_t nid)
2599{
2600 unsigned int val = 0;
2601 if (nid != codec->afg &&
2602 (get_wcaps(codec, nid) & AC_WCAP_FORMAT_OVRD))
2603 val = snd_hda_param_read(codec, nid, AC_PAR_PCM);
2604 if (!val || val == -1)
2605 val = snd_hda_param_read(codec, codec->afg, AC_PAR_PCM);
2606 if (!val || val == -1)
2607 return 0;
2608 return val;
2609}
2610
2611static unsigned int query_pcm_param(struct hda_codec *codec, hda_nid_t nid)
2612{
2613 return query_caps_hash(codec, nid, HDA_HASH_PARPCM_KEY(nid),
2614 get_pcm_param);
2615}
2616
2617static unsigned int get_stream_param(struct hda_codec *codec, hda_nid_t nid)
2618{
2619 unsigned int streams = snd_hda_param_read(codec, nid, AC_PAR_STREAM);
2620 if (!streams || streams == -1)
2621 streams = snd_hda_param_read(codec, codec->afg, AC_PAR_STREAM);
2622 if (!streams || streams == -1)
2623 return 0;
2624 return streams;
2625}
2626
2627static unsigned int query_stream_param(struct hda_codec *codec, hda_nid_t nid)
2628{
2629 return query_caps_hash(codec, nid, HDA_HASH_PARSTR_KEY(nid),
2630 get_stream_param);
2631}
2632
Linus Torvalds1da177e2005-04-16 15:20:36 -07002633/**
2634 * snd_hda_query_supported_pcm - query the supported PCM rates and formats
2635 * @codec: the HDA codec
2636 * @nid: NID to query
2637 * @ratesp: the pointer to store the detected rate bitflags
2638 * @formatsp: the pointer to store the detected formats
2639 * @bpsp: the pointer to store the detected format widths
2640 *
2641 * Queries the supported PCM rates and formats. The NULL @ratesp, @formatsp
2642 * or @bsps argument is ignored.
2643 *
2644 * Returns 0 if successful, otherwise a negative error code.
2645 */
Takashi Iwai986862bd2008-11-27 12:40:13 +01002646static int snd_hda_query_supported_pcm(struct hda_codec *codec, hda_nid_t nid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002647 u32 *ratesp, u64 *formatsp, unsigned int *bpsp)
2648{
Jaroslav Kyselaee504712009-03-17 14:30:31 +01002649 unsigned int i, val, wcaps;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002650
Jaroslav Kyselaee504712009-03-17 14:30:31 +01002651 wcaps = get_wcaps(codec, nid);
Takashi Iwai92c7c8a2009-03-24 07:32:14 +01002652 val = query_pcm_param(codec, nid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002653
2654 if (ratesp) {
2655 u32 rates = 0;
Takashi Iwaia961f9f2007-04-12 13:08:09 +02002656 for (i = 0; i < AC_PAR_PCM_RATE_BITS; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002657 if (val & (1 << i))
Takashi Iwaibefdf312005-08-22 13:57:55 +02002658 rates |= rate_bits[i].alsa_bits;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002659 }
Jaroslav Kyselaee504712009-03-17 14:30:31 +01002660 if (rates == 0) {
2661 snd_printk(KERN_ERR "hda_codec: rates == 0 "
2662 "(nid=0x%x, val=0x%x, ovrd=%i)\n",
2663 nid, val,
2664 (wcaps & AC_WCAP_FORMAT_OVRD) ? 1 : 0);
2665 return -EIO;
2666 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002667 *ratesp = rates;
2668 }
2669
2670 if (formatsp || bpsp) {
2671 u64 formats = 0;
Jaroslav Kyselaee504712009-03-17 14:30:31 +01002672 unsigned int streams, bps;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002673
Takashi Iwai92c7c8a2009-03-24 07:32:14 +01002674 streams = query_stream_param(codec, nid);
2675 if (!streams)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002676 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002677
2678 bps = 0;
2679 if (streams & AC_SUPFMT_PCM) {
2680 if (val & AC_SUPPCM_BITS_8) {
2681 formats |= SNDRV_PCM_FMTBIT_U8;
2682 bps = 8;
2683 }
2684 if (val & AC_SUPPCM_BITS_16) {
2685 formats |= SNDRV_PCM_FMTBIT_S16_LE;
2686 bps = 16;
2687 }
2688 if (wcaps & AC_WCAP_DIGITAL) {
2689 if (val & AC_SUPPCM_BITS_32)
2690 formats |= SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_LE;
2691 if (val & (AC_SUPPCM_BITS_20|AC_SUPPCM_BITS_24))
2692 formats |= SNDRV_PCM_FMTBIT_S32_LE;
2693 if (val & AC_SUPPCM_BITS_24)
2694 bps = 24;
2695 else if (val & AC_SUPPCM_BITS_20)
2696 bps = 20;
Takashi Iwai0ba21762007-04-16 11:29:14 +02002697 } else if (val & (AC_SUPPCM_BITS_20|AC_SUPPCM_BITS_24|
2698 AC_SUPPCM_BITS_32)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002699 formats |= SNDRV_PCM_FMTBIT_S32_LE;
2700 if (val & AC_SUPPCM_BITS_32)
2701 bps = 32;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002702 else if (val & AC_SUPPCM_BITS_24)
2703 bps = 24;
Nicolas Graziano33ef76512006-09-19 14:23:14 +02002704 else if (val & AC_SUPPCM_BITS_20)
2705 bps = 20;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002706 }
2707 }
Takashi Iwaib5025c52009-07-01 18:05:27 +02002708 if (streams & AC_SUPFMT_FLOAT32) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002709 formats |= SNDRV_PCM_FMTBIT_FLOAT_LE;
Takashi Iwaib0bb3aa2009-07-03 23:25:37 +02002710 if (!bps)
2711 bps = 32;
Takashi Iwaib5025c52009-07-01 18:05:27 +02002712 }
2713 if (streams == AC_SUPFMT_AC3) {
Takashi Iwai0ba21762007-04-16 11:29:14 +02002714 /* should be exclusive */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002715 /* temporary hack: we have still no proper support
2716 * for the direct AC3 stream...
2717 */
2718 formats |= SNDRV_PCM_FMTBIT_U8;
2719 bps = 8;
2720 }
Jaroslav Kyselaee504712009-03-17 14:30:31 +01002721 if (formats == 0) {
2722 snd_printk(KERN_ERR "hda_codec: formats == 0 "
2723 "(nid=0x%x, val=0x%x, ovrd=%i, "
2724 "streams=0x%x)\n",
2725 nid, val,
2726 (wcaps & AC_WCAP_FORMAT_OVRD) ? 1 : 0,
2727 streams);
2728 return -EIO;
2729 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002730 if (formatsp)
2731 *formatsp = formats;
2732 if (bpsp)
2733 *bpsp = bps;
2734 }
2735
2736 return 0;
2737}
2738
2739/**
Takashi Iwai0ba21762007-04-16 11:29:14 +02002740 * snd_hda_is_supported_format - check whether the given node supports
2741 * the format val
Linus Torvalds1da177e2005-04-16 15:20:36 -07002742 *
2743 * Returns 1 if supported, 0 if not.
2744 */
2745int snd_hda_is_supported_format(struct hda_codec *codec, hda_nid_t nid,
2746 unsigned int format)
2747{
2748 int i;
2749 unsigned int val = 0, rate, stream;
2750
Takashi Iwai92c7c8a2009-03-24 07:32:14 +01002751 val = query_pcm_param(codec, nid);
2752 if (!val)
2753 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002754
2755 rate = format & 0xff00;
Takashi Iwaia961f9f2007-04-12 13:08:09 +02002756 for (i = 0; i < AC_PAR_PCM_RATE_BITS; i++)
Takashi Iwaibefdf312005-08-22 13:57:55 +02002757 if (rate_bits[i].hda_fmt == rate) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002758 if (val & (1 << i))
2759 break;
2760 return 0;
2761 }
Takashi Iwaia961f9f2007-04-12 13:08:09 +02002762 if (i >= AC_PAR_PCM_RATE_BITS)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002763 return 0;
2764
Takashi Iwai92c7c8a2009-03-24 07:32:14 +01002765 stream = query_stream_param(codec, nid);
2766 if (!stream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002767 return 0;
2768
2769 if (stream & AC_SUPFMT_PCM) {
2770 switch (format & 0xf0) {
2771 case 0x00:
Takashi Iwai0ba21762007-04-16 11:29:14 +02002772 if (!(val & AC_SUPPCM_BITS_8))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002773 return 0;
2774 break;
2775 case 0x10:
Takashi Iwai0ba21762007-04-16 11:29:14 +02002776 if (!(val & AC_SUPPCM_BITS_16))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002777 return 0;
2778 break;
2779 case 0x20:
Takashi Iwai0ba21762007-04-16 11:29:14 +02002780 if (!(val & AC_SUPPCM_BITS_20))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002781 return 0;
2782 break;
2783 case 0x30:
Takashi Iwai0ba21762007-04-16 11:29:14 +02002784 if (!(val & AC_SUPPCM_BITS_24))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002785 return 0;
2786 break;
2787 case 0x40:
Takashi Iwai0ba21762007-04-16 11:29:14 +02002788 if (!(val & AC_SUPPCM_BITS_32))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002789 return 0;
2790 break;
2791 default:
2792 return 0;
2793 }
2794 } else {
2795 /* FIXME: check for float32 and AC3? */
2796 }
2797
2798 return 1;
2799}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002800EXPORT_SYMBOL_HDA(snd_hda_is_supported_format);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002801
2802/*
2803 * PCM stuff
2804 */
2805static int hda_pcm_default_open_close(struct hda_pcm_stream *hinfo,
2806 struct hda_codec *codec,
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01002807 struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002808{
2809 return 0;
2810}
2811
2812static int hda_pcm_default_prepare(struct hda_pcm_stream *hinfo,
2813 struct hda_codec *codec,
2814 unsigned int stream_tag,
2815 unsigned int format,
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01002816 struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002817{
2818 snd_hda_codec_setup_stream(codec, hinfo->nid, stream_tag, 0, format);
2819 return 0;
2820}
2821
2822static int hda_pcm_default_cleanup(struct hda_pcm_stream *hinfo,
2823 struct hda_codec *codec,
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01002824 struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002825{
Takashi Iwai888afa12008-03-18 09:57:50 +01002826 snd_hda_codec_cleanup_stream(codec, hinfo->nid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002827 return 0;
2828}
2829
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02002830static int set_pcm_default_values(struct hda_codec *codec,
2831 struct hda_pcm_stream *info)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002832{
Jaroslav Kyselaee504712009-03-17 14:30:31 +01002833 int err;
2834
Takashi Iwai0ba21762007-04-16 11:29:14 +02002835 /* query support PCM information from the given NID */
2836 if (info->nid && (!info->rates || !info->formats)) {
Jaroslav Kyselaee504712009-03-17 14:30:31 +01002837 err = snd_hda_query_supported_pcm(codec, info->nid,
Takashi Iwai0ba21762007-04-16 11:29:14 +02002838 info->rates ? NULL : &info->rates,
2839 info->formats ? NULL : &info->formats,
2840 info->maxbps ? NULL : &info->maxbps);
Jaroslav Kyselaee504712009-03-17 14:30:31 +01002841 if (err < 0)
2842 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002843 }
2844 if (info->ops.open == NULL)
2845 info->ops.open = hda_pcm_default_open_close;
2846 if (info->ops.close == NULL)
2847 info->ops.close = hda_pcm_default_open_close;
2848 if (info->ops.prepare == NULL) {
Takashi Iwaida3cec32008-08-08 17:12:14 +02002849 if (snd_BUG_ON(!info->nid))
2850 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002851 info->ops.prepare = hda_pcm_default_prepare;
2852 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002853 if (info->ops.cleanup == NULL) {
Takashi Iwaida3cec32008-08-08 17:12:14 +02002854 if (snd_BUG_ON(!info->nid))
2855 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002856 info->ops.cleanup = hda_pcm_default_cleanup;
2857 }
2858 return 0;
2859}
2860
Takashi Iwai176d5332008-07-30 15:01:44 +02002861/*
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002862 * get the empty PCM device number to assign
2863 */
2864static int get_empty_pcm_device(struct hda_bus *bus, int type)
2865{
2866 static const char *dev_name[HDA_PCM_NTYPES] = {
2867 "Audio", "SPDIF", "HDMI", "Modem"
2868 };
2869 /* starting device index for each PCM type */
2870 static int dev_idx[HDA_PCM_NTYPES] = {
2871 [HDA_PCM_TYPE_AUDIO] = 0,
2872 [HDA_PCM_TYPE_SPDIF] = 1,
2873 [HDA_PCM_TYPE_HDMI] = 3,
2874 [HDA_PCM_TYPE_MODEM] = 6
2875 };
2876 /* normal audio device indices; not linear to keep compatibility */
2877 static int audio_idx[4] = { 0, 2, 4, 5 };
2878 int i, dev;
2879
2880 switch (type) {
2881 case HDA_PCM_TYPE_AUDIO:
2882 for (i = 0; i < ARRAY_SIZE(audio_idx); i++) {
2883 dev = audio_idx[i];
2884 if (!test_bit(dev, bus->pcm_dev_bits))
Takashi Iwai82ad39f2009-03-03 15:00:35 +01002885 goto ok;
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002886 }
Takashi Iwai82ad39f2009-03-03 15:00:35 +01002887 snd_printk(KERN_WARNING "Too many audio devices\n");
2888 return -EAGAIN;
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002889 case HDA_PCM_TYPE_SPDIF:
2890 case HDA_PCM_TYPE_HDMI:
2891 case HDA_PCM_TYPE_MODEM:
2892 dev = dev_idx[type];
2893 if (test_bit(dev, bus->pcm_dev_bits)) {
2894 snd_printk(KERN_WARNING "%s already defined\n",
2895 dev_name[type]);
2896 return -EAGAIN;
2897 }
2898 break;
2899 default:
2900 snd_printk(KERN_WARNING "Invalid PCM type %d\n", type);
2901 return -EINVAL;
2902 }
Takashi Iwai82ad39f2009-03-03 15:00:35 +01002903 ok:
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002904 set_bit(dev, bus->pcm_dev_bits);
2905 return dev;
2906}
2907
2908/*
Takashi Iwai176d5332008-07-30 15:01:44 +02002909 * attach a new PCM stream
2910 */
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002911static int snd_hda_attach_pcm(struct hda_codec *codec, struct hda_pcm *pcm)
Takashi Iwai176d5332008-07-30 15:01:44 +02002912{
Takashi Iwai33fa35e2008-11-06 16:50:40 +01002913 struct hda_bus *bus = codec->bus;
Takashi Iwai176d5332008-07-30 15:01:44 +02002914 struct hda_pcm_stream *info;
2915 int stream, err;
2916
Takashi Iwaib91f0802008-11-04 08:43:08 +01002917 if (snd_BUG_ON(!pcm->name))
Takashi Iwai176d5332008-07-30 15:01:44 +02002918 return -EINVAL;
2919 for (stream = 0; stream < 2; stream++) {
2920 info = &pcm->stream[stream];
2921 if (info->substreams) {
2922 err = set_pcm_default_values(codec, info);
2923 if (err < 0)
2924 return err;
2925 }
2926 }
Takashi Iwai33fa35e2008-11-06 16:50:40 +01002927 return bus->ops.attach_pcm(bus, codec, pcm);
Takashi Iwai176d5332008-07-30 15:01:44 +02002928}
2929
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002930/* assign all PCMs of the given codec */
2931int snd_hda_codec_build_pcms(struct hda_codec *codec)
2932{
2933 unsigned int pcm;
2934 int err;
2935
2936 if (!codec->num_pcms) {
2937 if (!codec->patch_ops.build_pcms)
2938 return 0;
2939 err = codec->patch_ops.build_pcms(codec);
Takashi Iwai6e655bf2009-03-02 10:46:03 +01002940 if (err < 0) {
2941 printk(KERN_ERR "hda_codec: cannot build PCMs"
2942 "for #%d (error %d)\n", codec->addr, err);
2943 err = snd_hda_codec_reset(codec);
2944 if (err < 0) {
2945 printk(KERN_ERR
2946 "hda_codec: cannot revert codec\n");
2947 return err;
2948 }
2949 }
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002950 }
2951 for (pcm = 0; pcm < codec->num_pcms; pcm++) {
2952 struct hda_pcm *cpcm = &codec->pcm_info[pcm];
2953 int dev;
2954
2955 if (!cpcm->stream[0].substreams && !cpcm->stream[1].substreams)
Takashi Iwai41b5b012009-01-20 18:21:23 +01002956 continue; /* no substreams assigned */
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002957
2958 if (!cpcm->pcm) {
2959 dev = get_empty_pcm_device(codec->bus, cpcm->pcm_type);
2960 if (dev < 0)
Takashi Iwai6e655bf2009-03-02 10:46:03 +01002961 continue; /* no fatal error */
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002962 cpcm->device = dev;
2963 err = snd_hda_attach_pcm(codec, cpcm);
Takashi Iwai6e655bf2009-03-02 10:46:03 +01002964 if (err < 0) {
2965 printk(KERN_ERR "hda_codec: cannot attach "
2966 "PCM stream %d for codec #%d\n",
2967 dev, codec->addr);
2968 continue; /* no fatal error */
2969 }
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002970 }
2971 }
2972 return 0;
2973}
2974
Linus Torvalds1da177e2005-04-16 15:20:36 -07002975/**
2976 * snd_hda_build_pcms - build PCM information
2977 * @bus: the BUS
2978 *
2979 * Create PCM information for each codec included in the bus.
2980 *
2981 * The build_pcms codec patch is requested to set up codec->num_pcms and
2982 * codec->pcm_info properly. The array is referred by the top-level driver
2983 * to create its PCM instances.
2984 * The allocated codec->pcm_info should be released in codec->patch_ops.free
2985 * callback.
2986 *
2987 * At least, substreams, channels_min and channels_max must be filled for
2988 * each stream. substreams = 0 indicates that the stream doesn't exist.
2989 * When rates and/or formats are zero, the supported values are queried
2990 * from the given nid. The nid is used also by the default ops.prepare
2991 * and ops.cleanup callbacks.
2992 *
2993 * The driver needs to call ops.open in its open callback. Similarly,
2994 * ops.close is supposed to be called in the close callback.
2995 * ops.prepare should be called in the prepare or hw_params callback
2996 * with the proper parameters for set up.
2997 * ops.cleanup should be called in hw_free for clean up of streams.
2998 *
2999 * This function returns 0 if successfull, or a negative error code.
3000 */
Takashi Iwai529bd6c2008-11-27 14:17:01 +01003001int __devinit snd_hda_build_pcms(struct hda_bus *bus)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003002{
Takashi Iwai0ba21762007-04-16 11:29:14 +02003003 struct hda_codec *codec;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003004
Takashi Iwai0ba21762007-04-16 11:29:14 +02003005 list_for_each_entry(codec, &bus->codec_list, list) {
Takashi Iwai529bd6c2008-11-27 14:17:01 +01003006 int err = snd_hda_codec_build_pcms(codec);
3007 if (err < 0)
3008 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003009 }
3010 return 0;
3011}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003012EXPORT_SYMBOL_HDA(snd_hda_build_pcms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003013
Linus Torvalds1da177e2005-04-16 15:20:36 -07003014/**
3015 * snd_hda_check_board_config - compare the current codec with the config table
3016 * @codec: the HDA codec
Takashi Iwaif5fcc132006-11-24 17:07:44 +01003017 * @num_configs: number of config enums
3018 * @models: array of model name strings
Linus Torvalds1da177e2005-04-16 15:20:36 -07003019 * @tbl: configuration table, terminated by null entries
3020 *
3021 * Compares the modelname or PCI subsystem id of the current codec with the
3022 * given configuration table. If a matching entry is found, returns its
3023 * config value (supposed to be 0 or positive).
3024 *
3025 * If no entries are matching, the function returns a negative value.
3026 */
Takashi Iwai12f288b2007-08-02 15:51:59 +02003027int snd_hda_check_board_config(struct hda_codec *codec,
3028 int num_configs, const char **models,
3029 const struct snd_pci_quirk *tbl)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003030{
Takashi Iwaif44ac832008-07-30 15:01:45 +02003031 if (codec->modelname && models) {
Takashi Iwaif5fcc132006-11-24 17:07:44 +01003032 int i;
3033 for (i = 0; i < num_configs; i++) {
3034 if (models[i] &&
Takashi Iwaif44ac832008-07-30 15:01:45 +02003035 !strcmp(codec->modelname, models[i])) {
Takashi Iwaif5fcc132006-11-24 17:07:44 +01003036 snd_printd(KERN_INFO "hda_codec: model '%s' is "
3037 "selected\n", models[i]);
3038 return i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003039 }
3040 }
3041 }
3042
Takashi Iwaif5fcc132006-11-24 17:07:44 +01003043 if (!codec->bus->pci || !tbl)
3044 return -1;
3045
3046 tbl = snd_pci_quirk_lookup(codec->bus->pci, tbl);
3047 if (!tbl)
3048 return -1;
3049 if (tbl->value >= 0 && tbl->value < num_configs) {
Takashi Iwai62cf8722008-05-20 12:15:15 +02003050#ifdef CONFIG_SND_DEBUG_VERBOSE
Takashi Iwaif5fcc132006-11-24 17:07:44 +01003051 char tmp[10];
3052 const char *model = NULL;
3053 if (models)
3054 model = models[tbl->value];
3055 if (!model) {
3056 sprintf(tmp, "#%d", tbl->value);
3057 model = tmp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003058 }
Takashi Iwaif5fcc132006-11-24 17:07:44 +01003059 snd_printdd(KERN_INFO "hda_codec: model '%s' is selected "
3060 "for config %x:%x (%s)\n",
3061 model, tbl->subvendor, tbl->subdevice,
3062 (tbl->name ? tbl->name : "Unknown device"));
3063#endif
3064 return tbl->value;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003065 }
3066 return -1;
3067}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003068EXPORT_SYMBOL_HDA(snd_hda_check_board_config);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003069
3070/**
Mauro Carvalho Chehab2eda3442008-08-11 10:18:39 +02003071 * snd_hda_check_board_codec_sid_config - compare the current codec
3072 subsystem ID with the
3073 config table
3074
3075 This is important for Gateway notebooks with SB450 HDA Audio
3076 where the vendor ID of the PCI device is:
3077 ATI Technologies Inc SB450 HDA Audio [1002:437b]
3078 and the vendor/subvendor are found only at the codec.
3079
3080 * @codec: the HDA codec
3081 * @num_configs: number of config enums
3082 * @models: array of model name strings
3083 * @tbl: configuration table, terminated by null entries
3084 *
3085 * Compares the modelname or PCI subsystem id of the current codec with the
3086 * given configuration table. If a matching entry is found, returns its
3087 * config value (supposed to be 0 or positive).
3088 *
3089 * If no entries are matching, the function returns a negative value.
3090 */
3091int snd_hda_check_board_codec_sid_config(struct hda_codec *codec,
3092 int num_configs, const char **models,
3093 const struct snd_pci_quirk *tbl)
3094{
3095 const struct snd_pci_quirk *q;
3096
3097 /* Search for codec ID */
3098 for (q = tbl; q->subvendor; q++) {
3099 unsigned long vendorid = (q->subdevice) | (q->subvendor << 16);
3100
3101 if (vendorid == codec->subsystem_id)
3102 break;
3103 }
3104
3105 if (!q->subvendor)
3106 return -1;
3107
3108 tbl = q;
3109
3110 if (tbl->value >= 0 && tbl->value < num_configs) {
3111#ifdef CONFIG_SND_DEBUG_DETECT
3112 char tmp[10];
3113 const char *model = NULL;
3114 if (models)
3115 model = models[tbl->value];
3116 if (!model) {
3117 sprintf(tmp, "#%d", tbl->value);
3118 model = tmp;
3119 }
3120 snd_printdd(KERN_INFO "hda_codec: model '%s' is selected "
3121 "for config %x:%x (%s)\n",
3122 model, tbl->subvendor, tbl->subdevice,
3123 (tbl->name ? tbl->name : "Unknown device"));
3124#endif
3125 return tbl->value;
3126 }
3127 return -1;
3128}
3129EXPORT_SYMBOL_HDA(snd_hda_check_board_codec_sid_config);
3130
3131/**
Linus Torvalds1da177e2005-04-16 15:20:36 -07003132 * snd_hda_add_new_ctls - create controls from the array
3133 * @codec: the HDA codec
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01003134 * @knew: the array of struct snd_kcontrol_new
Linus Torvalds1da177e2005-04-16 15:20:36 -07003135 *
3136 * This helper function creates and add new controls in the given array.
3137 * The array must be terminated with an empty entry as terminator.
3138 *
3139 * Returns 0 if successful, or a negative error code.
3140 */
Takashi Iwai12f288b2007-08-02 15:51:59 +02003141int snd_hda_add_new_ctls(struct hda_codec *codec, struct snd_kcontrol_new *knew)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003142{
Takashi Iwaicb53c622007-08-10 17:21:45 +02003143 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003144
3145 for (; knew->name; knew++) {
Takashi Iwai54d17402005-11-21 16:33:22 +01003146 struct snd_kcontrol *kctl;
3147 kctl = snd_ctl_new1(knew, codec);
Takashi Iwai0ba21762007-04-16 11:29:14 +02003148 if (!kctl)
Takashi Iwai54d17402005-11-21 16:33:22 +01003149 return -ENOMEM;
Takashi Iwaid13bd412008-07-30 15:01:45 +02003150 err = snd_hda_ctl_add(codec, kctl);
Takashi Iwai54d17402005-11-21 16:33:22 +01003151 if (err < 0) {
Takashi Iwai0ba21762007-04-16 11:29:14 +02003152 if (!codec->addr)
Takashi Iwai54d17402005-11-21 16:33:22 +01003153 return err;
3154 kctl = snd_ctl_new1(knew, codec);
Takashi Iwai0ba21762007-04-16 11:29:14 +02003155 if (!kctl)
Takashi Iwai54d17402005-11-21 16:33:22 +01003156 return -ENOMEM;
3157 kctl->id.device = codec->addr;
Takashi Iwaid13bd412008-07-30 15:01:45 +02003158 err = snd_hda_ctl_add(codec, kctl);
Takashi Iwai0ba21762007-04-16 11:29:14 +02003159 if (err < 0)
Takashi Iwai54d17402005-11-21 16:33:22 +01003160 return err;
3161 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003162 }
3163 return 0;
3164}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003165EXPORT_SYMBOL_HDA(snd_hda_add_new_ctls);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003166
Takashi Iwaicb53c622007-08-10 17:21:45 +02003167#ifdef CONFIG_SND_HDA_POWER_SAVE
3168static void hda_set_power_state(struct hda_codec *codec, hda_nid_t fg,
3169 unsigned int power_state);
3170
3171static void hda_power_work(struct work_struct *work)
3172{
3173 struct hda_codec *codec =
3174 container_of(work, struct hda_codec, power_work.work);
Takashi Iwai33fa35e2008-11-06 16:50:40 +01003175 struct hda_bus *bus = codec->bus;
Takashi Iwaicb53c622007-08-10 17:21:45 +02003176
Maxim Levitsky2e492462007-09-03 15:26:57 +02003177 if (!codec->power_on || codec->power_count) {
3178 codec->power_transition = 0;
Takashi Iwaicb53c622007-08-10 17:21:45 +02003179 return;
Maxim Levitsky2e492462007-09-03 15:26:57 +02003180 }
Takashi Iwaicb53c622007-08-10 17:21:45 +02003181
3182 hda_call_codec_suspend(codec);
Takashi Iwai33fa35e2008-11-06 16:50:40 +01003183 if (bus->ops.pm_notify)
3184 bus->ops.pm_notify(bus);
Takashi Iwaicb53c622007-08-10 17:21:45 +02003185}
3186
3187static void hda_keep_power_on(struct hda_codec *codec)
3188{
3189 codec->power_count++;
3190 codec->power_on = 1;
3191}
3192
3193void snd_hda_power_up(struct hda_codec *codec)
3194{
Takashi Iwai33fa35e2008-11-06 16:50:40 +01003195 struct hda_bus *bus = codec->bus;
3196
Takashi Iwaicb53c622007-08-10 17:21:45 +02003197 codec->power_count++;
Takashi Iwaia221e282007-08-16 16:35:33 +02003198 if (codec->power_on || codec->power_transition)
Takashi Iwaicb53c622007-08-10 17:21:45 +02003199 return;
3200
3201 codec->power_on = 1;
Takashi Iwai33fa35e2008-11-06 16:50:40 +01003202 if (bus->ops.pm_notify)
3203 bus->ops.pm_notify(bus);
Takashi Iwaicb53c622007-08-10 17:21:45 +02003204 hda_call_codec_resume(codec);
3205 cancel_delayed_work(&codec->power_work);
Takashi Iwaia221e282007-08-16 16:35:33 +02003206 codec->power_transition = 0;
Takashi Iwaicb53c622007-08-10 17:21:45 +02003207}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003208EXPORT_SYMBOL_HDA(snd_hda_power_up);
Takashi Iwai1289e9e2008-11-27 15:47:11 +01003209
3210#define power_save(codec) \
3211 ((codec)->bus->power_save ? *(codec)->bus->power_save : 0)
Takashi Iwaicb53c622007-08-10 17:21:45 +02003212
Takashi Iwaifee2fba2008-11-27 12:43:28 +01003213#define power_save(codec) \
3214 ((codec)->bus->power_save ? *(codec)->bus->power_save : 0)
3215
Takashi Iwaicb53c622007-08-10 17:21:45 +02003216void snd_hda_power_down(struct hda_codec *codec)
3217{
3218 --codec->power_count;
Takashi Iwaia221e282007-08-16 16:35:33 +02003219 if (!codec->power_on || codec->power_count || codec->power_transition)
Takashi Iwaicb53c622007-08-10 17:21:45 +02003220 return;
Takashi Iwaifee2fba2008-11-27 12:43:28 +01003221 if (power_save(codec)) {
Takashi Iwaia221e282007-08-16 16:35:33 +02003222 codec->power_transition = 1; /* avoid reentrance */
Takashi Iwaic107b412009-01-13 17:46:37 +01003223 queue_delayed_work(codec->bus->workq, &codec->power_work,
Takashi Iwaifee2fba2008-11-27 12:43:28 +01003224 msecs_to_jiffies(power_save(codec) * 1000));
Takashi Iwaia221e282007-08-16 16:35:33 +02003225 }
Takashi Iwaicb53c622007-08-10 17:21:45 +02003226}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003227EXPORT_SYMBOL_HDA(snd_hda_power_down);
Takashi Iwaicb53c622007-08-10 17:21:45 +02003228
3229int snd_hda_check_amp_list_power(struct hda_codec *codec,
3230 struct hda_loopback_check *check,
3231 hda_nid_t nid)
3232{
3233 struct hda_amp_list *p;
3234 int ch, v;
3235
3236 if (!check->amplist)
3237 return 0;
3238 for (p = check->amplist; p->nid; p++) {
3239 if (p->nid == nid)
3240 break;
3241 }
3242 if (!p->nid)
3243 return 0; /* nothing changed */
3244
3245 for (p = check->amplist; p->nid; p++) {
3246 for (ch = 0; ch < 2; ch++) {
3247 v = snd_hda_codec_amp_read(codec, p->nid, ch, p->dir,
3248 p->idx);
3249 if (!(v & HDA_AMP_MUTE) && v > 0) {
3250 if (!check->power_on) {
3251 check->power_on = 1;
3252 snd_hda_power_up(codec);
3253 }
3254 return 1;
3255 }
3256 }
3257 }
3258 if (check->power_on) {
3259 check->power_on = 0;
3260 snd_hda_power_down(codec);
3261 }
3262 return 0;
3263}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003264EXPORT_SYMBOL_HDA(snd_hda_check_amp_list_power);
Takashi Iwaicb53c622007-08-10 17:21:45 +02003265#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07003266
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01003267/*
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01003268 * Channel mode helper
3269 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003270int snd_hda_ch_mode_info(struct hda_codec *codec,
3271 struct snd_ctl_elem_info *uinfo,
3272 const struct hda_channel_mode *chmode,
3273 int num_chmodes)
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01003274{
3275 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
3276 uinfo->count = 1;
3277 uinfo->value.enumerated.items = num_chmodes;
3278 if (uinfo->value.enumerated.item >= num_chmodes)
3279 uinfo->value.enumerated.item = num_chmodes - 1;
3280 sprintf(uinfo->value.enumerated.name, "%dch",
3281 chmode[uinfo->value.enumerated.item].channels);
3282 return 0;
3283}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003284EXPORT_SYMBOL_HDA(snd_hda_ch_mode_info);
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01003285
Takashi Iwai0ba21762007-04-16 11:29:14 +02003286int snd_hda_ch_mode_get(struct hda_codec *codec,
3287 struct snd_ctl_elem_value *ucontrol,
3288 const struct hda_channel_mode *chmode,
3289 int num_chmodes,
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01003290 int max_channels)
3291{
3292 int i;
3293
3294 for (i = 0; i < num_chmodes; i++) {
3295 if (max_channels == chmode[i].channels) {
3296 ucontrol->value.enumerated.item[0] = i;
3297 break;
3298 }
3299 }
3300 return 0;
3301}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003302EXPORT_SYMBOL_HDA(snd_hda_ch_mode_get);
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01003303
Takashi Iwai0ba21762007-04-16 11:29:14 +02003304int snd_hda_ch_mode_put(struct hda_codec *codec,
3305 struct snd_ctl_elem_value *ucontrol,
3306 const struct hda_channel_mode *chmode,
3307 int num_chmodes,
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01003308 int *max_channelsp)
3309{
3310 unsigned int mode;
3311
3312 mode = ucontrol->value.enumerated.item[0];
Takashi Iwai68ea7b22007-11-15 15:54:38 +01003313 if (mode >= num_chmodes)
3314 return -EINVAL;
Takashi Iwai82beb8f2007-08-10 17:09:26 +02003315 if (*max_channelsp == chmode[mode].channels)
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01003316 return 0;
3317 /* change the current channel setting */
3318 *max_channelsp = chmode[mode].channels;
3319 if (chmode[mode].sequence)
Takashi Iwai82beb8f2007-08-10 17:09:26 +02003320 snd_hda_sequence_write_cache(codec, chmode[mode].sequence);
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01003321 return 1;
3322}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003323EXPORT_SYMBOL_HDA(snd_hda_ch_mode_put);
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01003324
Linus Torvalds1da177e2005-04-16 15:20:36 -07003325/*
3326 * input MUX helper
3327 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003328int snd_hda_input_mux_info(const struct hda_input_mux *imux,
3329 struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003330{
3331 unsigned int index;
3332
3333 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
3334 uinfo->count = 1;
3335 uinfo->value.enumerated.items = imux->num_items;
Takashi Iwai5513b0c2007-10-09 11:58:41 +02003336 if (!imux->num_items)
3337 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003338 index = uinfo->value.enumerated.item;
3339 if (index >= imux->num_items)
3340 index = imux->num_items - 1;
3341 strcpy(uinfo->value.enumerated.name, imux->items[index].label);
3342 return 0;
3343}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003344EXPORT_SYMBOL_HDA(snd_hda_input_mux_info);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003345
Takashi Iwai0ba21762007-04-16 11:29:14 +02003346int snd_hda_input_mux_put(struct hda_codec *codec,
3347 const struct hda_input_mux *imux,
3348 struct snd_ctl_elem_value *ucontrol,
3349 hda_nid_t nid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003350 unsigned int *cur_val)
3351{
3352 unsigned int idx;
3353
Takashi Iwai5513b0c2007-10-09 11:58:41 +02003354 if (!imux->num_items)
3355 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003356 idx = ucontrol->value.enumerated.item[0];
3357 if (idx >= imux->num_items)
3358 idx = imux->num_items - 1;
Takashi Iwai82beb8f2007-08-10 17:09:26 +02003359 if (*cur_val == idx)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003360 return 0;
Takashi Iwai82beb8f2007-08-10 17:09:26 +02003361 snd_hda_codec_write_cache(codec, nid, 0, AC_VERB_SET_CONNECT_SEL,
3362 imux->items[idx].index);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003363 *cur_val = idx;
3364 return 1;
3365}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003366EXPORT_SYMBOL_HDA(snd_hda_input_mux_put);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003367
3368
3369/*
3370 * Multi-channel / digital-out PCM helper functions
3371 */
3372
Takashi Iwai6b97eb42007-04-05 14:51:48 +02003373/* setup SPDIF output stream */
3374static void setup_dig_out_stream(struct hda_codec *codec, hda_nid_t nid,
3375 unsigned int stream_tag, unsigned int format)
3376{
3377 /* turn off SPDIF once; otherwise the IEC958 bits won't be updated */
Takashi Iwai2f728532008-09-25 16:32:41 +02003378 if (codec->spdif_status_reset && (codec->spdif_ctls & AC_DIG1_ENABLE))
3379 set_dig_out_convert(codec, nid,
3380 codec->spdif_ctls & ~AC_DIG1_ENABLE & 0xff,
3381 -1);
Takashi Iwai6b97eb42007-04-05 14:51:48 +02003382 snd_hda_codec_setup_stream(codec, nid, stream_tag, 0, format);
Takashi Iwai2f728532008-09-25 16:32:41 +02003383 if (codec->slave_dig_outs) {
3384 hda_nid_t *d;
3385 for (d = codec->slave_dig_outs; *d; d++)
3386 snd_hda_codec_setup_stream(codec, *d, stream_tag, 0,
3387 format);
Matthew Ranostayde51ca12008-09-07 14:31:40 -04003388 }
Takashi Iwai2f728532008-09-25 16:32:41 +02003389 /* turn on again (if needed) */
3390 if (codec->spdif_status_reset && (codec->spdif_ctls & AC_DIG1_ENABLE))
3391 set_dig_out_convert(codec, nid,
3392 codec->spdif_ctls & 0xff, -1);
3393}
Matthew Ranostayde51ca12008-09-07 14:31:40 -04003394
Takashi Iwai2f728532008-09-25 16:32:41 +02003395static void cleanup_dig_out_stream(struct hda_codec *codec, hda_nid_t nid)
3396{
3397 snd_hda_codec_cleanup_stream(codec, nid);
3398 if (codec->slave_dig_outs) {
3399 hda_nid_t *d;
3400 for (d = codec->slave_dig_outs; *d; d++)
3401 snd_hda_codec_cleanup_stream(codec, *d);
3402 }
Takashi Iwai6b97eb42007-04-05 14:51:48 +02003403}
3404
Linus Torvalds1da177e2005-04-16 15:20:36 -07003405/*
3406 * open the digital out in the exclusive mode
3407 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003408int snd_hda_multi_out_dig_open(struct hda_codec *codec,
3409 struct hda_multi_out *mout)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003410{
Ingo Molnar62932df2006-01-16 16:34:20 +01003411 mutex_lock(&codec->spdif_mutex);
Takashi Iwai5930ca42007-04-16 11:23:56 +02003412 if (mout->dig_out_used == HDA_DIG_ANALOG_DUP)
3413 /* already opened as analog dup; reset it once */
Takashi Iwai2f728532008-09-25 16:32:41 +02003414 cleanup_dig_out_stream(codec, mout->dig_out_nid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003415 mout->dig_out_used = HDA_DIG_EXCLUSIVE;
Ingo Molnar62932df2006-01-16 16:34:20 +01003416 mutex_unlock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003417 return 0;
3418}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003419EXPORT_SYMBOL_HDA(snd_hda_multi_out_dig_open);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003420
Takashi Iwai6b97eb42007-04-05 14:51:48 +02003421int snd_hda_multi_out_dig_prepare(struct hda_codec *codec,
3422 struct hda_multi_out *mout,
3423 unsigned int stream_tag,
3424 unsigned int format,
3425 struct snd_pcm_substream *substream)
3426{
3427 mutex_lock(&codec->spdif_mutex);
3428 setup_dig_out_stream(codec, mout->dig_out_nid, stream_tag, format);
3429 mutex_unlock(&codec->spdif_mutex);
3430 return 0;
3431}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003432EXPORT_SYMBOL_HDA(snd_hda_multi_out_dig_prepare);
Takashi Iwai6b97eb42007-04-05 14:51:48 +02003433
Takashi Iwai9411e212009-02-13 11:32:28 +01003434int snd_hda_multi_out_dig_cleanup(struct hda_codec *codec,
3435 struct hda_multi_out *mout)
3436{
3437 mutex_lock(&codec->spdif_mutex);
3438 cleanup_dig_out_stream(codec, mout->dig_out_nid);
3439 mutex_unlock(&codec->spdif_mutex);
3440 return 0;
3441}
3442EXPORT_SYMBOL_HDA(snd_hda_multi_out_dig_cleanup);
3443
Linus Torvalds1da177e2005-04-16 15:20:36 -07003444/*
3445 * release the digital out
3446 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003447int snd_hda_multi_out_dig_close(struct hda_codec *codec,
3448 struct hda_multi_out *mout)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003449{
Ingo Molnar62932df2006-01-16 16:34:20 +01003450 mutex_lock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003451 mout->dig_out_used = 0;
Ingo Molnar62932df2006-01-16 16:34:20 +01003452 mutex_unlock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003453 return 0;
3454}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003455EXPORT_SYMBOL_HDA(snd_hda_multi_out_dig_close);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003456
3457/*
3458 * set up more restrictions for analog out
3459 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003460int snd_hda_multi_out_analog_open(struct hda_codec *codec,
3461 struct hda_multi_out *mout,
Takashi Iwai9a081602008-02-12 18:37:26 +01003462 struct snd_pcm_substream *substream,
3463 struct hda_pcm_stream *hinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003464{
Takashi Iwai9a081602008-02-12 18:37:26 +01003465 struct snd_pcm_runtime *runtime = substream->runtime;
3466 runtime->hw.channels_max = mout->max_channels;
3467 if (mout->dig_out_nid) {
3468 if (!mout->analog_rates) {
3469 mout->analog_rates = hinfo->rates;
3470 mout->analog_formats = hinfo->formats;
3471 mout->analog_maxbps = hinfo->maxbps;
3472 } else {
3473 runtime->hw.rates = mout->analog_rates;
3474 runtime->hw.formats = mout->analog_formats;
3475 hinfo->maxbps = mout->analog_maxbps;
3476 }
3477 if (!mout->spdif_rates) {
3478 snd_hda_query_supported_pcm(codec, mout->dig_out_nid,
3479 &mout->spdif_rates,
3480 &mout->spdif_formats,
3481 &mout->spdif_maxbps);
3482 }
3483 mutex_lock(&codec->spdif_mutex);
3484 if (mout->share_spdif) {
Takashi Iwai022b4662009-07-03 23:03:30 +02003485 if ((runtime->hw.rates & mout->spdif_rates) &&
3486 (runtime->hw.formats & mout->spdif_formats)) {
3487 runtime->hw.rates &= mout->spdif_rates;
3488 runtime->hw.formats &= mout->spdif_formats;
3489 if (mout->spdif_maxbps < hinfo->maxbps)
3490 hinfo->maxbps = mout->spdif_maxbps;
3491 } else {
3492 mout->share_spdif = 0;
3493 /* FIXME: need notify? */
3494 }
Takashi Iwai9a081602008-02-12 18:37:26 +01003495 }
Frederik Deweerdteaa99852008-04-14 13:11:44 +02003496 mutex_unlock(&codec->spdif_mutex);
Takashi Iwai9a081602008-02-12 18:37:26 +01003497 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003498 return snd_pcm_hw_constraint_step(substream->runtime, 0,
3499 SNDRV_PCM_HW_PARAM_CHANNELS, 2);
3500}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003501EXPORT_SYMBOL_HDA(snd_hda_multi_out_analog_open);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003502
3503/*
3504 * set up the i/o for analog out
3505 * when the digital out is available, copy the front out to digital out, too.
3506 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003507int snd_hda_multi_out_analog_prepare(struct hda_codec *codec,
3508 struct hda_multi_out *mout,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003509 unsigned int stream_tag,
3510 unsigned int format,
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01003511 struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003512{
3513 hda_nid_t *nids = mout->dac_nids;
3514 int chs = substream->runtime->channels;
3515 int i;
3516
Ingo Molnar62932df2006-01-16 16:34:20 +01003517 mutex_lock(&codec->spdif_mutex);
Takashi Iwai9a081602008-02-12 18:37:26 +01003518 if (mout->dig_out_nid && mout->share_spdif &&
3519 mout->dig_out_used != HDA_DIG_EXCLUSIVE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003520 if (chs == 2 &&
Takashi Iwai0ba21762007-04-16 11:29:14 +02003521 snd_hda_is_supported_format(codec, mout->dig_out_nid,
3522 format) &&
3523 !(codec->spdif_status & IEC958_AES0_NONAUDIO)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003524 mout->dig_out_used = HDA_DIG_ANALOG_DUP;
Takashi Iwai6b97eb42007-04-05 14:51:48 +02003525 setup_dig_out_stream(codec, mout->dig_out_nid,
3526 stream_tag, format);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003527 } else {
3528 mout->dig_out_used = 0;
Takashi Iwai2f728532008-09-25 16:32:41 +02003529 cleanup_dig_out_stream(codec, mout->dig_out_nid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003530 }
3531 }
Ingo Molnar62932df2006-01-16 16:34:20 +01003532 mutex_unlock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003533
3534 /* front */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003535 snd_hda_codec_setup_stream(codec, nids[HDA_FRONT], stream_tag,
3536 0, format);
Takashi Iwaid29240c2007-10-26 12:35:56 +02003537 if (!mout->no_share_stream &&
3538 mout->hp_nid && mout->hp_nid != nids[HDA_FRONT])
Linus Torvalds1da177e2005-04-16 15:20:36 -07003539 /* headphone out will just decode front left/right (stereo) */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003540 snd_hda_codec_setup_stream(codec, mout->hp_nid, stream_tag,
3541 0, format);
Takashi Iwai82bc9552006-03-21 11:24:42 +01003542 /* extra outputs copied from front */
3543 for (i = 0; i < ARRAY_SIZE(mout->extra_out_nid); i++)
Takashi Iwaid29240c2007-10-26 12:35:56 +02003544 if (!mout->no_share_stream && mout->extra_out_nid[i])
Takashi Iwai82bc9552006-03-21 11:24:42 +01003545 snd_hda_codec_setup_stream(codec,
3546 mout->extra_out_nid[i],
3547 stream_tag, 0, format);
3548
Linus Torvalds1da177e2005-04-16 15:20:36 -07003549 /* surrounds */
3550 for (i = 1; i < mout->num_dacs; i++) {
Takashi Iwai4b3acaf2005-06-10 19:48:10 +02003551 if (chs >= (i + 1) * 2) /* independent out */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003552 snd_hda_codec_setup_stream(codec, nids[i], stream_tag,
3553 i * 2, format);
Takashi Iwaid29240c2007-10-26 12:35:56 +02003554 else if (!mout->no_share_stream) /* copy front */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003555 snd_hda_codec_setup_stream(codec, nids[i], stream_tag,
3556 0, format);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003557 }
3558 return 0;
3559}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003560EXPORT_SYMBOL_HDA(snd_hda_multi_out_analog_prepare);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003561
3562/*
3563 * clean up the setting for analog out
3564 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003565int snd_hda_multi_out_analog_cleanup(struct hda_codec *codec,
3566 struct hda_multi_out *mout)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003567{
3568 hda_nid_t *nids = mout->dac_nids;
3569 int i;
3570
3571 for (i = 0; i < mout->num_dacs; i++)
Takashi Iwai888afa12008-03-18 09:57:50 +01003572 snd_hda_codec_cleanup_stream(codec, nids[i]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003573 if (mout->hp_nid)
Takashi Iwai888afa12008-03-18 09:57:50 +01003574 snd_hda_codec_cleanup_stream(codec, mout->hp_nid);
Takashi Iwai82bc9552006-03-21 11:24:42 +01003575 for (i = 0; i < ARRAY_SIZE(mout->extra_out_nid); i++)
3576 if (mout->extra_out_nid[i])
Takashi Iwai888afa12008-03-18 09:57:50 +01003577 snd_hda_codec_cleanup_stream(codec,
3578 mout->extra_out_nid[i]);
Ingo Molnar62932df2006-01-16 16:34:20 +01003579 mutex_lock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003580 if (mout->dig_out_nid && mout->dig_out_used == HDA_DIG_ANALOG_DUP) {
Takashi Iwai2f728532008-09-25 16:32:41 +02003581 cleanup_dig_out_stream(codec, mout->dig_out_nid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003582 mout->dig_out_used = 0;
3583 }
Ingo Molnar62932df2006-01-16 16:34:20 +01003584 mutex_unlock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003585 return 0;
3586}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003587EXPORT_SYMBOL_HDA(snd_hda_multi_out_analog_cleanup);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003588
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003589/*
Wu Fengguang6b345002008-10-07 14:21:41 +08003590 * Helper for automatic pin configuration
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003591 */
Kailang Yangdf694da2005-12-05 19:42:22 +01003592
Takashi Iwai12f288b2007-08-02 15:51:59 +02003593static int is_in_nid_list(hda_nid_t nid, hda_nid_t *list)
Kailang Yangdf694da2005-12-05 19:42:22 +01003594{
3595 for (; *list; list++)
3596 if (*list == nid)
3597 return 1;
3598 return 0;
3599}
3600
Steve Longerbeam81937d32007-05-08 15:33:03 +02003601
3602/*
3603 * Sort an associated group of pins according to their sequence numbers.
3604 */
3605static void sort_pins_by_sequence(hda_nid_t * pins, short * sequences,
3606 int num_pins)
3607{
3608 int i, j;
3609 short seq;
3610 hda_nid_t nid;
3611
3612 for (i = 0; i < num_pins; i++) {
3613 for (j = i + 1; j < num_pins; j++) {
3614 if (sequences[i] > sequences[j]) {
3615 seq = sequences[i];
3616 sequences[i] = sequences[j];
3617 sequences[j] = seq;
3618 nid = pins[i];
3619 pins[i] = pins[j];
3620 pins[j] = nid;
3621 }
3622 }
3623 }
3624}
3625
3626
Takashi Iwai82bc9552006-03-21 11:24:42 +01003627/*
3628 * Parse all pin widgets and store the useful pin nids to cfg
3629 *
3630 * The number of line-outs or any primary output is stored in line_outs,
3631 * and the corresponding output pins are assigned to line_out_pins[],
3632 * in the order of front, rear, CLFE, side, ...
3633 *
3634 * If more extra outputs (speaker and headphone) are found, the pins are
Takashi Iwaieb06ed82006-09-20 17:10:27 +02003635 * assisnged to hp_pins[] and speaker_pins[], respectively. If no line-out jack
Takashi Iwai82bc9552006-03-21 11:24:42 +01003636 * is detected, one of speaker of HP pins is assigned as the primary
3637 * output, i.e. to line_out_pins[0]. So, line_outs is always positive
3638 * if any analog output exists.
3639 *
3640 * The analog input pins are assigned to input_pins array.
3641 * The digital input/output pins are assigned to dig_in_pin and dig_out_pin,
3642 * respectively.
3643 */
Takashi Iwai12f288b2007-08-02 15:51:59 +02003644int snd_hda_parse_pin_def_config(struct hda_codec *codec,
3645 struct auto_pin_cfg *cfg,
3646 hda_nid_t *ignore_nids)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003647{
Takashi Iwai0ef6ce72008-01-22 15:35:37 +01003648 hda_nid_t nid, end_nid;
Steve Longerbeam81937d32007-05-08 15:33:03 +02003649 short seq, assoc_line_out, assoc_speaker;
3650 short sequences_line_out[ARRAY_SIZE(cfg->line_out_pins)];
3651 short sequences_speaker[ARRAY_SIZE(cfg->speaker_pins)];
Takashi Iwaif889fa92007-10-31 15:49:32 +01003652 short sequences_hp[ARRAY_SIZE(cfg->hp_pins)];
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003653
3654 memset(cfg, 0, sizeof(*cfg));
3655
Steve Longerbeam81937d32007-05-08 15:33:03 +02003656 memset(sequences_line_out, 0, sizeof(sequences_line_out));
3657 memset(sequences_speaker, 0, sizeof(sequences_speaker));
Takashi Iwaif889fa92007-10-31 15:49:32 +01003658 memset(sequences_hp, 0, sizeof(sequences_hp));
Steve Longerbeam81937d32007-05-08 15:33:03 +02003659 assoc_line_out = assoc_speaker = 0;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003660
Takashi Iwai0ef6ce72008-01-22 15:35:37 +01003661 end_nid = codec->start_nid + codec->num_nodes;
3662 for (nid = codec->start_nid; nid < end_nid; nid++) {
Takashi Iwai54d17402005-11-21 16:33:22 +01003663 unsigned int wid_caps = get_wcaps(codec, nid);
Takashi Iwai0ba21762007-04-16 11:29:14 +02003664 unsigned int wid_type =
3665 (wid_caps & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003666 unsigned int def_conf;
3667 short assoc, loc;
3668
3669 /* read all default configuration for pin complex */
3670 if (wid_type != AC_WID_PIN)
3671 continue;
Kailang Yangdf694da2005-12-05 19:42:22 +01003672 /* ignore the given nids (e.g. pc-beep returns error) */
3673 if (ignore_nids && is_in_nid_list(nid, ignore_nids))
3674 continue;
3675
Takashi Iwaic17a1ab2009-02-23 09:28:12 +01003676 def_conf = snd_hda_codec_get_pincfg(codec, nid);
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003677 if (get_defcfg_connect(def_conf) == AC_JACK_PORT_NONE)
3678 continue;
3679 loc = get_defcfg_location(def_conf);
3680 switch (get_defcfg_device(def_conf)) {
3681 case AC_JACK_LINE_OUT:
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003682 seq = get_defcfg_sequence(def_conf);
3683 assoc = get_defcfg_association(def_conf);
Matthew Ranostay90da78b2008-01-24 11:48:01 +01003684
3685 if (!(wid_caps & AC_WCAP_STEREO))
3686 if (!cfg->mono_out_pin)
3687 cfg->mono_out_pin = nid;
Takashi Iwai0ba21762007-04-16 11:29:14 +02003688 if (!assoc)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003689 continue;
Takashi Iwai0ba21762007-04-16 11:29:14 +02003690 if (!assoc_line_out)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003691 assoc_line_out = assoc;
3692 else if (assoc_line_out != assoc)
3693 continue;
3694 if (cfg->line_outs >= ARRAY_SIZE(cfg->line_out_pins))
3695 continue;
3696 cfg->line_out_pins[cfg->line_outs] = nid;
Steve Longerbeam81937d32007-05-08 15:33:03 +02003697 sequences_line_out[cfg->line_outs] = seq;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003698 cfg->line_outs++;
3699 break;
Takashi Iwai8d88bc32005-11-17 11:09:23 +01003700 case AC_JACK_SPEAKER:
Steve Longerbeam81937d32007-05-08 15:33:03 +02003701 seq = get_defcfg_sequence(def_conf);
3702 assoc = get_defcfg_association(def_conf);
3703 if (! assoc)
3704 continue;
3705 if (! assoc_speaker)
3706 assoc_speaker = assoc;
3707 else if (assoc_speaker != assoc)
3708 continue;
Takashi Iwai82bc9552006-03-21 11:24:42 +01003709 if (cfg->speaker_outs >= ARRAY_SIZE(cfg->speaker_pins))
3710 continue;
3711 cfg->speaker_pins[cfg->speaker_outs] = nid;
Steve Longerbeam81937d32007-05-08 15:33:03 +02003712 sequences_speaker[cfg->speaker_outs] = seq;
Takashi Iwai82bc9552006-03-21 11:24:42 +01003713 cfg->speaker_outs++;
Takashi Iwai8d88bc32005-11-17 11:09:23 +01003714 break;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003715 case AC_JACK_HP_OUT:
Takashi Iwaif889fa92007-10-31 15:49:32 +01003716 seq = get_defcfg_sequence(def_conf);
3717 assoc = get_defcfg_association(def_conf);
Takashi Iwaieb06ed82006-09-20 17:10:27 +02003718 if (cfg->hp_outs >= ARRAY_SIZE(cfg->hp_pins))
3719 continue;
3720 cfg->hp_pins[cfg->hp_outs] = nid;
Takashi Iwaif889fa92007-10-31 15:49:32 +01003721 sequences_hp[cfg->hp_outs] = (assoc << 4) | seq;
Takashi Iwaieb06ed82006-09-20 17:10:27 +02003722 cfg->hp_outs++;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003723 break;
Takashi Iwai314634b2006-09-21 11:56:18 +02003724 case AC_JACK_MIC_IN: {
3725 int preferred, alt;
3726 if (loc == AC_JACK_LOC_FRONT) {
3727 preferred = AUTO_PIN_FRONT_MIC;
3728 alt = AUTO_PIN_MIC;
3729 } else {
3730 preferred = AUTO_PIN_MIC;
3731 alt = AUTO_PIN_FRONT_MIC;
3732 }
3733 if (!cfg->input_pins[preferred])
3734 cfg->input_pins[preferred] = nid;
3735 else if (!cfg->input_pins[alt])
3736 cfg->input_pins[alt] = nid;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003737 break;
Takashi Iwai314634b2006-09-21 11:56:18 +02003738 }
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003739 case AC_JACK_LINE_IN:
3740 if (loc == AC_JACK_LOC_FRONT)
3741 cfg->input_pins[AUTO_PIN_FRONT_LINE] = nid;
3742 else
3743 cfg->input_pins[AUTO_PIN_LINE] = nid;
3744 break;
3745 case AC_JACK_CD:
3746 cfg->input_pins[AUTO_PIN_CD] = nid;
3747 break;
3748 case AC_JACK_AUX:
3749 cfg->input_pins[AUTO_PIN_AUX] = nid;
3750 break;
3751 case AC_JACK_SPDIF_OUT:
Takashi Iwai1b52ae72009-01-20 17:17:29 +01003752 case AC_JACK_DIG_OTHER_OUT:
Takashi Iwai0852d7a2009-02-11 11:35:15 +01003753 if (cfg->dig_outs >= ARRAY_SIZE(cfg->dig_out_pins))
3754 continue;
3755 cfg->dig_out_pins[cfg->dig_outs] = nid;
3756 cfg->dig_out_type[cfg->dig_outs] =
3757 (loc == AC_JACK_LOC_HDMI) ?
3758 HDA_PCM_TYPE_HDMI : HDA_PCM_TYPE_SPDIF;
3759 cfg->dig_outs++;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003760 break;
3761 case AC_JACK_SPDIF_IN:
Takashi Iwai1b52ae72009-01-20 17:17:29 +01003762 case AC_JACK_DIG_OTHER_IN:
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003763 cfg->dig_in_pin = nid;
Takashi Iwai2297bd62009-01-20 18:24:13 +01003764 if (loc == AC_JACK_LOC_HDMI)
3765 cfg->dig_in_type = HDA_PCM_TYPE_HDMI;
3766 else
3767 cfg->dig_in_type = HDA_PCM_TYPE_SPDIF;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003768 break;
3769 }
3770 }
3771
Takashi Iwai5832fcf2008-02-12 18:30:12 +01003772 /* FIX-UP:
3773 * If no line-out is defined but multiple HPs are found,
3774 * some of them might be the real line-outs.
3775 */
3776 if (!cfg->line_outs && cfg->hp_outs > 1) {
3777 int i = 0;
3778 while (i < cfg->hp_outs) {
3779 /* The real HPs should have the sequence 0x0f */
3780 if ((sequences_hp[i] & 0x0f) == 0x0f) {
3781 i++;
3782 continue;
3783 }
3784 /* Move it to the line-out table */
3785 cfg->line_out_pins[cfg->line_outs] = cfg->hp_pins[i];
3786 sequences_line_out[cfg->line_outs] = sequences_hp[i];
3787 cfg->line_outs++;
3788 cfg->hp_outs--;
3789 memmove(cfg->hp_pins + i, cfg->hp_pins + i + 1,
3790 sizeof(cfg->hp_pins[0]) * (cfg->hp_outs - i));
3791 memmove(sequences_hp + i - 1, sequences_hp + i,
3792 sizeof(sequences_hp[0]) * (cfg->hp_outs - i));
3793 }
3794 }
3795
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003796 /* sort by sequence */
Steve Longerbeam81937d32007-05-08 15:33:03 +02003797 sort_pins_by_sequence(cfg->line_out_pins, sequences_line_out,
3798 cfg->line_outs);
3799 sort_pins_by_sequence(cfg->speaker_pins, sequences_speaker,
3800 cfg->speaker_outs);
Takashi Iwaif889fa92007-10-31 15:49:32 +01003801 sort_pins_by_sequence(cfg->hp_pins, sequences_hp,
3802 cfg->hp_outs);
Steve Longerbeam81937d32007-05-08 15:33:03 +02003803
Takashi Iwaif889fa92007-10-31 15:49:32 +01003804 /* if we have only one mic, make it AUTO_PIN_MIC */
3805 if (!cfg->input_pins[AUTO_PIN_MIC] &&
3806 cfg->input_pins[AUTO_PIN_FRONT_MIC]) {
3807 cfg->input_pins[AUTO_PIN_MIC] =
3808 cfg->input_pins[AUTO_PIN_FRONT_MIC];
3809 cfg->input_pins[AUTO_PIN_FRONT_MIC] = 0;
3810 }
3811 /* ditto for line-in */
3812 if (!cfg->input_pins[AUTO_PIN_LINE] &&
3813 cfg->input_pins[AUTO_PIN_FRONT_LINE]) {
3814 cfg->input_pins[AUTO_PIN_LINE] =
3815 cfg->input_pins[AUTO_PIN_FRONT_LINE];
3816 cfg->input_pins[AUTO_PIN_FRONT_LINE] = 0;
3817 }
3818
Steve Longerbeam81937d32007-05-08 15:33:03 +02003819 /*
3820 * FIX-UP: if no line-outs are detected, try to use speaker or HP pin
3821 * as a primary output
3822 */
3823 if (!cfg->line_outs) {
3824 if (cfg->speaker_outs) {
3825 cfg->line_outs = cfg->speaker_outs;
3826 memcpy(cfg->line_out_pins, cfg->speaker_pins,
3827 sizeof(cfg->speaker_pins));
3828 cfg->speaker_outs = 0;
3829 memset(cfg->speaker_pins, 0, sizeof(cfg->speaker_pins));
3830 cfg->line_out_type = AUTO_PIN_SPEAKER_OUT;
3831 } else if (cfg->hp_outs) {
3832 cfg->line_outs = cfg->hp_outs;
3833 memcpy(cfg->line_out_pins, cfg->hp_pins,
3834 sizeof(cfg->hp_pins));
3835 cfg->hp_outs = 0;
3836 memset(cfg->hp_pins, 0, sizeof(cfg->hp_pins));
3837 cfg->line_out_type = AUTO_PIN_HP_OUT;
3838 }
3839 }
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003840
Takashi Iwaicb8e2f82005-07-29 11:54:32 +02003841 /* Reorder the surround channels
3842 * ALSA sequence is front/surr/clfe/side
3843 * HDA sequence is:
3844 * 4-ch: front/surr => OK as it is
3845 * 6-ch: front/clfe/surr
Takashi Iwai9422db42007-04-20 16:11:43 +02003846 * 8-ch: front/clfe/rear/side|fc
Takashi Iwaicb8e2f82005-07-29 11:54:32 +02003847 */
3848 switch (cfg->line_outs) {
3849 case 3:
Takashi Iwaicb8e2f82005-07-29 11:54:32 +02003850 case 4:
3851 nid = cfg->line_out_pins[1];
Takashi Iwai9422db42007-04-20 16:11:43 +02003852 cfg->line_out_pins[1] = cfg->line_out_pins[2];
Takashi Iwaicb8e2f82005-07-29 11:54:32 +02003853 cfg->line_out_pins[2] = nid;
3854 break;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003855 }
3856
Takashi Iwai82bc9552006-03-21 11:24:42 +01003857 /*
3858 * debug prints of the parsed results
3859 */
3860 snd_printd("autoconfig: line_outs=%d (0x%x/0x%x/0x%x/0x%x/0x%x)\n",
3861 cfg->line_outs, cfg->line_out_pins[0], cfg->line_out_pins[1],
3862 cfg->line_out_pins[2], cfg->line_out_pins[3],
3863 cfg->line_out_pins[4]);
3864 snd_printd(" speaker_outs=%d (0x%x/0x%x/0x%x/0x%x/0x%x)\n",
3865 cfg->speaker_outs, cfg->speaker_pins[0],
3866 cfg->speaker_pins[1], cfg->speaker_pins[2],
3867 cfg->speaker_pins[3], cfg->speaker_pins[4]);
Takashi Iwaieb06ed82006-09-20 17:10:27 +02003868 snd_printd(" hp_outs=%d (0x%x/0x%x/0x%x/0x%x/0x%x)\n",
3869 cfg->hp_outs, cfg->hp_pins[0],
3870 cfg->hp_pins[1], cfg->hp_pins[2],
3871 cfg->hp_pins[3], cfg->hp_pins[4]);
Matthew Ranostay90da78b2008-01-24 11:48:01 +01003872 snd_printd(" mono: mono_out=0x%x\n", cfg->mono_out_pin);
Takashi Iwai0852d7a2009-02-11 11:35:15 +01003873 if (cfg->dig_outs)
3874 snd_printd(" dig-out=0x%x/0x%x\n",
3875 cfg->dig_out_pins[0], cfg->dig_out_pins[1]);
Takashi Iwai82bc9552006-03-21 11:24:42 +01003876 snd_printd(" inputs: mic=0x%x, fmic=0x%x, line=0x%x, fline=0x%x,"
3877 " cd=0x%x, aux=0x%x\n",
3878 cfg->input_pins[AUTO_PIN_MIC],
3879 cfg->input_pins[AUTO_PIN_FRONT_MIC],
3880 cfg->input_pins[AUTO_PIN_LINE],
3881 cfg->input_pins[AUTO_PIN_FRONT_LINE],
3882 cfg->input_pins[AUTO_PIN_CD],
3883 cfg->input_pins[AUTO_PIN_AUX]);
Takashi Iwai32d2c7f2009-02-11 11:33:13 +01003884 if (cfg->dig_in_pin)
Takashi Iwai89ce9e82009-01-20 17:15:57 +01003885 snd_printd(" dig-in=0x%x\n", cfg->dig_in_pin);
Takashi Iwai82bc9552006-03-21 11:24:42 +01003886
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003887 return 0;
3888}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003889EXPORT_SYMBOL_HDA(snd_hda_parse_pin_def_config);
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003890
Takashi Iwai4a471b72005-12-07 13:56:29 +01003891/* labels for input pins */
3892const char *auto_pin_cfg_labels[AUTO_PIN_LAST] = {
3893 "Mic", "Front Mic", "Line", "Front Line", "CD", "Aux"
3894};
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003895EXPORT_SYMBOL_HDA(auto_pin_cfg_labels);
Takashi Iwai4a471b72005-12-07 13:56:29 +01003896
3897
Linus Torvalds1da177e2005-04-16 15:20:36 -07003898#ifdef CONFIG_PM
3899/*
3900 * power management
3901 */
3902
3903/**
3904 * snd_hda_suspend - suspend the codecs
3905 * @bus: the HDA bus
Linus Torvalds1da177e2005-04-16 15:20:36 -07003906 *
3907 * Returns 0 if successful.
3908 */
Takashi Iwai8dd78332009-06-02 01:16:07 +02003909int snd_hda_suspend(struct hda_bus *bus)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003910{
Takashi Iwai0ba21762007-04-16 11:29:14 +02003911 struct hda_codec *codec;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003912
Takashi Iwai0ba21762007-04-16 11:29:14 +02003913 list_for_each_entry(codec, &bus->codec_list, list) {
Takashi Iwai0b7a2e92007-08-14 15:18:26 +02003914#ifdef CONFIG_SND_HDA_POWER_SAVE
3915 if (!codec->power_on)
3916 continue;
3917#endif
Takashi Iwaicb53c622007-08-10 17:21:45 +02003918 hda_call_codec_suspend(codec);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003919 }
3920 return 0;
3921}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003922EXPORT_SYMBOL_HDA(snd_hda_suspend);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003923
3924/**
3925 * snd_hda_resume - resume the codecs
3926 * @bus: the HDA bus
Linus Torvalds1da177e2005-04-16 15:20:36 -07003927 *
3928 * Returns 0 if successful.
Takashi Iwaicb53c622007-08-10 17:21:45 +02003929 *
3930 * This fucntion is defined only when POWER_SAVE isn't set.
3931 * In the power-save mode, the codec is resumed dynamically.
Linus Torvalds1da177e2005-04-16 15:20:36 -07003932 */
3933int snd_hda_resume(struct hda_bus *bus)
3934{
Takashi Iwai0ba21762007-04-16 11:29:14 +02003935 struct hda_codec *codec;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003936
Takashi Iwai0ba21762007-04-16 11:29:14 +02003937 list_for_each_entry(codec, &bus->codec_list, list) {
Maxim Levitskyd804ad92007-09-03 15:28:04 +02003938 if (snd_hda_codec_needs_resume(codec))
3939 hda_call_codec_resume(codec);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003940 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003941 return 0;
3942}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003943EXPORT_SYMBOL_HDA(snd_hda_resume);
Takashi Iwai1289e9e2008-11-27 15:47:11 +01003944#endif /* CONFIG_PM */
Takashi Iwaib2e18592008-07-30 15:01:44 +02003945
3946/*
3947 * generic arrays
3948 */
3949
3950/* get a new element from the given array
3951 * if it exceeds the pre-allocated array size, re-allocate the array
3952 */
3953void *snd_array_new(struct snd_array *array)
3954{
3955 if (array->used >= array->alloced) {
3956 int num = array->alloced + array->alloc_align;
Takashi Iwaib910d9a2008-11-07 00:26:52 +01003957 void *nlist;
3958 if (snd_BUG_ON(num >= 4096))
3959 return NULL;
3960 nlist = kcalloc(num + 1, array->elem_size, GFP_KERNEL);
Takashi Iwaib2e18592008-07-30 15:01:44 +02003961 if (!nlist)
3962 return NULL;
3963 if (array->list) {
3964 memcpy(nlist, array->list,
3965 array->elem_size * array->alloced);
3966 kfree(array->list);
3967 }
3968 array->list = nlist;
3969 array->alloced = num;
3970 }
Takashi Iwaif43aa022008-11-10 16:24:26 +01003971 return snd_array_elem(array, array->used++);
Takashi Iwaib2e18592008-07-30 15:01:44 +02003972}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003973EXPORT_SYMBOL_HDA(snd_array_new);
Takashi Iwaib2e18592008-07-30 15:01:44 +02003974
3975/* free the given array elements */
3976void snd_array_free(struct snd_array *array)
3977{
3978 kfree(array->list);
3979 array->used = 0;
3980 array->alloced = 0;
3981 array->list = NULL;
3982}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003983EXPORT_SYMBOL_HDA(snd_array_free);
Takashi Iwaib2022262008-11-21 21:24:03 +01003984
3985/*
3986 * used by hda_proc.c and hda_eld.c
3987 */
3988void snd_print_pcm_rates(int pcm, char *buf, int buflen)
3989{
3990 static unsigned int rates[] = {
3991 8000, 11025, 16000, 22050, 32000, 44100, 48000, 88200,
3992 96000, 176400, 192000, 384000
3993 };
3994 int i, j;
3995
3996 for (i = 0, j = 0; i < ARRAY_SIZE(rates); i++)
3997 if (pcm & (1 << i))
3998 j += snprintf(buf + j, buflen - j, " %d", rates[i]);
3999
4000 buf[j] = '\0'; /* necessary when j == 0 */
4001}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01004002EXPORT_SYMBOL_HDA(snd_print_pcm_rates);
Takashi Iwaib2022262008-11-21 21:24:03 +01004003
4004void snd_print_pcm_bits(int pcm, char *buf, int buflen)
4005{
4006 static unsigned int bits[] = { 8, 16, 20, 24, 32 };
4007 int i, j;
4008
4009 for (i = 0, j = 0; i < ARRAY_SIZE(bits); i++)
4010 if (pcm & (AC_SUPPCM_BITS_8 << i))
4011 j += snprintf(buf + j, buflen - j, " %d", bits[i]);
4012
4013 buf[j] = '\0'; /* necessary when j == 0 */
4014}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01004015EXPORT_SYMBOL_HDA(snd_print_pcm_bits);
Takashi Iwai1289e9e2008-11-27 15:47:11 +01004016
4017MODULE_DESCRIPTION("HDA codec core");
4018MODULE_LICENSE("GPL");