blob: 3ecb45ddadf7f6710df320a421c6d45f2d76aeda [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * Universal Interface for Intel High Definition Audio Codec
3 *
4 * Copyright (c) 2004 Takashi Iwai <tiwai@suse.de>
5 *
6 *
7 * This driver is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This driver is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21
Linus Torvalds1da177e2005-04-16 15:20:36 -070022#include <linux/init.h>
23#include <linux/delay.h>
24#include <linux/slab.h>
25#include <linux/pci.h>
Ingo Molnar62932df2006-01-16 16:34:20 +010026#include <linux/mutex.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070027#include <sound/core.h>
28#include "hda_codec.h"
29#include <sound/asoundef.h>
Jaroslav Kysela302e9c52006-07-05 17:39:49 +020030#include <sound/tlv.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070031#include <sound/initval.h>
32#include "hda_local.h"
Takashi Iwai28073142007-07-27 18:58:06 +020033#include <sound/hda_hwdep.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070034
Linus Torvalds1da177e2005-04-16 15:20:36 -070035/*
36 * vendor / preset table
37 */
38
39struct hda_vendor_id {
40 unsigned int id;
41 const char *name;
42};
43
44/* codec vendor labels */
45static struct hda_vendor_id hda_vendor_ids[] = {
Takashi Iwaic8cd1282008-02-13 16:59:29 +010046 { 0x1002, "ATI" },
Takashi Iwaia9226252006-09-17 22:05:54 +020047 { 0x1057, "Motorola" },
Takashi Iwaic8cd1282008-02-13 16:59:29 +010048 { 0x1095, "Silicon Image" },
Takashi Iwai31117b72008-12-16 14:43:21 +010049 { 0x10de, "Nvidia" },
Takashi Iwaic8cd1282008-02-13 16:59:29 +010050 { 0x10ec, "Realtek" },
Takashi Iwai4e01f542009-04-16 08:53:34 +020051 { 0x1102, "Creative" },
Joseph Chanc577b8a2006-11-29 15:29:40 +010052 { 0x1106, "VIA" },
Matthew Ranostay7f168592007-10-18 17:38:17 +020053 { 0x111d, "IDT" },
Takashi Iwaic8cd1282008-02-13 16:59:29 +010054 { 0x11c1, "LSI" },
Takashi Iwai54b903e2005-05-15 14:30:10 +020055 { 0x11d4, "Analog Devices" },
Linus Torvalds1da177e2005-04-16 15:20:36 -070056 { 0x13f6, "C-Media" },
Takashi Iwaia9226252006-09-17 22:05:54 +020057 { 0x14f1, "Conexant" },
Takashi Iwaic8cd1282008-02-13 16:59:29 +010058 { 0x17e8, "Chrontel" },
59 { 0x1854, "LG" },
Mark Brown8199de32008-10-28 14:50:13 +000060 { 0x1aec, "Wolfson Microelectronics" },
Linus Torvalds1da177e2005-04-16 15:20:36 -070061 { 0x434d, "C-Media" },
Takashi Iwai74c61132008-12-18 09:11:33 +010062 { 0x8086, "Intel" },
Matt2f2f4252005-04-13 14:45:30 +020063 { 0x8384, "SigmaTel" },
Linus Torvalds1da177e2005-04-16 15:20:36 -070064 {} /* terminator */
65};
66
Takashi Iwai1289e9e2008-11-27 15:47:11 +010067static DEFINE_MUTEX(preset_mutex);
68static LIST_HEAD(hda_preset_tables);
69
70int snd_hda_add_codec_preset(struct hda_codec_preset_list *preset)
71{
72 mutex_lock(&preset_mutex);
73 list_add_tail(&preset->list, &hda_preset_tables);
74 mutex_unlock(&preset_mutex);
75 return 0;
76}
Takashi Iwaiff7a3262008-11-28 15:17:06 +010077EXPORT_SYMBOL_HDA(snd_hda_add_codec_preset);
Takashi Iwai1289e9e2008-11-27 15:47:11 +010078
79int snd_hda_delete_codec_preset(struct hda_codec_preset_list *preset)
80{
81 mutex_lock(&preset_mutex);
82 list_del(&preset->list);
83 mutex_unlock(&preset_mutex);
84 return 0;
85}
Takashi Iwaiff7a3262008-11-28 15:17:06 +010086EXPORT_SYMBOL_HDA(snd_hda_delete_codec_preset);
Linus Torvalds1da177e2005-04-16 15:20:36 -070087
Takashi Iwaicb53c622007-08-10 17:21:45 +020088#ifdef CONFIG_SND_HDA_POWER_SAVE
89static void hda_power_work(struct work_struct *work);
90static void hda_keep_power_on(struct hda_codec *codec);
91#else
92static inline void hda_keep_power_on(struct hda_codec *codec) {}
93#endif
94
Matthew Ranostay50a9f792008-10-25 01:05:45 -040095const char *snd_hda_get_jack_location(u32 cfg)
96{
97 static char *bases[7] = {
98 "N/A", "Rear", "Front", "Left", "Right", "Top", "Bottom",
99 };
100 static unsigned char specials_idx[] = {
101 0x07, 0x08,
102 0x17, 0x18, 0x19,
103 0x37, 0x38
104 };
105 static char *specials[] = {
106 "Rear Panel", "Drive Bar",
107 "Riser", "HDMI", "ATAPI",
108 "Mobile-In", "Mobile-Out"
109 };
110 int i;
111 cfg = (cfg & AC_DEFCFG_LOCATION) >> AC_DEFCFG_LOCATION_SHIFT;
112 if ((cfg & 0x0f) < 7)
113 return bases[cfg & 0x0f];
114 for (i = 0; i < ARRAY_SIZE(specials_idx); i++) {
115 if (cfg == specials_idx[i])
116 return specials[i];
117 }
118 return "UNKNOWN";
119}
Takashi Iwaiff7a3262008-11-28 15:17:06 +0100120EXPORT_SYMBOL_HDA(snd_hda_get_jack_location);
Matthew Ranostay50a9f792008-10-25 01:05:45 -0400121
122const char *snd_hda_get_jack_connectivity(u32 cfg)
123{
124 static char *jack_locations[4] = { "Ext", "Int", "Sep", "Oth" };
125
126 return jack_locations[(cfg >> (AC_DEFCFG_LOCATION_SHIFT + 4)) & 3];
127}
Takashi Iwaiff7a3262008-11-28 15:17:06 +0100128EXPORT_SYMBOL_HDA(snd_hda_get_jack_connectivity);
Matthew Ranostay50a9f792008-10-25 01:05:45 -0400129
130const char *snd_hda_get_jack_type(u32 cfg)
131{
132 static char *jack_types[16] = {
133 "Line Out", "Speaker", "HP Out", "CD",
134 "SPDIF Out", "Digital Out", "Modem Line", "Modem Hand",
135 "Line In", "Aux", "Mic", "Telephony",
136 "SPDIF In", "Digitial In", "Reserved", "Other"
137 };
138
139 return jack_types[(cfg & AC_DEFCFG_DEVICE)
140 >> AC_DEFCFG_DEVICE_SHIFT];
141}
Takashi Iwaiff7a3262008-11-28 15:17:06 +0100142EXPORT_SYMBOL_HDA(snd_hda_get_jack_type);
Matthew Ranostay50a9f792008-10-25 01:05:45 -0400143
Takashi Iwai33fa35e2008-11-06 16:50:40 +0100144/*
145 * Compose a 32bit command word to be sent to the HD-audio controller
146 */
147static inline unsigned int
148make_codec_cmd(struct hda_codec *codec, hda_nid_t nid, int direct,
149 unsigned int verb, unsigned int parm)
150{
151 u32 val;
152
Takashi Iwai82e1b802009-07-17 12:47:34 +0200153 if ((codec->addr & ~0xf) || (direct & ~1) || (nid & ~0x7f) ||
154 (verb & ~0xfff) || (parm & ~0xffff)) {
Wu Fengguang6430aee2009-07-17 16:49:19 +0800155 printk(KERN_ERR "hda-codec: out of range cmd %x:%x:%x:%x:%x\n",
156 codec->addr, direct, nid, verb, parm);
157 return ~0;
158 }
159
160 val = (u32)codec->addr << 28;
Takashi Iwai33fa35e2008-11-06 16:50:40 +0100161 val |= (u32)direct << 27;
162 val |= (u32)nid << 20;
163 val |= verb << 8;
164 val |= parm;
165 return val;
166}
167
Takashi Iwaiaa2936f2009-05-26 16:07:57 +0200168/*
169 * Send and receive a verb
170 */
171static int codec_exec_verb(struct hda_codec *codec, unsigned int cmd,
172 unsigned int *res)
173{
174 struct hda_bus *bus = codec->bus;
Takashi Iwai8dd78332009-06-02 01:16:07 +0200175 int err;
Takashi Iwaiaa2936f2009-05-26 16:07:57 +0200176
Wu Fengguang6430aee2009-07-17 16:49:19 +0800177 if (cmd == ~0)
178 return -1;
179
Takashi Iwaiaa2936f2009-05-26 16:07:57 +0200180 if (res)
181 *res = -1;
Takashi Iwai8dd78332009-06-02 01:16:07 +0200182 again:
Takashi Iwaiaa2936f2009-05-26 16:07:57 +0200183 snd_hda_power_up(codec);
184 mutex_lock(&bus->cmd_mutex);
Takashi Iwaiaa2936f2009-05-26 16:07:57 +0200185 err = bus->ops.command(bus, cmd);
Takashi Iwai8dd78332009-06-02 01:16:07 +0200186 if (!err && res)
187 *res = bus->ops.get_response(bus);
Takashi Iwaiaa2936f2009-05-26 16:07:57 +0200188 mutex_unlock(&bus->cmd_mutex);
189 snd_hda_power_down(codec);
Takashi Iwai8dd78332009-06-02 01:16:07 +0200190 if (res && *res == -1 && bus->rirb_error) {
191 if (bus->response_reset) {
192 snd_printd("hda_codec: resetting BUS due to "
193 "fatal communication error\n");
194 bus->ops.bus_reset(bus);
195 }
196 goto again;
197 }
198 /* clear reset-flag when the communication gets recovered */
199 if (!err)
200 bus->response_reset = 0;
Takashi Iwaiaa2936f2009-05-26 16:07:57 +0200201 return err;
202}
203
Linus Torvalds1da177e2005-04-16 15:20:36 -0700204/**
205 * snd_hda_codec_read - send a command and get the response
206 * @codec: the HDA codec
207 * @nid: NID to send the command
208 * @direct: direct flag
209 * @verb: the verb to send
210 * @parm: the parameter for the verb
211 *
212 * Send a single command and read the corresponding response.
213 *
214 * Returns the obtained response value, or -1 for an error.
215 */
Takashi Iwai0ba21762007-04-16 11:29:14 +0200216unsigned int snd_hda_codec_read(struct hda_codec *codec, hda_nid_t nid,
217 int direct,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700218 unsigned int verb, unsigned int parm)
219{
Takashi Iwaiaa2936f2009-05-26 16:07:57 +0200220 unsigned cmd = make_codec_cmd(codec, nid, direct, verb, parm);
221 unsigned int res;
222 codec_exec_verb(codec, cmd, &res);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700223 return res;
224}
Takashi Iwaiff7a3262008-11-28 15:17:06 +0100225EXPORT_SYMBOL_HDA(snd_hda_codec_read);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700226
227/**
228 * snd_hda_codec_write - send a single command without waiting for response
229 * @codec: the HDA codec
230 * @nid: NID to send the command
231 * @direct: direct flag
232 * @verb: the verb to send
233 * @parm: the parameter for the verb
234 *
235 * Send a single command without waiting for response.
236 *
237 * Returns 0 if successful, or a negative error code.
238 */
239int snd_hda_codec_write(struct hda_codec *codec, hda_nid_t nid, int direct,
240 unsigned int verb, unsigned int parm)
241{
Takashi Iwaiaa2936f2009-05-26 16:07:57 +0200242 unsigned int cmd = make_codec_cmd(codec, nid, direct, verb, parm);
Takashi Iwai33fa35e2008-11-06 16:50:40 +0100243 unsigned int res;
Takashi Iwaib20f3b82009-06-02 01:20:22 +0200244 return codec_exec_verb(codec, cmd,
245 codec->bus->sync_write ? &res : NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700246}
Takashi Iwaiff7a3262008-11-28 15:17:06 +0100247EXPORT_SYMBOL_HDA(snd_hda_codec_write);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700248
249/**
250 * snd_hda_sequence_write - sequence writes
251 * @codec: the HDA codec
252 * @seq: VERB array to send
253 *
254 * Send the commands sequentially from the given array.
255 * The array must be terminated with NID=0.
256 */
257void snd_hda_sequence_write(struct hda_codec *codec, const struct hda_verb *seq)
258{
259 for (; seq->nid; seq++)
260 snd_hda_codec_write(codec, seq->nid, 0, seq->verb, seq->param);
261}
Takashi Iwaiff7a3262008-11-28 15:17:06 +0100262EXPORT_SYMBOL_HDA(snd_hda_sequence_write);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700263
264/**
265 * snd_hda_get_sub_nodes - get the range of sub nodes
266 * @codec: the HDA codec
267 * @nid: NID to parse
268 * @start_id: the pointer to store the start NID
269 *
270 * Parse the NID and store the start NID of its sub-nodes.
271 * Returns the number of sub-nodes.
272 */
Takashi Iwai0ba21762007-04-16 11:29:14 +0200273int snd_hda_get_sub_nodes(struct hda_codec *codec, hda_nid_t nid,
274 hda_nid_t *start_id)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700275{
276 unsigned int parm;
277
278 parm = snd_hda_param_read(codec, nid, AC_PAR_NODE_COUNT);
Danny Tholene8a7f132007-09-11 21:41:56 +0200279 if (parm == -1)
280 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700281 *start_id = (parm >> 16) & 0x7fff;
282 return (int)(parm & 0x7fff);
283}
Takashi Iwaiff7a3262008-11-28 15:17:06 +0100284EXPORT_SYMBOL_HDA(snd_hda_get_sub_nodes);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700285
286/**
287 * snd_hda_get_connections - get connection list
288 * @codec: the HDA codec
289 * @nid: NID to parse
290 * @conn_list: connection list array
291 * @max_conns: max. number of connections to store
292 *
293 * Parses the connection list of the given widget and stores the list
294 * of NIDs.
295 *
296 * Returns the number of connections, or a negative error code.
297 */
298int snd_hda_get_connections(struct hda_codec *codec, hda_nid_t nid,
299 hda_nid_t *conn_list, int max_conns)
300{
301 unsigned int parm;
Takashi Iwai54d17402005-11-21 16:33:22 +0100302 int i, conn_len, conns;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700303 unsigned int shift, num_elems, mask;
Takashi Iwai54d17402005-11-21 16:33:22 +0100304 hda_nid_t prev_nid;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700305
Takashi Iwaida3cec32008-08-08 17:12:14 +0200306 if (snd_BUG_ON(!conn_list || max_conns <= 0))
307 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700308
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;
Jaroslav Kysela2e9bf242009-07-18 11:48:19 +0200350 if (val == 0) {
351 snd_printk(KERN_WARNING "hda_codec: "
352 "invalid CONNECT_LIST verb %x[%i]:%x\n",
353 nid, i, parm);
354 return 0;
355 }
Takashi Iwai54d17402005-11-21 16:33:22 +0100356 parm >>= shift;
357 if (range_val) {
358 /* ranges between the previous and this one */
Takashi Iwai0ba21762007-04-16 11:29:14 +0200359 if (!prev_nid || prev_nid >= val) {
360 snd_printk(KERN_WARNING "hda_codec: "
361 "invalid dep_range_val %x:%x\n",
362 prev_nid, val);
Takashi Iwai54d17402005-11-21 16:33:22 +0100363 continue;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700364 }
Takashi Iwai54d17402005-11-21 16:33:22 +0100365 for (n = prev_nid + 1; n <= val; n++) {
366 if (conns >= max_conns) {
Takashi Iwai0ba21762007-04-16 11:29:14 +0200367 snd_printk(KERN_ERR
368 "Too many connections\n");
Takashi Iwai54d17402005-11-21 16:33:22 +0100369 return -EINVAL;
370 }
371 conn_list[conns++] = n;
372 }
373 } else {
374 if (conns >= max_conns) {
375 snd_printk(KERN_ERR "Too many connections\n");
376 return -EINVAL;
377 }
378 conn_list[conns++] = val;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700379 }
Takashi Iwai54d17402005-11-21 16:33:22 +0100380 prev_nid = val;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700381 }
382 return conns;
383}
Takashi Iwaiff7a3262008-11-28 15:17:06 +0100384EXPORT_SYMBOL_HDA(snd_hda_get_connections);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700385
386
387/**
388 * snd_hda_queue_unsol_event - add an unsolicited event to queue
389 * @bus: the BUS
390 * @res: unsolicited event (lower 32bit of RIRB entry)
391 * @res_ex: codec addr and flags (upper 32bit or RIRB entry)
392 *
393 * Adds the given event to the queue. The events are processed in
394 * the workqueue asynchronously. Call this function in the interrupt
395 * hanlder when RIRB receives an unsolicited event.
396 *
397 * Returns 0 if successful, or a negative error code.
398 */
399int snd_hda_queue_unsol_event(struct hda_bus *bus, u32 res, u32 res_ex)
400{
401 struct hda_bus_unsolicited *unsol;
402 unsigned int wp;
403
Takashi Iwai0ba21762007-04-16 11:29:14 +0200404 unsol = bus->unsol;
405 if (!unsol)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700406 return 0;
407
408 wp = (unsol->wp + 1) % HDA_UNSOL_QUEUE_SIZE;
409 unsol->wp = wp;
410
411 wp <<= 1;
412 unsol->queue[wp] = res;
413 unsol->queue[wp + 1] = res_ex;
414
Takashi Iwai6acaed32009-01-12 10:09:24 +0100415 queue_work(bus->workq, &unsol->work);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700416
417 return 0;
418}
Takashi Iwaiff7a3262008-11-28 15:17:06 +0100419EXPORT_SYMBOL_HDA(snd_hda_queue_unsol_event);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700420
421/*
Wu Fengguang5c1d1a92008-10-07 14:17:53 +0800422 * process queued unsolicited events
Linus Torvalds1da177e2005-04-16 15:20:36 -0700423 */
David Howellsc4028952006-11-22 14:57:56 +0000424static void process_unsol_events(struct work_struct *work)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700425{
David Howellsc4028952006-11-22 14:57:56 +0000426 struct hda_bus_unsolicited *unsol =
427 container_of(work, struct hda_bus_unsolicited, work);
428 struct hda_bus *bus = unsol->bus;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700429 struct hda_codec *codec;
430 unsigned int rp, caddr, res;
431
432 while (unsol->rp != unsol->wp) {
433 rp = (unsol->rp + 1) % HDA_UNSOL_QUEUE_SIZE;
434 unsol->rp = rp;
435 rp <<= 1;
436 res = unsol->queue[rp];
437 caddr = unsol->queue[rp + 1];
Takashi Iwai0ba21762007-04-16 11:29:14 +0200438 if (!(caddr & (1 << 4))) /* no unsolicited event? */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700439 continue;
440 codec = bus->caddr_tbl[caddr & 0x0f];
441 if (codec && codec->patch_ops.unsol_event)
442 codec->patch_ops.unsol_event(codec, res);
443 }
444}
445
446/*
447 * initialize unsolicited queue
448 */
Takashi Iwai6c1f45e2008-07-30 15:01:45 +0200449static int init_unsol_queue(struct hda_bus *bus)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700450{
451 struct hda_bus_unsolicited *unsol;
452
Takashi Iwai9f146bb2005-11-17 11:07:49 +0100453 if (bus->unsol) /* already initialized */
454 return 0;
455
Takashi Iwaie560d8d2005-09-09 14:21:46 +0200456 unsol = kzalloc(sizeof(*unsol), GFP_KERNEL);
Takashi Iwai0ba21762007-04-16 11:29:14 +0200457 if (!unsol) {
458 snd_printk(KERN_ERR "hda_codec: "
459 "can't allocate unsolicited queue\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700460 return -ENOMEM;
461 }
David Howellsc4028952006-11-22 14:57:56 +0000462 INIT_WORK(&unsol->work, process_unsol_events);
463 unsol->bus = bus;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700464 bus->unsol = unsol;
465 return 0;
466}
467
468/*
469 * destructor
470 */
471static void snd_hda_codec_free(struct hda_codec *codec);
472
473static int snd_hda_bus_free(struct hda_bus *bus)
474{
Takashi Iwai0ba21762007-04-16 11:29:14 +0200475 struct hda_codec *codec, *n;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700476
Takashi Iwai0ba21762007-04-16 11:29:14 +0200477 if (!bus)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700478 return 0;
Takashi Iwai6acaed32009-01-12 10:09:24 +0100479 if (bus->workq)
480 flush_workqueue(bus->workq);
481 if (bus->unsol)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700482 kfree(bus->unsol);
Takashi Iwai0ba21762007-04-16 11:29:14 +0200483 list_for_each_entry_safe(codec, n, &bus->codec_list, list) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700484 snd_hda_codec_free(codec);
485 }
486 if (bus->ops.private_free)
487 bus->ops.private_free(bus);
Takashi Iwai6acaed32009-01-12 10:09:24 +0100488 if (bus->workq)
489 destroy_workqueue(bus->workq);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700490 kfree(bus);
491 return 0;
492}
493
Takashi Iwaic8b6bf92005-11-17 14:57:47 +0100494static int snd_hda_bus_dev_free(struct snd_device *device)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700495{
496 struct hda_bus *bus = device->device_data;
Takashi Iwaib94d35392008-11-21 09:08:06 +0100497 bus->shutdown = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700498 return snd_hda_bus_free(bus);
499}
500
Takashi Iwaid7ffba12008-07-30 15:01:46 +0200501#ifdef CONFIG_SND_HDA_HWDEP
502static int snd_hda_bus_dev_register(struct snd_device *device)
503{
504 struct hda_bus *bus = device->device_data;
505 struct hda_codec *codec;
506 list_for_each_entry(codec, &bus->codec_list, list) {
507 snd_hda_hwdep_add_sysfs(codec);
508 }
509 return 0;
510}
511#else
512#define snd_hda_bus_dev_register NULL
513#endif
514
Linus Torvalds1da177e2005-04-16 15:20:36 -0700515/**
516 * snd_hda_bus_new - create a HDA bus
517 * @card: the card entry
518 * @temp: the template for hda_bus information
519 * @busp: the pointer to store the created bus instance
520 *
521 * Returns 0 if successful, or a negative error code.
522 */
Takashi Iwai1289e9e2008-11-27 15:47:11 +0100523int /*__devinit*/ snd_hda_bus_new(struct snd_card *card,
Takashi Iwai756e2b02007-04-16 11:27:07 +0200524 const struct hda_bus_template *temp,
525 struct hda_bus **busp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700526{
527 struct hda_bus *bus;
528 int err;
Takashi Iwaic8b6bf92005-11-17 14:57:47 +0100529 static struct snd_device_ops dev_ops = {
Takashi Iwaid7ffba12008-07-30 15:01:46 +0200530 .dev_register = snd_hda_bus_dev_register,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700531 .dev_free = snd_hda_bus_dev_free,
532 };
533
Takashi Iwaida3cec32008-08-08 17:12:14 +0200534 if (snd_BUG_ON(!temp))
535 return -EINVAL;
536 if (snd_BUG_ON(!temp->ops.command || !temp->ops.get_response))
537 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700538
539 if (busp)
540 *busp = NULL;
541
Takashi Iwaie560d8d2005-09-09 14:21:46 +0200542 bus = kzalloc(sizeof(*bus), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700543 if (bus == NULL) {
544 snd_printk(KERN_ERR "can't allocate struct hda_bus\n");
545 return -ENOMEM;
546 }
547
548 bus->card = card;
549 bus->private_data = temp->private_data;
550 bus->pci = temp->pci;
551 bus->modelname = temp->modelname;
Takashi Iwaifee2fba2008-11-27 12:43:28 +0100552 bus->power_save = temp->power_save;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700553 bus->ops = temp->ops;
554
Ingo Molnar62932df2006-01-16 16:34:20 +0100555 mutex_init(&bus->cmd_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700556 INIT_LIST_HEAD(&bus->codec_list);
557
Takashi Iwaie8c0ee52009-02-05 07:34:28 +0100558 snprintf(bus->workq_name, sizeof(bus->workq_name),
559 "hd-audio%d", card->number);
560 bus->workq = create_singlethread_workqueue(bus->workq_name);
Takashi Iwai6acaed32009-01-12 10:09:24 +0100561 if (!bus->workq) {
Takashi Iwaie8c0ee52009-02-05 07:34:28 +0100562 snd_printk(KERN_ERR "cannot create workqueue %s\n",
563 bus->workq_name);
Takashi Iwai6acaed32009-01-12 10:09:24 +0100564 kfree(bus);
565 return -ENOMEM;
566 }
567
Takashi Iwai0ba21762007-04-16 11:29:14 +0200568 err = snd_device_new(card, SNDRV_DEV_BUS, bus, &dev_ops);
569 if (err < 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700570 snd_hda_bus_free(bus);
571 return err;
572 }
573 if (busp)
574 *busp = bus;
575 return 0;
576}
Takashi Iwaiff7a3262008-11-28 15:17:06 +0100577EXPORT_SYMBOL_HDA(snd_hda_bus_new);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700578
Takashi Iwai82467612007-07-27 19:15:54 +0200579#ifdef CONFIG_SND_HDA_GENERIC
580#define is_generic_config(codec) \
Takashi Iwaif44ac832008-07-30 15:01:45 +0200581 (codec->modelname && !strcmp(codec->modelname, "generic"))
Takashi Iwai82467612007-07-27 19:15:54 +0200582#else
583#define is_generic_config(codec) 0
584#endif
585
Takashi Iwai645f10c2008-11-28 15:07:37 +0100586#ifdef MODULE
Takashi Iwai1289e9e2008-11-27 15:47:11 +0100587#define HDA_MODREQ_MAX_COUNT 2 /* two request_modules()'s */
588#else
Takashi Iwai645f10c2008-11-28 15:07:37 +0100589#define HDA_MODREQ_MAX_COUNT 0 /* all presets are statically linked */
Takashi Iwai1289e9e2008-11-27 15:47:11 +0100590#endif
591
Linus Torvalds1da177e2005-04-16 15:20:36 -0700592/*
593 * find a matching codec preset
594 */
Takashi Iwai6c1f45e2008-07-30 15:01:45 +0200595static const struct hda_codec_preset *
Takashi Iwai756e2b02007-04-16 11:27:07 +0200596find_codec_preset(struct hda_codec *codec)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700597{
Takashi Iwai1289e9e2008-11-27 15:47:11 +0100598 struct hda_codec_preset_list *tbl;
599 const struct hda_codec_preset *preset;
600 int mod_requested = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700601
Takashi Iwai82467612007-07-27 19:15:54 +0200602 if (is_generic_config(codec))
Takashi Iwaid5ad6302007-03-07 15:55:59 +0100603 return NULL; /* use the generic parser */
604
Takashi Iwai1289e9e2008-11-27 15:47:11 +0100605 again:
606 mutex_lock(&preset_mutex);
607 list_for_each_entry(tbl, &hda_preset_tables, list) {
608 if (!try_module_get(tbl->owner)) {
609 snd_printk(KERN_ERR "hda_codec: cannot module_get\n");
610 continue;
611 }
612 for (preset = tbl->preset; preset->id; preset++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700613 u32 mask = preset->mask;
Marc Boucherca7cfae2008-01-22 15:32:25 +0100614 if (preset->afg && preset->afg != codec->afg)
615 continue;
616 if (preset->mfg && preset->mfg != codec->mfg)
617 continue;
Takashi Iwai0ba21762007-04-16 11:29:14 +0200618 if (!mask)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700619 mask = ~0;
Takashi Iwai9c7f8522006-06-28 15:08:22 +0200620 if (preset->id == (codec->vendor_id & mask) &&
Takashi Iwai0ba21762007-04-16 11:29:14 +0200621 (!preset->rev ||
Takashi Iwai1289e9e2008-11-27 15:47:11 +0100622 preset->rev == codec->revision_id)) {
623 mutex_unlock(&preset_mutex);
624 codec->owner = tbl->owner;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700625 return preset;
Takashi Iwai1289e9e2008-11-27 15:47:11 +0100626 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700627 }
Takashi Iwai1289e9e2008-11-27 15:47:11 +0100628 module_put(tbl->owner);
629 }
630 mutex_unlock(&preset_mutex);
631
632 if (mod_requested < HDA_MODREQ_MAX_COUNT) {
633 char name[32];
634 if (!mod_requested)
635 snprintf(name, sizeof(name), "snd-hda-codec-id:%08x",
636 codec->vendor_id);
637 else
638 snprintf(name, sizeof(name), "snd-hda-codec-id:%04x*",
639 (codec->vendor_id >> 16) & 0xffff);
640 request_module(name);
641 mod_requested++;
642 goto again;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700643 }
644 return NULL;
645}
646
647/*
Takashi Iwaif44ac832008-07-30 15:01:45 +0200648 * get_codec_name - store the codec name
Linus Torvalds1da177e2005-04-16 15:20:36 -0700649 */
Takashi Iwaif44ac832008-07-30 15:01:45 +0200650static int get_codec_name(struct hda_codec *codec)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700651{
652 const struct hda_vendor_id *c;
653 const char *vendor = NULL;
654 u16 vendor_id = codec->vendor_id >> 16;
Takashi Iwai812a2cc2009-05-16 10:00:49 +0200655 char tmp[16];
656
657 if (codec->vendor_name)
658 goto get_chip_name;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700659
660 for (c = hda_vendor_ids; c->id; c++) {
661 if (c->id == vendor_id) {
662 vendor = c->name;
663 break;
664 }
665 }
Takashi Iwai0ba21762007-04-16 11:29:14 +0200666 if (!vendor) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700667 sprintf(tmp, "Generic %04x", vendor_id);
668 vendor = tmp;
669 }
Takashi Iwai812a2cc2009-05-16 10:00:49 +0200670 codec->vendor_name = kstrdup(vendor, GFP_KERNEL);
671 if (!codec->vendor_name)
672 return -ENOMEM;
673
674 get_chip_name:
675 if (codec->chip_name)
676 return 0;
677
Linus Torvalds1da177e2005-04-16 15:20:36 -0700678 if (codec->preset && codec->preset->name)
Takashi Iwai812a2cc2009-05-16 10:00:49 +0200679 codec->chip_name = kstrdup(codec->preset->name, GFP_KERNEL);
680 else {
681 sprintf(tmp, "ID %x", codec->vendor_id & 0xffff);
682 codec->chip_name = kstrdup(tmp, GFP_KERNEL);
683 }
684 if (!codec->chip_name)
Takashi Iwaif44ac832008-07-30 15:01:45 +0200685 return -ENOMEM;
686 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700687}
688
689/*
Sasha Khapyorsky673b6832005-08-11 11:00:16 +0200690 * look for an AFG and MFG nodes
Linus Torvalds1da177e2005-04-16 15:20:36 -0700691 */
Takashi Iwai1289e9e2008-11-27 15:47:11 +0100692static void /*__devinit*/ setup_fg_nodes(struct hda_codec *codec)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700693{
Takashi Iwai93e82ae2009-04-17 18:04:41 +0200694 int i, total_nodes, function_id;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700695 hda_nid_t nid;
696
697 total_nodes = snd_hda_get_sub_nodes(codec, AC_NODE_ROOT, &nid);
698 for (i = 0; i < total_nodes; i++, nid++) {
Takashi Iwai93e82ae2009-04-17 18:04:41 +0200699 function_id = snd_hda_param_read(codec, nid,
Pascal de Bruijn234b4342009-03-23 11:15:59 +0100700 AC_PAR_FUNCTION_TYPE) & 0xff;
Takashi Iwai93e82ae2009-04-17 18:04:41 +0200701 switch (function_id) {
Sasha Khapyorsky673b6832005-08-11 11:00:16 +0200702 case AC_GRP_AUDIO_FUNCTION:
703 codec->afg = nid;
Takashi Iwai93e82ae2009-04-17 18:04:41 +0200704 codec->function_id = function_id;
Sasha Khapyorsky673b6832005-08-11 11:00:16 +0200705 break;
706 case AC_GRP_MODEM_FUNCTION:
707 codec->mfg = nid;
Takashi Iwai93e82ae2009-04-17 18:04:41 +0200708 codec->function_id = function_id;
Sasha Khapyorsky673b6832005-08-11 11:00:16 +0200709 break;
710 default:
711 break;
712 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700713 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700714}
715
716/*
Takashi Iwai54d17402005-11-21 16:33:22 +0100717 * read widget caps for each widget and store in cache
718 */
719static int read_widget_caps(struct hda_codec *codec, hda_nid_t fg_node)
720{
721 int i;
722 hda_nid_t nid;
723
724 codec->num_nodes = snd_hda_get_sub_nodes(codec, fg_node,
725 &codec->start_nid);
726 codec->wcaps = kmalloc(codec->num_nodes * 4, GFP_KERNEL);
Takashi Iwai0ba21762007-04-16 11:29:14 +0200727 if (!codec->wcaps)
Takashi Iwai54d17402005-11-21 16:33:22 +0100728 return -ENOMEM;
729 nid = codec->start_nid;
730 for (i = 0; i < codec->num_nodes; i++, nid++)
731 codec->wcaps[i] = snd_hda_param_read(codec, nid,
732 AC_PAR_AUDIO_WIDGET_CAP);
733 return 0;
734}
735
Takashi Iwai3be14142009-02-20 14:11:16 +0100736/* read all pin default configurations and save codec->init_pins */
737static int read_pin_defaults(struct hda_codec *codec)
738{
739 int i;
740 hda_nid_t nid = codec->start_nid;
741
742 for (i = 0; i < codec->num_nodes; i++, nid++) {
743 struct hda_pincfg *pin;
744 unsigned int wcaps = get_wcaps(codec, nid);
745 unsigned int wid_type = (wcaps & AC_WCAP_TYPE) >>
746 AC_WCAP_TYPE_SHIFT;
747 if (wid_type != AC_WID_PIN)
748 continue;
749 pin = snd_array_new(&codec->init_pins);
750 if (!pin)
751 return -ENOMEM;
752 pin->nid = nid;
753 pin->cfg = snd_hda_codec_read(codec, nid, 0,
754 AC_VERB_GET_CONFIG_DEFAULT, 0);
755 }
756 return 0;
757}
758
759/* look up the given pin config list and return the item matching with NID */
760static struct hda_pincfg *look_up_pincfg(struct hda_codec *codec,
761 struct snd_array *array,
762 hda_nid_t nid)
763{
764 int i;
765 for (i = 0; i < array->used; i++) {
766 struct hda_pincfg *pin = snd_array_elem(array, i);
767 if (pin->nid == nid)
768 return pin;
769 }
770 return NULL;
771}
772
773/* write a config value for the given NID */
774static void set_pincfg(struct hda_codec *codec, hda_nid_t nid,
775 unsigned int cfg)
776{
777 int i;
778 for (i = 0; i < 4; i++) {
779 snd_hda_codec_write(codec, nid, 0,
780 AC_VERB_SET_CONFIG_DEFAULT_BYTES_0 + i,
781 cfg & 0xff);
782 cfg >>= 8;
783 }
784}
785
786/* set the current pin config value for the given NID.
787 * the value is cached, and read via snd_hda_codec_get_pincfg()
788 */
789int snd_hda_add_pincfg(struct hda_codec *codec, struct snd_array *list,
790 hda_nid_t nid, unsigned int cfg)
791{
792 struct hda_pincfg *pin;
Takashi Iwai5e7b8e02009-02-23 09:45:59 +0100793 unsigned int oldcfg;
Takashi Iwai3be14142009-02-20 14:11:16 +0100794
Takashi Iwai5e7b8e02009-02-23 09:45:59 +0100795 oldcfg = snd_hda_codec_get_pincfg(codec, nid);
Takashi Iwai3be14142009-02-20 14:11:16 +0100796 pin = look_up_pincfg(codec, list, nid);
797 if (!pin) {
798 pin = snd_array_new(list);
799 if (!pin)
800 return -ENOMEM;
801 pin->nid = nid;
802 }
803 pin->cfg = cfg;
Takashi Iwai5e7b8e02009-02-23 09:45:59 +0100804
805 /* change only when needed; e.g. if the pincfg is already present
806 * in user_pins[], don't write it
807 */
808 cfg = snd_hda_codec_get_pincfg(codec, nid);
809 if (oldcfg != cfg)
810 set_pincfg(codec, nid, cfg);
Takashi Iwai3be14142009-02-20 14:11:16 +0100811 return 0;
812}
813
814int snd_hda_codec_set_pincfg(struct hda_codec *codec,
815 hda_nid_t nid, unsigned int cfg)
816{
Takashi Iwai346ff702009-02-23 09:42:57 +0100817 return snd_hda_add_pincfg(codec, &codec->driver_pins, nid, cfg);
Takashi Iwai3be14142009-02-20 14:11:16 +0100818}
819EXPORT_SYMBOL_HDA(snd_hda_codec_set_pincfg);
820
821/* get the current pin config value of the given pin NID */
822unsigned int snd_hda_codec_get_pincfg(struct hda_codec *codec, hda_nid_t nid)
823{
824 struct hda_pincfg *pin;
825
Takashi Iwai3be14142009-02-20 14:11:16 +0100826#ifdef CONFIG_SND_HDA_HWDEP
Takashi Iwai346ff702009-02-23 09:42:57 +0100827 pin = look_up_pincfg(codec, &codec->user_pins, nid);
Takashi Iwai3be14142009-02-20 14:11:16 +0100828 if (pin)
829 return pin->cfg;
830#endif
Takashi Iwai5e7b8e02009-02-23 09:45:59 +0100831 pin = look_up_pincfg(codec, &codec->driver_pins, nid);
832 if (pin)
833 return pin->cfg;
Takashi Iwai3be14142009-02-20 14:11:16 +0100834 pin = look_up_pincfg(codec, &codec->init_pins, nid);
835 if (pin)
836 return pin->cfg;
837 return 0;
838}
839EXPORT_SYMBOL_HDA(snd_hda_codec_get_pincfg);
840
841/* restore all current pin configs */
842static void restore_pincfgs(struct hda_codec *codec)
843{
844 int i;
845 for (i = 0; i < codec->init_pins.used; i++) {
846 struct hda_pincfg *pin = snd_array_elem(&codec->init_pins, i);
847 set_pincfg(codec, pin->nid,
848 snd_hda_codec_get_pincfg(codec, pin->nid));
849 }
850}
Takashi Iwai54d17402005-11-21 16:33:22 +0100851
Takashi Iwai01751f52007-08-10 16:59:39 +0200852static void init_hda_cache(struct hda_cache_rec *cache,
853 unsigned int record_size);
Takashi Iwai1fcaee62007-08-23 00:01:09 +0200854static void free_hda_cache(struct hda_cache_rec *cache);
Takashi Iwai01751f52007-08-10 16:59:39 +0200855
Takashi Iwai3be14142009-02-20 14:11:16 +0100856/* restore the initial pin cfgs and release all pincfg lists */
857static void restore_init_pincfgs(struct hda_codec *codec)
858{
Takashi Iwai346ff702009-02-23 09:42:57 +0100859 /* first free driver_pins and user_pins, then call restore_pincfg
Takashi Iwai3be14142009-02-20 14:11:16 +0100860 * so that only the values in init_pins are restored
861 */
Takashi Iwai346ff702009-02-23 09:42:57 +0100862 snd_array_free(&codec->driver_pins);
Takashi Iwai3be14142009-02-20 14:11:16 +0100863#ifdef CONFIG_SND_HDA_HWDEP
Takashi Iwai346ff702009-02-23 09:42:57 +0100864 snd_array_free(&codec->user_pins);
Takashi Iwai3be14142009-02-20 14:11:16 +0100865#endif
866 restore_pincfgs(codec);
867 snd_array_free(&codec->init_pins);
868}
869
Takashi Iwai54d17402005-11-21 16:33:22 +0100870/*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700871 * codec destructor
872 */
873static void snd_hda_codec_free(struct hda_codec *codec)
874{
Takashi Iwai0ba21762007-04-16 11:29:14 +0200875 if (!codec)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700876 return;
Takashi Iwai3be14142009-02-20 14:11:16 +0100877 restore_init_pincfgs(codec);
Takashi Iwaicb53c622007-08-10 17:21:45 +0200878#ifdef CONFIG_SND_HDA_POWER_SAVE
879 cancel_delayed_work(&codec->power_work);
Takashi Iwai6acaed32009-01-12 10:09:24 +0100880 flush_workqueue(codec->bus->workq);
Takashi Iwaicb53c622007-08-10 17:21:45 +0200881#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700882 list_del(&codec->list);
Takashi Iwaid13bd412008-07-30 15:01:45 +0200883 snd_array_free(&codec->mixers);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700884 codec->bus->caddr_tbl[codec->addr] = NULL;
885 if (codec->patch_ops.free)
886 codec->patch_ops.free(codec);
Takashi Iwai1289e9e2008-11-27 15:47:11 +0100887 module_put(codec->owner);
Takashi Iwai01751f52007-08-10 16:59:39 +0200888 free_hda_cache(&codec->amp_cache);
Takashi Iwaib3ac5632007-08-10 17:03:40 +0200889 free_hda_cache(&codec->cmd_cache);
Takashi Iwai812a2cc2009-05-16 10:00:49 +0200890 kfree(codec->vendor_name);
891 kfree(codec->chip_name);
Takashi Iwaif44ac832008-07-30 15:01:45 +0200892 kfree(codec->modelname);
Takashi Iwai54d17402005-11-21 16:33:22 +0100893 kfree(codec->wcaps);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700894 kfree(codec);
895}
896
Takashi Iwaibb6ac722009-03-13 09:02:42 +0100897static void hda_set_power_state(struct hda_codec *codec, hda_nid_t fg,
898 unsigned int power_state);
899
Linus Torvalds1da177e2005-04-16 15:20:36 -0700900/**
901 * snd_hda_codec_new - create a HDA codec
902 * @bus: the bus to assign
903 * @codec_addr: the codec address
904 * @codecp: the pointer to store the generated codec
905 *
906 * Returns 0 if successful, or a negative error code.
907 */
Takashi Iwai1289e9e2008-11-27 15:47:11 +0100908int /*__devinit*/ snd_hda_codec_new(struct hda_bus *bus, unsigned int codec_addr,
Takashi Iwaia1e21c92009-06-17 09:33:52 +0200909 struct hda_codec **codecp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700910{
911 struct hda_codec *codec;
Jaroslav Kyselaba443682008-08-13 20:55:32 +0200912 char component[31];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700913 int err;
914
Takashi Iwaida3cec32008-08-08 17:12:14 +0200915 if (snd_BUG_ON(!bus))
916 return -EINVAL;
917 if (snd_BUG_ON(codec_addr > HDA_MAX_CODEC_ADDRESS))
918 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700919
920 if (bus->caddr_tbl[codec_addr]) {
Takashi Iwai0ba21762007-04-16 11:29:14 +0200921 snd_printk(KERN_ERR "hda_codec: "
922 "address 0x%x is already occupied\n", codec_addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700923 return -EBUSY;
924 }
925
Takashi Iwaie560d8d2005-09-09 14:21:46 +0200926 codec = kzalloc(sizeof(*codec), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700927 if (codec == NULL) {
928 snd_printk(KERN_ERR "can't allocate struct hda_codec\n");
929 return -ENOMEM;
930 }
931
932 codec->bus = bus;
933 codec->addr = codec_addr;
Ingo Molnar62932df2006-01-16 16:34:20 +0100934 mutex_init(&codec->spdif_mutex);
Wu Fengguang5a9e02e2009-01-09 16:45:24 +0800935 mutex_init(&codec->control_mutex);
Takashi Iwai01751f52007-08-10 16:59:39 +0200936 init_hda_cache(&codec->amp_cache, sizeof(struct hda_amp_info));
Takashi Iwaib3ac5632007-08-10 17:03:40 +0200937 init_hda_cache(&codec->cmd_cache, sizeof(struct hda_cache_head));
Takashi Iwaid13bd412008-07-30 15:01:45 +0200938 snd_array_init(&codec->mixers, sizeof(struct snd_kcontrol *), 32);
Takashi Iwai3be14142009-02-20 14:11:16 +0100939 snd_array_init(&codec->init_pins, sizeof(struct hda_pincfg), 16);
Takashi Iwai346ff702009-02-23 09:42:57 +0100940 snd_array_init(&codec->driver_pins, sizeof(struct hda_pincfg), 16);
Takashi Iwai6c1f45e2008-07-30 15:01:45 +0200941 if (codec->bus->modelname) {
942 codec->modelname = kstrdup(codec->bus->modelname, GFP_KERNEL);
943 if (!codec->modelname) {
944 snd_hda_codec_free(codec);
945 return -ENODEV;
946 }
947 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700948
Takashi Iwaicb53c622007-08-10 17:21:45 +0200949#ifdef CONFIG_SND_HDA_POWER_SAVE
950 INIT_DELAYED_WORK(&codec->power_work, hda_power_work);
951 /* snd_hda_codec_new() marks the codec as power-up, and leave it as is.
952 * the caller has to power down appropriatley after initialization
953 * phase.
954 */
955 hda_keep_power_on(codec);
956#endif
957
Linus Torvalds1da177e2005-04-16 15:20:36 -0700958 list_add_tail(&codec->list, &bus->codec_list);
959 bus->caddr_tbl[codec_addr] = codec;
960
Takashi Iwai0ba21762007-04-16 11:29:14 +0200961 codec->vendor_id = snd_hda_param_read(codec, AC_NODE_ROOT,
962 AC_PAR_VENDOR_ID);
Takashi Iwai111d3af2006-02-16 18:17:58 +0100963 if (codec->vendor_id == -1)
964 /* read again, hopefully the access method was corrected
965 * in the last read...
966 */
967 codec->vendor_id = snd_hda_param_read(codec, AC_NODE_ROOT,
968 AC_PAR_VENDOR_ID);
Takashi Iwai0ba21762007-04-16 11:29:14 +0200969 codec->subsystem_id = snd_hda_param_read(codec, AC_NODE_ROOT,
970 AC_PAR_SUBSYSTEM_ID);
971 codec->revision_id = snd_hda_param_read(codec, AC_NODE_ROOT,
972 AC_PAR_REV_ID);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700973
Sasha Khapyorsky673b6832005-08-11 11:00:16 +0200974 setup_fg_nodes(codec);
Takashi Iwai0ba21762007-04-16 11:29:14 +0200975 if (!codec->afg && !codec->mfg) {
Sasha Khapyorsky673b6832005-08-11 11:00:16 +0200976 snd_printdd("hda_codec: no AFG or MFG node found\n");
Takashi Iwai3be14142009-02-20 14:11:16 +0100977 err = -ENODEV;
978 goto error;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700979 }
980
Takashi Iwai3be14142009-02-20 14:11:16 +0100981 err = read_widget_caps(codec, codec->afg ? codec->afg : codec->mfg);
982 if (err < 0) {
Takashi Iwai54d17402005-11-21 16:33:22 +0100983 snd_printk(KERN_ERR "hda_codec: cannot malloc\n");
Takashi Iwai3be14142009-02-20 14:11:16 +0100984 goto error;
Takashi Iwai54d17402005-11-21 16:33:22 +0100985 }
Takashi Iwai3be14142009-02-20 14:11:16 +0100986 err = read_pin_defaults(codec);
987 if (err < 0)
988 goto error;
Takashi Iwai54d17402005-11-21 16:33:22 +0100989
Takashi Iwai0ba21762007-04-16 11:29:14 +0200990 if (!codec->subsystem_id) {
Takashi Iwai86284e42005-10-11 15:05:54 +0200991 hda_nid_t nid = codec->afg ? codec->afg : codec->mfg;
Takashi Iwai0ba21762007-04-16 11:29:14 +0200992 codec->subsystem_id =
993 snd_hda_codec_read(codec, nid, 0,
994 AC_VERB_GET_SUBSYSTEM_ID, 0);
Takashi Iwai86284e42005-10-11 15:05:54 +0200995 }
996
Takashi Iwaibb6ac722009-03-13 09:02:42 +0100997 /* power-up all before initialization */
998 hda_set_power_state(codec,
999 codec->afg ? codec->afg : codec->mfg,
1000 AC_PWRST_D0);
1001
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001002 snd_hda_codec_proc_new(codec);
1003
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001004 snd_hda_create_hwdep(codec);
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001005
1006 sprintf(component, "HDA:%08x,%08x,%08x", codec->vendor_id,
1007 codec->subsystem_id, codec->revision_id);
1008 snd_component_add(codec->bus->card, component);
1009
1010 if (codecp)
1011 *codecp = codec;
1012 return 0;
Takashi Iwai3be14142009-02-20 14:11:16 +01001013
1014 error:
1015 snd_hda_codec_free(codec);
1016 return err;
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001017}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001018EXPORT_SYMBOL_HDA(snd_hda_codec_new);
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001019
1020int snd_hda_codec_configure(struct hda_codec *codec)
1021{
1022 int err;
1023
Takashi Iwaid5ad6302007-03-07 15:55:59 +01001024 codec->preset = find_codec_preset(codec);
Takashi Iwai812a2cc2009-05-16 10:00:49 +02001025 if (!codec->vendor_name || !codec->chip_name) {
Takashi Iwaif44ac832008-07-30 15:01:45 +02001026 err = get_codec_name(codec);
1027 if (err < 0)
1028 return err;
1029 }
Takashi Iwai43ea1d42007-04-26 19:12:08 +02001030 /* audio codec should override the mixer name */
Takashi Iwaif44ac832008-07-30 15:01:45 +02001031 if (codec->afg || !*codec->bus->card->mixername)
Takashi Iwai812a2cc2009-05-16 10:00:49 +02001032 snprintf(codec->bus->card->mixername,
1033 sizeof(codec->bus->card->mixername),
1034 "%s %s", codec->vendor_name, codec->chip_name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001035
Takashi Iwai82467612007-07-27 19:15:54 +02001036 if (is_generic_config(codec)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001037 err = snd_hda_parse_generic_codec(codec);
Takashi Iwai82467612007-07-27 19:15:54 +02001038 goto patched;
1039 }
Takashi Iwai82467612007-07-27 19:15:54 +02001040 if (codec->preset && codec->preset->patch) {
1041 err = codec->preset->patch(codec);
1042 goto patched;
1043 }
1044
1045 /* call the default parser */
Takashi Iwai82467612007-07-27 19:15:54 +02001046 err = snd_hda_parse_generic_codec(codec);
Takashi Iwai35a1e0c2007-10-19 08:13:40 +02001047 if (err < 0)
1048 printk(KERN_ERR "hda-codec: No codec parser is available\n");
Takashi Iwai82467612007-07-27 19:15:54 +02001049
1050 patched:
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001051 if (!err && codec->patch_ops.unsol_event)
1052 err = init_unsol_queue(codec->bus);
1053 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001054}
Takashi Iwaia1e21c92009-06-17 09:33:52 +02001055EXPORT_SYMBOL_HDA(snd_hda_codec_configure);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001056
1057/**
1058 * snd_hda_codec_setup_stream - set up the codec for streaming
1059 * @codec: the CODEC to set up
1060 * @nid: the NID to set up
1061 * @stream_tag: stream tag to pass, it's between 0x1 and 0xf.
1062 * @channel_id: channel id to pass, zero based.
1063 * @format: stream format.
1064 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02001065void snd_hda_codec_setup_stream(struct hda_codec *codec, hda_nid_t nid,
1066 u32 stream_tag,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001067 int channel_id, int format)
1068{
Takashi Iwai0ba21762007-04-16 11:29:14 +02001069 if (!nid)
Takashi Iwaid21b37e2005-04-20 13:45:55 +02001070 return;
1071
Takashi Iwai0ba21762007-04-16 11:29:14 +02001072 snd_printdd("hda_codec_setup_stream: "
1073 "NID=0x%x, stream=0x%x, channel=%d, format=0x%x\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07001074 nid, stream_tag, channel_id, format);
1075 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CHANNEL_STREAMID,
1076 (stream_tag << 4) | channel_id);
1077 msleep(1);
1078 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_STREAM_FORMAT, format);
1079}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001080EXPORT_SYMBOL_HDA(snd_hda_codec_setup_stream);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001081
Takashi Iwai888afa12008-03-18 09:57:50 +01001082void snd_hda_codec_cleanup_stream(struct hda_codec *codec, hda_nid_t nid)
1083{
1084 if (!nid)
1085 return;
1086
1087 snd_printdd("hda_codec_cleanup_stream: NID=0x%x\n", nid);
1088 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CHANNEL_STREAMID, 0);
1089#if 0 /* keep the format */
1090 msleep(1);
1091 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_STREAM_FORMAT, 0);
1092#endif
1093}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001094EXPORT_SYMBOL_HDA(snd_hda_codec_cleanup_stream);
Takashi Iwai888afa12008-03-18 09:57:50 +01001095
Linus Torvalds1da177e2005-04-16 15:20:36 -07001096/*
1097 * amp access functions
1098 */
1099
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001100/* FIXME: more better hash key? */
1101#define HDA_HASH_KEY(nid,dir,idx) (u32)((nid) + ((idx) << 16) + ((dir) << 24))
Takashi Iwai1327a322009-03-23 13:07:47 +01001102#define HDA_HASH_PINCAP_KEY(nid) (u32)((nid) + (0x02 << 24))
Takashi Iwai92c7c8a2009-03-24 07:32:14 +01001103#define HDA_HASH_PARPCM_KEY(nid) (u32)((nid) + (0x03 << 24))
1104#define HDA_HASH_PARSTR_KEY(nid) (u32)((nid) + (0x04 << 24))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001105#define INFO_AMP_CAPS (1<<0)
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001106#define INFO_AMP_VOL(ch) (1 << (1 + (ch)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001107
1108/* initialize the hash table */
Takashi Iwai1289e9e2008-11-27 15:47:11 +01001109static void /*__devinit*/ init_hda_cache(struct hda_cache_rec *cache,
Takashi Iwai01751f52007-08-10 16:59:39 +02001110 unsigned int record_size)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001111{
Takashi Iwai01751f52007-08-10 16:59:39 +02001112 memset(cache, 0, sizeof(*cache));
1113 memset(cache->hash, 0xff, sizeof(cache->hash));
Takashi Iwai603c4012008-07-30 15:01:44 +02001114 snd_array_init(&cache->buf, record_size, 64);
Takashi Iwai01751f52007-08-10 16:59:39 +02001115}
1116
Takashi Iwai1fcaee62007-08-23 00:01:09 +02001117static void free_hda_cache(struct hda_cache_rec *cache)
Takashi Iwai01751f52007-08-10 16:59:39 +02001118{
Takashi Iwai603c4012008-07-30 15:01:44 +02001119 snd_array_free(&cache->buf);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001120}
1121
1122/* query the hash. allocate an entry if not found. */
Takashi Iwai01751f52007-08-10 16:59:39 +02001123static struct hda_cache_head *get_alloc_hash(struct hda_cache_rec *cache,
1124 u32 key)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001125{
Takashi Iwai01751f52007-08-10 16:59:39 +02001126 u16 idx = key % (u16)ARRAY_SIZE(cache->hash);
1127 u16 cur = cache->hash[idx];
1128 struct hda_cache_head *info;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001129
1130 while (cur != 0xffff) {
Takashi Iwaif43aa022008-11-10 16:24:26 +01001131 info = snd_array_elem(&cache->buf, cur);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001132 if (info->key == key)
1133 return info;
1134 cur = info->next;
1135 }
1136
1137 /* add a new hash entry */
Takashi Iwai603c4012008-07-30 15:01:44 +02001138 info = snd_array_new(&cache->buf);
Takashi Iwaic2174292008-11-07 00:23:30 +01001139 if (!info)
1140 return NULL;
Takashi Iwaif43aa022008-11-10 16:24:26 +01001141 cur = snd_array_index(&cache->buf, info);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001142 info->key = key;
Takashi Iwai01751f52007-08-10 16:59:39 +02001143 info->val = 0;
1144 info->next = cache->hash[idx];
1145 cache->hash[idx] = cur;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001146
1147 return info;
1148}
1149
Takashi Iwai01751f52007-08-10 16:59:39 +02001150/* query and allocate an amp hash entry */
1151static inline struct hda_amp_info *
1152get_alloc_amp_hash(struct hda_codec *codec, u32 key)
1153{
1154 return (struct hda_amp_info *)get_alloc_hash(&codec->amp_cache, key);
1155}
1156
Linus Torvalds1da177e2005-04-16 15:20:36 -07001157/*
1158 * query AMP capabilities for the given widget and direction
1159 */
Matthew Ranostay09a99952008-01-24 11:49:21 +01001160u32 query_amp_caps(struct hda_codec *codec, hda_nid_t nid, int direction)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001161{
Takashi Iwai0ba21762007-04-16 11:29:14 +02001162 struct hda_amp_info *info;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001163
Takashi Iwai0ba21762007-04-16 11:29:14 +02001164 info = get_alloc_amp_hash(codec, HDA_HASH_KEY(nid, direction, 0));
1165 if (!info)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001166 return 0;
Takashi Iwai01751f52007-08-10 16:59:39 +02001167 if (!(info->head.val & INFO_AMP_CAPS)) {
Takashi Iwai0ba21762007-04-16 11:29:14 +02001168 if (!(get_wcaps(codec, nid) & AC_WCAP_AMP_OVRD))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001169 nid = codec->afg;
Takashi Iwai0ba21762007-04-16 11:29:14 +02001170 info->amp_caps = snd_hda_param_read(codec, nid,
1171 direction == HDA_OUTPUT ?
1172 AC_PAR_AMP_OUT_CAP :
1173 AC_PAR_AMP_IN_CAP);
Takashi Iwaib75e53f2007-05-10 16:56:09 +02001174 if (info->amp_caps)
Takashi Iwai01751f52007-08-10 16:59:39 +02001175 info->head.val |= INFO_AMP_CAPS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001176 }
1177 return info->amp_caps;
1178}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001179EXPORT_SYMBOL_HDA(query_amp_caps);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001180
Takashi Iwai897cc182007-05-29 19:01:37 +02001181int snd_hda_override_amp_caps(struct hda_codec *codec, hda_nid_t nid, int dir,
1182 unsigned int caps)
1183{
1184 struct hda_amp_info *info;
1185
1186 info = get_alloc_amp_hash(codec, HDA_HASH_KEY(nid, dir, 0));
1187 if (!info)
1188 return -EINVAL;
1189 info->amp_caps = caps;
Takashi Iwai01751f52007-08-10 16:59:39 +02001190 info->head.val |= INFO_AMP_CAPS;
Takashi Iwai897cc182007-05-29 19:01:37 +02001191 return 0;
1192}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001193EXPORT_SYMBOL_HDA(snd_hda_override_amp_caps);
Takashi Iwai897cc182007-05-29 19:01:37 +02001194
Takashi Iwai92c7c8a2009-03-24 07:32:14 +01001195static unsigned int
1196query_caps_hash(struct hda_codec *codec, hda_nid_t nid, u32 key,
1197 unsigned int (*func)(struct hda_codec *, hda_nid_t))
Takashi Iwai1327a322009-03-23 13:07:47 +01001198{
1199 struct hda_amp_info *info;
1200
Takashi Iwai92c7c8a2009-03-24 07:32:14 +01001201 info = get_alloc_amp_hash(codec, key);
Takashi Iwai1327a322009-03-23 13:07:47 +01001202 if (!info)
1203 return 0;
1204 if (!info->head.val) {
Takashi Iwai1327a322009-03-23 13:07:47 +01001205 info->head.val |= INFO_AMP_CAPS;
Takashi Iwai92c7c8a2009-03-24 07:32:14 +01001206 info->amp_caps = func(codec, nid);
Takashi Iwai1327a322009-03-23 13:07:47 +01001207 }
1208 return info->amp_caps;
1209}
Takashi Iwai92c7c8a2009-03-24 07:32:14 +01001210
1211static unsigned int read_pin_cap(struct hda_codec *codec, hda_nid_t nid)
1212{
1213 return snd_hda_param_read(codec, nid, AC_PAR_PIN_CAP);
1214}
1215
1216u32 snd_hda_query_pin_caps(struct hda_codec *codec, hda_nid_t nid)
1217{
1218 return query_caps_hash(codec, nid, HDA_HASH_PINCAP_KEY(nid),
1219 read_pin_cap);
1220}
Takashi Iwai1327a322009-03-23 13:07:47 +01001221EXPORT_SYMBOL_HDA(snd_hda_query_pin_caps);
1222
Linus Torvalds1da177e2005-04-16 15:20:36 -07001223/*
1224 * read the current volume to info
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001225 * if the cache exists, read the cache value.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001226 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02001227static unsigned int get_vol_mute(struct hda_codec *codec,
1228 struct hda_amp_info *info, hda_nid_t nid,
1229 int ch, int direction, int index)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001230{
1231 u32 val, parm;
1232
Takashi Iwai01751f52007-08-10 16:59:39 +02001233 if (info->head.val & INFO_AMP_VOL(ch))
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001234 return info->vol[ch];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001235
1236 parm = ch ? AC_AMP_GET_RIGHT : AC_AMP_GET_LEFT;
1237 parm |= direction == HDA_OUTPUT ? AC_AMP_GET_OUTPUT : AC_AMP_GET_INPUT;
1238 parm |= index;
Takashi Iwai0ba21762007-04-16 11:29:14 +02001239 val = snd_hda_codec_read(codec, nid, 0,
1240 AC_VERB_GET_AMP_GAIN_MUTE, parm);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001241 info->vol[ch] = val & 0xff;
Takashi Iwai01751f52007-08-10 16:59:39 +02001242 info->head.val |= INFO_AMP_VOL(ch);
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001243 return info->vol[ch];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001244}
1245
1246/*
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001247 * write the current volume in info to the h/w and update the cache
Linus Torvalds1da177e2005-04-16 15:20:36 -07001248 */
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001249static void put_vol_mute(struct hda_codec *codec, struct hda_amp_info *info,
Takashi Iwai0ba21762007-04-16 11:29:14 +02001250 hda_nid_t nid, int ch, int direction, int index,
1251 int val)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001252{
1253 u32 parm;
1254
1255 parm = ch ? AC_AMP_SET_RIGHT : AC_AMP_SET_LEFT;
1256 parm |= direction == HDA_OUTPUT ? AC_AMP_SET_OUTPUT : AC_AMP_SET_INPUT;
1257 parm |= index << AC_AMP_SET_INDEX_SHIFT;
1258 parm |= val;
1259 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, parm);
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001260 info->vol[ch] = val;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001261}
1262
1263/*
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001264 * read AMP value. The volume is between 0 to 0x7f, 0x80 = mute bit.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001265 */
Takashi Iwai834be882006-03-01 14:16:17 +01001266int snd_hda_codec_amp_read(struct hda_codec *codec, hda_nid_t nid, int ch,
1267 int direction, int index)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001268{
Takashi Iwai0ba21762007-04-16 11:29:14 +02001269 struct hda_amp_info *info;
1270 info = get_alloc_amp_hash(codec, HDA_HASH_KEY(nid, direction, index));
1271 if (!info)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001272 return 0;
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001273 return get_vol_mute(codec, info, nid, ch, direction, index);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001274}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001275EXPORT_SYMBOL_HDA(snd_hda_codec_amp_read);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001276
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001277/*
1278 * update the AMP value, mask = bit mask to set, val = the value
1279 */
Takashi Iwai834be882006-03-01 14:16:17 +01001280int snd_hda_codec_amp_update(struct hda_codec *codec, hda_nid_t nid, int ch,
1281 int direction, int idx, int mask, int val)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001282{
Takashi Iwai0ba21762007-04-16 11:29:14 +02001283 struct hda_amp_info *info;
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001284
Takashi Iwai0ba21762007-04-16 11:29:14 +02001285 info = get_alloc_amp_hash(codec, HDA_HASH_KEY(nid, direction, idx));
1286 if (!info)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001287 return 0;
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001288 val &= mask;
1289 val |= get_vol_mute(codec, info, nid, ch, direction, idx) & ~mask;
Takashi Iwai82beb8f2007-08-10 17:09:26 +02001290 if (info->vol[ch] == val)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001291 return 0;
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001292 put_vol_mute(codec, info, nid, ch, direction, idx, val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001293 return 1;
1294}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001295EXPORT_SYMBOL_HDA(snd_hda_codec_amp_update);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001296
Takashi Iwai47fd8302007-08-10 17:11:07 +02001297/*
1298 * update the AMP stereo with the same mask and value
1299 */
1300int snd_hda_codec_amp_stereo(struct hda_codec *codec, hda_nid_t nid,
1301 int direction, int idx, int mask, int val)
1302{
1303 int ch, ret = 0;
1304 for (ch = 0; ch < 2; ch++)
1305 ret |= snd_hda_codec_amp_update(codec, nid, ch, direction,
1306 idx, mask, val);
1307 return ret;
1308}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001309EXPORT_SYMBOL_HDA(snd_hda_codec_amp_stereo);
Takashi Iwai47fd8302007-08-10 17:11:07 +02001310
Takashi Iwaicb53c622007-08-10 17:21:45 +02001311#ifdef SND_HDA_NEEDS_RESUME
Takashi Iwaib3ac5632007-08-10 17:03:40 +02001312/* resume the all amp commands from the cache */
1313void snd_hda_codec_resume_amp(struct hda_codec *codec)
1314{
Takashi Iwai603c4012008-07-30 15:01:44 +02001315 struct hda_amp_info *buffer = codec->amp_cache.buf.list;
Takashi Iwaib3ac5632007-08-10 17:03:40 +02001316 int i;
1317
Takashi Iwai603c4012008-07-30 15:01:44 +02001318 for (i = 0; i < codec->amp_cache.buf.used; i++, buffer++) {
Takashi Iwaib3ac5632007-08-10 17:03:40 +02001319 u32 key = buffer->head.key;
1320 hda_nid_t nid;
1321 unsigned int idx, dir, ch;
1322 if (!key)
1323 continue;
1324 nid = key & 0xff;
1325 idx = (key >> 16) & 0xff;
1326 dir = (key >> 24) & 0xff;
1327 for (ch = 0; ch < 2; ch++) {
1328 if (!(buffer->head.val & INFO_AMP_VOL(ch)))
1329 continue;
1330 put_vol_mute(codec, buffer, nid, ch, dir, idx,
1331 buffer->vol[ch]);
1332 }
1333 }
1334}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001335EXPORT_SYMBOL_HDA(snd_hda_codec_resume_amp);
Takashi Iwaicb53c622007-08-10 17:21:45 +02001336#endif /* SND_HDA_NEEDS_RESUME */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001337
Linus Torvalds1da177e2005-04-16 15:20:36 -07001338/* volume */
Takashi Iwai0ba21762007-04-16 11:29:14 +02001339int snd_hda_mixer_amp_volume_info(struct snd_kcontrol *kcontrol,
1340 struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001341{
1342 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1343 u16 nid = get_amp_nid(kcontrol);
1344 u8 chs = get_amp_channels(kcontrol);
1345 int dir = get_amp_direction(kcontrol);
Takashi Iwai29fdbec2009-01-20 13:07:55 +01001346 unsigned int ofs = get_amp_offset(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001347 u32 caps;
1348
1349 caps = query_amp_caps(codec, nid, dir);
Takashi Iwai0ba21762007-04-16 11:29:14 +02001350 /* num steps */
1351 caps = (caps & AC_AMPCAP_NUM_STEPS) >> AC_AMPCAP_NUM_STEPS_SHIFT;
1352 if (!caps) {
1353 printk(KERN_WARNING "hda_codec: "
Takashi Iwai9c8f2ab2008-01-11 16:12:23 +01001354 "num_steps = 0 for NID=0x%x (ctl = %s)\n", nid,
1355 kcontrol->id.name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001356 return -EINVAL;
1357 }
Takashi Iwai29fdbec2009-01-20 13:07:55 +01001358 if (ofs < caps)
1359 caps -= ofs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001360 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
1361 uinfo->count = chs == 3 ? 2 : 1;
1362 uinfo->value.integer.min = 0;
1363 uinfo->value.integer.max = caps;
1364 return 0;
1365}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001366EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_volume_info);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001367
Takashi Iwai29fdbec2009-01-20 13:07:55 +01001368
1369static inline unsigned int
1370read_amp_value(struct hda_codec *codec, hda_nid_t nid,
1371 int ch, int dir, int idx, unsigned int ofs)
1372{
1373 unsigned int val;
1374 val = snd_hda_codec_amp_read(codec, nid, ch, dir, idx);
1375 val &= HDA_AMP_VOLMASK;
1376 if (val >= ofs)
1377 val -= ofs;
1378 else
1379 val = 0;
1380 return val;
1381}
1382
1383static inline int
1384update_amp_value(struct hda_codec *codec, hda_nid_t nid,
1385 int ch, int dir, int idx, unsigned int ofs,
1386 unsigned int val)
1387{
1388 if (val > 0)
1389 val += ofs;
1390 return snd_hda_codec_amp_update(codec, nid, ch, dir, idx,
1391 HDA_AMP_VOLMASK, val);
1392}
1393
Takashi Iwai0ba21762007-04-16 11:29:14 +02001394int snd_hda_mixer_amp_volume_get(struct snd_kcontrol *kcontrol,
1395 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001396{
1397 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1398 hda_nid_t nid = get_amp_nid(kcontrol);
1399 int chs = get_amp_channels(kcontrol);
1400 int dir = get_amp_direction(kcontrol);
1401 int idx = get_amp_index(kcontrol);
Takashi Iwai29fdbec2009-01-20 13:07:55 +01001402 unsigned int ofs = get_amp_offset(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001403 long *valp = ucontrol->value.integer.value;
1404
1405 if (chs & 1)
Takashi Iwai29fdbec2009-01-20 13:07:55 +01001406 *valp++ = read_amp_value(codec, nid, 0, dir, idx, ofs);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001407 if (chs & 2)
Takashi Iwai29fdbec2009-01-20 13:07:55 +01001408 *valp = read_amp_value(codec, nid, 1, dir, idx, ofs);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001409 return 0;
1410}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001411EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_volume_get);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001412
Takashi Iwai0ba21762007-04-16 11:29:14 +02001413int snd_hda_mixer_amp_volume_put(struct snd_kcontrol *kcontrol,
1414 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001415{
1416 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1417 hda_nid_t nid = get_amp_nid(kcontrol);
1418 int chs = get_amp_channels(kcontrol);
1419 int dir = get_amp_direction(kcontrol);
1420 int idx = get_amp_index(kcontrol);
Takashi Iwai29fdbec2009-01-20 13:07:55 +01001421 unsigned int ofs = get_amp_offset(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001422 long *valp = ucontrol->value.integer.value;
1423 int change = 0;
1424
Takashi Iwaicb53c622007-08-10 17:21:45 +02001425 snd_hda_power_up(codec);
Nicolas Grazianob9f5a892005-07-29 12:17:20 +02001426 if (chs & 1) {
Takashi Iwai29fdbec2009-01-20 13:07:55 +01001427 change = update_amp_value(codec, nid, 0, dir, idx, ofs, *valp);
Nicolas Grazianob9f5a892005-07-29 12:17:20 +02001428 valp++;
1429 }
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001430 if (chs & 2)
Takashi Iwai29fdbec2009-01-20 13:07:55 +01001431 change |= update_amp_value(codec, nid, 1, dir, idx, ofs, *valp);
Takashi Iwaicb53c622007-08-10 17:21:45 +02001432 snd_hda_power_down(codec);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001433 return change;
1434}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001435EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_volume_put);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001436
Jaroslav Kysela302e9c52006-07-05 17:39:49 +02001437int snd_hda_mixer_amp_tlv(struct snd_kcontrol *kcontrol, int op_flag,
1438 unsigned int size, unsigned int __user *_tlv)
1439{
1440 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1441 hda_nid_t nid = get_amp_nid(kcontrol);
1442 int dir = get_amp_direction(kcontrol);
Takashi Iwai29fdbec2009-01-20 13:07:55 +01001443 unsigned int ofs = get_amp_offset(kcontrol);
Jaroslav Kysela302e9c52006-07-05 17:39:49 +02001444 u32 caps, val1, val2;
1445
1446 if (size < 4 * sizeof(unsigned int))
1447 return -ENOMEM;
1448 caps = query_amp_caps(codec, nid, dir);
Takashi Iwai0ba21762007-04-16 11:29:14 +02001449 val2 = (caps & AC_AMPCAP_STEP_SIZE) >> AC_AMPCAP_STEP_SIZE_SHIFT;
1450 val2 = (val2 + 1) * 25;
Jaroslav Kysela302e9c52006-07-05 17:39:49 +02001451 val1 = -((caps & AC_AMPCAP_OFFSET) >> AC_AMPCAP_OFFSET_SHIFT);
Takashi Iwai29fdbec2009-01-20 13:07:55 +01001452 val1 += ofs;
Jaroslav Kysela302e9c52006-07-05 17:39:49 +02001453 val1 = ((int)val1) * ((int)val2);
Jaroslav Kysela302e9c52006-07-05 17:39:49 +02001454 if (put_user(SNDRV_CTL_TLVT_DB_SCALE, _tlv))
1455 return -EFAULT;
1456 if (put_user(2 * sizeof(unsigned int), _tlv + 1))
1457 return -EFAULT;
1458 if (put_user(val1, _tlv + 2))
1459 return -EFAULT;
1460 if (put_user(val2, _tlv + 3))
1461 return -EFAULT;
1462 return 0;
1463}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001464EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_tlv);
Jaroslav Kysela302e9c52006-07-05 17:39:49 +02001465
Takashi Iwai2134ea42008-01-10 16:53:55 +01001466/*
1467 * set (static) TLV for virtual master volume; recalculated as max 0dB
1468 */
1469void snd_hda_set_vmaster_tlv(struct hda_codec *codec, hda_nid_t nid, int dir,
1470 unsigned int *tlv)
1471{
1472 u32 caps;
1473 int nums, step;
1474
1475 caps = query_amp_caps(codec, nid, dir);
1476 nums = (caps & AC_AMPCAP_NUM_STEPS) >> AC_AMPCAP_NUM_STEPS_SHIFT;
1477 step = (caps & AC_AMPCAP_STEP_SIZE) >> AC_AMPCAP_STEP_SIZE_SHIFT;
1478 step = (step + 1) * 25;
1479 tlv[0] = SNDRV_CTL_TLVT_DB_SCALE;
1480 tlv[1] = 2 * sizeof(unsigned int);
1481 tlv[2] = -nums * step;
1482 tlv[3] = step;
1483}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001484EXPORT_SYMBOL_HDA(snd_hda_set_vmaster_tlv);
Takashi Iwai2134ea42008-01-10 16:53:55 +01001485
1486/* find a mixer control element with the given name */
Takashi Iwai09f99702008-02-04 12:31:13 +01001487static struct snd_kcontrol *
1488_snd_hda_find_mixer_ctl(struct hda_codec *codec,
1489 const char *name, int idx)
Takashi Iwai2134ea42008-01-10 16:53:55 +01001490{
1491 struct snd_ctl_elem_id id;
1492 memset(&id, 0, sizeof(id));
1493 id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
Takashi Iwai09f99702008-02-04 12:31:13 +01001494 id.index = idx;
Takashi Iwai18cb7102009-04-16 10:22:24 +02001495 if (snd_BUG_ON(strlen(name) >= sizeof(id.name)))
1496 return NULL;
Takashi Iwai2134ea42008-01-10 16:53:55 +01001497 strcpy(id.name, name);
1498 return snd_ctl_find_id(codec->bus->card, &id);
1499}
1500
Takashi Iwai09f99702008-02-04 12:31:13 +01001501struct snd_kcontrol *snd_hda_find_mixer_ctl(struct hda_codec *codec,
1502 const char *name)
1503{
1504 return _snd_hda_find_mixer_ctl(codec, name, 0);
1505}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001506EXPORT_SYMBOL_HDA(snd_hda_find_mixer_ctl);
Takashi Iwai09f99702008-02-04 12:31:13 +01001507
Takashi Iwaid13bd412008-07-30 15:01:45 +02001508/* Add a control element and assign to the codec */
1509int snd_hda_ctl_add(struct hda_codec *codec, struct snd_kcontrol *kctl)
1510{
1511 int err;
1512 struct snd_kcontrol **knewp;
1513
1514 err = snd_ctl_add(codec->bus->card, kctl);
1515 if (err < 0)
1516 return err;
1517 knewp = snd_array_new(&codec->mixers);
1518 if (!knewp)
1519 return -ENOMEM;
1520 *knewp = kctl;
1521 return 0;
1522}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001523EXPORT_SYMBOL_HDA(snd_hda_ctl_add);
Takashi Iwaid13bd412008-07-30 15:01:45 +02001524
1525/* Clear all controls assigned to the given codec */
1526void snd_hda_ctls_clear(struct hda_codec *codec)
1527{
1528 int i;
1529 struct snd_kcontrol **kctls = codec->mixers.list;
1530 for (i = 0; i < codec->mixers.used; i++)
1531 snd_ctl_remove(codec->bus->card, kctls[i]);
1532 snd_array_free(&codec->mixers);
1533}
1534
Takashi Iwaia65d6292009-02-23 16:57:04 +01001535/* pseudo device locking
1536 * toggle card->shutdown to allow/disallow the device access (as a hack)
1537 */
1538static int hda_lock_devices(struct snd_card *card)
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001539{
Takashi Iwaia65d6292009-02-23 16:57:04 +01001540 spin_lock(&card->files_lock);
1541 if (card->shutdown) {
1542 spin_unlock(&card->files_lock);
1543 return -EINVAL;
1544 }
1545 card->shutdown = 1;
1546 spin_unlock(&card->files_lock);
1547 return 0;
1548}
1549
1550static void hda_unlock_devices(struct snd_card *card)
1551{
1552 spin_lock(&card->files_lock);
1553 card->shutdown = 0;
1554 spin_unlock(&card->files_lock);
1555}
1556
1557int snd_hda_codec_reset(struct hda_codec *codec)
1558{
1559 struct snd_card *card = codec->bus->card;
1560 int i, pcm;
1561
1562 if (hda_lock_devices(card) < 0)
1563 return -EBUSY;
1564 /* check whether the codec isn't used by any mixer or PCM streams */
1565 if (!list_empty(&card->ctl_files)) {
1566 hda_unlock_devices(card);
1567 return -EBUSY;
1568 }
1569 for (pcm = 0; pcm < codec->num_pcms; pcm++) {
1570 struct hda_pcm *cpcm = &codec->pcm_info[pcm];
1571 if (!cpcm->pcm)
1572 continue;
1573 if (cpcm->pcm->streams[0].substream_opened ||
1574 cpcm->pcm->streams[1].substream_opened) {
1575 hda_unlock_devices(card);
1576 return -EBUSY;
1577 }
1578 }
1579
1580 /* OK, let it free */
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001581
1582#ifdef CONFIG_SND_HDA_POWER_SAVE
1583 cancel_delayed_work(&codec->power_work);
Takashi Iwai6acaed32009-01-12 10:09:24 +01001584 flush_workqueue(codec->bus->workq);
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001585#endif
1586 snd_hda_ctls_clear(codec);
1587 /* relase PCMs */
1588 for (i = 0; i < codec->num_pcms; i++) {
Takashi Iwai529bd6c2008-11-27 14:17:01 +01001589 if (codec->pcm_info[i].pcm) {
Takashi Iwaia65d6292009-02-23 16:57:04 +01001590 snd_device_free(card, codec->pcm_info[i].pcm);
Takashi Iwai529bd6c2008-11-27 14:17:01 +01001591 clear_bit(codec->pcm_info[i].device,
1592 codec->bus->pcm_dev_bits);
1593 }
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001594 }
1595 if (codec->patch_ops.free)
1596 codec->patch_ops.free(codec);
Takashi Iwai56d17712008-11-28 14:36:23 +01001597 codec->proc_widget_hook = NULL;
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001598 codec->spec = NULL;
1599 free_hda_cache(&codec->amp_cache);
1600 free_hda_cache(&codec->cmd_cache);
Takashi Iwai827057f2008-12-19 10:12:02 +01001601 init_hda_cache(&codec->amp_cache, sizeof(struct hda_amp_info));
1602 init_hda_cache(&codec->cmd_cache, sizeof(struct hda_cache_head));
Takashi Iwai346ff702009-02-23 09:42:57 +01001603 /* free only driver_pins so that init_pins + user_pins are restored */
1604 snd_array_free(&codec->driver_pins);
Takashi Iwai3be14142009-02-20 14:11:16 +01001605 restore_pincfgs(codec);
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001606 codec->num_pcms = 0;
1607 codec->pcm_info = NULL;
1608 codec->preset = NULL;
Takashi Iwaid1f1af22009-03-02 10:35:29 +01001609 memset(&codec->patch_ops, 0, sizeof(codec->patch_ops));
1610 codec->slave_dig_outs = NULL;
1611 codec->spdif_status_reset = 0;
Takashi Iwai1289e9e2008-11-27 15:47:11 +01001612 module_put(codec->owner);
1613 codec->owner = NULL;
Takashi Iwaia65d6292009-02-23 16:57:04 +01001614
1615 /* allow device access again */
1616 hda_unlock_devices(card);
1617 return 0;
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001618}
1619
Takashi Iwai2134ea42008-01-10 16:53:55 +01001620/* create a virtual master control and add slaves */
1621int snd_hda_add_vmaster(struct hda_codec *codec, char *name,
1622 unsigned int *tlv, const char **slaves)
1623{
1624 struct snd_kcontrol *kctl;
1625 const char **s;
1626 int err;
1627
Takashi Iwai2f085542008-02-22 18:43:50 +01001628 for (s = slaves; *s && !snd_hda_find_mixer_ctl(codec, *s); s++)
1629 ;
1630 if (!*s) {
1631 snd_printdd("No slave found for %s\n", name);
1632 return 0;
1633 }
Takashi Iwai2134ea42008-01-10 16:53:55 +01001634 kctl = snd_ctl_make_virtual_master(name, tlv);
1635 if (!kctl)
1636 return -ENOMEM;
Takashi Iwaid13bd412008-07-30 15:01:45 +02001637 err = snd_hda_ctl_add(codec, kctl);
Takashi Iwai2134ea42008-01-10 16:53:55 +01001638 if (err < 0)
1639 return err;
1640
1641 for (s = slaves; *s; s++) {
1642 struct snd_kcontrol *sctl;
Takashi Iwai7a411ee2009-03-06 10:08:14 +01001643 int i = 0;
1644 for (;;) {
1645 sctl = _snd_hda_find_mixer_ctl(codec, *s, i);
1646 if (!sctl) {
1647 if (!i)
1648 snd_printdd("Cannot find slave %s, "
1649 "skipped\n", *s);
1650 break;
1651 }
1652 err = snd_ctl_add_slave(kctl, sctl);
1653 if (err < 0)
1654 return err;
1655 i++;
Takashi Iwai2134ea42008-01-10 16:53:55 +01001656 }
Takashi Iwai2134ea42008-01-10 16:53:55 +01001657 }
1658 return 0;
1659}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001660EXPORT_SYMBOL_HDA(snd_hda_add_vmaster);
Takashi Iwai2134ea42008-01-10 16:53:55 +01001661
Linus Torvalds1da177e2005-04-16 15:20:36 -07001662/* switch */
Takashi Iwai0ba21762007-04-16 11:29:14 +02001663int snd_hda_mixer_amp_switch_info(struct snd_kcontrol *kcontrol,
1664 struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001665{
1666 int chs = get_amp_channels(kcontrol);
1667
1668 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
1669 uinfo->count = chs == 3 ? 2 : 1;
1670 uinfo->value.integer.min = 0;
1671 uinfo->value.integer.max = 1;
1672 return 0;
1673}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001674EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_switch_info);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001675
Takashi Iwai0ba21762007-04-16 11:29:14 +02001676int snd_hda_mixer_amp_switch_get(struct snd_kcontrol *kcontrol,
1677 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001678{
1679 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1680 hda_nid_t nid = get_amp_nid(kcontrol);
1681 int chs = get_amp_channels(kcontrol);
1682 int dir = get_amp_direction(kcontrol);
1683 int idx = get_amp_index(kcontrol);
1684 long *valp = ucontrol->value.integer.value;
1685
1686 if (chs & 1)
Takashi Iwai0ba21762007-04-16 11:29:14 +02001687 *valp++ = (snd_hda_codec_amp_read(codec, nid, 0, dir, idx) &
Takashi Iwai47fd8302007-08-10 17:11:07 +02001688 HDA_AMP_MUTE) ? 0 : 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001689 if (chs & 2)
Takashi Iwai0ba21762007-04-16 11:29:14 +02001690 *valp = (snd_hda_codec_amp_read(codec, nid, 1, dir, idx) &
Takashi Iwai47fd8302007-08-10 17:11:07 +02001691 HDA_AMP_MUTE) ? 0 : 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001692 return 0;
1693}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001694EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_switch_get);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001695
Takashi Iwai0ba21762007-04-16 11:29:14 +02001696int snd_hda_mixer_amp_switch_put(struct snd_kcontrol *kcontrol,
1697 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001698{
1699 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1700 hda_nid_t nid = get_amp_nid(kcontrol);
1701 int chs = get_amp_channels(kcontrol);
1702 int dir = get_amp_direction(kcontrol);
1703 int idx = get_amp_index(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001704 long *valp = ucontrol->value.integer.value;
1705 int change = 0;
1706
Takashi Iwaicb53c622007-08-10 17:21:45 +02001707 snd_hda_power_up(codec);
Nicolas Grazianob9f5a892005-07-29 12:17:20 +02001708 if (chs & 1) {
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001709 change = snd_hda_codec_amp_update(codec, nid, 0, dir, idx,
Takashi Iwai47fd8302007-08-10 17:11:07 +02001710 HDA_AMP_MUTE,
1711 *valp ? 0 : HDA_AMP_MUTE);
Nicolas Grazianob9f5a892005-07-29 12:17:20 +02001712 valp++;
1713 }
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001714 if (chs & 2)
1715 change |= snd_hda_codec_amp_update(codec, nid, 1, dir, idx,
Takashi Iwai47fd8302007-08-10 17:11:07 +02001716 HDA_AMP_MUTE,
1717 *valp ? 0 : HDA_AMP_MUTE);
Takashi Iwaicb53c622007-08-10 17:21:45 +02001718#ifdef CONFIG_SND_HDA_POWER_SAVE
1719 if (codec->patch_ops.check_power_status)
1720 codec->patch_ops.check_power_status(codec, nid);
1721#endif
1722 snd_hda_power_down(codec);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001723 return change;
1724}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001725EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_switch_put);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001726
1727/*
Takashi Iwai985be542005-11-02 18:26:49 +01001728 * bound volume controls
1729 *
1730 * bind multiple volumes (# indices, from 0)
1731 */
1732
1733#define AMP_VAL_IDX_SHIFT 19
1734#define AMP_VAL_IDX_MASK (0x0f<<19)
1735
Takashi Iwai0ba21762007-04-16 11:29:14 +02001736int snd_hda_mixer_bind_switch_get(struct snd_kcontrol *kcontrol,
1737 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai985be542005-11-02 18:26:49 +01001738{
1739 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1740 unsigned long pval;
1741 int err;
1742
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001743 mutex_lock(&codec->control_mutex);
Takashi Iwai985be542005-11-02 18:26:49 +01001744 pval = kcontrol->private_value;
1745 kcontrol->private_value = pval & ~AMP_VAL_IDX_MASK; /* index 0 */
1746 err = snd_hda_mixer_amp_switch_get(kcontrol, ucontrol);
1747 kcontrol->private_value = pval;
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001748 mutex_unlock(&codec->control_mutex);
Takashi Iwai985be542005-11-02 18:26:49 +01001749 return err;
1750}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001751EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_switch_get);
Takashi Iwai985be542005-11-02 18:26:49 +01001752
Takashi Iwai0ba21762007-04-16 11:29:14 +02001753int snd_hda_mixer_bind_switch_put(struct snd_kcontrol *kcontrol,
1754 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai985be542005-11-02 18:26:49 +01001755{
1756 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1757 unsigned long pval;
1758 int i, indices, err = 0, change = 0;
1759
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001760 mutex_lock(&codec->control_mutex);
Takashi Iwai985be542005-11-02 18:26:49 +01001761 pval = kcontrol->private_value;
1762 indices = (pval & AMP_VAL_IDX_MASK) >> AMP_VAL_IDX_SHIFT;
1763 for (i = 0; i < indices; i++) {
Takashi Iwai0ba21762007-04-16 11:29:14 +02001764 kcontrol->private_value = (pval & ~AMP_VAL_IDX_MASK) |
1765 (i << AMP_VAL_IDX_SHIFT);
Takashi Iwai985be542005-11-02 18:26:49 +01001766 err = snd_hda_mixer_amp_switch_put(kcontrol, ucontrol);
1767 if (err < 0)
1768 break;
1769 change |= err;
1770 }
1771 kcontrol->private_value = pval;
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001772 mutex_unlock(&codec->control_mutex);
Takashi Iwai985be542005-11-02 18:26:49 +01001773 return err < 0 ? err : change;
1774}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001775EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_switch_put);
Takashi Iwai985be542005-11-02 18:26:49 +01001776
1777/*
Takashi Iwai532d5382007-07-27 19:02:40 +02001778 * generic bound volume/swtich controls
1779 */
1780int snd_hda_mixer_bind_ctls_info(struct snd_kcontrol *kcontrol,
1781 struct snd_ctl_elem_info *uinfo)
1782{
1783 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1784 struct hda_bind_ctls *c;
1785 int err;
1786
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001787 mutex_lock(&codec->control_mutex);
Serge A. Suchkov14c65f92008-02-22 18:43:16 +01001788 c = (struct hda_bind_ctls *)kcontrol->private_value;
Takashi Iwai532d5382007-07-27 19:02:40 +02001789 kcontrol->private_value = *c->values;
1790 err = c->ops->info(kcontrol, uinfo);
1791 kcontrol->private_value = (long)c;
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001792 mutex_unlock(&codec->control_mutex);
Takashi Iwai532d5382007-07-27 19:02:40 +02001793 return err;
1794}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001795EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_ctls_info);
Takashi Iwai532d5382007-07-27 19:02:40 +02001796
1797int snd_hda_mixer_bind_ctls_get(struct snd_kcontrol *kcontrol,
1798 struct snd_ctl_elem_value *ucontrol)
1799{
1800 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1801 struct hda_bind_ctls *c;
1802 int err;
1803
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001804 mutex_lock(&codec->control_mutex);
Serge A. Suchkov14c65f92008-02-22 18:43:16 +01001805 c = (struct hda_bind_ctls *)kcontrol->private_value;
Takashi Iwai532d5382007-07-27 19:02:40 +02001806 kcontrol->private_value = *c->values;
1807 err = c->ops->get(kcontrol, ucontrol);
1808 kcontrol->private_value = (long)c;
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001809 mutex_unlock(&codec->control_mutex);
Takashi Iwai532d5382007-07-27 19:02:40 +02001810 return err;
1811}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001812EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_ctls_get);
Takashi Iwai532d5382007-07-27 19:02:40 +02001813
1814int snd_hda_mixer_bind_ctls_put(struct snd_kcontrol *kcontrol,
1815 struct snd_ctl_elem_value *ucontrol)
1816{
1817 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1818 struct hda_bind_ctls *c;
1819 unsigned long *vals;
1820 int err = 0, change = 0;
1821
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001822 mutex_lock(&codec->control_mutex);
Serge A. Suchkov14c65f92008-02-22 18:43:16 +01001823 c = (struct hda_bind_ctls *)kcontrol->private_value;
Takashi Iwai532d5382007-07-27 19:02:40 +02001824 for (vals = c->values; *vals; vals++) {
1825 kcontrol->private_value = *vals;
1826 err = c->ops->put(kcontrol, ucontrol);
1827 if (err < 0)
1828 break;
1829 change |= err;
1830 }
1831 kcontrol->private_value = (long)c;
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001832 mutex_unlock(&codec->control_mutex);
Takashi Iwai532d5382007-07-27 19:02:40 +02001833 return err < 0 ? err : change;
1834}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001835EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_ctls_put);
Takashi Iwai532d5382007-07-27 19:02:40 +02001836
1837int snd_hda_mixer_bind_tlv(struct snd_kcontrol *kcontrol, int op_flag,
1838 unsigned int size, unsigned int __user *tlv)
1839{
1840 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1841 struct hda_bind_ctls *c;
1842 int err;
1843
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001844 mutex_lock(&codec->control_mutex);
Serge A. Suchkov14c65f92008-02-22 18:43:16 +01001845 c = (struct hda_bind_ctls *)kcontrol->private_value;
Takashi Iwai532d5382007-07-27 19:02:40 +02001846 kcontrol->private_value = *c->values;
1847 err = c->ops->tlv(kcontrol, op_flag, size, tlv);
1848 kcontrol->private_value = (long)c;
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001849 mutex_unlock(&codec->control_mutex);
Takashi Iwai532d5382007-07-27 19:02:40 +02001850 return err;
1851}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001852EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_tlv);
Takashi Iwai532d5382007-07-27 19:02:40 +02001853
1854struct hda_ctl_ops snd_hda_bind_vol = {
1855 .info = snd_hda_mixer_amp_volume_info,
1856 .get = snd_hda_mixer_amp_volume_get,
1857 .put = snd_hda_mixer_amp_volume_put,
1858 .tlv = snd_hda_mixer_amp_tlv
1859};
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001860EXPORT_SYMBOL_HDA(snd_hda_bind_vol);
Takashi Iwai532d5382007-07-27 19:02:40 +02001861
1862struct hda_ctl_ops snd_hda_bind_sw = {
1863 .info = snd_hda_mixer_amp_switch_info,
1864 .get = snd_hda_mixer_amp_switch_get,
1865 .put = snd_hda_mixer_amp_switch_put,
1866 .tlv = snd_hda_mixer_amp_tlv
1867};
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001868EXPORT_SYMBOL_HDA(snd_hda_bind_sw);
Takashi Iwai532d5382007-07-27 19:02:40 +02001869
1870/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07001871 * SPDIF out controls
1872 */
1873
Takashi Iwai0ba21762007-04-16 11:29:14 +02001874static int snd_hda_spdif_mask_info(struct snd_kcontrol *kcontrol,
1875 struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001876{
1877 uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
1878 uinfo->count = 1;
1879 return 0;
1880}
1881
Takashi Iwai0ba21762007-04-16 11:29:14 +02001882static int snd_hda_spdif_cmask_get(struct snd_kcontrol *kcontrol,
1883 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001884{
1885 ucontrol->value.iec958.status[0] = IEC958_AES0_PROFESSIONAL |
1886 IEC958_AES0_NONAUDIO |
1887 IEC958_AES0_CON_EMPHASIS_5015 |
1888 IEC958_AES0_CON_NOT_COPYRIGHT;
1889 ucontrol->value.iec958.status[1] = IEC958_AES1_CON_CATEGORY |
1890 IEC958_AES1_CON_ORIGINAL;
1891 return 0;
1892}
1893
Takashi Iwai0ba21762007-04-16 11:29:14 +02001894static int snd_hda_spdif_pmask_get(struct snd_kcontrol *kcontrol,
1895 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001896{
1897 ucontrol->value.iec958.status[0] = IEC958_AES0_PROFESSIONAL |
1898 IEC958_AES0_NONAUDIO |
1899 IEC958_AES0_PRO_EMPHASIS_5015;
1900 return 0;
1901}
1902
Takashi Iwai0ba21762007-04-16 11:29:14 +02001903static int snd_hda_spdif_default_get(struct snd_kcontrol *kcontrol,
1904 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001905{
1906 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1907
1908 ucontrol->value.iec958.status[0] = codec->spdif_status & 0xff;
1909 ucontrol->value.iec958.status[1] = (codec->spdif_status >> 8) & 0xff;
1910 ucontrol->value.iec958.status[2] = (codec->spdif_status >> 16) & 0xff;
1911 ucontrol->value.iec958.status[3] = (codec->spdif_status >> 24) & 0xff;
1912
1913 return 0;
1914}
1915
1916/* convert from SPDIF status bits to HDA SPDIF bits
1917 * bit 0 (DigEn) is always set zero (to be filled later)
1918 */
1919static unsigned short convert_from_spdif_status(unsigned int sbits)
1920{
1921 unsigned short val = 0;
1922
1923 if (sbits & IEC958_AES0_PROFESSIONAL)
Takashi Iwai0ba21762007-04-16 11:29:14 +02001924 val |= AC_DIG1_PROFESSIONAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001925 if (sbits & IEC958_AES0_NONAUDIO)
Takashi Iwai0ba21762007-04-16 11:29:14 +02001926 val |= AC_DIG1_NONAUDIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001927 if (sbits & IEC958_AES0_PROFESSIONAL) {
Takashi Iwai0ba21762007-04-16 11:29:14 +02001928 if ((sbits & IEC958_AES0_PRO_EMPHASIS) ==
1929 IEC958_AES0_PRO_EMPHASIS_5015)
1930 val |= AC_DIG1_EMPHASIS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001931 } else {
Takashi Iwai0ba21762007-04-16 11:29:14 +02001932 if ((sbits & IEC958_AES0_CON_EMPHASIS) ==
1933 IEC958_AES0_CON_EMPHASIS_5015)
1934 val |= AC_DIG1_EMPHASIS;
1935 if (!(sbits & IEC958_AES0_CON_NOT_COPYRIGHT))
1936 val |= AC_DIG1_COPYRIGHT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001937 if (sbits & (IEC958_AES1_CON_ORIGINAL << 8))
Takashi Iwai0ba21762007-04-16 11:29:14 +02001938 val |= AC_DIG1_LEVEL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001939 val |= sbits & (IEC958_AES1_CON_CATEGORY << 8);
1940 }
1941 return val;
1942}
1943
1944/* convert to SPDIF status bits from HDA SPDIF bits
1945 */
1946static unsigned int convert_to_spdif_status(unsigned short val)
1947{
1948 unsigned int sbits = 0;
1949
Takashi Iwai0ba21762007-04-16 11:29:14 +02001950 if (val & AC_DIG1_NONAUDIO)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001951 sbits |= IEC958_AES0_NONAUDIO;
Takashi Iwai0ba21762007-04-16 11:29:14 +02001952 if (val & AC_DIG1_PROFESSIONAL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001953 sbits |= IEC958_AES0_PROFESSIONAL;
1954 if (sbits & IEC958_AES0_PROFESSIONAL) {
Takashi Iwai0ba21762007-04-16 11:29:14 +02001955 if (sbits & AC_DIG1_EMPHASIS)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001956 sbits |= IEC958_AES0_PRO_EMPHASIS_5015;
1957 } else {
Takashi Iwai0ba21762007-04-16 11:29:14 +02001958 if (val & AC_DIG1_EMPHASIS)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001959 sbits |= IEC958_AES0_CON_EMPHASIS_5015;
Takashi Iwai0ba21762007-04-16 11:29:14 +02001960 if (!(val & AC_DIG1_COPYRIGHT))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001961 sbits |= IEC958_AES0_CON_NOT_COPYRIGHT;
Takashi Iwai0ba21762007-04-16 11:29:14 +02001962 if (val & AC_DIG1_LEVEL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001963 sbits |= (IEC958_AES1_CON_ORIGINAL << 8);
1964 sbits |= val & (0x7f << 8);
1965 }
1966 return sbits;
1967}
1968
Takashi Iwai2f728532008-09-25 16:32:41 +02001969/* set digital convert verbs both for the given NID and its slaves */
1970static void set_dig_out(struct hda_codec *codec, hda_nid_t nid,
1971 int verb, int val)
1972{
1973 hda_nid_t *d;
1974
Takashi Iwai9e976972008-11-25 08:17:20 +01001975 snd_hda_codec_write_cache(codec, nid, 0, verb, val);
Takashi Iwai2f728532008-09-25 16:32:41 +02001976 d = codec->slave_dig_outs;
1977 if (!d)
1978 return;
1979 for (; *d; d++)
Takashi Iwai9e976972008-11-25 08:17:20 +01001980 snd_hda_codec_write_cache(codec, *d, 0, verb, val);
Takashi Iwai2f728532008-09-25 16:32:41 +02001981}
1982
1983static inline void set_dig_out_convert(struct hda_codec *codec, hda_nid_t nid,
1984 int dig1, int dig2)
1985{
1986 if (dig1 != -1)
1987 set_dig_out(codec, nid, AC_VERB_SET_DIGI_CONVERT_1, dig1);
1988 if (dig2 != -1)
1989 set_dig_out(codec, nid, AC_VERB_SET_DIGI_CONVERT_2, dig2);
1990}
1991
Takashi Iwai0ba21762007-04-16 11:29:14 +02001992static int snd_hda_spdif_default_put(struct snd_kcontrol *kcontrol,
1993 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001994{
1995 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1996 hda_nid_t nid = kcontrol->private_value;
1997 unsigned short val;
1998 int change;
1999
Ingo Molnar62932df2006-01-16 16:34:20 +01002000 mutex_lock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002001 codec->spdif_status = ucontrol->value.iec958.status[0] |
2002 ((unsigned int)ucontrol->value.iec958.status[1] << 8) |
2003 ((unsigned int)ucontrol->value.iec958.status[2] << 16) |
2004 ((unsigned int)ucontrol->value.iec958.status[3] << 24);
2005 val = convert_from_spdif_status(codec->spdif_status);
2006 val |= codec->spdif_ctls & 1;
2007 change = codec->spdif_ctls != val;
2008 codec->spdif_ctls = val;
2009
Takashi Iwai2f728532008-09-25 16:32:41 +02002010 if (change)
2011 set_dig_out_convert(codec, nid, val & 0xff, (val >> 8) & 0xff);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002012
Ingo Molnar62932df2006-01-16 16:34:20 +01002013 mutex_unlock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002014 return change;
2015}
2016
Takashi Iwaia5ce8892007-07-23 15:42:26 +02002017#define snd_hda_spdif_out_switch_info snd_ctl_boolean_mono_info
Linus Torvalds1da177e2005-04-16 15:20:36 -07002018
Takashi Iwai0ba21762007-04-16 11:29:14 +02002019static int snd_hda_spdif_out_switch_get(struct snd_kcontrol *kcontrol,
2020 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002021{
2022 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2023
Takashi Iwai0ba21762007-04-16 11:29:14 +02002024 ucontrol->value.integer.value[0] = codec->spdif_ctls & AC_DIG1_ENABLE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002025 return 0;
2026}
2027
Takashi Iwai0ba21762007-04-16 11:29:14 +02002028static int snd_hda_spdif_out_switch_put(struct snd_kcontrol *kcontrol,
2029 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002030{
2031 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2032 hda_nid_t nid = kcontrol->private_value;
2033 unsigned short val;
2034 int change;
2035
Ingo Molnar62932df2006-01-16 16:34:20 +01002036 mutex_lock(&codec->spdif_mutex);
Takashi Iwai0ba21762007-04-16 11:29:14 +02002037 val = codec->spdif_ctls & ~AC_DIG1_ENABLE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002038 if (ucontrol->value.integer.value[0])
Takashi Iwai0ba21762007-04-16 11:29:14 +02002039 val |= AC_DIG1_ENABLE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002040 change = codec->spdif_ctls != val;
Takashi Iwai82beb8f2007-08-10 17:09:26 +02002041 if (change) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002042 codec->spdif_ctls = val;
Takashi Iwai2f728532008-09-25 16:32:41 +02002043 set_dig_out_convert(codec, nid, val & 0xff, -1);
Takashi Iwai0ba21762007-04-16 11:29:14 +02002044 /* unmute amp switch (if any) */
2045 if ((get_wcaps(codec, nid) & AC_WCAP_OUT_AMP) &&
Takashi Iwai47fd8302007-08-10 17:11:07 +02002046 (val & AC_DIG1_ENABLE))
2047 snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0,
2048 HDA_AMP_MUTE, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002049 }
Ingo Molnar62932df2006-01-16 16:34:20 +01002050 mutex_unlock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002051 return change;
2052}
2053
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01002054static struct snd_kcontrol_new dig_mixes[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002055 {
2056 .access = SNDRV_CTL_ELEM_ACCESS_READ,
2057 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2058 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,CON_MASK),
2059 .info = snd_hda_spdif_mask_info,
2060 .get = snd_hda_spdif_cmask_get,
2061 },
2062 {
2063 .access = SNDRV_CTL_ELEM_ACCESS_READ,
2064 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2065 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,PRO_MASK),
2066 .info = snd_hda_spdif_mask_info,
2067 .get = snd_hda_spdif_pmask_get,
2068 },
2069 {
2070 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2071 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT),
2072 .info = snd_hda_spdif_mask_info,
2073 .get = snd_hda_spdif_default_get,
2074 .put = snd_hda_spdif_default_put,
2075 },
2076 {
2077 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2078 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,SWITCH),
2079 .info = snd_hda_spdif_out_switch_info,
2080 .get = snd_hda_spdif_out_switch_get,
2081 .put = snd_hda_spdif_out_switch_put,
2082 },
2083 { } /* end */
2084};
2085
Takashi Iwai09f99702008-02-04 12:31:13 +01002086#define SPDIF_MAX_IDX 4 /* 4 instances should be enough to probe */
2087
Linus Torvalds1da177e2005-04-16 15:20:36 -07002088/**
2089 * snd_hda_create_spdif_out_ctls - create Output SPDIF-related controls
2090 * @codec: the HDA codec
2091 * @nid: audio out widget NID
2092 *
2093 * Creates controls related with the SPDIF output.
2094 * Called from each patch supporting the SPDIF out.
2095 *
2096 * Returns 0 if successful, or a negative error code.
2097 */
Takashi Iwai12f288b2007-08-02 15:51:59 +02002098int snd_hda_create_spdif_out_ctls(struct hda_codec *codec, hda_nid_t nid)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002099{
2100 int err;
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01002101 struct snd_kcontrol *kctl;
2102 struct snd_kcontrol_new *dig_mix;
Takashi Iwai09f99702008-02-04 12:31:13 +01002103 int idx;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002104
Takashi Iwai09f99702008-02-04 12:31:13 +01002105 for (idx = 0; idx < SPDIF_MAX_IDX; idx++) {
2106 if (!_snd_hda_find_mixer_ctl(codec, "IEC958 Playback Switch",
2107 idx))
2108 break;
2109 }
2110 if (idx >= SPDIF_MAX_IDX) {
2111 printk(KERN_ERR "hda_codec: too many IEC958 outputs\n");
2112 return -EBUSY;
2113 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002114 for (dig_mix = dig_mixes; dig_mix->name; dig_mix++) {
2115 kctl = snd_ctl_new1(dig_mix, codec);
Takashi Iwaib91f0802008-11-04 08:43:08 +01002116 if (!kctl)
2117 return -ENOMEM;
Takashi Iwai09f99702008-02-04 12:31:13 +01002118 kctl->id.index = idx;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002119 kctl->private_value = nid;
Takashi Iwaid13bd412008-07-30 15:01:45 +02002120 err = snd_hda_ctl_add(codec, kctl);
Takashi Iwai0ba21762007-04-16 11:29:14 +02002121 if (err < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002122 return err;
2123 }
Takashi Iwai0ba21762007-04-16 11:29:14 +02002124 codec->spdif_ctls =
Andrew Paprocki3982d172007-12-19 12:13:44 +01002125 snd_hda_codec_read(codec, nid, 0,
2126 AC_VERB_GET_DIGI_CONVERT_1, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002127 codec->spdif_status = convert_to_spdif_status(codec->spdif_ctls);
2128 return 0;
2129}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002130EXPORT_SYMBOL_HDA(snd_hda_create_spdif_out_ctls);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002131
2132/*
Takashi Iwai9a081602008-02-12 18:37:26 +01002133 * SPDIF sharing with analog output
2134 */
2135static int spdif_share_sw_get(struct snd_kcontrol *kcontrol,
2136 struct snd_ctl_elem_value *ucontrol)
2137{
2138 struct hda_multi_out *mout = snd_kcontrol_chip(kcontrol);
2139 ucontrol->value.integer.value[0] = mout->share_spdif;
2140 return 0;
2141}
2142
2143static int spdif_share_sw_put(struct snd_kcontrol *kcontrol,
2144 struct snd_ctl_elem_value *ucontrol)
2145{
2146 struct hda_multi_out *mout = snd_kcontrol_chip(kcontrol);
2147 mout->share_spdif = !!ucontrol->value.integer.value[0];
2148 return 0;
2149}
2150
2151static struct snd_kcontrol_new spdif_share_sw = {
2152 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2153 .name = "IEC958 Default PCM Playback Switch",
2154 .info = snd_ctl_boolean_mono_info,
2155 .get = spdif_share_sw_get,
2156 .put = spdif_share_sw_put,
2157};
2158
2159int snd_hda_create_spdif_share_sw(struct hda_codec *codec,
2160 struct hda_multi_out *mout)
2161{
2162 if (!mout->dig_out_nid)
2163 return 0;
2164 /* ATTENTION: here mout is passed as private_data, instead of codec */
Takashi Iwaid13bd412008-07-30 15:01:45 +02002165 return snd_hda_ctl_add(codec,
Takashi Iwai9a081602008-02-12 18:37:26 +01002166 snd_ctl_new1(&spdif_share_sw, mout));
2167}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002168EXPORT_SYMBOL_HDA(snd_hda_create_spdif_share_sw);
Takashi Iwai9a081602008-02-12 18:37:26 +01002169
2170/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002171 * SPDIF input
2172 */
2173
2174#define snd_hda_spdif_in_switch_info snd_hda_spdif_out_switch_info
2175
Takashi Iwai0ba21762007-04-16 11:29:14 +02002176static int snd_hda_spdif_in_switch_get(struct snd_kcontrol *kcontrol,
2177 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002178{
2179 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2180
2181 ucontrol->value.integer.value[0] = codec->spdif_in_enable;
2182 return 0;
2183}
2184
Takashi Iwai0ba21762007-04-16 11:29:14 +02002185static int snd_hda_spdif_in_switch_put(struct snd_kcontrol *kcontrol,
2186 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002187{
2188 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2189 hda_nid_t nid = kcontrol->private_value;
2190 unsigned int val = !!ucontrol->value.integer.value[0];
2191 int change;
2192
Ingo Molnar62932df2006-01-16 16:34:20 +01002193 mutex_lock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002194 change = codec->spdif_in_enable != val;
Takashi Iwai82beb8f2007-08-10 17:09:26 +02002195 if (change) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002196 codec->spdif_in_enable = val;
Takashi Iwai82beb8f2007-08-10 17:09:26 +02002197 snd_hda_codec_write_cache(codec, nid, 0,
2198 AC_VERB_SET_DIGI_CONVERT_1, val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002199 }
Ingo Molnar62932df2006-01-16 16:34:20 +01002200 mutex_unlock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002201 return change;
2202}
2203
Takashi Iwai0ba21762007-04-16 11:29:14 +02002204static int snd_hda_spdif_in_status_get(struct snd_kcontrol *kcontrol,
2205 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002206{
2207 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2208 hda_nid_t nid = kcontrol->private_value;
2209 unsigned short val;
2210 unsigned int sbits;
2211
Andrew Paprocki3982d172007-12-19 12:13:44 +01002212 val = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_DIGI_CONVERT_1, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002213 sbits = convert_to_spdif_status(val);
2214 ucontrol->value.iec958.status[0] = sbits;
2215 ucontrol->value.iec958.status[1] = sbits >> 8;
2216 ucontrol->value.iec958.status[2] = sbits >> 16;
2217 ucontrol->value.iec958.status[3] = sbits >> 24;
2218 return 0;
2219}
2220
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01002221static struct snd_kcontrol_new dig_in_ctls[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002222 {
2223 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2224 .name = SNDRV_CTL_NAME_IEC958("",CAPTURE,SWITCH),
2225 .info = snd_hda_spdif_in_switch_info,
2226 .get = snd_hda_spdif_in_switch_get,
2227 .put = snd_hda_spdif_in_switch_put,
2228 },
2229 {
2230 .access = SNDRV_CTL_ELEM_ACCESS_READ,
2231 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2232 .name = SNDRV_CTL_NAME_IEC958("",CAPTURE,DEFAULT),
2233 .info = snd_hda_spdif_mask_info,
2234 .get = snd_hda_spdif_in_status_get,
2235 },
2236 { } /* end */
2237};
2238
2239/**
2240 * snd_hda_create_spdif_in_ctls - create Input SPDIF-related controls
2241 * @codec: the HDA codec
2242 * @nid: audio in widget NID
2243 *
2244 * Creates controls related with the SPDIF input.
2245 * Called from each patch supporting the SPDIF in.
2246 *
2247 * Returns 0 if successful, or a negative error code.
2248 */
Takashi Iwai12f288b2007-08-02 15:51:59 +02002249int snd_hda_create_spdif_in_ctls(struct hda_codec *codec, hda_nid_t nid)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002250{
2251 int err;
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01002252 struct snd_kcontrol *kctl;
2253 struct snd_kcontrol_new *dig_mix;
Takashi Iwai09f99702008-02-04 12:31:13 +01002254 int idx;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002255
Takashi Iwai09f99702008-02-04 12:31:13 +01002256 for (idx = 0; idx < SPDIF_MAX_IDX; idx++) {
2257 if (!_snd_hda_find_mixer_ctl(codec, "IEC958 Capture Switch",
2258 idx))
2259 break;
2260 }
2261 if (idx >= SPDIF_MAX_IDX) {
2262 printk(KERN_ERR "hda_codec: too many IEC958 inputs\n");
2263 return -EBUSY;
2264 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002265 for (dig_mix = dig_in_ctls; dig_mix->name; dig_mix++) {
2266 kctl = snd_ctl_new1(dig_mix, codec);
Takashi Iwaic8dcdf82009-02-06 16:21:20 +01002267 if (!kctl)
2268 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002269 kctl->private_value = nid;
Takashi Iwaid13bd412008-07-30 15:01:45 +02002270 err = snd_hda_ctl_add(codec, kctl);
Takashi Iwai0ba21762007-04-16 11:29:14 +02002271 if (err < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002272 return err;
2273 }
Takashi Iwai0ba21762007-04-16 11:29:14 +02002274 codec->spdif_in_enable =
Andrew Paprocki3982d172007-12-19 12:13:44 +01002275 snd_hda_codec_read(codec, nid, 0,
2276 AC_VERB_GET_DIGI_CONVERT_1, 0) &
Takashi Iwai0ba21762007-04-16 11:29:14 +02002277 AC_DIG1_ENABLE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002278 return 0;
2279}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002280EXPORT_SYMBOL_HDA(snd_hda_create_spdif_in_ctls);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002281
Takashi Iwaicb53c622007-08-10 17:21:45 +02002282#ifdef SND_HDA_NEEDS_RESUME
Takashi Iwai82beb8f2007-08-10 17:09:26 +02002283/*
2284 * command cache
2285 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002286
Takashi Iwaib3ac5632007-08-10 17:03:40 +02002287/* build a 32bit cache key with the widget id and the command parameter */
2288#define build_cmd_cache_key(nid, verb) ((verb << 8) | nid)
2289#define get_cmd_cache_nid(key) ((key) & 0xff)
2290#define get_cmd_cache_cmd(key) (((key) >> 8) & 0xffff)
2291
2292/**
2293 * snd_hda_codec_write_cache - send a single command with caching
2294 * @codec: the HDA codec
2295 * @nid: NID to send the command
2296 * @direct: direct flag
2297 * @verb: the verb to send
2298 * @parm: the parameter for the verb
2299 *
2300 * Send a single command without waiting for response.
2301 *
2302 * Returns 0 if successful, or a negative error code.
2303 */
2304int snd_hda_codec_write_cache(struct hda_codec *codec, hda_nid_t nid,
2305 int direct, unsigned int verb, unsigned int parm)
2306{
Takashi Iwaiaa2936f2009-05-26 16:07:57 +02002307 int err = snd_hda_codec_write(codec, nid, direct, verb, parm);
2308 struct hda_cache_head *c;
2309 u32 key;
Takashi Iwai33fa35e2008-11-06 16:50:40 +01002310
Takashi Iwaiaa2936f2009-05-26 16:07:57 +02002311 if (err < 0)
2312 return err;
2313 /* parm may contain the verb stuff for get/set amp */
2314 verb = verb | (parm >> 8);
2315 parm &= 0xff;
2316 key = build_cmd_cache_key(nid, verb);
2317 mutex_lock(&codec->bus->cmd_mutex);
2318 c = get_alloc_hash(&codec->cmd_cache, key);
2319 if (c)
2320 c->val = parm;
2321 mutex_unlock(&codec->bus->cmd_mutex);
2322 return 0;
Takashi Iwaib3ac5632007-08-10 17:03:40 +02002323}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002324EXPORT_SYMBOL_HDA(snd_hda_codec_write_cache);
Takashi Iwaib3ac5632007-08-10 17:03:40 +02002325
2326/* resume the all commands from the cache */
2327void snd_hda_codec_resume_cache(struct hda_codec *codec)
2328{
Takashi Iwai603c4012008-07-30 15:01:44 +02002329 struct hda_cache_head *buffer = codec->cmd_cache.buf.list;
Takashi Iwaib3ac5632007-08-10 17:03:40 +02002330 int i;
2331
Takashi Iwai603c4012008-07-30 15:01:44 +02002332 for (i = 0; i < codec->cmd_cache.buf.used; i++, buffer++) {
Takashi Iwaib3ac5632007-08-10 17:03:40 +02002333 u32 key = buffer->key;
2334 if (!key)
2335 continue;
2336 snd_hda_codec_write(codec, get_cmd_cache_nid(key), 0,
2337 get_cmd_cache_cmd(key), buffer->val);
2338 }
2339}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002340EXPORT_SYMBOL_HDA(snd_hda_codec_resume_cache);
Takashi Iwaib3ac5632007-08-10 17:03:40 +02002341
2342/**
2343 * snd_hda_sequence_write_cache - sequence writes with caching
2344 * @codec: the HDA codec
2345 * @seq: VERB array to send
2346 *
2347 * Send the commands sequentially from the given array.
2348 * Thte commands are recorded on cache for power-save and resume.
2349 * The array must be terminated with NID=0.
2350 */
2351void snd_hda_sequence_write_cache(struct hda_codec *codec,
2352 const struct hda_verb *seq)
2353{
2354 for (; seq->nid; seq++)
2355 snd_hda_codec_write_cache(codec, seq->nid, 0, seq->verb,
2356 seq->param);
2357}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002358EXPORT_SYMBOL_HDA(snd_hda_sequence_write_cache);
Takashi Iwaicb53c622007-08-10 17:21:45 +02002359#endif /* SND_HDA_NEEDS_RESUME */
Takashi Iwaib3ac5632007-08-10 17:03:40 +02002360
Takashi Iwai54d17402005-11-21 16:33:22 +01002361/*
2362 * set power state of the codec
2363 */
2364static void hda_set_power_state(struct hda_codec *codec, hda_nid_t fg,
2365 unsigned int power_state)
2366{
Takashi Iwaicb53c622007-08-10 17:21:45 +02002367 hda_nid_t nid;
2368 int i;
Takashi Iwai54d17402005-11-21 16:33:22 +01002369
Takashi Iwai05ff7e12009-07-22 12:39:24 +02002370 /* this delay seems necessary to avoid click noise at power-down */
2371 if (power_state == AC_PWRST_D3)
2372 msleep(100);
2373 snd_hda_codec_read(codec, fg, 0, AC_VERB_SET_POWER_STATE,
Takashi Iwai54d17402005-11-21 16:33:22 +01002374 power_state);
Takashi Iwai05ff7e12009-07-22 12:39:24 +02002375 /* partial workaround for "azx_get_response timeout" */
2376 if (power_state == AC_PWRST_D0)
2377 msleep(10);
Takashi Iwai54d17402005-11-21 16:33:22 +01002378
Takashi Iwaicb53c622007-08-10 17:21:45 +02002379 nid = codec->start_nid;
2380 for (i = 0; i < codec->num_nodes; i++, nid++) {
Takashi Iwai7eba5c92007-11-14 14:53:42 +01002381 unsigned int wcaps = get_wcaps(codec, nid);
2382 if (wcaps & AC_WCAP_POWER) {
2383 unsigned int wid_type = (wcaps & AC_WCAP_TYPE) >>
2384 AC_WCAP_TYPE_SHIFT;
Takashi Iwaia3b48c82009-04-21 13:37:29 +02002385 if (power_state == AC_PWRST_D3 &&
2386 wid_type == AC_WID_PIN) {
Takashi Iwai7eba5c92007-11-14 14:53:42 +01002387 unsigned int pincap;
2388 /*
2389 * don't power down the widget if it controls
2390 * eapd and EAPD_BTLENABLE is set.
2391 */
Takashi Iwai14bafe32009-03-23 16:35:39 +01002392 pincap = snd_hda_query_pin_caps(codec, nid);
Takashi Iwai7eba5c92007-11-14 14:53:42 +01002393 if (pincap & AC_PINCAP_EAPD) {
2394 int eapd = snd_hda_codec_read(codec,
2395 nid, 0,
2396 AC_VERB_GET_EAPD_BTLENABLE, 0);
2397 eapd &= 0x02;
Takashi Iwaia3b48c82009-04-21 13:37:29 +02002398 if (eapd)
Takashi Iwai7eba5c92007-11-14 14:53:42 +01002399 continue;
2400 }
Takashi Iwai1194b5b2007-10-10 10:04:26 +02002401 }
Takashi Iwai54d17402005-11-21 16:33:22 +01002402 snd_hda_codec_write(codec, nid, 0,
2403 AC_VERB_SET_POWER_STATE,
2404 power_state);
Takashi Iwai1194b5b2007-10-10 10:04:26 +02002405 }
Takashi Iwai54d17402005-11-21 16:33:22 +01002406 }
2407
Takashi Iwaicb53c622007-08-10 17:21:45 +02002408 if (power_state == AC_PWRST_D0) {
2409 unsigned long end_time;
2410 int state;
Takashi Iwai54d17402005-11-21 16:33:22 +01002411 msleep(10);
Takashi Iwaicb53c622007-08-10 17:21:45 +02002412 /* wait until the codec reachs to D0 */
2413 end_time = jiffies + msecs_to_jiffies(500);
2414 do {
2415 state = snd_hda_codec_read(codec, fg, 0,
2416 AC_VERB_GET_POWER_STATE, 0);
2417 if (state == power_state)
2418 break;
2419 msleep(1);
2420 } while (time_after_eq(end_time, jiffies));
2421 }
Takashi Iwai54d17402005-11-21 16:33:22 +01002422}
2423
Takashi Iwai11aeff02008-07-30 15:01:46 +02002424#ifdef CONFIG_SND_HDA_HWDEP
2425/* execute additional init verbs */
2426static void hda_exec_init_verbs(struct hda_codec *codec)
2427{
2428 if (codec->init_verbs.list)
2429 snd_hda_sequence_write(codec, codec->init_verbs.list);
2430}
2431#else
2432static inline void hda_exec_init_verbs(struct hda_codec *codec) {}
2433#endif
2434
Takashi Iwaicb53c622007-08-10 17:21:45 +02002435#ifdef SND_HDA_NEEDS_RESUME
2436/*
2437 * call suspend and power-down; used both from PM and power-save
2438 */
2439static void hda_call_codec_suspend(struct hda_codec *codec)
2440{
2441 if (codec->patch_ops.suspend)
2442 codec->patch_ops.suspend(codec, PMSG_SUSPEND);
2443 hda_set_power_state(codec,
2444 codec->afg ? codec->afg : codec->mfg,
2445 AC_PWRST_D3);
2446#ifdef CONFIG_SND_HDA_POWER_SAVE
2447 cancel_delayed_work(&codec->power_work);
Takashi Iwai95e99fd2007-08-13 15:29:04 +02002448 codec->power_on = 0;
Takashi Iwaia221e282007-08-16 16:35:33 +02002449 codec->power_transition = 0;
Takashi Iwaicb53c622007-08-10 17:21:45 +02002450#endif
2451}
2452
2453/*
2454 * kick up codec; used both from PM and power-save
2455 */
2456static void hda_call_codec_resume(struct hda_codec *codec)
2457{
2458 hda_set_power_state(codec,
2459 codec->afg ? codec->afg : codec->mfg,
2460 AC_PWRST_D0);
Takashi Iwai3be14142009-02-20 14:11:16 +01002461 restore_pincfgs(codec); /* restore all current pin configs */
Takashi Iwai11aeff02008-07-30 15:01:46 +02002462 hda_exec_init_verbs(codec);
Takashi Iwaicb53c622007-08-10 17:21:45 +02002463 if (codec->patch_ops.resume)
2464 codec->patch_ops.resume(codec);
2465 else {
Takashi Iwai9d99f312007-08-14 15:15:52 +02002466 if (codec->patch_ops.init)
2467 codec->patch_ops.init(codec);
Takashi Iwaicb53c622007-08-10 17:21:45 +02002468 snd_hda_codec_resume_amp(codec);
2469 snd_hda_codec_resume_cache(codec);
2470 }
2471}
2472#endif /* SND_HDA_NEEDS_RESUME */
2473
Takashi Iwai54d17402005-11-21 16:33:22 +01002474
Linus Torvalds1da177e2005-04-16 15:20:36 -07002475/**
2476 * snd_hda_build_controls - build mixer controls
2477 * @bus: the BUS
2478 *
2479 * Creates mixer controls for each codec included in the bus.
2480 *
2481 * Returns 0 if successful, otherwise a negative error code.
2482 */
Takashi Iwai1289e9e2008-11-27 15:47:11 +01002483int /*__devinit*/ snd_hda_build_controls(struct hda_bus *bus)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002484{
Takashi Iwai0ba21762007-04-16 11:29:14 +02002485 struct hda_codec *codec;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002486
Takashi Iwai0ba21762007-04-16 11:29:14 +02002487 list_for_each_entry(codec, &bus->codec_list, list) {
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02002488 int err = snd_hda_codec_build_controls(codec);
Takashi Iwaif93d4612009-03-02 10:44:15 +01002489 if (err < 0) {
2490 printk(KERN_ERR "hda_codec: cannot build controls"
2491 "for #%d (error %d)\n", codec->addr, err);
2492 err = snd_hda_codec_reset(codec);
2493 if (err < 0) {
2494 printk(KERN_ERR
2495 "hda_codec: cannot revert codec\n");
2496 return err;
2497 }
2498 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002499 }
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02002500 return 0;
2501}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002502EXPORT_SYMBOL_HDA(snd_hda_build_controls);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002503
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02002504int snd_hda_codec_build_controls(struct hda_codec *codec)
2505{
2506 int err = 0;
Takashi Iwai11aeff02008-07-30 15:01:46 +02002507 hda_exec_init_verbs(codec);
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02002508 /* continue to initialize... */
2509 if (codec->patch_ops.init)
2510 err = codec->patch_ops.init(codec);
2511 if (!err && codec->patch_ops.build_controls)
2512 err = codec->patch_ops.build_controls(codec);
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02002513 if (err < 0)
2514 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002515 return 0;
2516}
2517
Linus Torvalds1da177e2005-04-16 15:20:36 -07002518/*
2519 * stream formats
2520 */
Takashi Iwaibefdf312005-08-22 13:57:55 +02002521struct hda_rate_tbl {
2522 unsigned int hz;
2523 unsigned int alsa_bits;
2524 unsigned int hda_fmt;
2525};
2526
2527static struct hda_rate_tbl rate_bits[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002528 /* rate in Hz, ALSA rate bitmask, HDA format value */
Nicolas Graziano9d8f53f2005-08-22 13:47:16 +02002529
2530 /* autodetected value used in snd_hda_query_supported_pcm */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002531 { 8000, SNDRV_PCM_RATE_8000, 0x0500 }, /* 1/6 x 48 */
2532 { 11025, SNDRV_PCM_RATE_11025, 0x4300 }, /* 1/4 x 44 */
2533 { 16000, SNDRV_PCM_RATE_16000, 0x0200 }, /* 1/3 x 48 */
2534 { 22050, SNDRV_PCM_RATE_22050, 0x4100 }, /* 1/2 x 44 */
2535 { 32000, SNDRV_PCM_RATE_32000, 0x0a00 }, /* 2/3 x 48 */
2536 { 44100, SNDRV_PCM_RATE_44100, 0x4000 }, /* 44 */
2537 { 48000, SNDRV_PCM_RATE_48000, 0x0000 }, /* 48 */
2538 { 88200, SNDRV_PCM_RATE_88200, 0x4800 }, /* 2 x 44 */
2539 { 96000, SNDRV_PCM_RATE_96000, 0x0800 }, /* 2 x 48 */
2540 { 176400, SNDRV_PCM_RATE_176400, 0x5800 },/* 4 x 44 */
2541 { 192000, SNDRV_PCM_RATE_192000, 0x1800 }, /* 4 x 48 */
Takashi Iwaia961f9f2007-04-12 13:08:09 +02002542#define AC_PAR_PCM_RATE_BITS 11
2543 /* up to bits 10, 384kHZ isn't supported properly */
2544
2545 /* not autodetected value */
2546 { 9600, SNDRV_PCM_RATE_KNOT, 0x0400 }, /* 1/5 x 48 */
Nicolas Graziano9d8f53f2005-08-22 13:47:16 +02002547
Takashi Iwaibefdf312005-08-22 13:57:55 +02002548 { 0 } /* terminator */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002549};
2550
2551/**
2552 * snd_hda_calc_stream_format - calculate format bitset
2553 * @rate: the sample rate
2554 * @channels: the number of channels
2555 * @format: the PCM format (SNDRV_PCM_FORMAT_XXX)
2556 * @maxbps: the max. bps
2557 *
2558 * Calculate the format bitset from the given rate, channels and th PCM format.
2559 *
2560 * Return zero if invalid.
2561 */
2562unsigned int snd_hda_calc_stream_format(unsigned int rate,
2563 unsigned int channels,
2564 unsigned int format,
2565 unsigned int maxbps)
2566{
2567 int i;
2568 unsigned int val = 0;
2569
Takashi Iwaibefdf312005-08-22 13:57:55 +02002570 for (i = 0; rate_bits[i].hz; i++)
2571 if (rate_bits[i].hz == rate) {
2572 val = rate_bits[i].hda_fmt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002573 break;
2574 }
Takashi Iwai0ba21762007-04-16 11:29:14 +02002575 if (!rate_bits[i].hz) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002576 snd_printdd("invalid rate %d\n", rate);
2577 return 0;
2578 }
2579
2580 if (channels == 0 || channels > 8) {
2581 snd_printdd("invalid channels %d\n", channels);
2582 return 0;
2583 }
2584 val |= channels - 1;
2585
2586 switch (snd_pcm_format_width(format)) {
2587 case 8: val |= 0x00; break;
2588 case 16: val |= 0x10; break;
2589 case 20:
2590 case 24:
2591 case 32:
Takashi Iwaib0bb3aa2009-07-03 23:25:37 +02002592 if (maxbps >= 32 || format == SNDRV_PCM_FORMAT_FLOAT_LE)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002593 val |= 0x40;
2594 else if (maxbps >= 24)
2595 val |= 0x30;
2596 else
2597 val |= 0x20;
2598 break;
2599 default:
Takashi Iwai0ba21762007-04-16 11:29:14 +02002600 snd_printdd("invalid format width %d\n",
2601 snd_pcm_format_width(format));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002602 return 0;
2603 }
2604
2605 return val;
2606}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002607EXPORT_SYMBOL_HDA(snd_hda_calc_stream_format);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002608
Takashi Iwai92c7c8a2009-03-24 07:32:14 +01002609static unsigned int get_pcm_param(struct hda_codec *codec, hda_nid_t nid)
2610{
2611 unsigned int val = 0;
2612 if (nid != codec->afg &&
2613 (get_wcaps(codec, nid) & AC_WCAP_FORMAT_OVRD))
2614 val = snd_hda_param_read(codec, nid, AC_PAR_PCM);
2615 if (!val || val == -1)
2616 val = snd_hda_param_read(codec, codec->afg, AC_PAR_PCM);
2617 if (!val || val == -1)
2618 return 0;
2619 return val;
2620}
2621
2622static unsigned int query_pcm_param(struct hda_codec *codec, hda_nid_t nid)
2623{
2624 return query_caps_hash(codec, nid, HDA_HASH_PARPCM_KEY(nid),
2625 get_pcm_param);
2626}
2627
2628static unsigned int get_stream_param(struct hda_codec *codec, hda_nid_t nid)
2629{
2630 unsigned int streams = snd_hda_param_read(codec, nid, AC_PAR_STREAM);
2631 if (!streams || streams == -1)
2632 streams = snd_hda_param_read(codec, codec->afg, AC_PAR_STREAM);
2633 if (!streams || streams == -1)
2634 return 0;
2635 return streams;
2636}
2637
2638static unsigned int query_stream_param(struct hda_codec *codec, hda_nid_t nid)
2639{
2640 return query_caps_hash(codec, nid, HDA_HASH_PARSTR_KEY(nid),
2641 get_stream_param);
2642}
2643
Linus Torvalds1da177e2005-04-16 15:20:36 -07002644/**
2645 * snd_hda_query_supported_pcm - query the supported PCM rates and formats
2646 * @codec: the HDA codec
2647 * @nid: NID to query
2648 * @ratesp: the pointer to store the detected rate bitflags
2649 * @formatsp: the pointer to store the detected formats
2650 * @bpsp: the pointer to store the detected format widths
2651 *
2652 * Queries the supported PCM rates and formats. The NULL @ratesp, @formatsp
2653 * or @bsps argument is ignored.
2654 *
2655 * Returns 0 if successful, otherwise a negative error code.
2656 */
Takashi Iwai986862bd2008-11-27 12:40:13 +01002657static int snd_hda_query_supported_pcm(struct hda_codec *codec, hda_nid_t nid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002658 u32 *ratesp, u64 *formatsp, unsigned int *bpsp)
2659{
Jaroslav Kyselaee504712009-03-17 14:30:31 +01002660 unsigned int i, val, wcaps;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002661
Jaroslav Kyselaee504712009-03-17 14:30:31 +01002662 wcaps = get_wcaps(codec, nid);
Takashi Iwai92c7c8a2009-03-24 07:32:14 +01002663 val = query_pcm_param(codec, nid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002664
2665 if (ratesp) {
2666 u32 rates = 0;
Takashi Iwaia961f9f2007-04-12 13:08:09 +02002667 for (i = 0; i < AC_PAR_PCM_RATE_BITS; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002668 if (val & (1 << i))
Takashi Iwaibefdf312005-08-22 13:57:55 +02002669 rates |= rate_bits[i].alsa_bits;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002670 }
Jaroslav Kyselaee504712009-03-17 14:30:31 +01002671 if (rates == 0) {
2672 snd_printk(KERN_ERR "hda_codec: rates == 0 "
2673 "(nid=0x%x, val=0x%x, ovrd=%i)\n",
2674 nid, val,
2675 (wcaps & AC_WCAP_FORMAT_OVRD) ? 1 : 0);
2676 return -EIO;
2677 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002678 *ratesp = rates;
2679 }
2680
2681 if (formatsp || bpsp) {
2682 u64 formats = 0;
Jaroslav Kyselaee504712009-03-17 14:30:31 +01002683 unsigned int streams, bps;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002684
Takashi Iwai92c7c8a2009-03-24 07:32:14 +01002685 streams = query_stream_param(codec, nid);
2686 if (!streams)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002687 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002688
2689 bps = 0;
2690 if (streams & AC_SUPFMT_PCM) {
2691 if (val & AC_SUPPCM_BITS_8) {
2692 formats |= SNDRV_PCM_FMTBIT_U8;
2693 bps = 8;
2694 }
2695 if (val & AC_SUPPCM_BITS_16) {
2696 formats |= SNDRV_PCM_FMTBIT_S16_LE;
2697 bps = 16;
2698 }
2699 if (wcaps & AC_WCAP_DIGITAL) {
2700 if (val & AC_SUPPCM_BITS_32)
2701 formats |= SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_LE;
2702 if (val & (AC_SUPPCM_BITS_20|AC_SUPPCM_BITS_24))
2703 formats |= SNDRV_PCM_FMTBIT_S32_LE;
2704 if (val & AC_SUPPCM_BITS_24)
2705 bps = 24;
2706 else if (val & AC_SUPPCM_BITS_20)
2707 bps = 20;
Takashi Iwai0ba21762007-04-16 11:29:14 +02002708 } else if (val & (AC_SUPPCM_BITS_20|AC_SUPPCM_BITS_24|
2709 AC_SUPPCM_BITS_32)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002710 formats |= SNDRV_PCM_FMTBIT_S32_LE;
2711 if (val & AC_SUPPCM_BITS_32)
2712 bps = 32;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002713 else if (val & AC_SUPPCM_BITS_24)
2714 bps = 24;
Nicolas Graziano33ef76512006-09-19 14:23:14 +02002715 else if (val & AC_SUPPCM_BITS_20)
2716 bps = 20;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002717 }
2718 }
Takashi Iwaib5025c52009-07-01 18:05:27 +02002719 if (streams & AC_SUPFMT_FLOAT32) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002720 formats |= SNDRV_PCM_FMTBIT_FLOAT_LE;
Takashi Iwaib0bb3aa2009-07-03 23:25:37 +02002721 if (!bps)
2722 bps = 32;
Takashi Iwaib5025c52009-07-01 18:05:27 +02002723 }
2724 if (streams == AC_SUPFMT_AC3) {
Takashi Iwai0ba21762007-04-16 11:29:14 +02002725 /* should be exclusive */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002726 /* temporary hack: we have still no proper support
2727 * for the direct AC3 stream...
2728 */
2729 formats |= SNDRV_PCM_FMTBIT_U8;
2730 bps = 8;
2731 }
Jaroslav Kyselaee504712009-03-17 14:30:31 +01002732 if (formats == 0) {
2733 snd_printk(KERN_ERR "hda_codec: formats == 0 "
2734 "(nid=0x%x, val=0x%x, ovrd=%i, "
2735 "streams=0x%x)\n",
2736 nid, val,
2737 (wcaps & AC_WCAP_FORMAT_OVRD) ? 1 : 0,
2738 streams);
2739 return -EIO;
2740 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002741 if (formatsp)
2742 *formatsp = formats;
2743 if (bpsp)
2744 *bpsp = bps;
2745 }
2746
2747 return 0;
2748}
2749
2750/**
Takashi Iwai0ba21762007-04-16 11:29:14 +02002751 * snd_hda_is_supported_format - check whether the given node supports
2752 * the format val
Linus Torvalds1da177e2005-04-16 15:20:36 -07002753 *
2754 * Returns 1 if supported, 0 if not.
2755 */
2756int snd_hda_is_supported_format(struct hda_codec *codec, hda_nid_t nid,
2757 unsigned int format)
2758{
2759 int i;
2760 unsigned int val = 0, rate, stream;
2761
Takashi Iwai92c7c8a2009-03-24 07:32:14 +01002762 val = query_pcm_param(codec, nid);
2763 if (!val)
2764 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002765
2766 rate = format & 0xff00;
Takashi Iwaia961f9f2007-04-12 13:08:09 +02002767 for (i = 0; i < AC_PAR_PCM_RATE_BITS; i++)
Takashi Iwaibefdf312005-08-22 13:57:55 +02002768 if (rate_bits[i].hda_fmt == rate) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002769 if (val & (1 << i))
2770 break;
2771 return 0;
2772 }
Takashi Iwaia961f9f2007-04-12 13:08:09 +02002773 if (i >= AC_PAR_PCM_RATE_BITS)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002774 return 0;
2775
Takashi Iwai92c7c8a2009-03-24 07:32:14 +01002776 stream = query_stream_param(codec, nid);
2777 if (!stream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002778 return 0;
2779
2780 if (stream & AC_SUPFMT_PCM) {
2781 switch (format & 0xf0) {
2782 case 0x00:
Takashi Iwai0ba21762007-04-16 11:29:14 +02002783 if (!(val & AC_SUPPCM_BITS_8))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002784 return 0;
2785 break;
2786 case 0x10:
Takashi Iwai0ba21762007-04-16 11:29:14 +02002787 if (!(val & AC_SUPPCM_BITS_16))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002788 return 0;
2789 break;
2790 case 0x20:
Takashi Iwai0ba21762007-04-16 11:29:14 +02002791 if (!(val & AC_SUPPCM_BITS_20))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002792 return 0;
2793 break;
2794 case 0x30:
Takashi Iwai0ba21762007-04-16 11:29:14 +02002795 if (!(val & AC_SUPPCM_BITS_24))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002796 return 0;
2797 break;
2798 case 0x40:
Takashi Iwai0ba21762007-04-16 11:29:14 +02002799 if (!(val & AC_SUPPCM_BITS_32))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002800 return 0;
2801 break;
2802 default:
2803 return 0;
2804 }
2805 } else {
2806 /* FIXME: check for float32 and AC3? */
2807 }
2808
2809 return 1;
2810}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002811EXPORT_SYMBOL_HDA(snd_hda_is_supported_format);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002812
2813/*
2814 * PCM stuff
2815 */
2816static int hda_pcm_default_open_close(struct hda_pcm_stream *hinfo,
2817 struct hda_codec *codec,
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01002818 struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002819{
2820 return 0;
2821}
2822
2823static int hda_pcm_default_prepare(struct hda_pcm_stream *hinfo,
2824 struct hda_codec *codec,
2825 unsigned int stream_tag,
2826 unsigned int format,
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01002827 struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002828{
2829 snd_hda_codec_setup_stream(codec, hinfo->nid, stream_tag, 0, format);
2830 return 0;
2831}
2832
2833static int hda_pcm_default_cleanup(struct hda_pcm_stream *hinfo,
2834 struct hda_codec *codec,
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01002835 struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002836{
Takashi Iwai888afa12008-03-18 09:57:50 +01002837 snd_hda_codec_cleanup_stream(codec, hinfo->nid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002838 return 0;
2839}
2840
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02002841static int set_pcm_default_values(struct hda_codec *codec,
2842 struct hda_pcm_stream *info)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002843{
Jaroslav Kyselaee504712009-03-17 14:30:31 +01002844 int err;
2845
Takashi Iwai0ba21762007-04-16 11:29:14 +02002846 /* query support PCM information from the given NID */
2847 if (info->nid && (!info->rates || !info->formats)) {
Jaroslav Kyselaee504712009-03-17 14:30:31 +01002848 err = snd_hda_query_supported_pcm(codec, info->nid,
Takashi Iwai0ba21762007-04-16 11:29:14 +02002849 info->rates ? NULL : &info->rates,
2850 info->formats ? NULL : &info->formats,
2851 info->maxbps ? NULL : &info->maxbps);
Jaroslav Kyselaee504712009-03-17 14:30:31 +01002852 if (err < 0)
2853 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002854 }
2855 if (info->ops.open == NULL)
2856 info->ops.open = hda_pcm_default_open_close;
2857 if (info->ops.close == NULL)
2858 info->ops.close = hda_pcm_default_open_close;
2859 if (info->ops.prepare == NULL) {
Takashi Iwaida3cec32008-08-08 17:12:14 +02002860 if (snd_BUG_ON(!info->nid))
2861 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002862 info->ops.prepare = hda_pcm_default_prepare;
2863 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002864 if (info->ops.cleanup == NULL) {
Takashi Iwaida3cec32008-08-08 17:12:14 +02002865 if (snd_BUG_ON(!info->nid))
2866 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002867 info->ops.cleanup = hda_pcm_default_cleanup;
2868 }
2869 return 0;
2870}
2871
Takashi Iwai176d5332008-07-30 15:01:44 +02002872/*
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002873 * get the empty PCM device number to assign
2874 */
2875static int get_empty_pcm_device(struct hda_bus *bus, int type)
2876{
2877 static const char *dev_name[HDA_PCM_NTYPES] = {
2878 "Audio", "SPDIF", "HDMI", "Modem"
2879 };
2880 /* starting device index for each PCM type */
2881 static int dev_idx[HDA_PCM_NTYPES] = {
2882 [HDA_PCM_TYPE_AUDIO] = 0,
2883 [HDA_PCM_TYPE_SPDIF] = 1,
2884 [HDA_PCM_TYPE_HDMI] = 3,
2885 [HDA_PCM_TYPE_MODEM] = 6
2886 };
2887 /* normal audio device indices; not linear to keep compatibility */
2888 static int audio_idx[4] = { 0, 2, 4, 5 };
2889 int i, dev;
2890
2891 switch (type) {
2892 case HDA_PCM_TYPE_AUDIO:
2893 for (i = 0; i < ARRAY_SIZE(audio_idx); i++) {
2894 dev = audio_idx[i];
2895 if (!test_bit(dev, bus->pcm_dev_bits))
Takashi Iwai82ad39f2009-03-03 15:00:35 +01002896 goto ok;
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002897 }
Takashi Iwai82ad39f2009-03-03 15:00:35 +01002898 snd_printk(KERN_WARNING "Too many audio devices\n");
2899 return -EAGAIN;
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002900 case HDA_PCM_TYPE_SPDIF:
2901 case HDA_PCM_TYPE_HDMI:
2902 case HDA_PCM_TYPE_MODEM:
2903 dev = dev_idx[type];
2904 if (test_bit(dev, bus->pcm_dev_bits)) {
2905 snd_printk(KERN_WARNING "%s already defined\n",
2906 dev_name[type]);
2907 return -EAGAIN;
2908 }
2909 break;
2910 default:
2911 snd_printk(KERN_WARNING "Invalid PCM type %d\n", type);
2912 return -EINVAL;
2913 }
Takashi Iwai82ad39f2009-03-03 15:00:35 +01002914 ok:
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002915 set_bit(dev, bus->pcm_dev_bits);
2916 return dev;
2917}
2918
2919/*
Takashi Iwai176d5332008-07-30 15:01:44 +02002920 * attach a new PCM stream
2921 */
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002922static int snd_hda_attach_pcm(struct hda_codec *codec, struct hda_pcm *pcm)
Takashi Iwai176d5332008-07-30 15:01:44 +02002923{
Takashi Iwai33fa35e2008-11-06 16:50:40 +01002924 struct hda_bus *bus = codec->bus;
Takashi Iwai176d5332008-07-30 15:01:44 +02002925 struct hda_pcm_stream *info;
2926 int stream, err;
2927
Takashi Iwaib91f0802008-11-04 08:43:08 +01002928 if (snd_BUG_ON(!pcm->name))
Takashi Iwai176d5332008-07-30 15:01:44 +02002929 return -EINVAL;
2930 for (stream = 0; stream < 2; stream++) {
2931 info = &pcm->stream[stream];
2932 if (info->substreams) {
2933 err = set_pcm_default_values(codec, info);
2934 if (err < 0)
2935 return err;
2936 }
2937 }
Takashi Iwai33fa35e2008-11-06 16:50:40 +01002938 return bus->ops.attach_pcm(bus, codec, pcm);
Takashi Iwai176d5332008-07-30 15:01:44 +02002939}
2940
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002941/* assign all PCMs of the given codec */
2942int snd_hda_codec_build_pcms(struct hda_codec *codec)
2943{
2944 unsigned int pcm;
2945 int err;
2946
2947 if (!codec->num_pcms) {
2948 if (!codec->patch_ops.build_pcms)
2949 return 0;
2950 err = codec->patch_ops.build_pcms(codec);
Takashi Iwai6e655bf2009-03-02 10:46:03 +01002951 if (err < 0) {
2952 printk(KERN_ERR "hda_codec: cannot build PCMs"
2953 "for #%d (error %d)\n", codec->addr, err);
2954 err = snd_hda_codec_reset(codec);
2955 if (err < 0) {
2956 printk(KERN_ERR
2957 "hda_codec: cannot revert codec\n");
2958 return err;
2959 }
2960 }
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002961 }
2962 for (pcm = 0; pcm < codec->num_pcms; pcm++) {
2963 struct hda_pcm *cpcm = &codec->pcm_info[pcm];
2964 int dev;
2965
2966 if (!cpcm->stream[0].substreams && !cpcm->stream[1].substreams)
Takashi Iwai41b5b012009-01-20 18:21:23 +01002967 continue; /* no substreams assigned */
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002968
2969 if (!cpcm->pcm) {
2970 dev = get_empty_pcm_device(codec->bus, cpcm->pcm_type);
2971 if (dev < 0)
Takashi Iwai6e655bf2009-03-02 10:46:03 +01002972 continue; /* no fatal error */
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002973 cpcm->device = dev;
2974 err = snd_hda_attach_pcm(codec, cpcm);
Takashi Iwai6e655bf2009-03-02 10:46:03 +01002975 if (err < 0) {
2976 printk(KERN_ERR "hda_codec: cannot attach "
2977 "PCM stream %d for codec #%d\n",
2978 dev, codec->addr);
2979 continue; /* no fatal error */
2980 }
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002981 }
2982 }
2983 return 0;
2984}
2985
Linus Torvalds1da177e2005-04-16 15:20:36 -07002986/**
2987 * snd_hda_build_pcms - build PCM information
2988 * @bus: the BUS
2989 *
2990 * Create PCM information for each codec included in the bus.
2991 *
2992 * The build_pcms codec patch is requested to set up codec->num_pcms and
2993 * codec->pcm_info properly. The array is referred by the top-level driver
2994 * to create its PCM instances.
2995 * The allocated codec->pcm_info should be released in codec->patch_ops.free
2996 * callback.
2997 *
2998 * At least, substreams, channels_min and channels_max must be filled for
2999 * each stream. substreams = 0 indicates that the stream doesn't exist.
3000 * When rates and/or formats are zero, the supported values are queried
3001 * from the given nid. The nid is used also by the default ops.prepare
3002 * and ops.cleanup callbacks.
3003 *
3004 * The driver needs to call ops.open in its open callback. Similarly,
3005 * ops.close is supposed to be called in the close callback.
3006 * ops.prepare should be called in the prepare or hw_params callback
3007 * with the proper parameters for set up.
3008 * ops.cleanup should be called in hw_free for clean up of streams.
3009 *
3010 * This function returns 0 if successfull, or a negative error code.
3011 */
Takashi Iwai529bd6c2008-11-27 14:17:01 +01003012int __devinit snd_hda_build_pcms(struct hda_bus *bus)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003013{
Takashi Iwai0ba21762007-04-16 11:29:14 +02003014 struct hda_codec *codec;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003015
Takashi Iwai0ba21762007-04-16 11:29:14 +02003016 list_for_each_entry(codec, &bus->codec_list, list) {
Takashi Iwai529bd6c2008-11-27 14:17:01 +01003017 int err = snd_hda_codec_build_pcms(codec);
3018 if (err < 0)
3019 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003020 }
3021 return 0;
3022}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003023EXPORT_SYMBOL_HDA(snd_hda_build_pcms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003024
Linus Torvalds1da177e2005-04-16 15:20:36 -07003025/**
3026 * snd_hda_check_board_config - compare the current codec with the config table
3027 * @codec: the HDA codec
Takashi Iwaif5fcc132006-11-24 17:07:44 +01003028 * @num_configs: number of config enums
3029 * @models: array of model name strings
Linus Torvalds1da177e2005-04-16 15:20:36 -07003030 * @tbl: configuration table, terminated by null entries
3031 *
3032 * Compares the modelname or PCI subsystem id of the current codec with the
3033 * given configuration table. If a matching entry is found, returns its
3034 * config value (supposed to be 0 or positive).
3035 *
3036 * If no entries are matching, the function returns a negative value.
3037 */
Takashi Iwai12f288b2007-08-02 15:51:59 +02003038int snd_hda_check_board_config(struct hda_codec *codec,
3039 int num_configs, const char **models,
3040 const struct snd_pci_quirk *tbl)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003041{
Takashi Iwaif44ac832008-07-30 15:01:45 +02003042 if (codec->modelname && models) {
Takashi Iwaif5fcc132006-11-24 17:07:44 +01003043 int i;
3044 for (i = 0; i < num_configs; i++) {
3045 if (models[i] &&
Takashi Iwaif44ac832008-07-30 15:01:45 +02003046 !strcmp(codec->modelname, models[i])) {
Takashi Iwaif5fcc132006-11-24 17:07:44 +01003047 snd_printd(KERN_INFO "hda_codec: model '%s' is "
3048 "selected\n", models[i]);
3049 return i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003050 }
3051 }
3052 }
3053
Takashi Iwaif5fcc132006-11-24 17:07:44 +01003054 if (!codec->bus->pci || !tbl)
3055 return -1;
3056
3057 tbl = snd_pci_quirk_lookup(codec->bus->pci, tbl);
3058 if (!tbl)
3059 return -1;
3060 if (tbl->value >= 0 && tbl->value < num_configs) {
Takashi Iwai62cf8722008-05-20 12:15:15 +02003061#ifdef CONFIG_SND_DEBUG_VERBOSE
Takashi Iwaif5fcc132006-11-24 17:07:44 +01003062 char tmp[10];
3063 const char *model = NULL;
3064 if (models)
3065 model = models[tbl->value];
3066 if (!model) {
3067 sprintf(tmp, "#%d", tbl->value);
3068 model = tmp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003069 }
Takashi Iwaif5fcc132006-11-24 17:07:44 +01003070 snd_printdd(KERN_INFO "hda_codec: model '%s' is selected "
3071 "for config %x:%x (%s)\n",
3072 model, tbl->subvendor, tbl->subdevice,
3073 (tbl->name ? tbl->name : "Unknown device"));
3074#endif
3075 return tbl->value;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003076 }
3077 return -1;
3078}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003079EXPORT_SYMBOL_HDA(snd_hda_check_board_config);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003080
3081/**
Mauro Carvalho Chehab2eda3442008-08-11 10:18:39 +02003082 * snd_hda_check_board_codec_sid_config - compare the current codec
3083 subsystem ID with the
3084 config table
3085
3086 This is important for Gateway notebooks with SB450 HDA Audio
3087 where the vendor ID of the PCI device is:
3088 ATI Technologies Inc SB450 HDA Audio [1002:437b]
3089 and the vendor/subvendor are found only at the codec.
3090
3091 * @codec: the HDA codec
3092 * @num_configs: number of config enums
3093 * @models: array of model name strings
3094 * @tbl: configuration table, terminated by null entries
3095 *
3096 * Compares the modelname or PCI subsystem id of the current codec with the
3097 * given configuration table. If a matching entry is found, returns its
3098 * config value (supposed to be 0 or positive).
3099 *
3100 * If no entries are matching, the function returns a negative value.
3101 */
3102int snd_hda_check_board_codec_sid_config(struct hda_codec *codec,
3103 int num_configs, const char **models,
3104 const struct snd_pci_quirk *tbl)
3105{
3106 const struct snd_pci_quirk *q;
3107
3108 /* Search for codec ID */
3109 for (q = tbl; q->subvendor; q++) {
3110 unsigned long vendorid = (q->subdevice) | (q->subvendor << 16);
3111
3112 if (vendorid == codec->subsystem_id)
3113 break;
3114 }
3115
3116 if (!q->subvendor)
3117 return -1;
3118
3119 tbl = q;
3120
3121 if (tbl->value >= 0 && tbl->value < num_configs) {
3122#ifdef CONFIG_SND_DEBUG_DETECT
3123 char tmp[10];
3124 const char *model = NULL;
3125 if (models)
3126 model = models[tbl->value];
3127 if (!model) {
3128 sprintf(tmp, "#%d", tbl->value);
3129 model = tmp;
3130 }
3131 snd_printdd(KERN_INFO "hda_codec: model '%s' is selected "
3132 "for config %x:%x (%s)\n",
3133 model, tbl->subvendor, tbl->subdevice,
3134 (tbl->name ? tbl->name : "Unknown device"));
3135#endif
3136 return tbl->value;
3137 }
3138 return -1;
3139}
3140EXPORT_SYMBOL_HDA(snd_hda_check_board_codec_sid_config);
3141
3142/**
Linus Torvalds1da177e2005-04-16 15:20:36 -07003143 * snd_hda_add_new_ctls - create controls from the array
3144 * @codec: the HDA codec
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01003145 * @knew: the array of struct snd_kcontrol_new
Linus Torvalds1da177e2005-04-16 15:20:36 -07003146 *
3147 * This helper function creates and add new controls in the given array.
3148 * The array must be terminated with an empty entry as terminator.
3149 *
3150 * Returns 0 if successful, or a negative error code.
3151 */
Takashi Iwai12f288b2007-08-02 15:51:59 +02003152int snd_hda_add_new_ctls(struct hda_codec *codec, struct snd_kcontrol_new *knew)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003153{
Takashi Iwaicb53c622007-08-10 17:21:45 +02003154 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003155
3156 for (; knew->name; knew++) {
Takashi Iwai54d17402005-11-21 16:33:22 +01003157 struct snd_kcontrol *kctl;
3158 kctl = snd_ctl_new1(knew, codec);
Takashi Iwai0ba21762007-04-16 11:29:14 +02003159 if (!kctl)
Takashi Iwai54d17402005-11-21 16:33:22 +01003160 return -ENOMEM;
Takashi Iwaid13bd412008-07-30 15:01:45 +02003161 err = snd_hda_ctl_add(codec, kctl);
Takashi Iwai54d17402005-11-21 16:33:22 +01003162 if (err < 0) {
Takashi Iwai0ba21762007-04-16 11:29:14 +02003163 if (!codec->addr)
Takashi Iwai54d17402005-11-21 16:33:22 +01003164 return err;
3165 kctl = snd_ctl_new1(knew, codec);
Takashi Iwai0ba21762007-04-16 11:29:14 +02003166 if (!kctl)
Takashi Iwai54d17402005-11-21 16:33:22 +01003167 return -ENOMEM;
3168 kctl->id.device = codec->addr;
Takashi Iwaid13bd412008-07-30 15:01:45 +02003169 err = snd_hda_ctl_add(codec, kctl);
Takashi Iwai0ba21762007-04-16 11:29:14 +02003170 if (err < 0)
Takashi Iwai54d17402005-11-21 16:33:22 +01003171 return err;
3172 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003173 }
3174 return 0;
3175}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003176EXPORT_SYMBOL_HDA(snd_hda_add_new_ctls);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003177
Takashi Iwaicb53c622007-08-10 17:21:45 +02003178#ifdef CONFIG_SND_HDA_POWER_SAVE
3179static void hda_set_power_state(struct hda_codec *codec, hda_nid_t fg,
3180 unsigned int power_state);
3181
3182static void hda_power_work(struct work_struct *work)
3183{
3184 struct hda_codec *codec =
3185 container_of(work, struct hda_codec, power_work.work);
Takashi Iwai33fa35e2008-11-06 16:50:40 +01003186 struct hda_bus *bus = codec->bus;
Takashi Iwaicb53c622007-08-10 17:21:45 +02003187
Maxim Levitsky2e492462007-09-03 15:26:57 +02003188 if (!codec->power_on || codec->power_count) {
3189 codec->power_transition = 0;
Takashi Iwaicb53c622007-08-10 17:21:45 +02003190 return;
Maxim Levitsky2e492462007-09-03 15:26:57 +02003191 }
Takashi Iwaicb53c622007-08-10 17:21:45 +02003192
3193 hda_call_codec_suspend(codec);
Takashi Iwai33fa35e2008-11-06 16:50:40 +01003194 if (bus->ops.pm_notify)
3195 bus->ops.pm_notify(bus);
Takashi Iwaicb53c622007-08-10 17:21:45 +02003196}
3197
3198static void hda_keep_power_on(struct hda_codec *codec)
3199{
3200 codec->power_count++;
3201 codec->power_on = 1;
3202}
3203
3204void snd_hda_power_up(struct hda_codec *codec)
3205{
Takashi Iwai33fa35e2008-11-06 16:50:40 +01003206 struct hda_bus *bus = codec->bus;
3207
Takashi Iwaicb53c622007-08-10 17:21:45 +02003208 codec->power_count++;
Takashi Iwaia221e282007-08-16 16:35:33 +02003209 if (codec->power_on || codec->power_transition)
Takashi Iwaicb53c622007-08-10 17:21:45 +02003210 return;
3211
3212 codec->power_on = 1;
Takashi Iwai33fa35e2008-11-06 16:50:40 +01003213 if (bus->ops.pm_notify)
3214 bus->ops.pm_notify(bus);
Takashi Iwaicb53c622007-08-10 17:21:45 +02003215 hda_call_codec_resume(codec);
3216 cancel_delayed_work(&codec->power_work);
Takashi Iwaia221e282007-08-16 16:35:33 +02003217 codec->power_transition = 0;
Takashi Iwaicb53c622007-08-10 17:21:45 +02003218}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003219EXPORT_SYMBOL_HDA(snd_hda_power_up);
Takashi Iwai1289e9e2008-11-27 15:47:11 +01003220
3221#define power_save(codec) \
3222 ((codec)->bus->power_save ? *(codec)->bus->power_save : 0)
Takashi Iwaicb53c622007-08-10 17:21:45 +02003223
Takashi Iwaifee2fba2008-11-27 12:43:28 +01003224#define power_save(codec) \
3225 ((codec)->bus->power_save ? *(codec)->bus->power_save : 0)
3226
Takashi Iwaicb53c622007-08-10 17:21:45 +02003227void snd_hda_power_down(struct hda_codec *codec)
3228{
3229 --codec->power_count;
Takashi Iwaia221e282007-08-16 16:35:33 +02003230 if (!codec->power_on || codec->power_count || codec->power_transition)
Takashi Iwaicb53c622007-08-10 17:21:45 +02003231 return;
Takashi Iwaifee2fba2008-11-27 12:43:28 +01003232 if (power_save(codec)) {
Takashi Iwaia221e282007-08-16 16:35:33 +02003233 codec->power_transition = 1; /* avoid reentrance */
Takashi Iwaic107b412009-01-13 17:46:37 +01003234 queue_delayed_work(codec->bus->workq, &codec->power_work,
Takashi Iwaifee2fba2008-11-27 12:43:28 +01003235 msecs_to_jiffies(power_save(codec) * 1000));
Takashi Iwaia221e282007-08-16 16:35:33 +02003236 }
Takashi Iwaicb53c622007-08-10 17:21:45 +02003237}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003238EXPORT_SYMBOL_HDA(snd_hda_power_down);
Takashi Iwaicb53c622007-08-10 17:21:45 +02003239
3240int snd_hda_check_amp_list_power(struct hda_codec *codec,
3241 struct hda_loopback_check *check,
3242 hda_nid_t nid)
3243{
3244 struct hda_amp_list *p;
3245 int ch, v;
3246
3247 if (!check->amplist)
3248 return 0;
3249 for (p = check->amplist; p->nid; p++) {
3250 if (p->nid == nid)
3251 break;
3252 }
3253 if (!p->nid)
3254 return 0; /* nothing changed */
3255
3256 for (p = check->amplist; p->nid; p++) {
3257 for (ch = 0; ch < 2; ch++) {
3258 v = snd_hda_codec_amp_read(codec, p->nid, ch, p->dir,
3259 p->idx);
3260 if (!(v & HDA_AMP_MUTE) && v > 0) {
3261 if (!check->power_on) {
3262 check->power_on = 1;
3263 snd_hda_power_up(codec);
3264 }
3265 return 1;
3266 }
3267 }
3268 }
3269 if (check->power_on) {
3270 check->power_on = 0;
3271 snd_hda_power_down(codec);
3272 }
3273 return 0;
3274}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003275EXPORT_SYMBOL_HDA(snd_hda_check_amp_list_power);
Takashi Iwaicb53c622007-08-10 17:21:45 +02003276#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07003277
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01003278/*
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01003279 * Channel mode helper
3280 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003281int snd_hda_ch_mode_info(struct hda_codec *codec,
3282 struct snd_ctl_elem_info *uinfo,
3283 const struct hda_channel_mode *chmode,
3284 int num_chmodes)
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01003285{
3286 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
3287 uinfo->count = 1;
3288 uinfo->value.enumerated.items = num_chmodes;
3289 if (uinfo->value.enumerated.item >= num_chmodes)
3290 uinfo->value.enumerated.item = num_chmodes - 1;
3291 sprintf(uinfo->value.enumerated.name, "%dch",
3292 chmode[uinfo->value.enumerated.item].channels);
3293 return 0;
3294}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003295EXPORT_SYMBOL_HDA(snd_hda_ch_mode_info);
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01003296
Takashi Iwai0ba21762007-04-16 11:29:14 +02003297int snd_hda_ch_mode_get(struct hda_codec *codec,
3298 struct snd_ctl_elem_value *ucontrol,
3299 const struct hda_channel_mode *chmode,
3300 int num_chmodes,
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01003301 int max_channels)
3302{
3303 int i;
3304
3305 for (i = 0; i < num_chmodes; i++) {
3306 if (max_channels == chmode[i].channels) {
3307 ucontrol->value.enumerated.item[0] = i;
3308 break;
3309 }
3310 }
3311 return 0;
3312}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003313EXPORT_SYMBOL_HDA(snd_hda_ch_mode_get);
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01003314
Takashi Iwai0ba21762007-04-16 11:29:14 +02003315int snd_hda_ch_mode_put(struct hda_codec *codec,
3316 struct snd_ctl_elem_value *ucontrol,
3317 const struct hda_channel_mode *chmode,
3318 int num_chmodes,
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01003319 int *max_channelsp)
3320{
3321 unsigned int mode;
3322
3323 mode = ucontrol->value.enumerated.item[0];
Takashi Iwai68ea7b22007-11-15 15:54:38 +01003324 if (mode >= num_chmodes)
3325 return -EINVAL;
Takashi Iwai82beb8f2007-08-10 17:09:26 +02003326 if (*max_channelsp == chmode[mode].channels)
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01003327 return 0;
3328 /* change the current channel setting */
3329 *max_channelsp = chmode[mode].channels;
3330 if (chmode[mode].sequence)
Takashi Iwai82beb8f2007-08-10 17:09:26 +02003331 snd_hda_sequence_write_cache(codec, chmode[mode].sequence);
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01003332 return 1;
3333}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003334EXPORT_SYMBOL_HDA(snd_hda_ch_mode_put);
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01003335
Linus Torvalds1da177e2005-04-16 15:20:36 -07003336/*
3337 * input MUX helper
3338 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003339int snd_hda_input_mux_info(const struct hda_input_mux *imux,
3340 struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003341{
3342 unsigned int index;
3343
3344 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
3345 uinfo->count = 1;
3346 uinfo->value.enumerated.items = imux->num_items;
Takashi Iwai5513b0c2007-10-09 11:58:41 +02003347 if (!imux->num_items)
3348 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003349 index = uinfo->value.enumerated.item;
3350 if (index >= imux->num_items)
3351 index = imux->num_items - 1;
3352 strcpy(uinfo->value.enumerated.name, imux->items[index].label);
3353 return 0;
3354}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003355EXPORT_SYMBOL_HDA(snd_hda_input_mux_info);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003356
Takashi Iwai0ba21762007-04-16 11:29:14 +02003357int snd_hda_input_mux_put(struct hda_codec *codec,
3358 const struct hda_input_mux *imux,
3359 struct snd_ctl_elem_value *ucontrol,
3360 hda_nid_t nid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003361 unsigned int *cur_val)
3362{
3363 unsigned int idx;
3364
Takashi Iwai5513b0c2007-10-09 11:58:41 +02003365 if (!imux->num_items)
3366 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003367 idx = ucontrol->value.enumerated.item[0];
3368 if (idx >= imux->num_items)
3369 idx = imux->num_items - 1;
Takashi Iwai82beb8f2007-08-10 17:09:26 +02003370 if (*cur_val == idx)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003371 return 0;
Takashi Iwai82beb8f2007-08-10 17:09:26 +02003372 snd_hda_codec_write_cache(codec, nid, 0, AC_VERB_SET_CONNECT_SEL,
3373 imux->items[idx].index);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003374 *cur_val = idx;
3375 return 1;
3376}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003377EXPORT_SYMBOL_HDA(snd_hda_input_mux_put);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003378
3379
3380/*
3381 * Multi-channel / digital-out PCM helper functions
3382 */
3383
Takashi Iwai6b97eb42007-04-05 14:51:48 +02003384/* setup SPDIF output stream */
3385static void setup_dig_out_stream(struct hda_codec *codec, hda_nid_t nid,
3386 unsigned int stream_tag, unsigned int format)
3387{
3388 /* turn off SPDIF once; otherwise the IEC958 bits won't be updated */
Takashi Iwai2f728532008-09-25 16:32:41 +02003389 if (codec->spdif_status_reset && (codec->spdif_ctls & AC_DIG1_ENABLE))
3390 set_dig_out_convert(codec, nid,
3391 codec->spdif_ctls & ~AC_DIG1_ENABLE & 0xff,
3392 -1);
Takashi Iwai6b97eb42007-04-05 14:51:48 +02003393 snd_hda_codec_setup_stream(codec, nid, stream_tag, 0, format);
Takashi Iwai2f728532008-09-25 16:32:41 +02003394 if (codec->slave_dig_outs) {
3395 hda_nid_t *d;
3396 for (d = codec->slave_dig_outs; *d; d++)
3397 snd_hda_codec_setup_stream(codec, *d, stream_tag, 0,
3398 format);
Matthew Ranostayde51ca12008-09-07 14:31:40 -04003399 }
Takashi Iwai2f728532008-09-25 16:32:41 +02003400 /* turn on again (if needed) */
3401 if (codec->spdif_status_reset && (codec->spdif_ctls & AC_DIG1_ENABLE))
3402 set_dig_out_convert(codec, nid,
3403 codec->spdif_ctls & 0xff, -1);
3404}
Matthew Ranostayde51ca12008-09-07 14:31:40 -04003405
Takashi Iwai2f728532008-09-25 16:32:41 +02003406static void cleanup_dig_out_stream(struct hda_codec *codec, hda_nid_t nid)
3407{
3408 snd_hda_codec_cleanup_stream(codec, nid);
3409 if (codec->slave_dig_outs) {
3410 hda_nid_t *d;
3411 for (d = codec->slave_dig_outs; *d; d++)
3412 snd_hda_codec_cleanup_stream(codec, *d);
3413 }
Takashi Iwai6b97eb42007-04-05 14:51:48 +02003414}
3415
Linus Torvalds1da177e2005-04-16 15:20:36 -07003416/*
3417 * open the digital out in the exclusive mode
3418 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003419int snd_hda_multi_out_dig_open(struct hda_codec *codec,
3420 struct hda_multi_out *mout)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003421{
Ingo Molnar62932df2006-01-16 16:34:20 +01003422 mutex_lock(&codec->spdif_mutex);
Takashi Iwai5930ca42007-04-16 11:23:56 +02003423 if (mout->dig_out_used == HDA_DIG_ANALOG_DUP)
3424 /* already opened as analog dup; reset it once */
Takashi Iwai2f728532008-09-25 16:32:41 +02003425 cleanup_dig_out_stream(codec, mout->dig_out_nid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003426 mout->dig_out_used = HDA_DIG_EXCLUSIVE;
Ingo Molnar62932df2006-01-16 16:34:20 +01003427 mutex_unlock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003428 return 0;
3429}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003430EXPORT_SYMBOL_HDA(snd_hda_multi_out_dig_open);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003431
Takashi Iwai6b97eb42007-04-05 14:51:48 +02003432int snd_hda_multi_out_dig_prepare(struct hda_codec *codec,
3433 struct hda_multi_out *mout,
3434 unsigned int stream_tag,
3435 unsigned int format,
3436 struct snd_pcm_substream *substream)
3437{
3438 mutex_lock(&codec->spdif_mutex);
3439 setup_dig_out_stream(codec, mout->dig_out_nid, stream_tag, format);
3440 mutex_unlock(&codec->spdif_mutex);
3441 return 0;
3442}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003443EXPORT_SYMBOL_HDA(snd_hda_multi_out_dig_prepare);
Takashi Iwai6b97eb42007-04-05 14:51:48 +02003444
Takashi Iwai9411e212009-02-13 11:32:28 +01003445int snd_hda_multi_out_dig_cleanup(struct hda_codec *codec,
3446 struct hda_multi_out *mout)
3447{
3448 mutex_lock(&codec->spdif_mutex);
3449 cleanup_dig_out_stream(codec, mout->dig_out_nid);
3450 mutex_unlock(&codec->spdif_mutex);
3451 return 0;
3452}
3453EXPORT_SYMBOL_HDA(snd_hda_multi_out_dig_cleanup);
3454
Linus Torvalds1da177e2005-04-16 15:20:36 -07003455/*
3456 * release the digital out
3457 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003458int snd_hda_multi_out_dig_close(struct hda_codec *codec,
3459 struct hda_multi_out *mout)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003460{
Ingo Molnar62932df2006-01-16 16:34:20 +01003461 mutex_lock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003462 mout->dig_out_used = 0;
Ingo Molnar62932df2006-01-16 16:34:20 +01003463 mutex_unlock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003464 return 0;
3465}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003466EXPORT_SYMBOL_HDA(snd_hda_multi_out_dig_close);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003467
3468/*
3469 * set up more restrictions for analog out
3470 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003471int snd_hda_multi_out_analog_open(struct hda_codec *codec,
3472 struct hda_multi_out *mout,
Takashi Iwai9a081602008-02-12 18:37:26 +01003473 struct snd_pcm_substream *substream,
3474 struct hda_pcm_stream *hinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003475{
Takashi Iwai9a081602008-02-12 18:37:26 +01003476 struct snd_pcm_runtime *runtime = substream->runtime;
3477 runtime->hw.channels_max = mout->max_channels;
3478 if (mout->dig_out_nid) {
3479 if (!mout->analog_rates) {
3480 mout->analog_rates = hinfo->rates;
3481 mout->analog_formats = hinfo->formats;
3482 mout->analog_maxbps = hinfo->maxbps;
3483 } else {
3484 runtime->hw.rates = mout->analog_rates;
3485 runtime->hw.formats = mout->analog_formats;
3486 hinfo->maxbps = mout->analog_maxbps;
3487 }
3488 if (!mout->spdif_rates) {
3489 snd_hda_query_supported_pcm(codec, mout->dig_out_nid,
3490 &mout->spdif_rates,
3491 &mout->spdif_formats,
3492 &mout->spdif_maxbps);
3493 }
3494 mutex_lock(&codec->spdif_mutex);
3495 if (mout->share_spdif) {
Takashi Iwai022b4662009-07-03 23:03:30 +02003496 if ((runtime->hw.rates & mout->spdif_rates) &&
3497 (runtime->hw.formats & mout->spdif_formats)) {
3498 runtime->hw.rates &= mout->spdif_rates;
3499 runtime->hw.formats &= mout->spdif_formats;
3500 if (mout->spdif_maxbps < hinfo->maxbps)
3501 hinfo->maxbps = mout->spdif_maxbps;
3502 } else {
3503 mout->share_spdif = 0;
3504 /* FIXME: need notify? */
3505 }
Takashi Iwai9a081602008-02-12 18:37:26 +01003506 }
Frederik Deweerdteaa99852008-04-14 13:11:44 +02003507 mutex_unlock(&codec->spdif_mutex);
Takashi Iwai9a081602008-02-12 18:37:26 +01003508 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003509 return snd_pcm_hw_constraint_step(substream->runtime, 0,
3510 SNDRV_PCM_HW_PARAM_CHANNELS, 2);
3511}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003512EXPORT_SYMBOL_HDA(snd_hda_multi_out_analog_open);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003513
3514/*
3515 * set up the i/o for analog out
3516 * when the digital out is available, copy the front out to digital out, too.
3517 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003518int snd_hda_multi_out_analog_prepare(struct hda_codec *codec,
3519 struct hda_multi_out *mout,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003520 unsigned int stream_tag,
3521 unsigned int format,
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01003522 struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003523{
3524 hda_nid_t *nids = mout->dac_nids;
3525 int chs = substream->runtime->channels;
3526 int i;
3527
Ingo Molnar62932df2006-01-16 16:34:20 +01003528 mutex_lock(&codec->spdif_mutex);
Takashi Iwai9a081602008-02-12 18:37:26 +01003529 if (mout->dig_out_nid && mout->share_spdif &&
3530 mout->dig_out_used != HDA_DIG_EXCLUSIVE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003531 if (chs == 2 &&
Takashi Iwai0ba21762007-04-16 11:29:14 +02003532 snd_hda_is_supported_format(codec, mout->dig_out_nid,
3533 format) &&
3534 !(codec->spdif_status & IEC958_AES0_NONAUDIO)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003535 mout->dig_out_used = HDA_DIG_ANALOG_DUP;
Takashi Iwai6b97eb42007-04-05 14:51:48 +02003536 setup_dig_out_stream(codec, mout->dig_out_nid,
3537 stream_tag, format);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003538 } else {
3539 mout->dig_out_used = 0;
Takashi Iwai2f728532008-09-25 16:32:41 +02003540 cleanup_dig_out_stream(codec, mout->dig_out_nid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003541 }
3542 }
Ingo Molnar62932df2006-01-16 16:34:20 +01003543 mutex_unlock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003544
3545 /* front */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003546 snd_hda_codec_setup_stream(codec, nids[HDA_FRONT], stream_tag,
3547 0, format);
Takashi Iwaid29240c2007-10-26 12:35:56 +02003548 if (!mout->no_share_stream &&
3549 mout->hp_nid && mout->hp_nid != nids[HDA_FRONT])
Linus Torvalds1da177e2005-04-16 15:20:36 -07003550 /* headphone out will just decode front left/right (stereo) */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003551 snd_hda_codec_setup_stream(codec, mout->hp_nid, stream_tag,
3552 0, format);
Takashi Iwai82bc9552006-03-21 11:24:42 +01003553 /* extra outputs copied from front */
3554 for (i = 0; i < ARRAY_SIZE(mout->extra_out_nid); i++)
Takashi Iwaid29240c2007-10-26 12:35:56 +02003555 if (!mout->no_share_stream && mout->extra_out_nid[i])
Takashi Iwai82bc9552006-03-21 11:24:42 +01003556 snd_hda_codec_setup_stream(codec,
3557 mout->extra_out_nid[i],
3558 stream_tag, 0, format);
3559
Linus Torvalds1da177e2005-04-16 15:20:36 -07003560 /* surrounds */
3561 for (i = 1; i < mout->num_dacs; i++) {
Takashi Iwai4b3acaf2005-06-10 19:48:10 +02003562 if (chs >= (i + 1) * 2) /* independent out */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003563 snd_hda_codec_setup_stream(codec, nids[i], stream_tag,
3564 i * 2, format);
Takashi Iwaid29240c2007-10-26 12:35:56 +02003565 else if (!mout->no_share_stream) /* copy front */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003566 snd_hda_codec_setup_stream(codec, nids[i], stream_tag,
3567 0, format);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003568 }
3569 return 0;
3570}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003571EXPORT_SYMBOL_HDA(snd_hda_multi_out_analog_prepare);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003572
3573/*
3574 * clean up the setting for analog out
3575 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003576int snd_hda_multi_out_analog_cleanup(struct hda_codec *codec,
3577 struct hda_multi_out *mout)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003578{
3579 hda_nid_t *nids = mout->dac_nids;
3580 int i;
3581
3582 for (i = 0; i < mout->num_dacs; i++)
Takashi Iwai888afa12008-03-18 09:57:50 +01003583 snd_hda_codec_cleanup_stream(codec, nids[i]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003584 if (mout->hp_nid)
Takashi Iwai888afa12008-03-18 09:57:50 +01003585 snd_hda_codec_cleanup_stream(codec, mout->hp_nid);
Takashi Iwai82bc9552006-03-21 11:24:42 +01003586 for (i = 0; i < ARRAY_SIZE(mout->extra_out_nid); i++)
3587 if (mout->extra_out_nid[i])
Takashi Iwai888afa12008-03-18 09:57:50 +01003588 snd_hda_codec_cleanup_stream(codec,
3589 mout->extra_out_nid[i]);
Ingo Molnar62932df2006-01-16 16:34:20 +01003590 mutex_lock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003591 if (mout->dig_out_nid && mout->dig_out_used == HDA_DIG_ANALOG_DUP) {
Takashi Iwai2f728532008-09-25 16:32:41 +02003592 cleanup_dig_out_stream(codec, mout->dig_out_nid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003593 mout->dig_out_used = 0;
3594 }
Ingo Molnar62932df2006-01-16 16:34:20 +01003595 mutex_unlock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003596 return 0;
3597}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003598EXPORT_SYMBOL_HDA(snd_hda_multi_out_analog_cleanup);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003599
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003600/*
Wu Fengguang6b345002008-10-07 14:21:41 +08003601 * Helper for automatic pin configuration
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003602 */
Kailang Yangdf694da2005-12-05 19:42:22 +01003603
Takashi Iwai12f288b2007-08-02 15:51:59 +02003604static int is_in_nid_list(hda_nid_t nid, hda_nid_t *list)
Kailang Yangdf694da2005-12-05 19:42:22 +01003605{
3606 for (; *list; list++)
3607 if (*list == nid)
3608 return 1;
3609 return 0;
3610}
3611
Steve Longerbeam81937d32007-05-08 15:33:03 +02003612
3613/*
3614 * Sort an associated group of pins according to their sequence numbers.
3615 */
3616static void sort_pins_by_sequence(hda_nid_t * pins, short * sequences,
3617 int num_pins)
3618{
3619 int i, j;
3620 short seq;
3621 hda_nid_t nid;
3622
3623 for (i = 0; i < num_pins; i++) {
3624 for (j = i + 1; j < num_pins; j++) {
3625 if (sequences[i] > sequences[j]) {
3626 seq = sequences[i];
3627 sequences[i] = sequences[j];
3628 sequences[j] = seq;
3629 nid = pins[i];
3630 pins[i] = pins[j];
3631 pins[j] = nid;
3632 }
3633 }
3634 }
3635}
3636
3637
Takashi Iwai82bc9552006-03-21 11:24:42 +01003638/*
3639 * Parse all pin widgets and store the useful pin nids to cfg
3640 *
3641 * The number of line-outs or any primary output is stored in line_outs,
3642 * and the corresponding output pins are assigned to line_out_pins[],
3643 * in the order of front, rear, CLFE, side, ...
3644 *
3645 * If more extra outputs (speaker and headphone) are found, the pins are
Takashi Iwaieb06ed82006-09-20 17:10:27 +02003646 * assisnged to hp_pins[] and speaker_pins[], respectively. If no line-out jack
Takashi Iwai82bc9552006-03-21 11:24:42 +01003647 * is detected, one of speaker of HP pins is assigned as the primary
3648 * output, i.e. to line_out_pins[0]. So, line_outs is always positive
3649 * if any analog output exists.
3650 *
3651 * The analog input pins are assigned to input_pins array.
3652 * The digital input/output pins are assigned to dig_in_pin and dig_out_pin,
3653 * respectively.
3654 */
Takashi Iwai12f288b2007-08-02 15:51:59 +02003655int snd_hda_parse_pin_def_config(struct hda_codec *codec,
3656 struct auto_pin_cfg *cfg,
3657 hda_nid_t *ignore_nids)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003658{
Takashi Iwai0ef6ce72008-01-22 15:35:37 +01003659 hda_nid_t nid, end_nid;
Steve Longerbeam81937d32007-05-08 15:33:03 +02003660 short seq, assoc_line_out, assoc_speaker;
3661 short sequences_line_out[ARRAY_SIZE(cfg->line_out_pins)];
3662 short sequences_speaker[ARRAY_SIZE(cfg->speaker_pins)];
Takashi Iwaif889fa92007-10-31 15:49:32 +01003663 short sequences_hp[ARRAY_SIZE(cfg->hp_pins)];
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003664
3665 memset(cfg, 0, sizeof(*cfg));
3666
Steve Longerbeam81937d32007-05-08 15:33:03 +02003667 memset(sequences_line_out, 0, sizeof(sequences_line_out));
3668 memset(sequences_speaker, 0, sizeof(sequences_speaker));
Takashi Iwaif889fa92007-10-31 15:49:32 +01003669 memset(sequences_hp, 0, sizeof(sequences_hp));
Steve Longerbeam81937d32007-05-08 15:33:03 +02003670 assoc_line_out = assoc_speaker = 0;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003671
Takashi Iwai0ef6ce72008-01-22 15:35:37 +01003672 end_nid = codec->start_nid + codec->num_nodes;
3673 for (nid = codec->start_nid; nid < end_nid; nid++) {
Takashi Iwai54d17402005-11-21 16:33:22 +01003674 unsigned int wid_caps = get_wcaps(codec, nid);
Takashi Iwai0ba21762007-04-16 11:29:14 +02003675 unsigned int wid_type =
3676 (wid_caps & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003677 unsigned int def_conf;
3678 short assoc, loc;
3679
3680 /* read all default configuration for pin complex */
3681 if (wid_type != AC_WID_PIN)
3682 continue;
Kailang Yangdf694da2005-12-05 19:42:22 +01003683 /* ignore the given nids (e.g. pc-beep returns error) */
3684 if (ignore_nids && is_in_nid_list(nid, ignore_nids))
3685 continue;
3686
Takashi Iwaic17a1ab2009-02-23 09:28:12 +01003687 def_conf = snd_hda_codec_get_pincfg(codec, nid);
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003688 if (get_defcfg_connect(def_conf) == AC_JACK_PORT_NONE)
3689 continue;
3690 loc = get_defcfg_location(def_conf);
3691 switch (get_defcfg_device(def_conf)) {
3692 case AC_JACK_LINE_OUT:
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003693 seq = get_defcfg_sequence(def_conf);
3694 assoc = get_defcfg_association(def_conf);
Matthew Ranostay90da78b2008-01-24 11:48:01 +01003695
3696 if (!(wid_caps & AC_WCAP_STEREO))
3697 if (!cfg->mono_out_pin)
3698 cfg->mono_out_pin = nid;
Takashi Iwai0ba21762007-04-16 11:29:14 +02003699 if (!assoc)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003700 continue;
Takashi Iwai0ba21762007-04-16 11:29:14 +02003701 if (!assoc_line_out)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003702 assoc_line_out = assoc;
3703 else if (assoc_line_out != assoc)
3704 continue;
3705 if (cfg->line_outs >= ARRAY_SIZE(cfg->line_out_pins))
3706 continue;
3707 cfg->line_out_pins[cfg->line_outs] = nid;
Steve Longerbeam81937d32007-05-08 15:33:03 +02003708 sequences_line_out[cfg->line_outs] = seq;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003709 cfg->line_outs++;
3710 break;
Takashi Iwai8d88bc32005-11-17 11:09:23 +01003711 case AC_JACK_SPEAKER:
Steve Longerbeam81937d32007-05-08 15:33:03 +02003712 seq = get_defcfg_sequence(def_conf);
3713 assoc = get_defcfg_association(def_conf);
3714 if (! assoc)
3715 continue;
3716 if (! assoc_speaker)
3717 assoc_speaker = assoc;
3718 else if (assoc_speaker != assoc)
3719 continue;
Takashi Iwai82bc9552006-03-21 11:24:42 +01003720 if (cfg->speaker_outs >= ARRAY_SIZE(cfg->speaker_pins))
3721 continue;
3722 cfg->speaker_pins[cfg->speaker_outs] = nid;
Steve Longerbeam81937d32007-05-08 15:33:03 +02003723 sequences_speaker[cfg->speaker_outs] = seq;
Takashi Iwai82bc9552006-03-21 11:24:42 +01003724 cfg->speaker_outs++;
Takashi Iwai8d88bc32005-11-17 11:09:23 +01003725 break;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003726 case AC_JACK_HP_OUT:
Takashi Iwaif889fa92007-10-31 15:49:32 +01003727 seq = get_defcfg_sequence(def_conf);
3728 assoc = get_defcfg_association(def_conf);
Takashi Iwaieb06ed82006-09-20 17:10:27 +02003729 if (cfg->hp_outs >= ARRAY_SIZE(cfg->hp_pins))
3730 continue;
3731 cfg->hp_pins[cfg->hp_outs] = nid;
Takashi Iwaif889fa92007-10-31 15:49:32 +01003732 sequences_hp[cfg->hp_outs] = (assoc << 4) | seq;
Takashi Iwaieb06ed82006-09-20 17:10:27 +02003733 cfg->hp_outs++;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003734 break;
Takashi Iwai314634b2006-09-21 11:56:18 +02003735 case AC_JACK_MIC_IN: {
3736 int preferred, alt;
3737 if (loc == AC_JACK_LOC_FRONT) {
3738 preferred = AUTO_PIN_FRONT_MIC;
3739 alt = AUTO_PIN_MIC;
3740 } else {
3741 preferred = AUTO_PIN_MIC;
3742 alt = AUTO_PIN_FRONT_MIC;
3743 }
3744 if (!cfg->input_pins[preferred])
3745 cfg->input_pins[preferred] = nid;
3746 else if (!cfg->input_pins[alt])
3747 cfg->input_pins[alt] = nid;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003748 break;
Takashi Iwai314634b2006-09-21 11:56:18 +02003749 }
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003750 case AC_JACK_LINE_IN:
3751 if (loc == AC_JACK_LOC_FRONT)
3752 cfg->input_pins[AUTO_PIN_FRONT_LINE] = nid;
3753 else
3754 cfg->input_pins[AUTO_PIN_LINE] = nid;
3755 break;
3756 case AC_JACK_CD:
3757 cfg->input_pins[AUTO_PIN_CD] = nid;
3758 break;
3759 case AC_JACK_AUX:
3760 cfg->input_pins[AUTO_PIN_AUX] = nid;
3761 break;
3762 case AC_JACK_SPDIF_OUT:
Takashi Iwai1b52ae72009-01-20 17:17:29 +01003763 case AC_JACK_DIG_OTHER_OUT:
Takashi Iwai0852d7a2009-02-11 11:35:15 +01003764 if (cfg->dig_outs >= ARRAY_SIZE(cfg->dig_out_pins))
3765 continue;
3766 cfg->dig_out_pins[cfg->dig_outs] = nid;
3767 cfg->dig_out_type[cfg->dig_outs] =
3768 (loc == AC_JACK_LOC_HDMI) ?
3769 HDA_PCM_TYPE_HDMI : HDA_PCM_TYPE_SPDIF;
3770 cfg->dig_outs++;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003771 break;
3772 case AC_JACK_SPDIF_IN:
Takashi Iwai1b52ae72009-01-20 17:17:29 +01003773 case AC_JACK_DIG_OTHER_IN:
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003774 cfg->dig_in_pin = nid;
Takashi Iwai2297bd62009-01-20 18:24:13 +01003775 if (loc == AC_JACK_LOC_HDMI)
3776 cfg->dig_in_type = HDA_PCM_TYPE_HDMI;
3777 else
3778 cfg->dig_in_type = HDA_PCM_TYPE_SPDIF;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003779 break;
3780 }
3781 }
3782
Takashi Iwai5832fcf82008-02-12 18:30:12 +01003783 /* FIX-UP:
3784 * If no line-out is defined but multiple HPs are found,
3785 * some of them might be the real line-outs.
3786 */
3787 if (!cfg->line_outs && cfg->hp_outs > 1) {
3788 int i = 0;
3789 while (i < cfg->hp_outs) {
3790 /* The real HPs should have the sequence 0x0f */
3791 if ((sequences_hp[i] & 0x0f) == 0x0f) {
3792 i++;
3793 continue;
3794 }
3795 /* Move it to the line-out table */
3796 cfg->line_out_pins[cfg->line_outs] = cfg->hp_pins[i];
3797 sequences_line_out[cfg->line_outs] = sequences_hp[i];
3798 cfg->line_outs++;
3799 cfg->hp_outs--;
3800 memmove(cfg->hp_pins + i, cfg->hp_pins + i + 1,
3801 sizeof(cfg->hp_pins[0]) * (cfg->hp_outs - i));
3802 memmove(sequences_hp + i - 1, sequences_hp + i,
3803 sizeof(sequences_hp[0]) * (cfg->hp_outs - i));
3804 }
3805 }
3806
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003807 /* sort by sequence */
Steve Longerbeam81937d32007-05-08 15:33:03 +02003808 sort_pins_by_sequence(cfg->line_out_pins, sequences_line_out,
3809 cfg->line_outs);
3810 sort_pins_by_sequence(cfg->speaker_pins, sequences_speaker,
3811 cfg->speaker_outs);
Takashi Iwaif889fa92007-10-31 15:49:32 +01003812 sort_pins_by_sequence(cfg->hp_pins, sequences_hp,
3813 cfg->hp_outs);
Steve Longerbeam81937d32007-05-08 15:33:03 +02003814
Takashi Iwaif889fa92007-10-31 15:49:32 +01003815 /* if we have only one mic, make it AUTO_PIN_MIC */
3816 if (!cfg->input_pins[AUTO_PIN_MIC] &&
3817 cfg->input_pins[AUTO_PIN_FRONT_MIC]) {
3818 cfg->input_pins[AUTO_PIN_MIC] =
3819 cfg->input_pins[AUTO_PIN_FRONT_MIC];
3820 cfg->input_pins[AUTO_PIN_FRONT_MIC] = 0;
3821 }
3822 /* ditto for line-in */
3823 if (!cfg->input_pins[AUTO_PIN_LINE] &&
3824 cfg->input_pins[AUTO_PIN_FRONT_LINE]) {
3825 cfg->input_pins[AUTO_PIN_LINE] =
3826 cfg->input_pins[AUTO_PIN_FRONT_LINE];
3827 cfg->input_pins[AUTO_PIN_FRONT_LINE] = 0;
3828 }
3829
Steve Longerbeam81937d32007-05-08 15:33:03 +02003830 /*
3831 * FIX-UP: if no line-outs are detected, try to use speaker or HP pin
3832 * as a primary output
3833 */
3834 if (!cfg->line_outs) {
3835 if (cfg->speaker_outs) {
3836 cfg->line_outs = cfg->speaker_outs;
3837 memcpy(cfg->line_out_pins, cfg->speaker_pins,
3838 sizeof(cfg->speaker_pins));
3839 cfg->speaker_outs = 0;
3840 memset(cfg->speaker_pins, 0, sizeof(cfg->speaker_pins));
3841 cfg->line_out_type = AUTO_PIN_SPEAKER_OUT;
3842 } else if (cfg->hp_outs) {
3843 cfg->line_outs = cfg->hp_outs;
3844 memcpy(cfg->line_out_pins, cfg->hp_pins,
3845 sizeof(cfg->hp_pins));
3846 cfg->hp_outs = 0;
3847 memset(cfg->hp_pins, 0, sizeof(cfg->hp_pins));
3848 cfg->line_out_type = AUTO_PIN_HP_OUT;
3849 }
3850 }
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003851
Takashi Iwaicb8e2f82005-07-29 11:54:32 +02003852 /* Reorder the surround channels
3853 * ALSA sequence is front/surr/clfe/side
3854 * HDA sequence is:
3855 * 4-ch: front/surr => OK as it is
3856 * 6-ch: front/clfe/surr
Takashi Iwai9422db42007-04-20 16:11:43 +02003857 * 8-ch: front/clfe/rear/side|fc
Takashi Iwaicb8e2f82005-07-29 11:54:32 +02003858 */
3859 switch (cfg->line_outs) {
3860 case 3:
Takashi Iwaicb8e2f82005-07-29 11:54:32 +02003861 case 4:
3862 nid = cfg->line_out_pins[1];
Takashi Iwai9422db42007-04-20 16:11:43 +02003863 cfg->line_out_pins[1] = cfg->line_out_pins[2];
Takashi Iwaicb8e2f82005-07-29 11:54:32 +02003864 cfg->line_out_pins[2] = nid;
3865 break;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003866 }
3867
Takashi Iwai82bc9552006-03-21 11:24:42 +01003868 /*
3869 * debug prints of the parsed results
3870 */
3871 snd_printd("autoconfig: line_outs=%d (0x%x/0x%x/0x%x/0x%x/0x%x)\n",
3872 cfg->line_outs, cfg->line_out_pins[0], cfg->line_out_pins[1],
3873 cfg->line_out_pins[2], cfg->line_out_pins[3],
3874 cfg->line_out_pins[4]);
3875 snd_printd(" speaker_outs=%d (0x%x/0x%x/0x%x/0x%x/0x%x)\n",
3876 cfg->speaker_outs, cfg->speaker_pins[0],
3877 cfg->speaker_pins[1], cfg->speaker_pins[2],
3878 cfg->speaker_pins[3], cfg->speaker_pins[4]);
Takashi Iwaieb06ed82006-09-20 17:10:27 +02003879 snd_printd(" hp_outs=%d (0x%x/0x%x/0x%x/0x%x/0x%x)\n",
3880 cfg->hp_outs, cfg->hp_pins[0],
3881 cfg->hp_pins[1], cfg->hp_pins[2],
3882 cfg->hp_pins[3], cfg->hp_pins[4]);
Matthew Ranostay90da78b2008-01-24 11:48:01 +01003883 snd_printd(" mono: mono_out=0x%x\n", cfg->mono_out_pin);
Takashi Iwai0852d7a2009-02-11 11:35:15 +01003884 if (cfg->dig_outs)
3885 snd_printd(" dig-out=0x%x/0x%x\n",
3886 cfg->dig_out_pins[0], cfg->dig_out_pins[1]);
Takashi Iwai82bc9552006-03-21 11:24:42 +01003887 snd_printd(" inputs: mic=0x%x, fmic=0x%x, line=0x%x, fline=0x%x,"
3888 " cd=0x%x, aux=0x%x\n",
3889 cfg->input_pins[AUTO_PIN_MIC],
3890 cfg->input_pins[AUTO_PIN_FRONT_MIC],
3891 cfg->input_pins[AUTO_PIN_LINE],
3892 cfg->input_pins[AUTO_PIN_FRONT_LINE],
3893 cfg->input_pins[AUTO_PIN_CD],
3894 cfg->input_pins[AUTO_PIN_AUX]);
Takashi Iwai32d2c7f2009-02-11 11:33:13 +01003895 if (cfg->dig_in_pin)
Takashi Iwai89ce9e82009-01-20 17:15:57 +01003896 snd_printd(" dig-in=0x%x\n", cfg->dig_in_pin);
Takashi Iwai82bc9552006-03-21 11:24:42 +01003897
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003898 return 0;
3899}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003900EXPORT_SYMBOL_HDA(snd_hda_parse_pin_def_config);
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003901
Takashi Iwai4a471b72005-12-07 13:56:29 +01003902/* labels for input pins */
3903const char *auto_pin_cfg_labels[AUTO_PIN_LAST] = {
3904 "Mic", "Front Mic", "Line", "Front Line", "CD", "Aux"
3905};
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003906EXPORT_SYMBOL_HDA(auto_pin_cfg_labels);
Takashi Iwai4a471b72005-12-07 13:56:29 +01003907
3908
Linus Torvalds1da177e2005-04-16 15:20:36 -07003909#ifdef CONFIG_PM
3910/*
3911 * power management
3912 */
3913
3914/**
3915 * snd_hda_suspend - suspend the codecs
3916 * @bus: the HDA bus
Linus Torvalds1da177e2005-04-16 15:20:36 -07003917 *
3918 * Returns 0 if successful.
3919 */
Takashi Iwai8dd78332009-06-02 01:16:07 +02003920int snd_hda_suspend(struct hda_bus *bus)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003921{
Takashi Iwai0ba21762007-04-16 11:29:14 +02003922 struct hda_codec *codec;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003923
Takashi Iwai0ba21762007-04-16 11:29:14 +02003924 list_for_each_entry(codec, &bus->codec_list, list) {
Takashi Iwai0b7a2e92007-08-14 15:18:26 +02003925#ifdef CONFIG_SND_HDA_POWER_SAVE
3926 if (!codec->power_on)
3927 continue;
3928#endif
Takashi Iwaicb53c622007-08-10 17:21:45 +02003929 hda_call_codec_suspend(codec);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003930 }
3931 return 0;
3932}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003933EXPORT_SYMBOL_HDA(snd_hda_suspend);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003934
3935/**
3936 * snd_hda_resume - resume the codecs
3937 * @bus: the HDA bus
Linus Torvalds1da177e2005-04-16 15:20:36 -07003938 *
3939 * Returns 0 if successful.
Takashi Iwaicb53c622007-08-10 17:21:45 +02003940 *
3941 * This fucntion is defined only when POWER_SAVE isn't set.
3942 * In the power-save mode, the codec is resumed dynamically.
Linus Torvalds1da177e2005-04-16 15:20:36 -07003943 */
3944int snd_hda_resume(struct hda_bus *bus)
3945{
Takashi Iwai0ba21762007-04-16 11:29:14 +02003946 struct hda_codec *codec;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003947
Takashi Iwai0ba21762007-04-16 11:29:14 +02003948 list_for_each_entry(codec, &bus->codec_list, list) {
Maxim Levitskyd804ad92007-09-03 15:28:04 +02003949 if (snd_hda_codec_needs_resume(codec))
3950 hda_call_codec_resume(codec);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003951 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003952 return 0;
3953}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003954EXPORT_SYMBOL_HDA(snd_hda_resume);
Takashi Iwai1289e9e2008-11-27 15:47:11 +01003955#endif /* CONFIG_PM */
Takashi Iwaib2e18592008-07-30 15:01:44 +02003956
3957/*
3958 * generic arrays
3959 */
3960
3961/* get a new element from the given array
3962 * if it exceeds the pre-allocated array size, re-allocate the array
3963 */
3964void *snd_array_new(struct snd_array *array)
3965{
3966 if (array->used >= array->alloced) {
3967 int num = array->alloced + array->alloc_align;
Takashi Iwaib910d9a2008-11-07 00:26:52 +01003968 void *nlist;
3969 if (snd_BUG_ON(num >= 4096))
3970 return NULL;
3971 nlist = kcalloc(num + 1, array->elem_size, GFP_KERNEL);
Takashi Iwaib2e18592008-07-30 15:01:44 +02003972 if (!nlist)
3973 return NULL;
3974 if (array->list) {
3975 memcpy(nlist, array->list,
3976 array->elem_size * array->alloced);
3977 kfree(array->list);
3978 }
3979 array->list = nlist;
3980 array->alloced = num;
3981 }
Takashi Iwaif43aa022008-11-10 16:24:26 +01003982 return snd_array_elem(array, array->used++);
Takashi Iwaib2e18592008-07-30 15:01:44 +02003983}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003984EXPORT_SYMBOL_HDA(snd_array_new);
Takashi Iwaib2e18592008-07-30 15:01:44 +02003985
3986/* free the given array elements */
3987void snd_array_free(struct snd_array *array)
3988{
3989 kfree(array->list);
3990 array->used = 0;
3991 array->alloced = 0;
3992 array->list = NULL;
3993}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003994EXPORT_SYMBOL_HDA(snd_array_free);
Takashi Iwaib2022262008-11-21 21:24:03 +01003995
3996/*
3997 * used by hda_proc.c and hda_eld.c
3998 */
3999void snd_print_pcm_rates(int pcm, char *buf, int buflen)
4000{
4001 static unsigned int rates[] = {
4002 8000, 11025, 16000, 22050, 32000, 44100, 48000, 88200,
4003 96000, 176400, 192000, 384000
4004 };
4005 int i, j;
4006
4007 for (i = 0, j = 0; i < ARRAY_SIZE(rates); i++)
4008 if (pcm & (1 << i))
4009 j += snprintf(buf + j, buflen - j, " %d", rates[i]);
4010
4011 buf[j] = '\0'; /* necessary when j == 0 */
4012}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01004013EXPORT_SYMBOL_HDA(snd_print_pcm_rates);
Takashi Iwaib2022262008-11-21 21:24:03 +01004014
4015void snd_print_pcm_bits(int pcm, char *buf, int buflen)
4016{
4017 static unsigned int bits[] = { 8, 16, 20, 24, 32 };
4018 int i, j;
4019
4020 for (i = 0, j = 0; i < ARRAY_SIZE(bits); i++)
4021 if (pcm & (AC_SUPPCM_BITS_8 << i))
4022 j += snprintf(buf + j, buflen - j, " %d", bits[i]);
4023
4024 buf[j] = '\0'; /* necessary when j == 0 */
4025}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01004026EXPORT_SYMBOL_HDA(snd_print_pcm_bits);
Takashi Iwai1289e9e2008-11-27 15:47:11 +01004027
4028MODULE_DESCRIPTION("HDA codec core");
4029MODULE_LICENSE("GPL");