blob: 37f24ce7c3a20cd584912742c08d7bbe4ad51b65 [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
153 val = (u32)(codec->addr & 0x0f) << 28;
154 val |= (u32)direct << 27;
155 val |= (u32)nid << 20;
156 val |= verb << 8;
157 val |= parm;
158 return val;
159}
160
Linus Torvalds1da177e2005-04-16 15:20:36 -0700161/**
162 * snd_hda_codec_read - send a command and get the response
163 * @codec: the HDA codec
164 * @nid: NID to send the command
165 * @direct: direct flag
166 * @verb: the verb to send
167 * @parm: the parameter for the verb
168 *
169 * Send a single command and read the corresponding response.
170 *
171 * Returns the obtained response value, or -1 for an error.
172 */
Takashi Iwai0ba21762007-04-16 11:29:14 +0200173unsigned int snd_hda_codec_read(struct hda_codec *codec, hda_nid_t nid,
174 int direct,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700175 unsigned int verb, unsigned int parm)
176{
Takashi Iwai33fa35e2008-11-06 16:50:40 +0100177 struct hda_bus *bus = codec->bus;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700178 unsigned int res;
Takashi Iwai33fa35e2008-11-06 16:50:40 +0100179
180 res = make_codec_cmd(codec, nid, direct, verb, parm);
Takashi Iwaicb53c622007-08-10 17:21:45 +0200181 snd_hda_power_up(codec);
Takashi Iwai33fa35e2008-11-06 16:50:40 +0100182 mutex_lock(&bus->cmd_mutex);
183 if (!bus->ops.command(bus, res))
184 res = bus->ops.get_response(bus);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700185 else
186 res = (unsigned int)-1;
Takashi Iwai33fa35e2008-11-06 16:50:40 +0100187 mutex_unlock(&bus->cmd_mutex);
Takashi Iwaicb53c622007-08-10 17:21:45 +0200188 snd_hda_power_down(codec);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700189 return res;
190}
Takashi Iwaiff7a3262008-11-28 15:17:06 +0100191EXPORT_SYMBOL_HDA(snd_hda_codec_read);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700192
193/**
194 * snd_hda_codec_write - send a single command without waiting for response
195 * @codec: the HDA codec
196 * @nid: NID to send the command
197 * @direct: direct flag
198 * @verb: the verb to send
199 * @parm: the parameter for the verb
200 *
201 * Send a single command without waiting for response.
202 *
203 * Returns 0 if successful, or a negative error code.
204 */
205int snd_hda_codec_write(struct hda_codec *codec, hda_nid_t nid, int direct,
206 unsigned int verb, unsigned int parm)
207{
Takashi Iwai33fa35e2008-11-06 16:50:40 +0100208 struct hda_bus *bus = codec->bus;
209 unsigned int res;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700210 int err;
Takashi Iwai33fa35e2008-11-06 16:50:40 +0100211
212 res = make_codec_cmd(codec, nid, direct, verb, parm);
Takashi Iwaicb53c622007-08-10 17:21:45 +0200213 snd_hda_power_up(codec);
Takashi Iwai33fa35e2008-11-06 16:50:40 +0100214 mutex_lock(&bus->cmd_mutex);
215 err = bus->ops.command(bus, res);
216 mutex_unlock(&bus->cmd_mutex);
Takashi Iwaicb53c622007-08-10 17:21:45 +0200217 snd_hda_power_down(codec);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700218 return err;
219}
Takashi Iwaiff7a3262008-11-28 15:17:06 +0100220EXPORT_SYMBOL_HDA(snd_hda_codec_write);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700221
222/**
223 * snd_hda_sequence_write - sequence writes
224 * @codec: the HDA codec
225 * @seq: VERB array to send
226 *
227 * Send the commands sequentially from the given array.
228 * The array must be terminated with NID=0.
229 */
230void snd_hda_sequence_write(struct hda_codec *codec, const struct hda_verb *seq)
231{
232 for (; seq->nid; seq++)
233 snd_hda_codec_write(codec, seq->nid, 0, seq->verb, seq->param);
234}
Takashi Iwaiff7a3262008-11-28 15:17:06 +0100235EXPORT_SYMBOL_HDA(snd_hda_sequence_write);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700236
237/**
238 * snd_hda_get_sub_nodes - get the range of sub nodes
239 * @codec: the HDA codec
240 * @nid: NID to parse
241 * @start_id: the pointer to store the start NID
242 *
243 * Parse the NID and store the start NID of its sub-nodes.
244 * Returns the number of sub-nodes.
245 */
Takashi Iwai0ba21762007-04-16 11:29:14 +0200246int snd_hda_get_sub_nodes(struct hda_codec *codec, hda_nid_t nid,
247 hda_nid_t *start_id)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700248{
249 unsigned int parm;
250
251 parm = snd_hda_param_read(codec, nid, AC_PAR_NODE_COUNT);
Danny Tholene8a7f132007-09-11 21:41:56 +0200252 if (parm == -1)
253 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700254 *start_id = (parm >> 16) & 0x7fff;
255 return (int)(parm & 0x7fff);
256}
Takashi Iwaiff7a3262008-11-28 15:17:06 +0100257EXPORT_SYMBOL_HDA(snd_hda_get_sub_nodes);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700258
259/**
260 * snd_hda_get_connections - get connection list
261 * @codec: the HDA codec
262 * @nid: NID to parse
263 * @conn_list: connection list array
264 * @max_conns: max. number of connections to store
265 *
266 * Parses the connection list of the given widget and stores the list
267 * of NIDs.
268 *
269 * Returns the number of connections, or a negative error code.
270 */
271int snd_hda_get_connections(struct hda_codec *codec, hda_nid_t nid,
272 hda_nid_t *conn_list, int max_conns)
273{
274 unsigned int parm;
Takashi Iwai54d17402005-11-21 16:33:22 +0100275 int i, conn_len, conns;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700276 unsigned int shift, num_elems, mask;
Takashi Iwai54d17402005-11-21 16:33:22 +0100277 hda_nid_t prev_nid;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700278
Takashi Iwaida3cec32008-08-08 17:12:14 +0200279 if (snd_BUG_ON(!conn_list || max_conns <= 0))
280 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700281
282 parm = snd_hda_param_read(codec, nid, AC_PAR_CONNLIST_LEN);
283 if (parm & AC_CLIST_LONG) {
284 /* long form */
285 shift = 16;
286 num_elems = 2;
287 } else {
288 /* short form */
289 shift = 8;
290 num_elems = 4;
291 }
292 conn_len = parm & AC_CLIST_LENGTH;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700293 mask = (1 << (shift-1)) - 1;
294
Takashi Iwai0ba21762007-04-16 11:29:14 +0200295 if (!conn_len)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700296 return 0; /* no connection */
297
298 if (conn_len == 1) {
299 /* single connection */
Takashi Iwai0ba21762007-04-16 11:29:14 +0200300 parm = snd_hda_codec_read(codec, nid, 0,
301 AC_VERB_GET_CONNECT_LIST, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700302 conn_list[0] = parm & mask;
303 return 1;
304 }
305
306 /* multi connection */
307 conns = 0;
Takashi Iwai54d17402005-11-21 16:33:22 +0100308 prev_nid = 0;
309 for (i = 0; i < conn_len; i++) {
310 int range_val;
311 hda_nid_t val, n;
312
313 if (i % num_elems == 0)
314 parm = snd_hda_codec_read(codec, nid, 0,
315 AC_VERB_GET_CONNECT_LIST, i);
Takashi Iwai0ba21762007-04-16 11:29:14 +0200316 range_val = !!(parm & (1 << (shift-1))); /* ranges */
Takashi Iwai54d17402005-11-21 16:33:22 +0100317 val = parm & mask;
318 parm >>= shift;
319 if (range_val) {
320 /* ranges between the previous and this one */
Takashi Iwai0ba21762007-04-16 11:29:14 +0200321 if (!prev_nid || prev_nid >= val) {
322 snd_printk(KERN_WARNING "hda_codec: "
323 "invalid dep_range_val %x:%x\n",
324 prev_nid, val);
Takashi Iwai54d17402005-11-21 16:33:22 +0100325 continue;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700326 }
Takashi Iwai54d17402005-11-21 16:33:22 +0100327 for (n = prev_nid + 1; n <= val; n++) {
328 if (conns >= max_conns) {
Takashi Iwai0ba21762007-04-16 11:29:14 +0200329 snd_printk(KERN_ERR
330 "Too many connections\n");
Takashi Iwai54d17402005-11-21 16:33:22 +0100331 return -EINVAL;
332 }
333 conn_list[conns++] = n;
334 }
335 } else {
336 if (conns >= max_conns) {
337 snd_printk(KERN_ERR "Too many connections\n");
338 return -EINVAL;
339 }
340 conn_list[conns++] = val;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700341 }
Takashi Iwai54d17402005-11-21 16:33:22 +0100342 prev_nid = val;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700343 }
344 return conns;
345}
Takashi Iwaiff7a3262008-11-28 15:17:06 +0100346EXPORT_SYMBOL_HDA(snd_hda_get_connections);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700347
348
349/**
350 * snd_hda_queue_unsol_event - add an unsolicited event to queue
351 * @bus: the BUS
352 * @res: unsolicited event (lower 32bit of RIRB entry)
353 * @res_ex: codec addr and flags (upper 32bit or RIRB entry)
354 *
355 * Adds the given event to the queue. The events are processed in
356 * the workqueue asynchronously. Call this function in the interrupt
357 * hanlder when RIRB receives an unsolicited event.
358 *
359 * Returns 0 if successful, or a negative error code.
360 */
361int snd_hda_queue_unsol_event(struct hda_bus *bus, u32 res, u32 res_ex)
362{
363 struct hda_bus_unsolicited *unsol;
364 unsigned int wp;
365
Takashi Iwai0ba21762007-04-16 11:29:14 +0200366 unsol = bus->unsol;
367 if (!unsol)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700368 return 0;
369
370 wp = (unsol->wp + 1) % HDA_UNSOL_QUEUE_SIZE;
371 unsol->wp = wp;
372
373 wp <<= 1;
374 unsol->queue[wp] = res;
375 unsol->queue[wp + 1] = res_ex;
376
Takashi Iwai6acaed32009-01-12 10:09:24 +0100377 queue_work(bus->workq, &unsol->work);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700378
379 return 0;
380}
Takashi Iwaiff7a3262008-11-28 15:17:06 +0100381EXPORT_SYMBOL_HDA(snd_hda_queue_unsol_event);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700382
383/*
Wu Fengguang5c1d1a92008-10-07 14:17:53 +0800384 * process queued unsolicited events
Linus Torvalds1da177e2005-04-16 15:20:36 -0700385 */
David Howellsc4028952006-11-22 14:57:56 +0000386static void process_unsol_events(struct work_struct *work)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700387{
David Howellsc4028952006-11-22 14:57:56 +0000388 struct hda_bus_unsolicited *unsol =
389 container_of(work, struct hda_bus_unsolicited, work);
390 struct hda_bus *bus = unsol->bus;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700391 struct hda_codec *codec;
392 unsigned int rp, caddr, res;
393
394 while (unsol->rp != unsol->wp) {
395 rp = (unsol->rp + 1) % HDA_UNSOL_QUEUE_SIZE;
396 unsol->rp = rp;
397 rp <<= 1;
398 res = unsol->queue[rp];
399 caddr = unsol->queue[rp + 1];
Takashi Iwai0ba21762007-04-16 11:29:14 +0200400 if (!(caddr & (1 << 4))) /* no unsolicited event? */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700401 continue;
402 codec = bus->caddr_tbl[caddr & 0x0f];
403 if (codec && codec->patch_ops.unsol_event)
404 codec->patch_ops.unsol_event(codec, res);
405 }
406}
407
408/*
409 * initialize unsolicited queue
410 */
Takashi Iwai6c1f45e2008-07-30 15:01:45 +0200411static int init_unsol_queue(struct hda_bus *bus)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700412{
413 struct hda_bus_unsolicited *unsol;
414
Takashi Iwai9f146bb2005-11-17 11:07:49 +0100415 if (bus->unsol) /* already initialized */
416 return 0;
417
Takashi Iwaie560d8d2005-09-09 14:21:46 +0200418 unsol = kzalloc(sizeof(*unsol), GFP_KERNEL);
Takashi Iwai0ba21762007-04-16 11:29:14 +0200419 if (!unsol) {
420 snd_printk(KERN_ERR "hda_codec: "
421 "can't allocate unsolicited queue\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700422 return -ENOMEM;
423 }
David Howellsc4028952006-11-22 14:57:56 +0000424 INIT_WORK(&unsol->work, process_unsol_events);
425 unsol->bus = bus;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700426 bus->unsol = unsol;
427 return 0;
428}
429
430/*
431 * destructor
432 */
433static void snd_hda_codec_free(struct hda_codec *codec);
434
435static int snd_hda_bus_free(struct hda_bus *bus)
436{
Takashi Iwai0ba21762007-04-16 11:29:14 +0200437 struct hda_codec *codec, *n;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700438
Takashi Iwai0ba21762007-04-16 11:29:14 +0200439 if (!bus)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700440 return 0;
Takashi Iwai6acaed32009-01-12 10:09:24 +0100441 if (bus->workq)
442 flush_workqueue(bus->workq);
443 if (bus->unsol)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700444 kfree(bus->unsol);
Takashi Iwai0ba21762007-04-16 11:29:14 +0200445 list_for_each_entry_safe(codec, n, &bus->codec_list, list) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700446 snd_hda_codec_free(codec);
447 }
448 if (bus->ops.private_free)
449 bus->ops.private_free(bus);
Takashi Iwai6acaed32009-01-12 10:09:24 +0100450 if (bus->workq)
451 destroy_workqueue(bus->workq);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700452 kfree(bus);
453 return 0;
454}
455
Takashi Iwaic8b6bf92005-11-17 14:57:47 +0100456static int snd_hda_bus_dev_free(struct snd_device *device)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700457{
458 struct hda_bus *bus = device->device_data;
Takashi Iwaib94d35392008-11-21 09:08:06 +0100459 bus->shutdown = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700460 return snd_hda_bus_free(bus);
461}
462
Takashi Iwaid7ffba12008-07-30 15:01:46 +0200463#ifdef CONFIG_SND_HDA_HWDEP
464static int snd_hda_bus_dev_register(struct snd_device *device)
465{
466 struct hda_bus *bus = device->device_data;
467 struct hda_codec *codec;
468 list_for_each_entry(codec, &bus->codec_list, list) {
469 snd_hda_hwdep_add_sysfs(codec);
470 }
471 return 0;
472}
473#else
474#define snd_hda_bus_dev_register NULL
475#endif
476
Linus Torvalds1da177e2005-04-16 15:20:36 -0700477/**
478 * snd_hda_bus_new - create a HDA bus
479 * @card: the card entry
480 * @temp: the template for hda_bus information
481 * @busp: the pointer to store the created bus instance
482 *
483 * Returns 0 if successful, or a negative error code.
484 */
Takashi Iwai1289e9e2008-11-27 15:47:11 +0100485int /*__devinit*/ snd_hda_bus_new(struct snd_card *card,
Takashi Iwai756e2b02007-04-16 11:27:07 +0200486 const struct hda_bus_template *temp,
487 struct hda_bus **busp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700488{
489 struct hda_bus *bus;
490 int err;
Takashi Iwaic8b6bf92005-11-17 14:57:47 +0100491 static struct snd_device_ops dev_ops = {
Takashi Iwaid7ffba12008-07-30 15:01:46 +0200492 .dev_register = snd_hda_bus_dev_register,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700493 .dev_free = snd_hda_bus_dev_free,
494 };
495
Takashi Iwaida3cec32008-08-08 17:12:14 +0200496 if (snd_BUG_ON(!temp))
497 return -EINVAL;
498 if (snd_BUG_ON(!temp->ops.command || !temp->ops.get_response))
499 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700500
501 if (busp)
502 *busp = NULL;
503
Takashi Iwaie560d8d2005-09-09 14:21:46 +0200504 bus = kzalloc(sizeof(*bus), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700505 if (bus == NULL) {
506 snd_printk(KERN_ERR "can't allocate struct hda_bus\n");
507 return -ENOMEM;
508 }
509
510 bus->card = card;
511 bus->private_data = temp->private_data;
512 bus->pci = temp->pci;
513 bus->modelname = temp->modelname;
Takashi Iwaifee2fba2008-11-27 12:43:28 +0100514 bus->power_save = temp->power_save;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700515 bus->ops = temp->ops;
516
Ingo Molnar62932df2006-01-16 16:34:20 +0100517 mutex_init(&bus->cmd_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700518 INIT_LIST_HEAD(&bus->codec_list);
519
Takashi Iwaie8c0ee52009-02-05 07:34:28 +0100520 snprintf(bus->workq_name, sizeof(bus->workq_name),
521 "hd-audio%d", card->number);
522 bus->workq = create_singlethread_workqueue(bus->workq_name);
Takashi Iwai6acaed32009-01-12 10:09:24 +0100523 if (!bus->workq) {
Takashi Iwaie8c0ee52009-02-05 07:34:28 +0100524 snd_printk(KERN_ERR "cannot create workqueue %s\n",
525 bus->workq_name);
Takashi Iwai6acaed32009-01-12 10:09:24 +0100526 kfree(bus);
527 return -ENOMEM;
528 }
529
Takashi Iwai0ba21762007-04-16 11:29:14 +0200530 err = snd_device_new(card, SNDRV_DEV_BUS, bus, &dev_ops);
531 if (err < 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700532 snd_hda_bus_free(bus);
533 return err;
534 }
535 if (busp)
536 *busp = bus;
537 return 0;
538}
Takashi Iwaiff7a3262008-11-28 15:17:06 +0100539EXPORT_SYMBOL_HDA(snd_hda_bus_new);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700540
Takashi Iwai82467612007-07-27 19:15:54 +0200541#ifdef CONFIG_SND_HDA_GENERIC
542#define is_generic_config(codec) \
Takashi Iwaif44ac832008-07-30 15:01:45 +0200543 (codec->modelname && !strcmp(codec->modelname, "generic"))
Takashi Iwai82467612007-07-27 19:15:54 +0200544#else
545#define is_generic_config(codec) 0
546#endif
547
Takashi Iwai645f10c2008-11-28 15:07:37 +0100548#ifdef MODULE
Takashi Iwai1289e9e2008-11-27 15:47:11 +0100549#define HDA_MODREQ_MAX_COUNT 2 /* two request_modules()'s */
550#else
Takashi Iwai645f10c2008-11-28 15:07:37 +0100551#define HDA_MODREQ_MAX_COUNT 0 /* all presets are statically linked */
Takashi Iwai1289e9e2008-11-27 15:47:11 +0100552#endif
553
Linus Torvalds1da177e2005-04-16 15:20:36 -0700554/*
555 * find a matching codec preset
556 */
Takashi Iwai6c1f45e2008-07-30 15:01:45 +0200557static const struct hda_codec_preset *
Takashi Iwai756e2b02007-04-16 11:27:07 +0200558find_codec_preset(struct hda_codec *codec)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700559{
Takashi Iwai1289e9e2008-11-27 15:47:11 +0100560 struct hda_codec_preset_list *tbl;
561 const struct hda_codec_preset *preset;
562 int mod_requested = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700563
Takashi Iwai82467612007-07-27 19:15:54 +0200564 if (is_generic_config(codec))
Takashi Iwaid5ad6302007-03-07 15:55:59 +0100565 return NULL; /* use the generic parser */
566
Takashi Iwai1289e9e2008-11-27 15:47:11 +0100567 again:
568 mutex_lock(&preset_mutex);
569 list_for_each_entry(tbl, &hda_preset_tables, list) {
570 if (!try_module_get(tbl->owner)) {
571 snd_printk(KERN_ERR "hda_codec: cannot module_get\n");
572 continue;
573 }
574 for (preset = tbl->preset; preset->id; preset++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700575 u32 mask = preset->mask;
Marc Boucherca7cfae2008-01-22 15:32:25 +0100576 if (preset->afg && preset->afg != codec->afg)
577 continue;
578 if (preset->mfg && preset->mfg != codec->mfg)
579 continue;
Takashi Iwai0ba21762007-04-16 11:29:14 +0200580 if (!mask)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700581 mask = ~0;
Takashi Iwai9c7f8522006-06-28 15:08:22 +0200582 if (preset->id == (codec->vendor_id & mask) &&
Takashi Iwai0ba21762007-04-16 11:29:14 +0200583 (!preset->rev ||
Takashi Iwai1289e9e2008-11-27 15:47:11 +0100584 preset->rev == codec->revision_id)) {
585 mutex_unlock(&preset_mutex);
586 codec->owner = tbl->owner;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700587 return preset;
Takashi Iwai1289e9e2008-11-27 15:47:11 +0100588 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700589 }
Takashi Iwai1289e9e2008-11-27 15:47:11 +0100590 module_put(tbl->owner);
591 }
592 mutex_unlock(&preset_mutex);
593
594 if (mod_requested < HDA_MODREQ_MAX_COUNT) {
595 char name[32];
596 if (!mod_requested)
597 snprintf(name, sizeof(name), "snd-hda-codec-id:%08x",
598 codec->vendor_id);
599 else
600 snprintf(name, sizeof(name), "snd-hda-codec-id:%04x*",
601 (codec->vendor_id >> 16) & 0xffff);
602 request_module(name);
603 mod_requested++;
604 goto again;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700605 }
606 return NULL;
607}
608
609/*
Takashi Iwaif44ac832008-07-30 15:01:45 +0200610 * get_codec_name - store the codec name
Linus Torvalds1da177e2005-04-16 15:20:36 -0700611 */
Takashi Iwaif44ac832008-07-30 15:01:45 +0200612static int get_codec_name(struct hda_codec *codec)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700613{
614 const struct hda_vendor_id *c;
615 const char *vendor = NULL;
616 u16 vendor_id = codec->vendor_id >> 16;
Takashi Iwaif44ac832008-07-30 15:01:45 +0200617 char tmp[16], name[32];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700618
619 for (c = hda_vendor_ids; c->id; c++) {
620 if (c->id == vendor_id) {
621 vendor = c->name;
622 break;
623 }
624 }
Takashi Iwai0ba21762007-04-16 11:29:14 +0200625 if (!vendor) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700626 sprintf(tmp, "Generic %04x", vendor_id);
627 vendor = tmp;
628 }
629 if (codec->preset && codec->preset->name)
Takashi Iwaif44ac832008-07-30 15:01:45 +0200630 snprintf(name, sizeof(name), "%s %s", vendor,
631 codec->preset->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700632 else
Takashi Iwaif44ac832008-07-30 15:01:45 +0200633 snprintf(name, sizeof(name), "%s ID %x", vendor,
Takashi Iwai0ba21762007-04-16 11:29:14 +0200634 codec->vendor_id & 0xffff);
Takashi Iwaif44ac832008-07-30 15:01:45 +0200635 codec->name = kstrdup(name, GFP_KERNEL);
636 if (!codec->name)
637 return -ENOMEM;
638 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700639}
640
641/*
Sasha Khapyorsky673b6832005-08-11 11:00:16 +0200642 * look for an AFG and MFG nodes
Linus Torvalds1da177e2005-04-16 15:20:36 -0700643 */
Takashi Iwai1289e9e2008-11-27 15:47:11 +0100644static void /*__devinit*/ setup_fg_nodes(struct hda_codec *codec)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700645{
646 int i, total_nodes;
647 hda_nid_t nid;
648
649 total_nodes = snd_hda_get_sub_nodes(codec, AC_NODE_ROOT, &nid);
650 for (i = 0; i < total_nodes; i++, nid++) {
Pascal de Bruijn234b4342009-03-23 11:15:59 +0100651 codec->function_id = snd_hda_param_read(codec, nid,
652 AC_PAR_FUNCTION_TYPE) & 0xff;
653 switch (codec->function_id) {
Sasha Khapyorsky673b6832005-08-11 11:00:16 +0200654 case AC_GRP_AUDIO_FUNCTION:
655 codec->afg = nid;
656 break;
657 case AC_GRP_MODEM_FUNCTION:
658 codec->mfg = nid;
659 break;
660 default:
661 break;
662 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700663 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700664}
665
666/*
Takashi Iwai54d17402005-11-21 16:33:22 +0100667 * read widget caps for each widget and store in cache
668 */
669static int read_widget_caps(struct hda_codec *codec, hda_nid_t fg_node)
670{
671 int i;
672 hda_nid_t nid;
673
674 codec->num_nodes = snd_hda_get_sub_nodes(codec, fg_node,
675 &codec->start_nid);
676 codec->wcaps = kmalloc(codec->num_nodes * 4, GFP_KERNEL);
Takashi Iwai0ba21762007-04-16 11:29:14 +0200677 if (!codec->wcaps)
Takashi Iwai54d17402005-11-21 16:33:22 +0100678 return -ENOMEM;
679 nid = codec->start_nid;
680 for (i = 0; i < codec->num_nodes; i++, nid++)
681 codec->wcaps[i] = snd_hda_param_read(codec, nid,
682 AC_PAR_AUDIO_WIDGET_CAP);
683 return 0;
684}
685
Takashi Iwai3be14142009-02-20 14:11:16 +0100686/* read all pin default configurations and save codec->init_pins */
687static int read_pin_defaults(struct hda_codec *codec)
688{
689 int i;
690 hda_nid_t nid = codec->start_nid;
691
692 for (i = 0; i < codec->num_nodes; i++, nid++) {
693 struct hda_pincfg *pin;
694 unsigned int wcaps = get_wcaps(codec, nid);
695 unsigned int wid_type = (wcaps & AC_WCAP_TYPE) >>
696 AC_WCAP_TYPE_SHIFT;
697 if (wid_type != AC_WID_PIN)
698 continue;
699 pin = snd_array_new(&codec->init_pins);
700 if (!pin)
701 return -ENOMEM;
702 pin->nid = nid;
703 pin->cfg = snd_hda_codec_read(codec, nid, 0,
704 AC_VERB_GET_CONFIG_DEFAULT, 0);
705 }
706 return 0;
707}
708
709/* look up the given pin config list and return the item matching with NID */
710static struct hda_pincfg *look_up_pincfg(struct hda_codec *codec,
711 struct snd_array *array,
712 hda_nid_t nid)
713{
714 int i;
715 for (i = 0; i < array->used; i++) {
716 struct hda_pincfg *pin = snd_array_elem(array, i);
717 if (pin->nid == nid)
718 return pin;
719 }
720 return NULL;
721}
722
723/* write a config value for the given NID */
724static void set_pincfg(struct hda_codec *codec, hda_nid_t nid,
725 unsigned int cfg)
726{
727 int i;
728 for (i = 0; i < 4; i++) {
729 snd_hda_codec_write(codec, nid, 0,
730 AC_VERB_SET_CONFIG_DEFAULT_BYTES_0 + i,
731 cfg & 0xff);
732 cfg >>= 8;
733 }
734}
735
736/* set the current pin config value for the given NID.
737 * the value is cached, and read via snd_hda_codec_get_pincfg()
738 */
739int snd_hda_add_pincfg(struct hda_codec *codec, struct snd_array *list,
740 hda_nid_t nid, unsigned int cfg)
741{
742 struct hda_pincfg *pin;
Takashi Iwai5e7b8e02009-02-23 09:45:59 +0100743 unsigned int oldcfg;
Takashi Iwai3be14142009-02-20 14:11:16 +0100744
Takashi Iwai5e7b8e02009-02-23 09:45:59 +0100745 oldcfg = snd_hda_codec_get_pincfg(codec, nid);
Takashi Iwai3be14142009-02-20 14:11:16 +0100746 pin = look_up_pincfg(codec, list, nid);
747 if (!pin) {
748 pin = snd_array_new(list);
749 if (!pin)
750 return -ENOMEM;
751 pin->nid = nid;
752 }
753 pin->cfg = cfg;
Takashi Iwai5e7b8e02009-02-23 09:45:59 +0100754
755 /* change only when needed; e.g. if the pincfg is already present
756 * in user_pins[], don't write it
757 */
758 cfg = snd_hda_codec_get_pincfg(codec, nid);
759 if (oldcfg != cfg)
760 set_pincfg(codec, nid, cfg);
Takashi Iwai3be14142009-02-20 14:11:16 +0100761 return 0;
762}
763
764int snd_hda_codec_set_pincfg(struct hda_codec *codec,
765 hda_nid_t nid, unsigned int cfg)
766{
Takashi Iwai346ff702009-02-23 09:42:57 +0100767 return snd_hda_add_pincfg(codec, &codec->driver_pins, nid, cfg);
Takashi Iwai3be14142009-02-20 14:11:16 +0100768}
769EXPORT_SYMBOL_HDA(snd_hda_codec_set_pincfg);
770
771/* get the current pin config value of the given pin NID */
772unsigned int snd_hda_codec_get_pincfg(struct hda_codec *codec, hda_nid_t nid)
773{
774 struct hda_pincfg *pin;
775
Takashi Iwai3be14142009-02-20 14:11:16 +0100776#ifdef CONFIG_SND_HDA_HWDEP
Takashi Iwai346ff702009-02-23 09:42:57 +0100777 pin = look_up_pincfg(codec, &codec->user_pins, nid);
Takashi Iwai3be14142009-02-20 14:11:16 +0100778 if (pin)
779 return pin->cfg;
780#endif
Takashi Iwai5e7b8e02009-02-23 09:45:59 +0100781 pin = look_up_pincfg(codec, &codec->driver_pins, nid);
782 if (pin)
783 return pin->cfg;
Takashi Iwai3be14142009-02-20 14:11:16 +0100784 pin = look_up_pincfg(codec, &codec->init_pins, nid);
785 if (pin)
786 return pin->cfg;
787 return 0;
788}
789EXPORT_SYMBOL_HDA(snd_hda_codec_get_pincfg);
790
791/* restore all current pin configs */
792static void restore_pincfgs(struct hda_codec *codec)
793{
794 int i;
795 for (i = 0; i < codec->init_pins.used; i++) {
796 struct hda_pincfg *pin = snd_array_elem(&codec->init_pins, i);
797 set_pincfg(codec, pin->nid,
798 snd_hda_codec_get_pincfg(codec, pin->nid));
799 }
800}
Takashi Iwai54d17402005-11-21 16:33:22 +0100801
Takashi Iwai01751f52007-08-10 16:59:39 +0200802static void init_hda_cache(struct hda_cache_rec *cache,
803 unsigned int record_size);
Takashi Iwai1fcaee62007-08-23 00:01:09 +0200804static void free_hda_cache(struct hda_cache_rec *cache);
Takashi Iwai01751f52007-08-10 16:59:39 +0200805
Takashi Iwai3be14142009-02-20 14:11:16 +0100806/* restore the initial pin cfgs and release all pincfg lists */
807static void restore_init_pincfgs(struct hda_codec *codec)
808{
Takashi Iwai346ff702009-02-23 09:42:57 +0100809 /* first free driver_pins and user_pins, then call restore_pincfg
Takashi Iwai3be14142009-02-20 14:11:16 +0100810 * so that only the values in init_pins are restored
811 */
Takashi Iwai346ff702009-02-23 09:42:57 +0100812 snd_array_free(&codec->driver_pins);
Takashi Iwai3be14142009-02-20 14:11:16 +0100813#ifdef CONFIG_SND_HDA_HWDEP
Takashi Iwai346ff702009-02-23 09:42:57 +0100814 snd_array_free(&codec->user_pins);
Takashi Iwai3be14142009-02-20 14:11:16 +0100815#endif
816 restore_pincfgs(codec);
817 snd_array_free(&codec->init_pins);
818}
819
Takashi Iwai54d17402005-11-21 16:33:22 +0100820/*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700821 * codec destructor
822 */
823static void snd_hda_codec_free(struct hda_codec *codec)
824{
Takashi Iwai0ba21762007-04-16 11:29:14 +0200825 if (!codec)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700826 return;
Takashi Iwai3be14142009-02-20 14:11:16 +0100827 restore_init_pincfgs(codec);
Takashi Iwaicb53c622007-08-10 17:21:45 +0200828#ifdef CONFIG_SND_HDA_POWER_SAVE
829 cancel_delayed_work(&codec->power_work);
Takashi Iwai6acaed32009-01-12 10:09:24 +0100830 flush_workqueue(codec->bus->workq);
Takashi Iwaicb53c622007-08-10 17:21:45 +0200831#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700832 list_del(&codec->list);
Takashi Iwaid13bd412008-07-30 15:01:45 +0200833 snd_array_free(&codec->mixers);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700834 codec->bus->caddr_tbl[codec->addr] = NULL;
835 if (codec->patch_ops.free)
836 codec->patch_ops.free(codec);
Takashi Iwai1289e9e2008-11-27 15:47:11 +0100837 module_put(codec->owner);
Takashi Iwai01751f52007-08-10 16:59:39 +0200838 free_hda_cache(&codec->amp_cache);
Takashi Iwaib3ac5632007-08-10 17:03:40 +0200839 free_hda_cache(&codec->cmd_cache);
Takashi Iwaif44ac832008-07-30 15:01:45 +0200840 kfree(codec->name);
841 kfree(codec->modelname);
Takashi Iwai54d17402005-11-21 16:33:22 +0100842 kfree(codec->wcaps);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700843 kfree(codec);
844}
845
Takashi Iwaibb6ac722009-03-13 09:02:42 +0100846static void hda_set_power_state(struct hda_codec *codec, hda_nid_t fg,
847 unsigned int power_state);
848
Linus Torvalds1da177e2005-04-16 15:20:36 -0700849/**
850 * snd_hda_codec_new - create a HDA codec
851 * @bus: the bus to assign
852 * @codec_addr: the codec address
853 * @codecp: the pointer to store the generated codec
854 *
855 * Returns 0 if successful, or a negative error code.
856 */
Takashi Iwai1289e9e2008-11-27 15:47:11 +0100857int /*__devinit*/ snd_hda_codec_new(struct hda_bus *bus, unsigned int codec_addr,
Takashi Iwaid4d9cd032008-12-19 15:19:11 +0100858 int do_init, struct hda_codec **codecp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700859{
860 struct hda_codec *codec;
Jaroslav Kyselaba443682008-08-13 20:55:32 +0200861 char component[31];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700862 int err;
863
Takashi Iwaida3cec32008-08-08 17:12:14 +0200864 if (snd_BUG_ON(!bus))
865 return -EINVAL;
866 if (snd_BUG_ON(codec_addr > HDA_MAX_CODEC_ADDRESS))
867 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700868
869 if (bus->caddr_tbl[codec_addr]) {
Takashi Iwai0ba21762007-04-16 11:29:14 +0200870 snd_printk(KERN_ERR "hda_codec: "
871 "address 0x%x is already occupied\n", codec_addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700872 return -EBUSY;
873 }
874
Takashi Iwaie560d8d2005-09-09 14:21:46 +0200875 codec = kzalloc(sizeof(*codec), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700876 if (codec == NULL) {
877 snd_printk(KERN_ERR "can't allocate struct hda_codec\n");
878 return -ENOMEM;
879 }
880
881 codec->bus = bus;
882 codec->addr = codec_addr;
Ingo Molnar62932df2006-01-16 16:34:20 +0100883 mutex_init(&codec->spdif_mutex);
Wu Fengguang5a9e02e2009-01-09 16:45:24 +0800884 mutex_init(&codec->control_mutex);
Takashi Iwai01751f52007-08-10 16:59:39 +0200885 init_hda_cache(&codec->amp_cache, sizeof(struct hda_amp_info));
Takashi Iwaib3ac5632007-08-10 17:03:40 +0200886 init_hda_cache(&codec->cmd_cache, sizeof(struct hda_cache_head));
Takashi Iwaid13bd412008-07-30 15:01:45 +0200887 snd_array_init(&codec->mixers, sizeof(struct snd_kcontrol *), 32);
Takashi Iwai3be14142009-02-20 14:11:16 +0100888 snd_array_init(&codec->init_pins, sizeof(struct hda_pincfg), 16);
Takashi Iwai346ff702009-02-23 09:42:57 +0100889 snd_array_init(&codec->driver_pins, sizeof(struct hda_pincfg), 16);
Takashi Iwai6c1f45e2008-07-30 15:01:45 +0200890 if (codec->bus->modelname) {
891 codec->modelname = kstrdup(codec->bus->modelname, GFP_KERNEL);
892 if (!codec->modelname) {
893 snd_hda_codec_free(codec);
894 return -ENODEV;
895 }
896 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700897
Takashi Iwaicb53c622007-08-10 17:21:45 +0200898#ifdef CONFIG_SND_HDA_POWER_SAVE
899 INIT_DELAYED_WORK(&codec->power_work, hda_power_work);
900 /* snd_hda_codec_new() marks the codec as power-up, and leave it as is.
901 * the caller has to power down appropriatley after initialization
902 * phase.
903 */
904 hda_keep_power_on(codec);
905#endif
906
Linus Torvalds1da177e2005-04-16 15:20:36 -0700907 list_add_tail(&codec->list, &bus->codec_list);
908 bus->caddr_tbl[codec_addr] = codec;
909
Takashi Iwai0ba21762007-04-16 11:29:14 +0200910 codec->vendor_id = snd_hda_param_read(codec, AC_NODE_ROOT,
911 AC_PAR_VENDOR_ID);
Takashi Iwai111d3af2006-02-16 18:17:58 +0100912 if (codec->vendor_id == -1)
913 /* read again, hopefully the access method was corrected
914 * in the last read...
915 */
916 codec->vendor_id = snd_hda_param_read(codec, AC_NODE_ROOT,
917 AC_PAR_VENDOR_ID);
Takashi Iwai0ba21762007-04-16 11:29:14 +0200918 codec->subsystem_id = snd_hda_param_read(codec, AC_NODE_ROOT,
919 AC_PAR_SUBSYSTEM_ID);
920 codec->revision_id = snd_hda_param_read(codec, AC_NODE_ROOT,
921 AC_PAR_REV_ID);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700922
Sasha Khapyorsky673b6832005-08-11 11:00:16 +0200923 setup_fg_nodes(codec);
Takashi Iwai0ba21762007-04-16 11:29:14 +0200924 if (!codec->afg && !codec->mfg) {
Sasha Khapyorsky673b6832005-08-11 11:00:16 +0200925 snd_printdd("hda_codec: no AFG or MFG node found\n");
Takashi Iwai3be14142009-02-20 14:11:16 +0100926 err = -ENODEV;
927 goto error;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700928 }
929
Takashi Iwai3be14142009-02-20 14:11:16 +0100930 err = read_widget_caps(codec, codec->afg ? codec->afg : codec->mfg);
931 if (err < 0) {
Takashi Iwai54d17402005-11-21 16:33:22 +0100932 snd_printk(KERN_ERR "hda_codec: cannot malloc\n");
Takashi Iwai3be14142009-02-20 14:11:16 +0100933 goto error;
Takashi Iwai54d17402005-11-21 16:33:22 +0100934 }
Takashi Iwai3be14142009-02-20 14:11:16 +0100935 err = read_pin_defaults(codec);
936 if (err < 0)
937 goto error;
Takashi Iwai54d17402005-11-21 16:33:22 +0100938
Takashi Iwai0ba21762007-04-16 11:29:14 +0200939 if (!codec->subsystem_id) {
Takashi Iwai86284e42005-10-11 15:05:54 +0200940 hda_nid_t nid = codec->afg ? codec->afg : codec->mfg;
Takashi Iwai0ba21762007-04-16 11:29:14 +0200941 codec->subsystem_id =
942 snd_hda_codec_read(codec, nid, 0,
943 AC_VERB_GET_SUBSYSTEM_ID, 0);
Takashi Iwai86284e42005-10-11 15:05:54 +0200944 }
Takashi Iwaif44ac832008-07-30 15:01:45 +0200945 if (bus->modelname)
946 codec->modelname = kstrdup(bus->modelname, GFP_KERNEL);
Takashi Iwai86284e42005-10-11 15:05:54 +0200947
Takashi Iwaibb6ac722009-03-13 09:02:42 +0100948 /* power-up all before initialization */
949 hda_set_power_state(codec,
950 codec->afg ? codec->afg : codec->mfg,
951 AC_PWRST_D0);
952
Takashi Iwaid4d9cd032008-12-19 15:19:11 +0100953 if (do_init) {
954 err = snd_hda_codec_configure(codec);
Takashi Iwai3be14142009-02-20 14:11:16 +0100955 if (err < 0)
956 goto error;
Takashi Iwai6c1f45e2008-07-30 15:01:45 +0200957 }
958 snd_hda_codec_proc_new(codec);
959
Takashi Iwai6c1f45e2008-07-30 15:01:45 +0200960 snd_hda_create_hwdep(codec);
Takashi Iwai6c1f45e2008-07-30 15:01:45 +0200961
962 sprintf(component, "HDA:%08x,%08x,%08x", codec->vendor_id,
963 codec->subsystem_id, codec->revision_id);
964 snd_component_add(codec->bus->card, component);
965
966 if (codecp)
967 *codecp = codec;
968 return 0;
Takashi Iwai3be14142009-02-20 14:11:16 +0100969
970 error:
971 snd_hda_codec_free(codec);
972 return err;
Takashi Iwai6c1f45e2008-07-30 15:01:45 +0200973}
Takashi Iwaiff7a3262008-11-28 15:17:06 +0100974EXPORT_SYMBOL_HDA(snd_hda_codec_new);
Takashi Iwai6c1f45e2008-07-30 15:01:45 +0200975
976int snd_hda_codec_configure(struct hda_codec *codec)
977{
978 int err;
979
Takashi Iwaid5ad6302007-03-07 15:55:59 +0100980 codec->preset = find_codec_preset(codec);
Takashi Iwaif44ac832008-07-30 15:01:45 +0200981 if (!codec->name) {
982 err = get_codec_name(codec);
983 if (err < 0)
984 return err;
985 }
Takashi Iwai43ea1d42007-04-26 19:12:08 +0200986 /* audio codec should override the mixer name */
Takashi Iwaif44ac832008-07-30 15:01:45 +0200987 if (codec->afg || !*codec->bus->card->mixername)
988 strlcpy(codec->bus->card->mixername, codec->name,
989 sizeof(codec->bus->card->mixername));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700990
Takashi Iwai82467612007-07-27 19:15:54 +0200991 if (is_generic_config(codec)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700992 err = snd_hda_parse_generic_codec(codec);
Takashi Iwai82467612007-07-27 19:15:54 +0200993 goto patched;
994 }
Takashi Iwai82467612007-07-27 19:15:54 +0200995 if (codec->preset && codec->preset->patch) {
996 err = codec->preset->patch(codec);
997 goto patched;
998 }
999
1000 /* call the default parser */
Takashi Iwai82467612007-07-27 19:15:54 +02001001 err = snd_hda_parse_generic_codec(codec);
Takashi Iwai35a1e0c2007-10-19 08:13:40 +02001002 if (err < 0)
1003 printk(KERN_ERR "hda-codec: No codec parser is available\n");
Takashi Iwai82467612007-07-27 19:15:54 +02001004
1005 patched:
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001006 if (!err && codec->patch_ops.unsol_event)
1007 err = init_unsol_queue(codec->bus);
1008 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001009}
1010
1011/**
1012 * snd_hda_codec_setup_stream - set up the codec for streaming
1013 * @codec: the CODEC to set up
1014 * @nid: the NID to set up
1015 * @stream_tag: stream tag to pass, it's between 0x1 and 0xf.
1016 * @channel_id: channel id to pass, zero based.
1017 * @format: stream format.
1018 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02001019void snd_hda_codec_setup_stream(struct hda_codec *codec, hda_nid_t nid,
1020 u32 stream_tag,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001021 int channel_id, int format)
1022{
Takashi Iwai0ba21762007-04-16 11:29:14 +02001023 if (!nid)
Takashi Iwaid21b37e2005-04-20 13:45:55 +02001024 return;
1025
Takashi Iwai0ba21762007-04-16 11:29:14 +02001026 snd_printdd("hda_codec_setup_stream: "
1027 "NID=0x%x, stream=0x%x, channel=%d, format=0x%x\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07001028 nid, stream_tag, channel_id, format);
1029 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CHANNEL_STREAMID,
1030 (stream_tag << 4) | channel_id);
1031 msleep(1);
1032 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_STREAM_FORMAT, format);
1033}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001034EXPORT_SYMBOL_HDA(snd_hda_codec_setup_stream);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001035
Takashi Iwai888afa12008-03-18 09:57:50 +01001036void snd_hda_codec_cleanup_stream(struct hda_codec *codec, hda_nid_t nid)
1037{
1038 if (!nid)
1039 return;
1040
1041 snd_printdd("hda_codec_cleanup_stream: NID=0x%x\n", nid);
1042 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CHANNEL_STREAMID, 0);
1043#if 0 /* keep the format */
1044 msleep(1);
1045 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_STREAM_FORMAT, 0);
1046#endif
1047}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001048EXPORT_SYMBOL_HDA(snd_hda_codec_cleanup_stream);
Takashi Iwai888afa12008-03-18 09:57:50 +01001049
Linus Torvalds1da177e2005-04-16 15:20:36 -07001050/*
1051 * amp access functions
1052 */
1053
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001054/* FIXME: more better hash key? */
1055#define HDA_HASH_KEY(nid,dir,idx) (u32)((nid) + ((idx) << 16) + ((dir) << 24))
Takashi Iwai1327a322009-03-23 13:07:47 +01001056#define HDA_HASH_PINCAP_KEY(nid) (u32)((nid) + (0x02 << 24))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001057#define INFO_AMP_CAPS (1<<0)
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001058#define INFO_AMP_VOL(ch) (1 << (1 + (ch)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001059
1060/* initialize the hash table */
Takashi Iwai1289e9e2008-11-27 15:47:11 +01001061static void /*__devinit*/ init_hda_cache(struct hda_cache_rec *cache,
Takashi Iwai01751f52007-08-10 16:59:39 +02001062 unsigned int record_size)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001063{
Takashi Iwai01751f52007-08-10 16:59:39 +02001064 memset(cache, 0, sizeof(*cache));
1065 memset(cache->hash, 0xff, sizeof(cache->hash));
Takashi Iwai603c4012008-07-30 15:01:44 +02001066 snd_array_init(&cache->buf, record_size, 64);
Takashi Iwai01751f52007-08-10 16:59:39 +02001067}
1068
Takashi Iwai1fcaee62007-08-23 00:01:09 +02001069static void free_hda_cache(struct hda_cache_rec *cache)
Takashi Iwai01751f52007-08-10 16:59:39 +02001070{
Takashi Iwai603c4012008-07-30 15:01:44 +02001071 snd_array_free(&cache->buf);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001072}
1073
1074/* query the hash. allocate an entry if not found. */
Takashi Iwai01751f52007-08-10 16:59:39 +02001075static struct hda_cache_head *get_alloc_hash(struct hda_cache_rec *cache,
1076 u32 key)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001077{
Takashi Iwai01751f52007-08-10 16:59:39 +02001078 u16 idx = key % (u16)ARRAY_SIZE(cache->hash);
1079 u16 cur = cache->hash[idx];
1080 struct hda_cache_head *info;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001081
1082 while (cur != 0xffff) {
Takashi Iwaif43aa022008-11-10 16:24:26 +01001083 info = snd_array_elem(&cache->buf, cur);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001084 if (info->key == key)
1085 return info;
1086 cur = info->next;
1087 }
1088
1089 /* add a new hash entry */
Takashi Iwai603c4012008-07-30 15:01:44 +02001090 info = snd_array_new(&cache->buf);
Takashi Iwaic2174292008-11-07 00:23:30 +01001091 if (!info)
1092 return NULL;
Takashi Iwaif43aa022008-11-10 16:24:26 +01001093 cur = snd_array_index(&cache->buf, info);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001094 info->key = key;
Takashi Iwai01751f52007-08-10 16:59:39 +02001095 info->val = 0;
1096 info->next = cache->hash[idx];
1097 cache->hash[idx] = cur;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001098
1099 return info;
1100}
1101
Takashi Iwai01751f52007-08-10 16:59:39 +02001102/* query and allocate an amp hash entry */
1103static inline struct hda_amp_info *
1104get_alloc_amp_hash(struct hda_codec *codec, u32 key)
1105{
1106 return (struct hda_amp_info *)get_alloc_hash(&codec->amp_cache, key);
1107}
1108
Linus Torvalds1da177e2005-04-16 15:20:36 -07001109/*
1110 * query AMP capabilities for the given widget and direction
1111 */
Matthew Ranostay09a99952008-01-24 11:49:21 +01001112u32 query_amp_caps(struct hda_codec *codec, hda_nid_t nid, int direction)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001113{
Takashi Iwai0ba21762007-04-16 11:29:14 +02001114 struct hda_amp_info *info;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001115
Takashi Iwai0ba21762007-04-16 11:29:14 +02001116 info = get_alloc_amp_hash(codec, HDA_HASH_KEY(nid, direction, 0));
1117 if (!info)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001118 return 0;
Takashi Iwai01751f52007-08-10 16:59:39 +02001119 if (!(info->head.val & INFO_AMP_CAPS)) {
Takashi Iwai0ba21762007-04-16 11:29:14 +02001120 if (!(get_wcaps(codec, nid) & AC_WCAP_AMP_OVRD))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001121 nid = codec->afg;
Takashi Iwai0ba21762007-04-16 11:29:14 +02001122 info->amp_caps = snd_hda_param_read(codec, nid,
1123 direction == HDA_OUTPUT ?
1124 AC_PAR_AMP_OUT_CAP :
1125 AC_PAR_AMP_IN_CAP);
Takashi Iwaib75e53f2007-05-10 16:56:09 +02001126 if (info->amp_caps)
Takashi Iwai01751f52007-08-10 16:59:39 +02001127 info->head.val |= INFO_AMP_CAPS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001128 }
1129 return info->amp_caps;
1130}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001131EXPORT_SYMBOL_HDA(query_amp_caps);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001132
Takashi Iwai897cc182007-05-29 19:01:37 +02001133int snd_hda_override_amp_caps(struct hda_codec *codec, hda_nid_t nid, int dir,
1134 unsigned int caps)
1135{
1136 struct hda_amp_info *info;
1137
1138 info = get_alloc_amp_hash(codec, HDA_HASH_KEY(nid, dir, 0));
1139 if (!info)
1140 return -EINVAL;
1141 info->amp_caps = caps;
Takashi Iwai01751f52007-08-10 16:59:39 +02001142 info->head.val |= INFO_AMP_CAPS;
Takashi Iwai897cc182007-05-29 19:01:37 +02001143 return 0;
1144}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001145EXPORT_SYMBOL_HDA(snd_hda_override_amp_caps);
Takashi Iwai897cc182007-05-29 19:01:37 +02001146
Takashi Iwai1327a322009-03-23 13:07:47 +01001147u32 snd_hda_query_pin_caps(struct hda_codec *codec, hda_nid_t nid)
1148{
1149 struct hda_amp_info *info;
1150
1151 info = get_alloc_amp_hash(codec, HDA_HASH_PINCAP_KEY(nid));
1152 if (!info)
1153 return 0;
1154 if (!info->head.val) {
1155 info->amp_caps = snd_hda_param_read(codec, nid, AC_PAR_PIN_CAP);
1156 info->head.val |= INFO_AMP_CAPS;
1157 }
1158 return info->amp_caps;
1159}
1160EXPORT_SYMBOL_HDA(snd_hda_query_pin_caps);
1161
Linus Torvalds1da177e2005-04-16 15:20:36 -07001162/*
1163 * read the current volume to info
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001164 * if the cache exists, read the cache value.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001165 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02001166static unsigned int get_vol_mute(struct hda_codec *codec,
1167 struct hda_amp_info *info, hda_nid_t nid,
1168 int ch, int direction, int index)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001169{
1170 u32 val, parm;
1171
Takashi Iwai01751f52007-08-10 16:59:39 +02001172 if (info->head.val & INFO_AMP_VOL(ch))
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001173 return info->vol[ch];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001174
1175 parm = ch ? AC_AMP_GET_RIGHT : AC_AMP_GET_LEFT;
1176 parm |= direction == HDA_OUTPUT ? AC_AMP_GET_OUTPUT : AC_AMP_GET_INPUT;
1177 parm |= index;
Takashi Iwai0ba21762007-04-16 11:29:14 +02001178 val = snd_hda_codec_read(codec, nid, 0,
1179 AC_VERB_GET_AMP_GAIN_MUTE, parm);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001180 info->vol[ch] = val & 0xff;
Takashi Iwai01751f52007-08-10 16:59:39 +02001181 info->head.val |= INFO_AMP_VOL(ch);
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001182 return info->vol[ch];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001183}
1184
1185/*
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001186 * write the current volume in info to the h/w and update the cache
Linus Torvalds1da177e2005-04-16 15:20:36 -07001187 */
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001188static void put_vol_mute(struct hda_codec *codec, struct hda_amp_info *info,
Takashi Iwai0ba21762007-04-16 11:29:14 +02001189 hda_nid_t nid, int ch, int direction, int index,
1190 int val)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001191{
1192 u32 parm;
1193
1194 parm = ch ? AC_AMP_SET_RIGHT : AC_AMP_SET_LEFT;
1195 parm |= direction == HDA_OUTPUT ? AC_AMP_SET_OUTPUT : AC_AMP_SET_INPUT;
1196 parm |= index << AC_AMP_SET_INDEX_SHIFT;
1197 parm |= val;
1198 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, parm);
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001199 info->vol[ch] = val;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001200}
1201
1202/*
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001203 * read AMP value. The volume is between 0 to 0x7f, 0x80 = mute bit.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001204 */
Takashi Iwai834be882006-03-01 14:16:17 +01001205int snd_hda_codec_amp_read(struct hda_codec *codec, hda_nid_t nid, int ch,
1206 int direction, int index)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001207{
Takashi Iwai0ba21762007-04-16 11:29:14 +02001208 struct hda_amp_info *info;
1209 info = get_alloc_amp_hash(codec, HDA_HASH_KEY(nid, direction, index));
1210 if (!info)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001211 return 0;
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001212 return get_vol_mute(codec, info, nid, ch, direction, index);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001213}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001214EXPORT_SYMBOL_HDA(snd_hda_codec_amp_read);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001215
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001216/*
1217 * update the AMP value, mask = bit mask to set, val = the value
1218 */
Takashi Iwai834be882006-03-01 14:16:17 +01001219int snd_hda_codec_amp_update(struct hda_codec *codec, hda_nid_t nid, int ch,
1220 int direction, int idx, int mask, int val)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001221{
Takashi Iwai0ba21762007-04-16 11:29:14 +02001222 struct hda_amp_info *info;
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001223
Takashi Iwai0ba21762007-04-16 11:29:14 +02001224 info = get_alloc_amp_hash(codec, HDA_HASH_KEY(nid, direction, idx));
1225 if (!info)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001226 return 0;
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001227 val &= mask;
1228 val |= get_vol_mute(codec, info, nid, ch, direction, idx) & ~mask;
Takashi Iwai82beb8f2007-08-10 17:09:26 +02001229 if (info->vol[ch] == val)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001230 return 0;
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001231 put_vol_mute(codec, info, nid, ch, direction, idx, val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001232 return 1;
1233}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001234EXPORT_SYMBOL_HDA(snd_hda_codec_amp_update);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001235
Takashi Iwai47fd8302007-08-10 17:11:07 +02001236/*
1237 * update the AMP stereo with the same mask and value
1238 */
1239int snd_hda_codec_amp_stereo(struct hda_codec *codec, hda_nid_t nid,
1240 int direction, int idx, int mask, int val)
1241{
1242 int ch, ret = 0;
1243 for (ch = 0; ch < 2; ch++)
1244 ret |= snd_hda_codec_amp_update(codec, nid, ch, direction,
1245 idx, mask, val);
1246 return ret;
1247}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001248EXPORT_SYMBOL_HDA(snd_hda_codec_amp_stereo);
Takashi Iwai47fd8302007-08-10 17:11:07 +02001249
Takashi Iwaicb53c622007-08-10 17:21:45 +02001250#ifdef SND_HDA_NEEDS_RESUME
Takashi Iwaib3ac5632007-08-10 17:03:40 +02001251/* resume the all amp commands from the cache */
1252void snd_hda_codec_resume_amp(struct hda_codec *codec)
1253{
Takashi Iwai603c4012008-07-30 15:01:44 +02001254 struct hda_amp_info *buffer = codec->amp_cache.buf.list;
Takashi Iwaib3ac5632007-08-10 17:03:40 +02001255 int i;
1256
Takashi Iwai603c4012008-07-30 15:01:44 +02001257 for (i = 0; i < codec->amp_cache.buf.used; i++, buffer++) {
Takashi Iwaib3ac5632007-08-10 17:03:40 +02001258 u32 key = buffer->head.key;
1259 hda_nid_t nid;
1260 unsigned int idx, dir, ch;
1261 if (!key)
1262 continue;
1263 nid = key & 0xff;
1264 idx = (key >> 16) & 0xff;
1265 dir = (key >> 24) & 0xff;
1266 for (ch = 0; ch < 2; ch++) {
1267 if (!(buffer->head.val & INFO_AMP_VOL(ch)))
1268 continue;
1269 put_vol_mute(codec, buffer, nid, ch, dir, idx,
1270 buffer->vol[ch]);
1271 }
1272 }
1273}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001274EXPORT_SYMBOL_HDA(snd_hda_codec_resume_amp);
Takashi Iwaicb53c622007-08-10 17:21:45 +02001275#endif /* SND_HDA_NEEDS_RESUME */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001276
Linus Torvalds1da177e2005-04-16 15:20:36 -07001277/* volume */
Takashi Iwai0ba21762007-04-16 11:29:14 +02001278int snd_hda_mixer_amp_volume_info(struct snd_kcontrol *kcontrol,
1279 struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001280{
1281 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1282 u16 nid = get_amp_nid(kcontrol);
1283 u8 chs = get_amp_channels(kcontrol);
1284 int dir = get_amp_direction(kcontrol);
Takashi Iwai29fdbec2009-01-20 13:07:55 +01001285 unsigned int ofs = get_amp_offset(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001286 u32 caps;
1287
1288 caps = query_amp_caps(codec, nid, dir);
Takashi Iwai0ba21762007-04-16 11:29:14 +02001289 /* num steps */
1290 caps = (caps & AC_AMPCAP_NUM_STEPS) >> AC_AMPCAP_NUM_STEPS_SHIFT;
1291 if (!caps) {
1292 printk(KERN_WARNING "hda_codec: "
Takashi Iwai9c8f2ab2008-01-11 16:12:23 +01001293 "num_steps = 0 for NID=0x%x (ctl = %s)\n", nid,
1294 kcontrol->id.name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001295 return -EINVAL;
1296 }
Takashi Iwai29fdbec2009-01-20 13:07:55 +01001297 if (ofs < caps)
1298 caps -= ofs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001299 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
1300 uinfo->count = chs == 3 ? 2 : 1;
1301 uinfo->value.integer.min = 0;
1302 uinfo->value.integer.max = caps;
1303 return 0;
1304}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001305EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_volume_info);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001306
Takashi Iwai29fdbec2009-01-20 13:07:55 +01001307
1308static inline unsigned int
1309read_amp_value(struct hda_codec *codec, hda_nid_t nid,
1310 int ch, int dir, int idx, unsigned int ofs)
1311{
1312 unsigned int val;
1313 val = snd_hda_codec_amp_read(codec, nid, ch, dir, idx);
1314 val &= HDA_AMP_VOLMASK;
1315 if (val >= ofs)
1316 val -= ofs;
1317 else
1318 val = 0;
1319 return val;
1320}
1321
1322static inline int
1323update_amp_value(struct hda_codec *codec, hda_nid_t nid,
1324 int ch, int dir, int idx, unsigned int ofs,
1325 unsigned int val)
1326{
1327 if (val > 0)
1328 val += ofs;
1329 return snd_hda_codec_amp_update(codec, nid, ch, dir, idx,
1330 HDA_AMP_VOLMASK, val);
1331}
1332
Takashi Iwai0ba21762007-04-16 11:29:14 +02001333int snd_hda_mixer_amp_volume_get(struct snd_kcontrol *kcontrol,
1334 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001335{
1336 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1337 hda_nid_t nid = get_amp_nid(kcontrol);
1338 int chs = get_amp_channels(kcontrol);
1339 int dir = get_amp_direction(kcontrol);
1340 int idx = get_amp_index(kcontrol);
Takashi Iwai29fdbec2009-01-20 13:07:55 +01001341 unsigned int ofs = get_amp_offset(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001342 long *valp = ucontrol->value.integer.value;
1343
1344 if (chs & 1)
Takashi Iwai29fdbec2009-01-20 13:07:55 +01001345 *valp++ = read_amp_value(codec, nid, 0, dir, idx, ofs);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001346 if (chs & 2)
Takashi Iwai29fdbec2009-01-20 13:07:55 +01001347 *valp = read_amp_value(codec, nid, 1, dir, idx, ofs);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001348 return 0;
1349}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001350EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_volume_get);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001351
Takashi Iwai0ba21762007-04-16 11:29:14 +02001352int snd_hda_mixer_amp_volume_put(struct snd_kcontrol *kcontrol,
1353 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001354{
1355 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1356 hda_nid_t nid = get_amp_nid(kcontrol);
1357 int chs = get_amp_channels(kcontrol);
1358 int dir = get_amp_direction(kcontrol);
1359 int idx = get_amp_index(kcontrol);
Takashi Iwai29fdbec2009-01-20 13:07:55 +01001360 unsigned int ofs = get_amp_offset(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001361 long *valp = ucontrol->value.integer.value;
1362 int change = 0;
1363
Takashi Iwaicb53c622007-08-10 17:21:45 +02001364 snd_hda_power_up(codec);
Nicolas Grazianob9f5a892005-07-29 12:17:20 +02001365 if (chs & 1) {
Takashi Iwai29fdbec2009-01-20 13:07:55 +01001366 change = update_amp_value(codec, nid, 0, dir, idx, ofs, *valp);
Nicolas Grazianob9f5a892005-07-29 12:17:20 +02001367 valp++;
1368 }
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001369 if (chs & 2)
Takashi Iwai29fdbec2009-01-20 13:07:55 +01001370 change |= update_amp_value(codec, nid, 1, dir, idx, ofs, *valp);
Takashi Iwaicb53c622007-08-10 17:21:45 +02001371 snd_hda_power_down(codec);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001372 return change;
1373}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001374EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_volume_put);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001375
Jaroslav Kysela302e9c52006-07-05 17:39:49 +02001376int snd_hda_mixer_amp_tlv(struct snd_kcontrol *kcontrol, int op_flag,
1377 unsigned int size, unsigned int __user *_tlv)
1378{
1379 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1380 hda_nid_t nid = get_amp_nid(kcontrol);
1381 int dir = get_amp_direction(kcontrol);
Takashi Iwai29fdbec2009-01-20 13:07:55 +01001382 unsigned int ofs = get_amp_offset(kcontrol);
Jaroslav Kysela302e9c52006-07-05 17:39:49 +02001383 u32 caps, val1, val2;
1384
1385 if (size < 4 * sizeof(unsigned int))
1386 return -ENOMEM;
1387 caps = query_amp_caps(codec, nid, dir);
Takashi Iwai0ba21762007-04-16 11:29:14 +02001388 val2 = (caps & AC_AMPCAP_STEP_SIZE) >> AC_AMPCAP_STEP_SIZE_SHIFT;
1389 val2 = (val2 + 1) * 25;
Jaroslav Kysela302e9c52006-07-05 17:39:49 +02001390 val1 = -((caps & AC_AMPCAP_OFFSET) >> AC_AMPCAP_OFFSET_SHIFT);
Takashi Iwai29fdbec2009-01-20 13:07:55 +01001391 val1 += ofs;
Jaroslav Kysela302e9c52006-07-05 17:39:49 +02001392 val1 = ((int)val1) * ((int)val2);
Jaroslav Kysela302e9c52006-07-05 17:39:49 +02001393 if (put_user(SNDRV_CTL_TLVT_DB_SCALE, _tlv))
1394 return -EFAULT;
1395 if (put_user(2 * sizeof(unsigned int), _tlv + 1))
1396 return -EFAULT;
1397 if (put_user(val1, _tlv + 2))
1398 return -EFAULT;
1399 if (put_user(val2, _tlv + 3))
1400 return -EFAULT;
1401 return 0;
1402}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001403EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_tlv);
Jaroslav Kysela302e9c52006-07-05 17:39:49 +02001404
Takashi Iwai2134ea42008-01-10 16:53:55 +01001405/*
1406 * set (static) TLV for virtual master volume; recalculated as max 0dB
1407 */
1408void snd_hda_set_vmaster_tlv(struct hda_codec *codec, hda_nid_t nid, int dir,
1409 unsigned int *tlv)
1410{
1411 u32 caps;
1412 int nums, step;
1413
1414 caps = query_amp_caps(codec, nid, dir);
1415 nums = (caps & AC_AMPCAP_NUM_STEPS) >> AC_AMPCAP_NUM_STEPS_SHIFT;
1416 step = (caps & AC_AMPCAP_STEP_SIZE) >> AC_AMPCAP_STEP_SIZE_SHIFT;
1417 step = (step + 1) * 25;
1418 tlv[0] = SNDRV_CTL_TLVT_DB_SCALE;
1419 tlv[1] = 2 * sizeof(unsigned int);
1420 tlv[2] = -nums * step;
1421 tlv[3] = step;
1422}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001423EXPORT_SYMBOL_HDA(snd_hda_set_vmaster_tlv);
Takashi Iwai2134ea42008-01-10 16:53:55 +01001424
1425/* find a mixer control element with the given name */
Takashi Iwai09f99702008-02-04 12:31:13 +01001426static struct snd_kcontrol *
1427_snd_hda_find_mixer_ctl(struct hda_codec *codec,
1428 const char *name, int idx)
Takashi Iwai2134ea42008-01-10 16:53:55 +01001429{
1430 struct snd_ctl_elem_id id;
1431 memset(&id, 0, sizeof(id));
1432 id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
Takashi Iwai09f99702008-02-04 12:31:13 +01001433 id.index = idx;
Takashi Iwai2134ea42008-01-10 16:53:55 +01001434 strcpy(id.name, name);
1435 return snd_ctl_find_id(codec->bus->card, &id);
1436}
1437
Takashi Iwai09f99702008-02-04 12:31:13 +01001438struct snd_kcontrol *snd_hda_find_mixer_ctl(struct hda_codec *codec,
1439 const char *name)
1440{
1441 return _snd_hda_find_mixer_ctl(codec, name, 0);
1442}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001443EXPORT_SYMBOL_HDA(snd_hda_find_mixer_ctl);
Takashi Iwai09f99702008-02-04 12:31:13 +01001444
Takashi Iwaid13bd412008-07-30 15:01:45 +02001445/* Add a control element and assign to the codec */
1446int snd_hda_ctl_add(struct hda_codec *codec, struct snd_kcontrol *kctl)
1447{
1448 int err;
1449 struct snd_kcontrol **knewp;
1450
1451 err = snd_ctl_add(codec->bus->card, kctl);
1452 if (err < 0)
1453 return err;
1454 knewp = snd_array_new(&codec->mixers);
1455 if (!knewp)
1456 return -ENOMEM;
1457 *knewp = kctl;
1458 return 0;
1459}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001460EXPORT_SYMBOL_HDA(snd_hda_ctl_add);
Takashi Iwaid13bd412008-07-30 15:01:45 +02001461
1462/* Clear all controls assigned to the given codec */
1463void snd_hda_ctls_clear(struct hda_codec *codec)
1464{
1465 int i;
1466 struct snd_kcontrol **kctls = codec->mixers.list;
1467 for (i = 0; i < codec->mixers.used; i++)
1468 snd_ctl_remove(codec->bus->card, kctls[i]);
1469 snd_array_free(&codec->mixers);
1470}
1471
Takashi Iwaia65d6292009-02-23 16:57:04 +01001472/* pseudo device locking
1473 * toggle card->shutdown to allow/disallow the device access (as a hack)
1474 */
1475static int hda_lock_devices(struct snd_card *card)
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001476{
Takashi Iwaia65d6292009-02-23 16:57:04 +01001477 spin_lock(&card->files_lock);
1478 if (card->shutdown) {
1479 spin_unlock(&card->files_lock);
1480 return -EINVAL;
1481 }
1482 card->shutdown = 1;
1483 spin_unlock(&card->files_lock);
1484 return 0;
1485}
1486
1487static void hda_unlock_devices(struct snd_card *card)
1488{
1489 spin_lock(&card->files_lock);
1490 card->shutdown = 0;
1491 spin_unlock(&card->files_lock);
1492}
1493
1494int snd_hda_codec_reset(struct hda_codec *codec)
1495{
1496 struct snd_card *card = codec->bus->card;
1497 int i, pcm;
1498
1499 if (hda_lock_devices(card) < 0)
1500 return -EBUSY;
1501 /* check whether the codec isn't used by any mixer or PCM streams */
1502 if (!list_empty(&card->ctl_files)) {
1503 hda_unlock_devices(card);
1504 return -EBUSY;
1505 }
1506 for (pcm = 0; pcm < codec->num_pcms; pcm++) {
1507 struct hda_pcm *cpcm = &codec->pcm_info[pcm];
1508 if (!cpcm->pcm)
1509 continue;
1510 if (cpcm->pcm->streams[0].substream_opened ||
1511 cpcm->pcm->streams[1].substream_opened) {
1512 hda_unlock_devices(card);
1513 return -EBUSY;
1514 }
1515 }
1516
1517 /* OK, let it free */
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001518
1519#ifdef CONFIG_SND_HDA_POWER_SAVE
1520 cancel_delayed_work(&codec->power_work);
Takashi Iwai6acaed32009-01-12 10:09:24 +01001521 flush_workqueue(codec->bus->workq);
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001522#endif
1523 snd_hda_ctls_clear(codec);
1524 /* relase PCMs */
1525 for (i = 0; i < codec->num_pcms; i++) {
Takashi Iwai529bd6c2008-11-27 14:17:01 +01001526 if (codec->pcm_info[i].pcm) {
Takashi Iwaia65d6292009-02-23 16:57:04 +01001527 snd_device_free(card, codec->pcm_info[i].pcm);
Takashi Iwai529bd6c2008-11-27 14:17:01 +01001528 clear_bit(codec->pcm_info[i].device,
1529 codec->bus->pcm_dev_bits);
1530 }
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001531 }
1532 if (codec->patch_ops.free)
1533 codec->patch_ops.free(codec);
Takashi Iwai56d17712008-11-28 14:36:23 +01001534 codec->proc_widget_hook = NULL;
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001535 codec->spec = NULL;
1536 free_hda_cache(&codec->amp_cache);
1537 free_hda_cache(&codec->cmd_cache);
Takashi Iwai827057f2008-12-19 10:12:02 +01001538 init_hda_cache(&codec->amp_cache, sizeof(struct hda_amp_info));
1539 init_hda_cache(&codec->cmd_cache, sizeof(struct hda_cache_head));
Takashi Iwai346ff702009-02-23 09:42:57 +01001540 /* free only driver_pins so that init_pins + user_pins are restored */
1541 snd_array_free(&codec->driver_pins);
Takashi Iwai3be14142009-02-20 14:11:16 +01001542 restore_pincfgs(codec);
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001543 codec->num_pcms = 0;
1544 codec->pcm_info = NULL;
1545 codec->preset = NULL;
Takashi Iwaid1f1af22009-03-02 10:35:29 +01001546 memset(&codec->patch_ops, 0, sizeof(codec->patch_ops));
1547 codec->slave_dig_outs = NULL;
1548 codec->spdif_status_reset = 0;
Takashi Iwai1289e9e2008-11-27 15:47:11 +01001549 module_put(codec->owner);
1550 codec->owner = NULL;
Takashi Iwaia65d6292009-02-23 16:57:04 +01001551
1552 /* allow device access again */
1553 hda_unlock_devices(card);
1554 return 0;
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001555}
1556
Takashi Iwai2134ea42008-01-10 16:53:55 +01001557/* create a virtual master control and add slaves */
1558int snd_hda_add_vmaster(struct hda_codec *codec, char *name,
1559 unsigned int *tlv, const char **slaves)
1560{
1561 struct snd_kcontrol *kctl;
1562 const char **s;
1563 int err;
1564
Takashi Iwai2f085542008-02-22 18:43:50 +01001565 for (s = slaves; *s && !snd_hda_find_mixer_ctl(codec, *s); s++)
1566 ;
1567 if (!*s) {
1568 snd_printdd("No slave found for %s\n", name);
1569 return 0;
1570 }
Takashi Iwai2134ea42008-01-10 16:53:55 +01001571 kctl = snd_ctl_make_virtual_master(name, tlv);
1572 if (!kctl)
1573 return -ENOMEM;
Takashi Iwaid13bd412008-07-30 15:01:45 +02001574 err = snd_hda_ctl_add(codec, kctl);
Takashi Iwai2134ea42008-01-10 16:53:55 +01001575 if (err < 0)
1576 return err;
1577
1578 for (s = slaves; *s; s++) {
1579 struct snd_kcontrol *sctl;
Takashi Iwai7a411ee2009-03-06 10:08:14 +01001580 int i = 0;
1581 for (;;) {
1582 sctl = _snd_hda_find_mixer_ctl(codec, *s, i);
1583 if (!sctl) {
1584 if (!i)
1585 snd_printdd("Cannot find slave %s, "
1586 "skipped\n", *s);
1587 break;
1588 }
1589 err = snd_ctl_add_slave(kctl, sctl);
1590 if (err < 0)
1591 return err;
1592 i++;
Takashi Iwai2134ea42008-01-10 16:53:55 +01001593 }
Takashi Iwai2134ea42008-01-10 16:53:55 +01001594 }
1595 return 0;
1596}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001597EXPORT_SYMBOL_HDA(snd_hda_add_vmaster);
Takashi Iwai2134ea42008-01-10 16:53:55 +01001598
Linus Torvalds1da177e2005-04-16 15:20:36 -07001599/* switch */
Takashi Iwai0ba21762007-04-16 11:29:14 +02001600int snd_hda_mixer_amp_switch_info(struct snd_kcontrol *kcontrol,
1601 struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001602{
1603 int chs = get_amp_channels(kcontrol);
1604
1605 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
1606 uinfo->count = chs == 3 ? 2 : 1;
1607 uinfo->value.integer.min = 0;
1608 uinfo->value.integer.max = 1;
1609 return 0;
1610}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001611EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_switch_info);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001612
Takashi Iwai0ba21762007-04-16 11:29:14 +02001613int snd_hda_mixer_amp_switch_get(struct snd_kcontrol *kcontrol,
1614 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001615{
1616 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1617 hda_nid_t nid = get_amp_nid(kcontrol);
1618 int chs = get_amp_channels(kcontrol);
1619 int dir = get_amp_direction(kcontrol);
1620 int idx = get_amp_index(kcontrol);
1621 long *valp = ucontrol->value.integer.value;
1622
1623 if (chs & 1)
Takashi Iwai0ba21762007-04-16 11:29:14 +02001624 *valp++ = (snd_hda_codec_amp_read(codec, nid, 0, dir, idx) &
Takashi Iwai47fd8302007-08-10 17:11:07 +02001625 HDA_AMP_MUTE) ? 0 : 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001626 if (chs & 2)
Takashi Iwai0ba21762007-04-16 11:29:14 +02001627 *valp = (snd_hda_codec_amp_read(codec, nid, 1, dir, idx) &
Takashi Iwai47fd8302007-08-10 17:11:07 +02001628 HDA_AMP_MUTE) ? 0 : 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001629 return 0;
1630}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001631EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_switch_get);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001632
Takashi Iwai0ba21762007-04-16 11:29:14 +02001633int snd_hda_mixer_amp_switch_put(struct snd_kcontrol *kcontrol,
1634 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001635{
1636 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1637 hda_nid_t nid = get_amp_nid(kcontrol);
1638 int chs = get_amp_channels(kcontrol);
1639 int dir = get_amp_direction(kcontrol);
1640 int idx = get_amp_index(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001641 long *valp = ucontrol->value.integer.value;
1642 int change = 0;
1643
Takashi Iwaicb53c622007-08-10 17:21:45 +02001644 snd_hda_power_up(codec);
Nicolas Grazianob9f5a892005-07-29 12:17:20 +02001645 if (chs & 1) {
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001646 change = snd_hda_codec_amp_update(codec, nid, 0, dir, idx,
Takashi Iwai47fd8302007-08-10 17:11:07 +02001647 HDA_AMP_MUTE,
1648 *valp ? 0 : HDA_AMP_MUTE);
Nicolas Grazianob9f5a892005-07-29 12:17:20 +02001649 valp++;
1650 }
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001651 if (chs & 2)
1652 change |= snd_hda_codec_amp_update(codec, nid, 1, dir, idx,
Takashi Iwai47fd8302007-08-10 17:11:07 +02001653 HDA_AMP_MUTE,
1654 *valp ? 0 : HDA_AMP_MUTE);
Takashi Iwaicb53c622007-08-10 17:21:45 +02001655#ifdef CONFIG_SND_HDA_POWER_SAVE
1656 if (codec->patch_ops.check_power_status)
1657 codec->patch_ops.check_power_status(codec, nid);
1658#endif
1659 snd_hda_power_down(codec);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001660 return change;
1661}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001662EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_switch_put);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001663
1664/*
Takashi Iwai985be542005-11-02 18:26:49 +01001665 * bound volume controls
1666 *
1667 * bind multiple volumes (# indices, from 0)
1668 */
1669
1670#define AMP_VAL_IDX_SHIFT 19
1671#define AMP_VAL_IDX_MASK (0x0f<<19)
1672
Takashi Iwai0ba21762007-04-16 11:29:14 +02001673int snd_hda_mixer_bind_switch_get(struct snd_kcontrol *kcontrol,
1674 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai985be542005-11-02 18:26:49 +01001675{
1676 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1677 unsigned long pval;
1678 int err;
1679
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001680 mutex_lock(&codec->control_mutex);
Takashi Iwai985be542005-11-02 18:26:49 +01001681 pval = kcontrol->private_value;
1682 kcontrol->private_value = pval & ~AMP_VAL_IDX_MASK; /* index 0 */
1683 err = snd_hda_mixer_amp_switch_get(kcontrol, ucontrol);
1684 kcontrol->private_value = pval;
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001685 mutex_unlock(&codec->control_mutex);
Takashi Iwai985be542005-11-02 18:26:49 +01001686 return err;
1687}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001688EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_switch_get);
Takashi Iwai985be542005-11-02 18:26:49 +01001689
Takashi Iwai0ba21762007-04-16 11:29:14 +02001690int snd_hda_mixer_bind_switch_put(struct snd_kcontrol *kcontrol,
1691 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai985be542005-11-02 18:26:49 +01001692{
1693 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1694 unsigned long pval;
1695 int i, indices, err = 0, change = 0;
1696
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001697 mutex_lock(&codec->control_mutex);
Takashi Iwai985be542005-11-02 18:26:49 +01001698 pval = kcontrol->private_value;
1699 indices = (pval & AMP_VAL_IDX_MASK) >> AMP_VAL_IDX_SHIFT;
1700 for (i = 0; i < indices; i++) {
Takashi Iwai0ba21762007-04-16 11:29:14 +02001701 kcontrol->private_value = (pval & ~AMP_VAL_IDX_MASK) |
1702 (i << AMP_VAL_IDX_SHIFT);
Takashi Iwai985be542005-11-02 18:26:49 +01001703 err = snd_hda_mixer_amp_switch_put(kcontrol, ucontrol);
1704 if (err < 0)
1705 break;
1706 change |= err;
1707 }
1708 kcontrol->private_value = pval;
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001709 mutex_unlock(&codec->control_mutex);
Takashi Iwai985be542005-11-02 18:26:49 +01001710 return err < 0 ? err : change;
1711}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001712EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_switch_put);
Takashi Iwai985be542005-11-02 18:26:49 +01001713
1714/*
Takashi Iwai532d5382007-07-27 19:02:40 +02001715 * generic bound volume/swtich controls
1716 */
1717int snd_hda_mixer_bind_ctls_info(struct snd_kcontrol *kcontrol,
1718 struct snd_ctl_elem_info *uinfo)
1719{
1720 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1721 struct hda_bind_ctls *c;
1722 int err;
1723
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001724 mutex_lock(&codec->control_mutex);
Serge A. Suchkov14c65f92008-02-22 18:43:16 +01001725 c = (struct hda_bind_ctls *)kcontrol->private_value;
Takashi Iwai532d5382007-07-27 19:02:40 +02001726 kcontrol->private_value = *c->values;
1727 err = c->ops->info(kcontrol, uinfo);
1728 kcontrol->private_value = (long)c;
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001729 mutex_unlock(&codec->control_mutex);
Takashi Iwai532d5382007-07-27 19:02:40 +02001730 return err;
1731}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001732EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_ctls_info);
Takashi Iwai532d5382007-07-27 19:02:40 +02001733
1734int snd_hda_mixer_bind_ctls_get(struct snd_kcontrol *kcontrol,
1735 struct snd_ctl_elem_value *ucontrol)
1736{
1737 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1738 struct hda_bind_ctls *c;
1739 int err;
1740
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001741 mutex_lock(&codec->control_mutex);
Serge A. Suchkov14c65f92008-02-22 18:43:16 +01001742 c = (struct hda_bind_ctls *)kcontrol->private_value;
Takashi Iwai532d5382007-07-27 19:02:40 +02001743 kcontrol->private_value = *c->values;
1744 err = c->ops->get(kcontrol, ucontrol);
1745 kcontrol->private_value = (long)c;
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001746 mutex_unlock(&codec->control_mutex);
Takashi Iwai532d5382007-07-27 19:02:40 +02001747 return err;
1748}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001749EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_ctls_get);
Takashi Iwai532d5382007-07-27 19:02:40 +02001750
1751int snd_hda_mixer_bind_ctls_put(struct snd_kcontrol *kcontrol,
1752 struct snd_ctl_elem_value *ucontrol)
1753{
1754 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1755 struct hda_bind_ctls *c;
1756 unsigned long *vals;
1757 int err = 0, change = 0;
1758
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001759 mutex_lock(&codec->control_mutex);
Serge A. Suchkov14c65f92008-02-22 18:43:16 +01001760 c = (struct hda_bind_ctls *)kcontrol->private_value;
Takashi Iwai532d5382007-07-27 19:02:40 +02001761 for (vals = c->values; *vals; vals++) {
1762 kcontrol->private_value = *vals;
1763 err = c->ops->put(kcontrol, ucontrol);
1764 if (err < 0)
1765 break;
1766 change |= err;
1767 }
1768 kcontrol->private_value = (long)c;
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001769 mutex_unlock(&codec->control_mutex);
Takashi Iwai532d5382007-07-27 19:02:40 +02001770 return err < 0 ? err : change;
1771}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001772EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_ctls_put);
Takashi Iwai532d5382007-07-27 19:02:40 +02001773
1774int snd_hda_mixer_bind_tlv(struct snd_kcontrol *kcontrol, int op_flag,
1775 unsigned int size, unsigned int __user *tlv)
1776{
1777 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1778 struct hda_bind_ctls *c;
1779 int err;
1780
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001781 mutex_lock(&codec->control_mutex);
Serge A. Suchkov14c65f92008-02-22 18:43:16 +01001782 c = (struct hda_bind_ctls *)kcontrol->private_value;
Takashi Iwai532d5382007-07-27 19:02:40 +02001783 kcontrol->private_value = *c->values;
1784 err = c->ops->tlv(kcontrol, op_flag, size, tlv);
1785 kcontrol->private_value = (long)c;
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001786 mutex_unlock(&codec->control_mutex);
Takashi Iwai532d5382007-07-27 19:02:40 +02001787 return err;
1788}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001789EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_tlv);
Takashi Iwai532d5382007-07-27 19:02:40 +02001790
1791struct hda_ctl_ops snd_hda_bind_vol = {
1792 .info = snd_hda_mixer_amp_volume_info,
1793 .get = snd_hda_mixer_amp_volume_get,
1794 .put = snd_hda_mixer_amp_volume_put,
1795 .tlv = snd_hda_mixer_amp_tlv
1796};
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001797EXPORT_SYMBOL_HDA(snd_hda_bind_vol);
Takashi Iwai532d5382007-07-27 19:02:40 +02001798
1799struct hda_ctl_ops snd_hda_bind_sw = {
1800 .info = snd_hda_mixer_amp_switch_info,
1801 .get = snd_hda_mixer_amp_switch_get,
1802 .put = snd_hda_mixer_amp_switch_put,
1803 .tlv = snd_hda_mixer_amp_tlv
1804};
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001805EXPORT_SYMBOL_HDA(snd_hda_bind_sw);
Takashi Iwai532d5382007-07-27 19:02:40 +02001806
1807/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07001808 * SPDIF out controls
1809 */
1810
Takashi Iwai0ba21762007-04-16 11:29:14 +02001811static int snd_hda_spdif_mask_info(struct snd_kcontrol *kcontrol,
1812 struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001813{
1814 uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
1815 uinfo->count = 1;
1816 return 0;
1817}
1818
Takashi Iwai0ba21762007-04-16 11:29:14 +02001819static int snd_hda_spdif_cmask_get(struct snd_kcontrol *kcontrol,
1820 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001821{
1822 ucontrol->value.iec958.status[0] = IEC958_AES0_PROFESSIONAL |
1823 IEC958_AES0_NONAUDIO |
1824 IEC958_AES0_CON_EMPHASIS_5015 |
1825 IEC958_AES0_CON_NOT_COPYRIGHT;
1826 ucontrol->value.iec958.status[1] = IEC958_AES1_CON_CATEGORY |
1827 IEC958_AES1_CON_ORIGINAL;
1828 return 0;
1829}
1830
Takashi Iwai0ba21762007-04-16 11:29:14 +02001831static int snd_hda_spdif_pmask_get(struct snd_kcontrol *kcontrol,
1832 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001833{
1834 ucontrol->value.iec958.status[0] = IEC958_AES0_PROFESSIONAL |
1835 IEC958_AES0_NONAUDIO |
1836 IEC958_AES0_PRO_EMPHASIS_5015;
1837 return 0;
1838}
1839
Takashi Iwai0ba21762007-04-16 11:29:14 +02001840static int snd_hda_spdif_default_get(struct snd_kcontrol *kcontrol,
1841 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001842{
1843 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1844
1845 ucontrol->value.iec958.status[0] = codec->spdif_status & 0xff;
1846 ucontrol->value.iec958.status[1] = (codec->spdif_status >> 8) & 0xff;
1847 ucontrol->value.iec958.status[2] = (codec->spdif_status >> 16) & 0xff;
1848 ucontrol->value.iec958.status[3] = (codec->spdif_status >> 24) & 0xff;
1849
1850 return 0;
1851}
1852
1853/* convert from SPDIF status bits to HDA SPDIF bits
1854 * bit 0 (DigEn) is always set zero (to be filled later)
1855 */
1856static unsigned short convert_from_spdif_status(unsigned int sbits)
1857{
1858 unsigned short val = 0;
1859
1860 if (sbits & IEC958_AES0_PROFESSIONAL)
Takashi Iwai0ba21762007-04-16 11:29:14 +02001861 val |= AC_DIG1_PROFESSIONAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001862 if (sbits & IEC958_AES0_NONAUDIO)
Takashi Iwai0ba21762007-04-16 11:29:14 +02001863 val |= AC_DIG1_NONAUDIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001864 if (sbits & IEC958_AES0_PROFESSIONAL) {
Takashi Iwai0ba21762007-04-16 11:29:14 +02001865 if ((sbits & IEC958_AES0_PRO_EMPHASIS) ==
1866 IEC958_AES0_PRO_EMPHASIS_5015)
1867 val |= AC_DIG1_EMPHASIS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001868 } else {
Takashi Iwai0ba21762007-04-16 11:29:14 +02001869 if ((sbits & IEC958_AES0_CON_EMPHASIS) ==
1870 IEC958_AES0_CON_EMPHASIS_5015)
1871 val |= AC_DIG1_EMPHASIS;
1872 if (!(sbits & IEC958_AES0_CON_NOT_COPYRIGHT))
1873 val |= AC_DIG1_COPYRIGHT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001874 if (sbits & (IEC958_AES1_CON_ORIGINAL << 8))
Takashi Iwai0ba21762007-04-16 11:29:14 +02001875 val |= AC_DIG1_LEVEL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001876 val |= sbits & (IEC958_AES1_CON_CATEGORY << 8);
1877 }
1878 return val;
1879}
1880
1881/* convert to SPDIF status bits from HDA SPDIF bits
1882 */
1883static unsigned int convert_to_spdif_status(unsigned short val)
1884{
1885 unsigned int sbits = 0;
1886
Takashi Iwai0ba21762007-04-16 11:29:14 +02001887 if (val & AC_DIG1_NONAUDIO)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001888 sbits |= IEC958_AES0_NONAUDIO;
Takashi Iwai0ba21762007-04-16 11:29:14 +02001889 if (val & AC_DIG1_PROFESSIONAL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001890 sbits |= IEC958_AES0_PROFESSIONAL;
1891 if (sbits & IEC958_AES0_PROFESSIONAL) {
Takashi Iwai0ba21762007-04-16 11:29:14 +02001892 if (sbits & AC_DIG1_EMPHASIS)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001893 sbits |= IEC958_AES0_PRO_EMPHASIS_5015;
1894 } else {
Takashi Iwai0ba21762007-04-16 11:29:14 +02001895 if (val & AC_DIG1_EMPHASIS)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001896 sbits |= IEC958_AES0_CON_EMPHASIS_5015;
Takashi Iwai0ba21762007-04-16 11:29:14 +02001897 if (!(val & AC_DIG1_COPYRIGHT))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001898 sbits |= IEC958_AES0_CON_NOT_COPYRIGHT;
Takashi Iwai0ba21762007-04-16 11:29:14 +02001899 if (val & AC_DIG1_LEVEL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001900 sbits |= (IEC958_AES1_CON_ORIGINAL << 8);
1901 sbits |= val & (0x7f << 8);
1902 }
1903 return sbits;
1904}
1905
Takashi Iwai2f728532008-09-25 16:32:41 +02001906/* set digital convert verbs both for the given NID and its slaves */
1907static void set_dig_out(struct hda_codec *codec, hda_nid_t nid,
1908 int verb, int val)
1909{
1910 hda_nid_t *d;
1911
Takashi Iwai9e976972008-11-25 08:17:20 +01001912 snd_hda_codec_write_cache(codec, nid, 0, verb, val);
Takashi Iwai2f728532008-09-25 16:32:41 +02001913 d = codec->slave_dig_outs;
1914 if (!d)
1915 return;
1916 for (; *d; d++)
Takashi Iwai9e976972008-11-25 08:17:20 +01001917 snd_hda_codec_write_cache(codec, *d, 0, verb, val);
Takashi Iwai2f728532008-09-25 16:32:41 +02001918}
1919
1920static inline void set_dig_out_convert(struct hda_codec *codec, hda_nid_t nid,
1921 int dig1, int dig2)
1922{
1923 if (dig1 != -1)
1924 set_dig_out(codec, nid, AC_VERB_SET_DIGI_CONVERT_1, dig1);
1925 if (dig2 != -1)
1926 set_dig_out(codec, nid, AC_VERB_SET_DIGI_CONVERT_2, dig2);
1927}
1928
Takashi Iwai0ba21762007-04-16 11:29:14 +02001929static int snd_hda_spdif_default_put(struct snd_kcontrol *kcontrol,
1930 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001931{
1932 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1933 hda_nid_t nid = kcontrol->private_value;
1934 unsigned short val;
1935 int change;
1936
Ingo Molnar62932df2006-01-16 16:34:20 +01001937 mutex_lock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001938 codec->spdif_status = ucontrol->value.iec958.status[0] |
1939 ((unsigned int)ucontrol->value.iec958.status[1] << 8) |
1940 ((unsigned int)ucontrol->value.iec958.status[2] << 16) |
1941 ((unsigned int)ucontrol->value.iec958.status[3] << 24);
1942 val = convert_from_spdif_status(codec->spdif_status);
1943 val |= codec->spdif_ctls & 1;
1944 change = codec->spdif_ctls != val;
1945 codec->spdif_ctls = val;
1946
Takashi Iwai2f728532008-09-25 16:32:41 +02001947 if (change)
1948 set_dig_out_convert(codec, nid, val & 0xff, (val >> 8) & 0xff);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001949
Ingo Molnar62932df2006-01-16 16:34:20 +01001950 mutex_unlock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001951 return change;
1952}
1953
Takashi Iwaia5ce8892007-07-23 15:42:26 +02001954#define snd_hda_spdif_out_switch_info snd_ctl_boolean_mono_info
Linus Torvalds1da177e2005-04-16 15:20:36 -07001955
Takashi Iwai0ba21762007-04-16 11:29:14 +02001956static int snd_hda_spdif_out_switch_get(struct snd_kcontrol *kcontrol,
1957 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001958{
1959 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1960
Takashi Iwai0ba21762007-04-16 11:29:14 +02001961 ucontrol->value.integer.value[0] = codec->spdif_ctls & AC_DIG1_ENABLE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001962 return 0;
1963}
1964
Takashi Iwai0ba21762007-04-16 11:29:14 +02001965static int snd_hda_spdif_out_switch_put(struct snd_kcontrol *kcontrol,
1966 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001967{
1968 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1969 hda_nid_t nid = kcontrol->private_value;
1970 unsigned short val;
1971 int change;
1972
Ingo Molnar62932df2006-01-16 16:34:20 +01001973 mutex_lock(&codec->spdif_mutex);
Takashi Iwai0ba21762007-04-16 11:29:14 +02001974 val = codec->spdif_ctls & ~AC_DIG1_ENABLE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001975 if (ucontrol->value.integer.value[0])
Takashi Iwai0ba21762007-04-16 11:29:14 +02001976 val |= AC_DIG1_ENABLE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001977 change = codec->spdif_ctls != val;
Takashi Iwai82beb8f2007-08-10 17:09:26 +02001978 if (change) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001979 codec->spdif_ctls = val;
Takashi Iwai2f728532008-09-25 16:32:41 +02001980 set_dig_out_convert(codec, nid, val & 0xff, -1);
Takashi Iwai0ba21762007-04-16 11:29:14 +02001981 /* unmute amp switch (if any) */
1982 if ((get_wcaps(codec, nid) & AC_WCAP_OUT_AMP) &&
Takashi Iwai47fd8302007-08-10 17:11:07 +02001983 (val & AC_DIG1_ENABLE))
1984 snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0,
1985 HDA_AMP_MUTE, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001986 }
Ingo Molnar62932df2006-01-16 16:34:20 +01001987 mutex_unlock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001988 return change;
1989}
1990
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01001991static struct snd_kcontrol_new dig_mixes[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001992 {
1993 .access = SNDRV_CTL_ELEM_ACCESS_READ,
1994 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1995 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,CON_MASK),
1996 .info = snd_hda_spdif_mask_info,
1997 .get = snd_hda_spdif_cmask_get,
1998 },
1999 {
2000 .access = SNDRV_CTL_ELEM_ACCESS_READ,
2001 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2002 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,PRO_MASK),
2003 .info = snd_hda_spdif_mask_info,
2004 .get = snd_hda_spdif_pmask_get,
2005 },
2006 {
2007 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2008 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT),
2009 .info = snd_hda_spdif_mask_info,
2010 .get = snd_hda_spdif_default_get,
2011 .put = snd_hda_spdif_default_put,
2012 },
2013 {
2014 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2015 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,SWITCH),
2016 .info = snd_hda_spdif_out_switch_info,
2017 .get = snd_hda_spdif_out_switch_get,
2018 .put = snd_hda_spdif_out_switch_put,
2019 },
2020 { } /* end */
2021};
2022
Takashi Iwai09f99702008-02-04 12:31:13 +01002023#define SPDIF_MAX_IDX 4 /* 4 instances should be enough to probe */
2024
Linus Torvalds1da177e2005-04-16 15:20:36 -07002025/**
2026 * snd_hda_create_spdif_out_ctls - create Output SPDIF-related controls
2027 * @codec: the HDA codec
2028 * @nid: audio out widget NID
2029 *
2030 * Creates controls related with the SPDIF output.
2031 * Called from each patch supporting the SPDIF out.
2032 *
2033 * Returns 0 if successful, or a negative error code.
2034 */
Takashi Iwai12f288b2007-08-02 15:51:59 +02002035int snd_hda_create_spdif_out_ctls(struct hda_codec *codec, hda_nid_t nid)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002036{
2037 int err;
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01002038 struct snd_kcontrol *kctl;
2039 struct snd_kcontrol_new *dig_mix;
Takashi Iwai09f99702008-02-04 12:31:13 +01002040 int idx;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002041
Takashi Iwai09f99702008-02-04 12:31:13 +01002042 for (idx = 0; idx < SPDIF_MAX_IDX; idx++) {
2043 if (!_snd_hda_find_mixer_ctl(codec, "IEC958 Playback Switch",
2044 idx))
2045 break;
2046 }
2047 if (idx >= SPDIF_MAX_IDX) {
2048 printk(KERN_ERR "hda_codec: too many IEC958 outputs\n");
2049 return -EBUSY;
2050 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002051 for (dig_mix = dig_mixes; dig_mix->name; dig_mix++) {
2052 kctl = snd_ctl_new1(dig_mix, codec);
Takashi Iwaib91f0802008-11-04 08:43:08 +01002053 if (!kctl)
2054 return -ENOMEM;
Takashi Iwai09f99702008-02-04 12:31:13 +01002055 kctl->id.index = idx;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002056 kctl->private_value = nid;
Takashi Iwaid13bd412008-07-30 15:01:45 +02002057 err = snd_hda_ctl_add(codec, kctl);
Takashi Iwai0ba21762007-04-16 11:29:14 +02002058 if (err < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002059 return err;
2060 }
Takashi Iwai0ba21762007-04-16 11:29:14 +02002061 codec->spdif_ctls =
Andrew Paprocki3982d172007-12-19 12:13:44 +01002062 snd_hda_codec_read(codec, nid, 0,
2063 AC_VERB_GET_DIGI_CONVERT_1, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002064 codec->spdif_status = convert_to_spdif_status(codec->spdif_ctls);
2065 return 0;
2066}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002067EXPORT_SYMBOL_HDA(snd_hda_create_spdif_out_ctls);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002068
2069/*
Takashi Iwai9a081602008-02-12 18:37:26 +01002070 * SPDIF sharing with analog output
2071 */
2072static int spdif_share_sw_get(struct snd_kcontrol *kcontrol,
2073 struct snd_ctl_elem_value *ucontrol)
2074{
2075 struct hda_multi_out *mout = snd_kcontrol_chip(kcontrol);
2076 ucontrol->value.integer.value[0] = mout->share_spdif;
2077 return 0;
2078}
2079
2080static int spdif_share_sw_put(struct snd_kcontrol *kcontrol,
2081 struct snd_ctl_elem_value *ucontrol)
2082{
2083 struct hda_multi_out *mout = snd_kcontrol_chip(kcontrol);
2084 mout->share_spdif = !!ucontrol->value.integer.value[0];
2085 return 0;
2086}
2087
2088static struct snd_kcontrol_new spdif_share_sw = {
2089 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2090 .name = "IEC958 Default PCM Playback Switch",
2091 .info = snd_ctl_boolean_mono_info,
2092 .get = spdif_share_sw_get,
2093 .put = spdif_share_sw_put,
2094};
2095
2096int snd_hda_create_spdif_share_sw(struct hda_codec *codec,
2097 struct hda_multi_out *mout)
2098{
2099 if (!mout->dig_out_nid)
2100 return 0;
2101 /* ATTENTION: here mout is passed as private_data, instead of codec */
Takashi Iwaid13bd412008-07-30 15:01:45 +02002102 return snd_hda_ctl_add(codec,
Takashi Iwai9a081602008-02-12 18:37:26 +01002103 snd_ctl_new1(&spdif_share_sw, mout));
2104}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002105EXPORT_SYMBOL_HDA(snd_hda_create_spdif_share_sw);
Takashi Iwai9a081602008-02-12 18:37:26 +01002106
2107/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002108 * SPDIF input
2109 */
2110
2111#define snd_hda_spdif_in_switch_info snd_hda_spdif_out_switch_info
2112
Takashi Iwai0ba21762007-04-16 11:29:14 +02002113static int snd_hda_spdif_in_switch_get(struct snd_kcontrol *kcontrol,
2114 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002115{
2116 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2117
2118 ucontrol->value.integer.value[0] = codec->spdif_in_enable;
2119 return 0;
2120}
2121
Takashi Iwai0ba21762007-04-16 11:29:14 +02002122static int snd_hda_spdif_in_switch_put(struct snd_kcontrol *kcontrol,
2123 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002124{
2125 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2126 hda_nid_t nid = kcontrol->private_value;
2127 unsigned int val = !!ucontrol->value.integer.value[0];
2128 int change;
2129
Ingo Molnar62932df2006-01-16 16:34:20 +01002130 mutex_lock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002131 change = codec->spdif_in_enable != val;
Takashi Iwai82beb8f2007-08-10 17:09:26 +02002132 if (change) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002133 codec->spdif_in_enable = val;
Takashi Iwai82beb8f2007-08-10 17:09:26 +02002134 snd_hda_codec_write_cache(codec, nid, 0,
2135 AC_VERB_SET_DIGI_CONVERT_1, val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002136 }
Ingo Molnar62932df2006-01-16 16:34:20 +01002137 mutex_unlock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002138 return change;
2139}
2140
Takashi Iwai0ba21762007-04-16 11:29:14 +02002141static int snd_hda_spdif_in_status_get(struct snd_kcontrol *kcontrol,
2142 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002143{
2144 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2145 hda_nid_t nid = kcontrol->private_value;
2146 unsigned short val;
2147 unsigned int sbits;
2148
Andrew Paprocki3982d172007-12-19 12:13:44 +01002149 val = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_DIGI_CONVERT_1, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002150 sbits = convert_to_spdif_status(val);
2151 ucontrol->value.iec958.status[0] = sbits;
2152 ucontrol->value.iec958.status[1] = sbits >> 8;
2153 ucontrol->value.iec958.status[2] = sbits >> 16;
2154 ucontrol->value.iec958.status[3] = sbits >> 24;
2155 return 0;
2156}
2157
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01002158static struct snd_kcontrol_new dig_in_ctls[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002159 {
2160 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2161 .name = SNDRV_CTL_NAME_IEC958("",CAPTURE,SWITCH),
2162 .info = snd_hda_spdif_in_switch_info,
2163 .get = snd_hda_spdif_in_switch_get,
2164 .put = snd_hda_spdif_in_switch_put,
2165 },
2166 {
2167 .access = SNDRV_CTL_ELEM_ACCESS_READ,
2168 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2169 .name = SNDRV_CTL_NAME_IEC958("",CAPTURE,DEFAULT),
2170 .info = snd_hda_spdif_mask_info,
2171 .get = snd_hda_spdif_in_status_get,
2172 },
2173 { } /* end */
2174};
2175
2176/**
2177 * snd_hda_create_spdif_in_ctls - create Input SPDIF-related controls
2178 * @codec: the HDA codec
2179 * @nid: audio in widget NID
2180 *
2181 * Creates controls related with the SPDIF input.
2182 * Called from each patch supporting the SPDIF in.
2183 *
2184 * Returns 0 if successful, or a negative error code.
2185 */
Takashi Iwai12f288b2007-08-02 15:51:59 +02002186int snd_hda_create_spdif_in_ctls(struct hda_codec *codec, hda_nid_t nid)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002187{
2188 int err;
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01002189 struct snd_kcontrol *kctl;
2190 struct snd_kcontrol_new *dig_mix;
Takashi Iwai09f99702008-02-04 12:31:13 +01002191 int idx;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002192
Takashi Iwai09f99702008-02-04 12:31:13 +01002193 for (idx = 0; idx < SPDIF_MAX_IDX; idx++) {
2194 if (!_snd_hda_find_mixer_ctl(codec, "IEC958 Capture Switch",
2195 idx))
2196 break;
2197 }
2198 if (idx >= SPDIF_MAX_IDX) {
2199 printk(KERN_ERR "hda_codec: too many IEC958 inputs\n");
2200 return -EBUSY;
2201 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002202 for (dig_mix = dig_in_ctls; dig_mix->name; dig_mix++) {
2203 kctl = snd_ctl_new1(dig_mix, codec);
Takashi Iwaic8dcdf82009-02-06 16:21:20 +01002204 if (!kctl)
2205 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002206 kctl->private_value = nid;
Takashi Iwaid13bd412008-07-30 15:01:45 +02002207 err = snd_hda_ctl_add(codec, kctl);
Takashi Iwai0ba21762007-04-16 11:29:14 +02002208 if (err < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002209 return err;
2210 }
Takashi Iwai0ba21762007-04-16 11:29:14 +02002211 codec->spdif_in_enable =
Andrew Paprocki3982d172007-12-19 12:13:44 +01002212 snd_hda_codec_read(codec, nid, 0,
2213 AC_VERB_GET_DIGI_CONVERT_1, 0) &
Takashi Iwai0ba21762007-04-16 11:29:14 +02002214 AC_DIG1_ENABLE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002215 return 0;
2216}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002217EXPORT_SYMBOL_HDA(snd_hda_create_spdif_in_ctls);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002218
Takashi Iwaicb53c622007-08-10 17:21:45 +02002219#ifdef SND_HDA_NEEDS_RESUME
Takashi Iwai82beb8f2007-08-10 17:09:26 +02002220/*
2221 * command cache
2222 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002223
Takashi Iwaib3ac5632007-08-10 17:03:40 +02002224/* build a 32bit cache key with the widget id and the command parameter */
2225#define build_cmd_cache_key(nid, verb) ((verb << 8) | nid)
2226#define get_cmd_cache_nid(key) ((key) & 0xff)
2227#define get_cmd_cache_cmd(key) (((key) >> 8) & 0xffff)
2228
2229/**
2230 * snd_hda_codec_write_cache - send a single command with caching
2231 * @codec: the HDA codec
2232 * @nid: NID to send the command
2233 * @direct: direct flag
2234 * @verb: the verb to send
2235 * @parm: the parameter for the verb
2236 *
2237 * Send a single command without waiting for response.
2238 *
2239 * Returns 0 if successful, or a negative error code.
2240 */
2241int snd_hda_codec_write_cache(struct hda_codec *codec, hda_nid_t nid,
2242 int direct, unsigned int verb, unsigned int parm)
2243{
Takashi Iwai33fa35e2008-11-06 16:50:40 +01002244 struct hda_bus *bus = codec->bus;
2245 unsigned int res;
Takashi Iwaib3ac5632007-08-10 17:03:40 +02002246 int err;
Takashi Iwai33fa35e2008-11-06 16:50:40 +01002247
2248 res = make_codec_cmd(codec, nid, direct, verb, parm);
Takashi Iwaicb53c622007-08-10 17:21:45 +02002249 snd_hda_power_up(codec);
Takashi Iwai33fa35e2008-11-06 16:50:40 +01002250 mutex_lock(&bus->cmd_mutex);
2251 err = bus->ops.command(bus, res);
Takashi Iwaib3ac5632007-08-10 17:03:40 +02002252 if (!err) {
2253 struct hda_cache_head *c;
Takashi Iwaifcad94a2009-04-15 17:48:35 +02002254 u32 key;
2255 /* parm may contain the verb stuff for get/set amp */
2256 verb = verb | (parm >> 8);
2257 parm &= 0xff;
2258 key = build_cmd_cache_key(nid, verb);
Takashi Iwaib3ac5632007-08-10 17:03:40 +02002259 c = get_alloc_hash(&codec->cmd_cache, key);
2260 if (c)
2261 c->val = parm;
2262 }
Takashi Iwai33fa35e2008-11-06 16:50:40 +01002263 mutex_unlock(&bus->cmd_mutex);
Takashi Iwaicb53c622007-08-10 17:21:45 +02002264 snd_hda_power_down(codec);
Takashi Iwaib3ac5632007-08-10 17:03:40 +02002265 return err;
2266}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002267EXPORT_SYMBOL_HDA(snd_hda_codec_write_cache);
Takashi Iwaib3ac5632007-08-10 17:03:40 +02002268
2269/* resume the all commands from the cache */
2270void snd_hda_codec_resume_cache(struct hda_codec *codec)
2271{
Takashi Iwai603c4012008-07-30 15:01:44 +02002272 struct hda_cache_head *buffer = codec->cmd_cache.buf.list;
Takashi Iwaib3ac5632007-08-10 17:03:40 +02002273 int i;
2274
Takashi Iwai603c4012008-07-30 15:01:44 +02002275 for (i = 0; i < codec->cmd_cache.buf.used; i++, buffer++) {
Takashi Iwaib3ac5632007-08-10 17:03:40 +02002276 u32 key = buffer->key;
2277 if (!key)
2278 continue;
2279 snd_hda_codec_write(codec, get_cmd_cache_nid(key), 0,
2280 get_cmd_cache_cmd(key), buffer->val);
2281 }
2282}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002283EXPORT_SYMBOL_HDA(snd_hda_codec_resume_cache);
Takashi Iwaib3ac5632007-08-10 17:03:40 +02002284
2285/**
2286 * snd_hda_sequence_write_cache - sequence writes with caching
2287 * @codec: the HDA codec
2288 * @seq: VERB array to send
2289 *
2290 * Send the commands sequentially from the given array.
2291 * Thte commands are recorded on cache for power-save and resume.
2292 * The array must be terminated with NID=0.
2293 */
2294void snd_hda_sequence_write_cache(struct hda_codec *codec,
2295 const struct hda_verb *seq)
2296{
2297 for (; seq->nid; seq++)
2298 snd_hda_codec_write_cache(codec, seq->nid, 0, seq->verb,
2299 seq->param);
2300}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002301EXPORT_SYMBOL_HDA(snd_hda_sequence_write_cache);
Takashi Iwaicb53c622007-08-10 17:21:45 +02002302#endif /* SND_HDA_NEEDS_RESUME */
Takashi Iwaib3ac5632007-08-10 17:03:40 +02002303
Takashi Iwai54d17402005-11-21 16:33:22 +01002304/*
2305 * set power state of the codec
2306 */
2307static void hda_set_power_state(struct hda_codec *codec, hda_nid_t fg,
2308 unsigned int power_state)
2309{
Takashi Iwaicb53c622007-08-10 17:21:45 +02002310 hda_nid_t nid;
2311 int i;
Takashi Iwai54d17402005-11-21 16:33:22 +01002312
2313 snd_hda_codec_write(codec, fg, 0, AC_VERB_SET_POWER_STATE,
2314 power_state);
Marc Boucherd2595d82008-01-22 15:23:30 +01002315 msleep(10); /* partial workaround for "azx_get_response timeout" */
Takashi Iwai54d17402005-11-21 16:33:22 +01002316
Takashi Iwaicb53c622007-08-10 17:21:45 +02002317 nid = codec->start_nid;
2318 for (i = 0; i < codec->num_nodes; i++, nid++) {
Takashi Iwai7eba5c92007-11-14 14:53:42 +01002319 unsigned int wcaps = get_wcaps(codec, nid);
2320 if (wcaps & AC_WCAP_POWER) {
2321 unsigned int wid_type = (wcaps & AC_WCAP_TYPE) >>
2322 AC_WCAP_TYPE_SHIFT;
2323 if (wid_type == AC_WID_PIN) {
2324 unsigned int pincap;
2325 /*
2326 * don't power down the widget if it controls
2327 * eapd and EAPD_BTLENABLE is set.
2328 */
Takashi Iwai14bafe32009-03-23 16:35:39 +01002329 pincap = snd_hda_query_pin_caps(codec, nid);
Takashi Iwai7eba5c92007-11-14 14:53:42 +01002330 if (pincap & AC_PINCAP_EAPD) {
2331 int eapd = snd_hda_codec_read(codec,
2332 nid, 0,
2333 AC_VERB_GET_EAPD_BTLENABLE, 0);
2334 eapd &= 0x02;
2335 if (power_state == AC_PWRST_D3 && eapd)
2336 continue;
2337 }
Takashi Iwai1194b5b2007-10-10 10:04:26 +02002338 }
Takashi Iwai54d17402005-11-21 16:33:22 +01002339 snd_hda_codec_write(codec, nid, 0,
2340 AC_VERB_SET_POWER_STATE,
2341 power_state);
Takashi Iwai1194b5b2007-10-10 10:04:26 +02002342 }
Takashi Iwai54d17402005-11-21 16:33:22 +01002343 }
2344
Takashi Iwaicb53c622007-08-10 17:21:45 +02002345 if (power_state == AC_PWRST_D0) {
2346 unsigned long end_time;
2347 int state;
Takashi Iwai54d17402005-11-21 16:33:22 +01002348 msleep(10);
Takashi Iwaicb53c622007-08-10 17:21:45 +02002349 /* wait until the codec reachs to D0 */
2350 end_time = jiffies + msecs_to_jiffies(500);
2351 do {
2352 state = snd_hda_codec_read(codec, fg, 0,
2353 AC_VERB_GET_POWER_STATE, 0);
2354 if (state == power_state)
2355 break;
2356 msleep(1);
2357 } while (time_after_eq(end_time, jiffies));
2358 }
Takashi Iwai54d17402005-11-21 16:33:22 +01002359}
2360
Takashi Iwai11aeff02008-07-30 15:01:46 +02002361#ifdef CONFIG_SND_HDA_HWDEP
2362/* execute additional init verbs */
2363static void hda_exec_init_verbs(struct hda_codec *codec)
2364{
2365 if (codec->init_verbs.list)
2366 snd_hda_sequence_write(codec, codec->init_verbs.list);
2367}
2368#else
2369static inline void hda_exec_init_verbs(struct hda_codec *codec) {}
2370#endif
2371
Takashi Iwaicb53c622007-08-10 17:21:45 +02002372#ifdef SND_HDA_NEEDS_RESUME
2373/*
2374 * call suspend and power-down; used both from PM and power-save
2375 */
2376static void hda_call_codec_suspend(struct hda_codec *codec)
2377{
2378 if (codec->patch_ops.suspend)
2379 codec->patch_ops.suspend(codec, PMSG_SUSPEND);
2380 hda_set_power_state(codec,
2381 codec->afg ? codec->afg : codec->mfg,
2382 AC_PWRST_D3);
2383#ifdef CONFIG_SND_HDA_POWER_SAVE
2384 cancel_delayed_work(&codec->power_work);
Takashi Iwai95e99fd2007-08-13 15:29:04 +02002385 codec->power_on = 0;
Takashi Iwaia221e282007-08-16 16:35:33 +02002386 codec->power_transition = 0;
Takashi Iwaicb53c622007-08-10 17:21:45 +02002387#endif
2388}
2389
2390/*
2391 * kick up codec; used both from PM and power-save
2392 */
2393static void hda_call_codec_resume(struct hda_codec *codec)
2394{
2395 hda_set_power_state(codec,
2396 codec->afg ? codec->afg : codec->mfg,
2397 AC_PWRST_D0);
Takashi Iwai3be14142009-02-20 14:11:16 +01002398 restore_pincfgs(codec); /* restore all current pin configs */
Takashi Iwai11aeff02008-07-30 15:01:46 +02002399 hda_exec_init_verbs(codec);
Takashi Iwaicb53c622007-08-10 17:21:45 +02002400 if (codec->patch_ops.resume)
2401 codec->patch_ops.resume(codec);
2402 else {
Takashi Iwai9d99f312007-08-14 15:15:52 +02002403 if (codec->patch_ops.init)
2404 codec->patch_ops.init(codec);
Takashi Iwaicb53c622007-08-10 17:21:45 +02002405 snd_hda_codec_resume_amp(codec);
2406 snd_hda_codec_resume_cache(codec);
2407 }
2408}
2409#endif /* SND_HDA_NEEDS_RESUME */
2410
Takashi Iwai54d17402005-11-21 16:33:22 +01002411
Linus Torvalds1da177e2005-04-16 15:20:36 -07002412/**
2413 * snd_hda_build_controls - build mixer controls
2414 * @bus: the BUS
2415 *
2416 * Creates mixer controls for each codec included in the bus.
2417 *
2418 * Returns 0 if successful, otherwise a negative error code.
2419 */
Takashi Iwai1289e9e2008-11-27 15:47:11 +01002420int /*__devinit*/ snd_hda_build_controls(struct hda_bus *bus)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002421{
Takashi Iwai0ba21762007-04-16 11:29:14 +02002422 struct hda_codec *codec;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002423
Takashi Iwai0ba21762007-04-16 11:29:14 +02002424 list_for_each_entry(codec, &bus->codec_list, list) {
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02002425 int err = snd_hda_codec_build_controls(codec);
Takashi Iwaif93d4612009-03-02 10:44:15 +01002426 if (err < 0) {
2427 printk(KERN_ERR "hda_codec: cannot build controls"
2428 "for #%d (error %d)\n", codec->addr, err);
2429 err = snd_hda_codec_reset(codec);
2430 if (err < 0) {
2431 printk(KERN_ERR
2432 "hda_codec: cannot revert codec\n");
2433 return err;
2434 }
2435 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002436 }
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02002437 return 0;
2438}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002439EXPORT_SYMBOL_HDA(snd_hda_build_controls);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002440
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02002441int snd_hda_codec_build_controls(struct hda_codec *codec)
2442{
2443 int err = 0;
Takashi Iwai11aeff02008-07-30 15:01:46 +02002444 hda_exec_init_verbs(codec);
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02002445 /* continue to initialize... */
2446 if (codec->patch_ops.init)
2447 err = codec->patch_ops.init(codec);
2448 if (!err && codec->patch_ops.build_controls)
2449 err = codec->patch_ops.build_controls(codec);
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02002450 if (err < 0)
2451 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002452 return 0;
2453}
2454
Linus Torvalds1da177e2005-04-16 15:20:36 -07002455/*
2456 * stream formats
2457 */
Takashi Iwaibefdf312005-08-22 13:57:55 +02002458struct hda_rate_tbl {
2459 unsigned int hz;
2460 unsigned int alsa_bits;
2461 unsigned int hda_fmt;
2462};
2463
2464static struct hda_rate_tbl rate_bits[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002465 /* rate in Hz, ALSA rate bitmask, HDA format value */
Nicolas Graziano9d8f53f2005-08-22 13:47:16 +02002466
2467 /* autodetected value used in snd_hda_query_supported_pcm */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002468 { 8000, SNDRV_PCM_RATE_8000, 0x0500 }, /* 1/6 x 48 */
2469 { 11025, SNDRV_PCM_RATE_11025, 0x4300 }, /* 1/4 x 44 */
2470 { 16000, SNDRV_PCM_RATE_16000, 0x0200 }, /* 1/3 x 48 */
2471 { 22050, SNDRV_PCM_RATE_22050, 0x4100 }, /* 1/2 x 44 */
2472 { 32000, SNDRV_PCM_RATE_32000, 0x0a00 }, /* 2/3 x 48 */
2473 { 44100, SNDRV_PCM_RATE_44100, 0x4000 }, /* 44 */
2474 { 48000, SNDRV_PCM_RATE_48000, 0x0000 }, /* 48 */
2475 { 88200, SNDRV_PCM_RATE_88200, 0x4800 }, /* 2 x 44 */
2476 { 96000, SNDRV_PCM_RATE_96000, 0x0800 }, /* 2 x 48 */
2477 { 176400, SNDRV_PCM_RATE_176400, 0x5800 },/* 4 x 44 */
2478 { 192000, SNDRV_PCM_RATE_192000, 0x1800 }, /* 4 x 48 */
Takashi Iwaia961f9f2007-04-12 13:08:09 +02002479#define AC_PAR_PCM_RATE_BITS 11
2480 /* up to bits 10, 384kHZ isn't supported properly */
2481
2482 /* not autodetected value */
2483 { 9600, SNDRV_PCM_RATE_KNOT, 0x0400 }, /* 1/5 x 48 */
Nicolas Graziano9d8f53f2005-08-22 13:47:16 +02002484
Takashi Iwaibefdf312005-08-22 13:57:55 +02002485 { 0 } /* terminator */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002486};
2487
2488/**
2489 * snd_hda_calc_stream_format - calculate format bitset
2490 * @rate: the sample rate
2491 * @channels: the number of channels
2492 * @format: the PCM format (SNDRV_PCM_FORMAT_XXX)
2493 * @maxbps: the max. bps
2494 *
2495 * Calculate the format bitset from the given rate, channels and th PCM format.
2496 *
2497 * Return zero if invalid.
2498 */
2499unsigned int snd_hda_calc_stream_format(unsigned int rate,
2500 unsigned int channels,
2501 unsigned int format,
2502 unsigned int maxbps)
2503{
2504 int i;
2505 unsigned int val = 0;
2506
Takashi Iwaibefdf312005-08-22 13:57:55 +02002507 for (i = 0; rate_bits[i].hz; i++)
2508 if (rate_bits[i].hz == rate) {
2509 val = rate_bits[i].hda_fmt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002510 break;
2511 }
Takashi Iwai0ba21762007-04-16 11:29:14 +02002512 if (!rate_bits[i].hz) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002513 snd_printdd("invalid rate %d\n", rate);
2514 return 0;
2515 }
2516
2517 if (channels == 0 || channels > 8) {
2518 snd_printdd("invalid channels %d\n", channels);
2519 return 0;
2520 }
2521 val |= channels - 1;
2522
2523 switch (snd_pcm_format_width(format)) {
2524 case 8: val |= 0x00; break;
2525 case 16: val |= 0x10; break;
2526 case 20:
2527 case 24:
2528 case 32:
2529 if (maxbps >= 32)
2530 val |= 0x40;
2531 else if (maxbps >= 24)
2532 val |= 0x30;
2533 else
2534 val |= 0x20;
2535 break;
2536 default:
Takashi Iwai0ba21762007-04-16 11:29:14 +02002537 snd_printdd("invalid format width %d\n",
2538 snd_pcm_format_width(format));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002539 return 0;
2540 }
2541
2542 return val;
2543}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002544EXPORT_SYMBOL_HDA(snd_hda_calc_stream_format);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002545
2546/**
2547 * snd_hda_query_supported_pcm - query the supported PCM rates and formats
2548 * @codec: the HDA codec
2549 * @nid: NID to query
2550 * @ratesp: the pointer to store the detected rate bitflags
2551 * @formatsp: the pointer to store the detected formats
2552 * @bpsp: the pointer to store the detected format widths
2553 *
2554 * Queries the supported PCM rates and formats. The NULL @ratesp, @formatsp
2555 * or @bsps argument is ignored.
2556 *
2557 * Returns 0 if successful, otherwise a negative error code.
2558 */
Takashi Iwai986862bd2008-11-27 12:40:13 +01002559static int snd_hda_query_supported_pcm(struct hda_codec *codec, hda_nid_t nid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002560 u32 *ratesp, u64 *formatsp, unsigned int *bpsp)
2561{
Jaroslav Kyselaee504712009-03-17 14:30:31 +01002562 unsigned int i, val, wcaps;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002563
2564 val = 0;
Jaroslav Kyselaee504712009-03-17 14:30:31 +01002565 wcaps = get_wcaps(codec, nid);
2566 if (nid != codec->afg && (wcaps & AC_WCAP_FORMAT_OVRD)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002567 val = snd_hda_param_read(codec, nid, AC_PAR_PCM);
2568 if (val == -1)
2569 return -EIO;
2570 }
Takashi Iwai0ba21762007-04-16 11:29:14 +02002571 if (!val)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002572 val = snd_hda_param_read(codec, codec->afg, AC_PAR_PCM);
2573
2574 if (ratesp) {
2575 u32 rates = 0;
Takashi Iwaia961f9f2007-04-12 13:08:09 +02002576 for (i = 0; i < AC_PAR_PCM_RATE_BITS; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002577 if (val & (1 << i))
Takashi Iwaibefdf312005-08-22 13:57:55 +02002578 rates |= rate_bits[i].alsa_bits;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002579 }
Jaroslav Kyselaee504712009-03-17 14:30:31 +01002580 if (rates == 0) {
2581 snd_printk(KERN_ERR "hda_codec: rates == 0 "
2582 "(nid=0x%x, val=0x%x, ovrd=%i)\n",
2583 nid, val,
2584 (wcaps & AC_WCAP_FORMAT_OVRD) ? 1 : 0);
2585 return -EIO;
2586 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002587 *ratesp = rates;
2588 }
2589
2590 if (formatsp || bpsp) {
2591 u64 formats = 0;
Jaroslav Kyselaee504712009-03-17 14:30:31 +01002592 unsigned int streams, bps;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002593
Linus Torvalds1da177e2005-04-16 15:20:36 -07002594 streams = snd_hda_param_read(codec, nid, AC_PAR_STREAM);
2595 if (streams == -1)
2596 return -EIO;
Takashi Iwai0ba21762007-04-16 11:29:14 +02002597 if (!streams) {
2598 streams = snd_hda_param_read(codec, codec->afg,
2599 AC_PAR_STREAM);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002600 if (streams == -1)
2601 return -EIO;
2602 }
2603
2604 bps = 0;
2605 if (streams & AC_SUPFMT_PCM) {
2606 if (val & AC_SUPPCM_BITS_8) {
2607 formats |= SNDRV_PCM_FMTBIT_U8;
2608 bps = 8;
2609 }
2610 if (val & AC_SUPPCM_BITS_16) {
2611 formats |= SNDRV_PCM_FMTBIT_S16_LE;
2612 bps = 16;
2613 }
2614 if (wcaps & AC_WCAP_DIGITAL) {
2615 if (val & AC_SUPPCM_BITS_32)
2616 formats |= SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_LE;
2617 if (val & (AC_SUPPCM_BITS_20|AC_SUPPCM_BITS_24))
2618 formats |= SNDRV_PCM_FMTBIT_S32_LE;
2619 if (val & AC_SUPPCM_BITS_24)
2620 bps = 24;
2621 else if (val & AC_SUPPCM_BITS_20)
2622 bps = 20;
Takashi Iwai0ba21762007-04-16 11:29:14 +02002623 } else if (val & (AC_SUPPCM_BITS_20|AC_SUPPCM_BITS_24|
2624 AC_SUPPCM_BITS_32)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002625 formats |= SNDRV_PCM_FMTBIT_S32_LE;
2626 if (val & AC_SUPPCM_BITS_32)
2627 bps = 32;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002628 else if (val & AC_SUPPCM_BITS_24)
2629 bps = 24;
Nicolas Graziano33ef76512006-09-19 14:23:14 +02002630 else if (val & AC_SUPPCM_BITS_20)
2631 bps = 20;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002632 }
2633 }
Takashi Iwai0ba21762007-04-16 11:29:14 +02002634 else if (streams == AC_SUPFMT_FLOAT32) {
2635 /* should be exclusive */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002636 formats |= SNDRV_PCM_FMTBIT_FLOAT_LE;
2637 bps = 32;
Takashi Iwai0ba21762007-04-16 11:29:14 +02002638 } else if (streams == AC_SUPFMT_AC3) {
2639 /* should be exclusive */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002640 /* temporary hack: we have still no proper support
2641 * for the direct AC3 stream...
2642 */
2643 formats |= SNDRV_PCM_FMTBIT_U8;
2644 bps = 8;
2645 }
Jaroslav Kyselaee504712009-03-17 14:30:31 +01002646 if (formats == 0) {
2647 snd_printk(KERN_ERR "hda_codec: formats == 0 "
2648 "(nid=0x%x, val=0x%x, ovrd=%i, "
2649 "streams=0x%x)\n",
2650 nid, val,
2651 (wcaps & AC_WCAP_FORMAT_OVRD) ? 1 : 0,
2652 streams);
2653 return -EIO;
2654 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002655 if (formatsp)
2656 *formatsp = formats;
2657 if (bpsp)
2658 *bpsp = bps;
2659 }
2660
2661 return 0;
2662}
2663
2664/**
Takashi Iwai0ba21762007-04-16 11:29:14 +02002665 * snd_hda_is_supported_format - check whether the given node supports
2666 * the format val
Linus Torvalds1da177e2005-04-16 15:20:36 -07002667 *
2668 * Returns 1 if supported, 0 if not.
2669 */
2670int snd_hda_is_supported_format(struct hda_codec *codec, hda_nid_t nid,
2671 unsigned int format)
2672{
2673 int i;
2674 unsigned int val = 0, rate, stream;
2675
2676 if (nid != codec->afg &&
Takashi Iwai54d17402005-11-21 16:33:22 +01002677 (get_wcaps(codec, nid) & AC_WCAP_FORMAT_OVRD)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002678 val = snd_hda_param_read(codec, nid, AC_PAR_PCM);
2679 if (val == -1)
2680 return 0;
2681 }
Takashi Iwai0ba21762007-04-16 11:29:14 +02002682 if (!val) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002683 val = snd_hda_param_read(codec, codec->afg, AC_PAR_PCM);
2684 if (val == -1)
2685 return 0;
2686 }
2687
2688 rate = format & 0xff00;
Takashi Iwaia961f9f2007-04-12 13:08:09 +02002689 for (i = 0; i < AC_PAR_PCM_RATE_BITS; i++)
Takashi Iwaibefdf312005-08-22 13:57:55 +02002690 if (rate_bits[i].hda_fmt == rate) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002691 if (val & (1 << i))
2692 break;
2693 return 0;
2694 }
Takashi Iwaia961f9f2007-04-12 13:08:09 +02002695 if (i >= AC_PAR_PCM_RATE_BITS)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002696 return 0;
2697
2698 stream = snd_hda_param_read(codec, nid, AC_PAR_STREAM);
2699 if (stream == -1)
2700 return 0;
Takashi Iwai0ba21762007-04-16 11:29:14 +02002701 if (!stream && nid != codec->afg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002702 stream = snd_hda_param_read(codec, codec->afg, AC_PAR_STREAM);
Takashi Iwai0ba21762007-04-16 11:29:14 +02002703 if (!stream || stream == -1)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002704 return 0;
2705
2706 if (stream & AC_SUPFMT_PCM) {
2707 switch (format & 0xf0) {
2708 case 0x00:
Takashi Iwai0ba21762007-04-16 11:29:14 +02002709 if (!(val & AC_SUPPCM_BITS_8))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002710 return 0;
2711 break;
2712 case 0x10:
Takashi Iwai0ba21762007-04-16 11:29:14 +02002713 if (!(val & AC_SUPPCM_BITS_16))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002714 return 0;
2715 break;
2716 case 0x20:
Takashi Iwai0ba21762007-04-16 11:29:14 +02002717 if (!(val & AC_SUPPCM_BITS_20))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002718 return 0;
2719 break;
2720 case 0x30:
Takashi Iwai0ba21762007-04-16 11:29:14 +02002721 if (!(val & AC_SUPPCM_BITS_24))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002722 return 0;
2723 break;
2724 case 0x40:
Takashi Iwai0ba21762007-04-16 11:29:14 +02002725 if (!(val & AC_SUPPCM_BITS_32))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002726 return 0;
2727 break;
2728 default:
2729 return 0;
2730 }
2731 } else {
2732 /* FIXME: check for float32 and AC3? */
2733 }
2734
2735 return 1;
2736}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002737EXPORT_SYMBOL_HDA(snd_hda_is_supported_format);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002738
2739/*
2740 * PCM stuff
2741 */
2742static int hda_pcm_default_open_close(struct hda_pcm_stream *hinfo,
2743 struct hda_codec *codec,
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01002744 struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002745{
2746 return 0;
2747}
2748
2749static int hda_pcm_default_prepare(struct hda_pcm_stream *hinfo,
2750 struct hda_codec *codec,
2751 unsigned int stream_tag,
2752 unsigned int format,
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01002753 struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002754{
2755 snd_hda_codec_setup_stream(codec, hinfo->nid, stream_tag, 0, format);
2756 return 0;
2757}
2758
2759static int hda_pcm_default_cleanup(struct hda_pcm_stream *hinfo,
2760 struct hda_codec *codec,
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01002761 struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002762{
Takashi Iwai888afa12008-03-18 09:57:50 +01002763 snd_hda_codec_cleanup_stream(codec, hinfo->nid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002764 return 0;
2765}
2766
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02002767static int set_pcm_default_values(struct hda_codec *codec,
2768 struct hda_pcm_stream *info)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002769{
Jaroslav Kyselaee504712009-03-17 14:30:31 +01002770 int err;
2771
Takashi Iwai0ba21762007-04-16 11:29:14 +02002772 /* query support PCM information from the given NID */
2773 if (info->nid && (!info->rates || !info->formats)) {
Jaroslav Kyselaee504712009-03-17 14:30:31 +01002774 err = snd_hda_query_supported_pcm(codec, info->nid,
Takashi Iwai0ba21762007-04-16 11:29:14 +02002775 info->rates ? NULL : &info->rates,
2776 info->formats ? NULL : &info->formats,
2777 info->maxbps ? NULL : &info->maxbps);
Jaroslav Kyselaee504712009-03-17 14:30:31 +01002778 if (err < 0)
2779 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002780 }
2781 if (info->ops.open == NULL)
2782 info->ops.open = hda_pcm_default_open_close;
2783 if (info->ops.close == NULL)
2784 info->ops.close = hda_pcm_default_open_close;
2785 if (info->ops.prepare == NULL) {
Takashi Iwaida3cec32008-08-08 17:12:14 +02002786 if (snd_BUG_ON(!info->nid))
2787 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002788 info->ops.prepare = hda_pcm_default_prepare;
2789 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002790 if (info->ops.cleanup == NULL) {
Takashi Iwaida3cec32008-08-08 17:12:14 +02002791 if (snd_BUG_ON(!info->nid))
2792 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002793 info->ops.cleanup = hda_pcm_default_cleanup;
2794 }
2795 return 0;
2796}
2797
Takashi Iwai176d5332008-07-30 15:01:44 +02002798/*
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002799 * get the empty PCM device number to assign
2800 */
2801static int get_empty_pcm_device(struct hda_bus *bus, int type)
2802{
2803 static const char *dev_name[HDA_PCM_NTYPES] = {
2804 "Audio", "SPDIF", "HDMI", "Modem"
2805 };
2806 /* starting device index for each PCM type */
2807 static int dev_idx[HDA_PCM_NTYPES] = {
2808 [HDA_PCM_TYPE_AUDIO] = 0,
2809 [HDA_PCM_TYPE_SPDIF] = 1,
2810 [HDA_PCM_TYPE_HDMI] = 3,
2811 [HDA_PCM_TYPE_MODEM] = 6
2812 };
2813 /* normal audio device indices; not linear to keep compatibility */
2814 static int audio_idx[4] = { 0, 2, 4, 5 };
2815 int i, dev;
2816
2817 switch (type) {
2818 case HDA_PCM_TYPE_AUDIO:
2819 for (i = 0; i < ARRAY_SIZE(audio_idx); i++) {
2820 dev = audio_idx[i];
2821 if (!test_bit(dev, bus->pcm_dev_bits))
Takashi Iwai82ad39f2009-03-03 15:00:35 +01002822 goto ok;
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002823 }
Takashi Iwai82ad39f2009-03-03 15:00:35 +01002824 snd_printk(KERN_WARNING "Too many audio devices\n");
2825 return -EAGAIN;
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002826 case HDA_PCM_TYPE_SPDIF:
2827 case HDA_PCM_TYPE_HDMI:
2828 case HDA_PCM_TYPE_MODEM:
2829 dev = dev_idx[type];
2830 if (test_bit(dev, bus->pcm_dev_bits)) {
2831 snd_printk(KERN_WARNING "%s already defined\n",
2832 dev_name[type]);
2833 return -EAGAIN;
2834 }
2835 break;
2836 default:
2837 snd_printk(KERN_WARNING "Invalid PCM type %d\n", type);
2838 return -EINVAL;
2839 }
Takashi Iwai82ad39f2009-03-03 15:00:35 +01002840 ok:
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002841 set_bit(dev, bus->pcm_dev_bits);
2842 return dev;
2843}
2844
2845/*
Takashi Iwai176d5332008-07-30 15:01:44 +02002846 * attach a new PCM stream
2847 */
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002848static int snd_hda_attach_pcm(struct hda_codec *codec, struct hda_pcm *pcm)
Takashi Iwai176d5332008-07-30 15:01:44 +02002849{
Takashi Iwai33fa35e2008-11-06 16:50:40 +01002850 struct hda_bus *bus = codec->bus;
Takashi Iwai176d5332008-07-30 15:01:44 +02002851 struct hda_pcm_stream *info;
2852 int stream, err;
2853
Takashi Iwaib91f0802008-11-04 08:43:08 +01002854 if (snd_BUG_ON(!pcm->name))
Takashi Iwai176d5332008-07-30 15:01:44 +02002855 return -EINVAL;
2856 for (stream = 0; stream < 2; stream++) {
2857 info = &pcm->stream[stream];
2858 if (info->substreams) {
2859 err = set_pcm_default_values(codec, info);
2860 if (err < 0)
2861 return err;
2862 }
2863 }
Takashi Iwai33fa35e2008-11-06 16:50:40 +01002864 return bus->ops.attach_pcm(bus, codec, pcm);
Takashi Iwai176d5332008-07-30 15:01:44 +02002865}
2866
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002867/* assign all PCMs of the given codec */
2868int snd_hda_codec_build_pcms(struct hda_codec *codec)
2869{
2870 unsigned int pcm;
2871 int err;
2872
2873 if (!codec->num_pcms) {
2874 if (!codec->patch_ops.build_pcms)
2875 return 0;
2876 err = codec->patch_ops.build_pcms(codec);
Takashi Iwai6e655bf2009-03-02 10:46:03 +01002877 if (err < 0) {
2878 printk(KERN_ERR "hda_codec: cannot build PCMs"
2879 "for #%d (error %d)\n", codec->addr, err);
2880 err = snd_hda_codec_reset(codec);
2881 if (err < 0) {
2882 printk(KERN_ERR
2883 "hda_codec: cannot revert codec\n");
2884 return err;
2885 }
2886 }
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002887 }
2888 for (pcm = 0; pcm < codec->num_pcms; pcm++) {
2889 struct hda_pcm *cpcm = &codec->pcm_info[pcm];
2890 int dev;
2891
2892 if (!cpcm->stream[0].substreams && !cpcm->stream[1].substreams)
Takashi Iwai41b5b012009-01-20 18:21:23 +01002893 continue; /* no substreams assigned */
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002894
2895 if (!cpcm->pcm) {
2896 dev = get_empty_pcm_device(codec->bus, cpcm->pcm_type);
2897 if (dev < 0)
Takashi Iwai6e655bf2009-03-02 10:46:03 +01002898 continue; /* no fatal error */
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002899 cpcm->device = dev;
2900 err = snd_hda_attach_pcm(codec, cpcm);
Takashi Iwai6e655bf2009-03-02 10:46:03 +01002901 if (err < 0) {
2902 printk(KERN_ERR "hda_codec: cannot attach "
2903 "PCM stream %d for codec #%d\n",
2904 dev, codec->addr);
2905 continue; /* no fatal error */
2906 }
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002907 }
2908 }
2909 return 0;
2910}
2911
Linus Torvalds1da177e2005-04-16 15:20:36 -07002912/**
2913 * snd_hda_build_pcms - build PCM information
2914 * @bus: the BUS
2915 *
2916 * Create PCM information for each codec included in the bus.
2917 *
2918 * The build_pcms codec patch is requested to set up codec->num_pcms and
2919 * codec->pcm_info properly. The array is referred by the top-level driver
2920 * to create its PCM instances.
2921 * The allocated codec->pcm_info should be released in codec->patch_ops.free
2922 * callback.
2923 *
2924 * At least, substreams, channels_min and channels_max must be filled for
2925 * each stream. substreams = 0 indicates that the stream doesn't exist.
2926 * When rates and/or formats are zero, the supported values are queried
2927 * from the given nid. The nid is used also by the default ops.prepare
2928 * and ops.cleanup callbacks.
2929 *
2930 * The driver needs to call ops.open in its open callback. Similarly,
2931 * ops.close is supposed to be called in the close callback.
2932 * ops.prepare should be called in the prepare or hw_params callback
2933 * with the proper parameters for set up.
2934 * ops.cleanup should be called in hw_free for clean up of streams.
2935 *
2936 * This function returns 0 if successfull, or a negative error code.
2937 */
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002938int __devinit snd_hda_build_pcms(struct hda_bus *bus)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002939{
Takashi Iwai0ba21762007-04-16 11:29:14 +02002940 struct hda_codec *codec;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002941
Takashi Iwai0ba21762007-04-16 11:29:14 +02002942 list_for_each_entry(codec, &bus->codec_list, list) {
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002943 int err = snd_hda_codec_build_pcms(codec);
2944 if (err < 0)
2945 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002946 }
2947 return 0;
2948}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002949EXPORT_SYMBOL_HDA(snd_hda_build_pcms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002950
Linus Torvalds1da177e2005-04-16 15:20:36 -07002951/**
2952 * snd_hda_check_board_config - compare the current codec with the config table
2953 * @codec: the HDA codec
Takashi Iwaif5fcc132006-11-24 17:07:44 +01002954 * @num_configs: number of config enums
2955 * @models: array of model name strings
Linus Torvalds1da177e2005-04-16 15:20:36 -07002956 * @tbl: configuration table, terminated by null entries
2957 *
2958 * Compares the modelname or PCI subsystem id of the current codec with the
2959 * given configuration table. If a matching entry is found, returns its
2960 * config value (supposed to be 0 or positive).
2961 *
2962 * If no entries are matching, the function returns a negative value.
2963 */
Takashi Iwai12f288b2007-08-02 15:51:59 +02002964int snd_hda_check_board_config(struct hda_codec *codec,
2965 int num_configs, const char **models,
2966 const struct snd_pci_quirk *tbl)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002967{
Takashi Iwaif44ac832008-07-30 15:01:45 +02002968 if (codec->modelname && models) {
Takashi Iwaif5fcc132006-11-24 17:07:44 +01002969 int i;
2970 for (i = 0; i < num_configs; i++) {
2971 if (models[i] &&
Takashi Iwaif44ac832008-07-30 15:01:45 +02002972 !strcmp(codec->modelname, models[i])) {
Takashi Iwaif5fcc132006-11-24 17:07:44 +01002973 snd_printd(KERN_INFO "hda_codec: model '%s' is "
2974 "selected\n", models[i]);
2975 return i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002976 }
2977 }
2978 }
2979
Takashi Iwaif5fcc132006-11-24 17:07:44 +01002980 if (!codec->bus->pci || !tbl)
2981 return -1;
2982
2983 tbl = snd_pci_quirk_lookup(codec->bus->pci, tbl);
2984 if (!tbl)
2985 return -1;
2986 if (tbl->value >= 0 && tbl->value < num_configs) {
Takashi Iwai62cf8722008-05-20 12:15:15 +02002987#ifdef CONFIG_SND_DEBUG_VERBOSE
Takashi Iwaif5fcc132006-11-24 17:07:44 +01002988 char tmp[10];
2989 const char *model = NULL;
2990 if (models)
2991 model = models[tbl->value];
2992 if (!model) {
2993 sprintf(tmp, "#%d", tbl->value);
2994 model = tmp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002995 }
Takashi Iwaif5fcc132006-11-24 17:07:44 +01002996 snd_printdd(KERN_INFO "hda_codec: model '%s' is selected "
2997 "for config %x:%x (%s)\n",
2998 model, tbl->subvendor, tbl->subdevice,
2999 (tbl->name ? tbl->name : "Unknown device"));
3000#endif
3001 return tbl->value;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003002 }
3003 return -1;
3004}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003005EXPORT_SYMBOL_HDA(snd_hda_check_board_config);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003006
3007/**
Mauro Carvalho Chehab2eda3442008-08-11 10:18:39 +02003008 * snd_hda_check_board_codec_sid_config - compare the current codec
3009 subsystem ID with the
3010 config table
3011
3012 This is important for Gateway notebooks with SB450 HDA Audio
3013 where the vendor ID of the PCI device is:
3014 ATI Technologies Inc SB450 HDA Audio [1002:437b]
3015 and the vendor/subvendor are found only at the codec.
3016
3017 * @codec: the HDA codec
3018 * @num_configs: number of config enums
3019 * @models: array of model name strings
3020 * @tbl: configuration table, terminated by null entries
3021 *
3022 * Compares the modelname or PCI subsystem id of the current codec with the
3023 * given configuration table. If a matching entry is found, returns its
3024 * config value (supposed to be 0 or positive).
3025 *
3026 * If no entries are matching, the function returns a negative value.
3027 */
3028int snd_hda_check_board_codec_sid_config(struct hda_codec *codec,
3029 int num_configs, const char **models,
3030 const struct snd_pci_quirk *tbl)
3031{
3032 const struct snd_pci_quirk *q;
3033
3034 /* Search for codec ID */
3035 for (q = tbl; q->subvendor; q++) {
3036 unsigned long vendorid = (q->subdevice) | (q->subvendor << 16);
3037
3038 if (vendorid == codec->subsystem_id)
3039 break;
3040 }
3041
3042 if (!q->subvendor)
3043 return -1;
3044
3045 tbl = q;
3046
3047 if (tbl->value >= 0 && tbl->value < num_configs) {
3048#ifdef CONFIG_SND_DEBUG_DETECT
3049 char tmp[10];
3050 const char *model = NULL;
3051 if (models)
3052 model = models[tbl->value];
3053 if (!model) {
3054 sprintf(tmp, "#%d", tbl->value);
3055 model = tmp;
3056 }
3057 snd_printdd(KERN_INFO "hda_codec: model '%s' is selected "
3058 "for config %x:%x (%s)\n",
3059 model, tbl->subvendor, tbl->subdevice,
3060 (tbl->name ? tbl->name : "Unknown device"));
3061#endif
3062 return tbl->value;
3063 }
3064 return -1;
3065}
3066EXPORT_SYMBOL_HDA(snd_hda_check_board_codec_sid_config);
3067
3068/**
Linus Torvalds1da177e2005-04-16 15:20:36 -07003069 * snd_hda_add_new_ctls - create controls from the array
3070 * @codec: the HDA codec
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01003071 * @knew: the array of struct snd_kcontrol_new
Linus Torvalds1da177e2005-04-16 15:20:36 -07003072 *
3073 * This helper function creates and add new controls in the given array.
3074 * The array must be terminated with an empty entry as terminator.
3075 *
3076 * Returns 0 if successful, or a negative error code.
3077 */
Takashi Iwai12f288b2007-08-02 15:51:59 +02003078int snd_hda_add_new_ctls(struct hda_codec *codec, struct snd_kcontrol_new *knew)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003079{
Takashi Iwaicb53c622007-08-10 17:21:45 +02003080 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003081
3082 for (; knew->name; knew++) {
Takashi Iwai54d17402005-11-21 16:33:22 +01003083 struct snd_kcontrol *kctl;
3084 kctl = snd_ctl_new1(knew, codec);
Takashi Iwai0ba21762007-04-16 11:29:14 +02003085 if (!kctl)
Takashi Iwai54d17402005-11-21 16:33:22 +01003086 return -ENOMEM;
Takashi Iwaid13bd412008-07-30 15:01:45 +02003087 err = snd_hda_ctl_add(codec, kctl);
Takashi Iwai54d17402005-11-21 16:33:22 +01003088 if (err < 0) {
Takashi Iwai0ba21762007-04-16 11:29:14 +02003089 if (!codec->addr)
Takashi Iwai54d17402005-11-21 16:33:22 +01003090 return err;
3091 kctl = snd_ctl_new1(knew, codec);
Takashi Iwai0ba21762007-04-16 11:29:14 +02003092 if (!kctl)
Takashi Iwai54d17402005-11-21 16:33:22 +01003093 return -ENOMEM;
3094 kctl->id.device = codec->addr;
Takashi Iwaid13bd412008-07-30 15:01:45 +02003095 err = snd_hda_ctl_add(codec, kctl);
Takashi Iwai0ba21762007-04-16 11:29:14 +02003096 if (err < 0)
Takashi Iwai54d17402005-11-21 16:33:22 +01003097 return err;
3098 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003099 }
3100 return 0;
3101}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003102EXPORT_SYMBOL_HDA(snd_hda_add_new_ctls);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003103
Takashi Iwaicb53c622007-08-10 17:21:45 +02003104#ifdef CONFIG_SND_HDA_POWER_SAVE
3105static void hda_set_power_state(struct hda_codec *codec, hda_nid_t fg,
3106 unsigned int power_state);
3107
3108static void hda_power_work(struct work_struct *work)
3109{
3110 struct hda_codec *codec =
3111 container_of(work, struct hda_codec, power_work.work);
Takashi Iwai33fa35e2008-11-06 16:50:40 +01003112 struct hda_bus *bus = codec->bus;
Takashi Iwaicb53c622007-08-10 17:21:45 +02003113
Maxim Levitsky2e492462007-09-03 15:26:57 +02003114 if (!codec->power_on || codec->power_count) {
3115 codec->power_transition = 0;
Takashi Iwaicb53c622007-08-10 17:21:45 +02003116 return;
Maxim Levitsky2e492462007-09-03 15:26:57 +02003117 }
Takashi Iwaicb53c622007-08-10 17:21:45 +02003118
3119 hda_call_codec_suspend(codec);
Takashi Iwai33fa35e2008-11-06 16:50:40 +01003120 if (bus->ops.pm_notify)
3121 bus->ops.pm_notify(bus);
Takashi Iwaicb53c622007-08-10 17:21:45 +02003122}
3123
3124static void hda_keep_power_on(struct hda_codec *codec)
3125{
3126 codec->power_count++;
3127 codec->power_on = 1;
3128}
3129
3130void snd_hda_power_up(struct hda_codec *codec)
3131{
Takashi Iwai33fa35e2008-11-06 16:50:40 +01003132 struct hda_bus *bus = codec->bus;
3133
Takashi Iwaicb53c622007-08-10 17:21:45 +02003134 codec->power_count++;
Takashi Iwaia221e282007-08-16 16:35:33 +02003135 if (codec->power_on || codec->power_transition)
Takashi Iwaicb53c622007-08-10 17:21:45 +02003136 return;
3137
3138 codec->power_on = 1;
Takashi Iwai33fa35e2008-11-06 16:50:40 +01003139 if (bus->ops.pm_notify)
3140 bus->ops.pm_notify(bus);
Takashi Iwaicb53c622007-08-10 17:21:45 +02003141 hda_call_codec_resume(codec);
3142 cancel_delayed_work(&codec->power_work);
Takashi Iwaia221e282007-08-16 16:35:33 +02003143 codec->power_transition = 0;
Takashi Iwaicb53c622007-08-10 17:21:45 +02003144}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003145EXPORT_SYMBOL_HDA(snd_hda_power_up);
Takashi Iwai1289e9e2008-11-27 15:47:11 +01003146
3147#define power_save(codec) \
3148 ((codec)->bus->power_save ? *(codec)->bus->power_save : 0)
Takashi Iwaicb53c622007-08-10 17:21:45 +02003149
Takashi Iwaifee2fba2008-11-27 12:43:28 +01003150#define power_save(codec) \
3151 ((codec)->bus->power_save ? *(codec)->bus->power_save : 0)
3152
Takashi Iwaicb53c622007-08-10 17:21:45 +02003153void snd_hda_power_down(struct hda_codec *codec)
3154{
3155 --codec->power_count;
Takashi Iwaia221e282007-08-16 16:35:33 +02003156 if (!codec->power_on || codec->power_count || codec->power_transition)
Takashi Iwaicb53c622007-08-10 17:21:45 +02003157 return;
Takashi Iwaifee2fba2008-11-27 12:43:28 +01003158 if (power_save(codec)) {
Takashi Iwaia221e282007-08-16 16:35:33 +02003159 codec->power_transition = 1; /* avoid reentrance */
Takashi Iwaic107b412009-01-13 17:46:37 +01003160 queue_delayed_work(codec->bus->workq, &codec->power_work,
Takashi Iwaifee2fba2008-11-27 12:43:28 +01003161 msecs_to_jiffies(power_save(codec) * 1000));
Takashi Iwaia221e282007-08-16 16:35:33 +02003162 }
Takashi Iwaicb53c622007-08-10 17:21:45 +02003163}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003164EXPORT_SYMBOL_HDA(snd_hda_power_down);
Takashi Iwaicb53c622007-08-10 17:21:45 +02003165
3166int snd_hda_check_amp_list_power(struct hda_codec *codec,
3167 struct hda_loopback_check *check,
3168 hda_nid_t nid)
3169{
3170 struct hda_amp_list *p;
3171 int ch, v;
3172
3173 if (!check->amplist)
3174 return 0;
3175 for (p = check->amplist; p->nid; p++) {
3176 if (p->nid == nid)
3177 break;
3178 }
3179 if (!p->nid)
3180 return 0; /* nothing changed */
3181
3182 for (p = check->amplist; p->nid; p++) {
3183 for (ch = 0; ch < 2; ch++) {
3184 v = snd_hda_codec_amp_read(codec, p->nid, ch, p->dir,
3185 p->idx);
3186 if (!(v & HDA_AMP_MUTE) && v > 0) {
3187 if (!check->power_on) {
3188 check->power_on = 1;
3189 snd_hda_power_up(codec);
3190 }
3191 return 1;
3192 }
3193 }
3194 }
3195 if (check->power_on) {
3196 check->power_on = 0;
3197 snd_hda_power_down(codec);
3198 }
3199 return 0;
3200}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003201EXPORT_SYMBOL_HDA(snd_hda_check_amp_list_power);
Takashi Iwaicb53c622007-08-10 17:21:45 +02003202#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07003203
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01003204/*
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01003205 * Channel mode helper
3206 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003207int snd_hda_ch_mode_info(struct hda_codec *codec,
3208 struct snd_ctl_elem_info *uinfo,
3209 const struct hda_channel_mode *chmode,
3210 int num_chmodes)
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01003211{
3212 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
3213 uinfo->count = 1;
3214 uinfo->value.enumerated.items = num_chmodes;
3215 if (uinfo->value.enumerated.item >= num_chmodes)
3216 uinfo->value.enumerated.item = num_chmodes - 1;
3217 sprintf(uinfo->value.enumerated.name, "%dch",
3218 chmode[uinfo->value.enumerated.item].channels);
3219 return 0;
3220}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003221EXPORT_SYMBOL_HDA(snd_hda_ch_mode_info);
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01003222
Takashi Iwai0ba21762007-04-16 11:29:14 +02003223int snd_hda_ch_mode_get(struct hda_codec *codec,
3224 struct snd_ctl_elem_value *ucontrol,
3225 const struct hda_channel_mode *chmode,
3226 int num_chmodes,
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01003227 int max_channels)
3228{
3229 int i;
3230
3231 for (i = 0; i < num_chmodes; i++) {
3232 if (max_channels == chmode[i].channels) {
3233 ucontrol->value.enumerated.item[0] = i;
3234 break;
3235 }
3236 }
3237 return 0;
3238}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003239EXPORT_SYMBOL_HDA(snd_hda_ch_mode_get);
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01003240
Takashi Iwai0ba21762007-04-16 11:29:14 +02003241int snd_hda_ch_mode_put(struct hda_codec *codec,
3242 struct snd_ctl_elem_value *ucontrol,
3243 const struct hda_channel_mode *chmode,
3244 int num_chmodes,
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01003245 int *max_channelsp)
3246{
3247 unsigned int mode;
3248
3249 mode = ucontrol->value.enumerated.item[0];
Takashi Iwai68ea7b22007-11-15 15:54:38 +01003250 if (mode >= num_chmodes)
3251 return -EINVAL;
Takashi Iwai82beb8f2007-08-10 17:09:26 +02003252 if (*max_channelsp == chmode[mode].channels)
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01003253 return 0;
3254 /* change the current channel setting */
3255 *max_channelsp = chmode[mode].channels;
3256 if (chmode[mode].sequence)
Takashi Iwai82beb8f2007-08-10 17:09:26 +02003257 snd_hda_sequence_write_cache(codec, chmode[mode].sequence);
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01003258 return 1;
3259}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003260EXPORT_SYMBOL_HDA(snd_hda_ch_mode_put);
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01003261
Linus Torvalds1da177e2005-04-16 15:20:36 -07003262/*
3263 * input MUX helper
3264 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003265int snd_hda_input_mux_info(const struct hda_input_mux *imux,
3266 struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003267{
3268 unsigned int index;
3269
3270 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
3271 uinfo->count = 1;
3272 uinfo->value.enumerated.items = imux->num_items;
Takashi Iwai5513b0c2007-10-09 11:58:41 +02003273 if (!imux->num_items)
3274 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003275 index = uinfo->value.enumerated.item;
3276 if (index >= imux->num_items)
3277 index = imux->num_items - 1;
3278 strcpy(uinfo->value.enumerated.name, imux->items[index].label);
3279 return 0;
3280}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003281EXPORT_SYMBOL_HDA(snd_hda_input_mux_info);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003282
Takashi Iwai0ba21762007-04-16 11:29:14 +02003283int snd_hda_input_mux_put(struct hda_codec *codec,
3284 const struct hda_input_mux *imux,
3285 struct snd_ctl_elem_value *ucontrol,
3286 hda_nid_t nid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003287 unsigned int *cur_val)
3288{
3289 unsigned int idx;
3290
Takashi Iwai5513b0c2007-10-09 11:58:41 +02003291 if (!imux->num_items)
3292 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003293 idx = ucontrol->value.enumerated.item[0];
3294 if (idx >= imux->num_items)
3295 idx = imux->num_items - 1;
Takashi Iwai82beb8f2007-08-10 17:09:26 +02003296 if (*cur_val == idx)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003297 return 0;
Takashi Iwai82beb8f2007-08-10 17:09:26 +02003298 snd_hda_codec_write_cache(codec, nid, 0, AC_VERB_SET_CONNECT_SEL,
3299 imux->items[idx].index);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003300 *cur_val = idx;
3301 return 1;
3302}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003303EXPORT_SYMBOL_HDA(snd_hda_input_mux_put);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003304
3305
3306/*
3307 * Multi-channel / digital-out PCM helper functions
3308 */
3309
Takashi Iwai6b97eb42007-04-05 14:51:48 +02003310/* setup SPDIF output stream */
3311static void setup_dig_out_stream(struct hda_codec *codec, hda_nid_t nid,
3312 unsigned int stream_tag, unsigned int format)
3313{
3314 /* turn off SPDIF once; otherwise the IEC958 bits won't be updated */
Takashi Iwai2f728532008-09-25 16:32:41 +02003315 if (codec->spdif_status_reset && (codec->spdif_ctls & AC_DIG1_ENABLE))
3316 set_dig_out_convert(codec, nid,
3317 codec->spdif_ctls & ~AC_DIG1_ENABLE & 0xff,
3318 -1);
Takashi Iwai6b97eb42007-04-05 14:51:48 +02003319 snd_hda_codec_setup_stream(codec, nid, stream_tag, 0, format);
Takashi Iwai2f728532008-09-25 16:32:41 +02003320 if (codec->slave_dig_outs) {
3321 hda_nid_t *d;
3322 for (d = codec->slave_dig_outs; *d; d++)
3323 snd_hda_codec_setup_stream(codec, *d, stream_tag, 0,
3324 format);
Matthew Ranostayde51ca12008-09-07 14:31:40 -04003325 }
Takashi Iwai2f728532008-09-25 16:32:41 +02003326 /* turn on again (if needed) */
3327 if (codec->spdif_status_reset && (codec->spdif_ctls & AC_DIG1_ENABLE))
3328 set_dig_out_convert(codec, nid,
3329 codec->spdif_ctls & 0xff, -1);
3330}
Matthew Ranostayde51ca12008-09-07 14:31:40 -04003331
Takashi Iwai2f728532008-09-25 16:32:41 +02003332static void cleanup_dig_out_stream(struct hda_codec *codec, hda_nid_t nid)
3333{
3334 snd_hda_codec_cleanup_stream(codec, nid);
3335 if (codec->slave_dig_outs) {
3336 hda_nid_t *d;
3337 for (d = codec->slave_dig_outs; *d; d++)
3338 snd_hda_codec_cleanup_stream(codec, *d);
3339 }
Takashi Iwai6b97eb42007-04-05 14:51:48 +02003340}
3341
Linus Torvalds1da177e2005-04-16 15:20:36 -07003342/*
3343 * open the digital out in the exclusive mode
3344 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003345int snd_hda_multi_out_dig_open(struct hda_codec *codec,
3346 struct hda_multi_out *mout)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003347{
Ingo Molnar62932df2006-01-16 16:34:20 +01003348 mutex_lock(&codec->spdif_mutex);
Takashi Iwai5930ca42007-04-16 11:23:56 +02003349 if (mout->dig_out_used == HDA_DIG_ANALOG_DUP)
3350 /* already opened as analog dup; reset it once */
Takashi Iwai2f728532008-09-25 16:32:41 +02003351 cleanup_dig_out_stream(codec, mout->dig_out_nid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003352 mout->dig_out_used = HDA_DIG_EXCLUSIVE;
Ingo Molnar62932df2006-01-16 16:34:20 +01003353 mutex_unlock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003354 return 0;
3355}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003356EXPORT_SYMBOL_HDA(snd_hda_multi_out_dig_open);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003357
Takashi Iwai6b97eb42007-04-05 14:51:48 +02003358int snd_hda_multi_out_dig_prepare(struct hda_codec *codec,
3359 struct hda_multi_out *mout,
3360 unsigned int stream_tag,
3361 unsigned int format,
3362 struct snd_pcm_substream *substream)
3363{
3364 mutex_lock(&codec->spdif_mutex);
3365 setup_dig_out_stream(codec, mout->dig_out_nid, stream_tag, format);
3366 mutex_unlock(&codec->spdif_mutex);
3367 return 0;
3368}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003369EXPORT_SYMBOL_HDA(snd_hda_multi_out_dig_prepare);
Takashi Iwai6b97eb42007-04-05 14:51:48 +02003370
Takashi Iwai9411e212009-02-13 11:32:28 +01003371int snd_hda_multi_out_dig_cleanup(struct hda_codec *codec,
3372 struct hda_multi_out *mout)
3373{
3374 mutex_lock(&codec->spdif_mutex);
3375 cleanup_dig_out_stream(codec, mout->dig_out_nid);
3376 mutex_unlock(&codec->spdif_mutex);
3377 return 0;
3378}
3379EXPORT_SYMBOL_HDA(snd_hda_multi_out_dig_cleanup);
3380
Linus Torvalds1da177e2005-04-16 15:20:36 -07003381/*
3382 * release the digital out
3383 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003384int snd_hda_multi_out_dig_close(struct hda_codec *codec,
3385 struct hda_multi_out *mout)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003386{
Ingo Molnar62932df2006-01-16 16:34:20 +01003387 mutex_lock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003388 mout->dig_out_used = 0;
Ingo Molnar62932df2006-01-16 16:34:20 +01003389 mutex_unlock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003390 return 0;
3391}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003392EXPORT_SYMBOL_HDA(snd_hda_multi_out_dig_close);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003393
3394/*
3395 * set up more restrictions for analog out
3396 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003397int snd_hda_multi_out_analog_open(struct hda_codec *codec,
3398 struct hda_multi_out *mout,
Takashi Iwai9a081602008-02-12 18:37:26 +01003399 struct snd_pcm_substream *substream,
3400 struct hda_pcm_stream *hinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003401{
Takashi Iwai9a081602008-02-12 18:37:26 +01003402 struct snd_pcm_runtime *runtime = substream->runtime;
3403 runtime->hw.channels_max = mout->max_channels;
3404 if (mout->dig_out_nid) {
3405 if (!mout->analog_rates) {
3406 mout->analog_rates = hinfo->rates;
3407 mout->analog_formats = hinfo->formats;
3408 mout->analog_maxbps = hinfo->maxbps;
3409 } else {
3410 runtime->hw.rates = mout->analog_rates;
3411 runtime->hw.formats = mout->analog_formats;
3412 hinfo->maxbps = mout->analog_maxbps;
3413 }
3414 if (!mout->spdif_rates) {
3415 snd_hda_query_supported_pcm(codec, mout->dig_out_nid,
3416 &mout->spdif_rates,
3417 &mout->spdif_formats,
3418 &mout->spdif_maxbps);
3419 }
3420 mutex_lock(&codec->spdif_mutex);
3421 if (mout->share_spdif) {
3422 runtime->hw.rates &= mout->spdif_rates;
3423 runtime->hw.formats &= mout->spdif_formats;
3424 if (mout->spdif_maxbps < hinfo->maxbps)
3425 hinfo->maxbps = mout->spdif_maxbps;
3426 }
Frederik Deweerdteaa99852008-04-14 13:11:44 +02003427 mutex_unlock(&codec->spdif_mutex);
Takashi Iwai9a081602008-02-12 18:37:26 +01003428 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003429 return snd_pcm_hw_constraint_step(substream->runtime, 0,
3430 SNDRV_PCM_HW_PARAM_CHANNELS, 2);
3431}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003432EXPORT_SYMBOL_HDA(snd_hda_multi_out_analog_open);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003433
3434/*
3435 * set up the i/o for analog out
3436 * when the digital out is available, copy the front out to digital out, too.
3437 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003438int snd_hda_multi_out_analog_prepare(struct hda_codec *codec,
3439 struct hda_multi_out *mout,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003440 unsigned int stream_tag,
3441 unsigned int format,
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01003442 struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003443{
3444 hda_nid_t *nids = mout->dac_nids;
3445 int chs = substream->runtime->channels;
3446 int i;
3447
Ingo Molnar62932df2006-01-16 16:34:20 +01003448 mutex_lock(&codec->spdif_mutex);
Takashi Iwai9a081602008-02-12 18:37:26 +01003449 if (mout->dig_out_nid && mout->share_spdif &&
3450 mout->dig_out_used != HDA_DIG_EXCLUSIVE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003451 if (chs == 2 &&
Takashi Iwai0ba21762007-04-16 11:29:14 +02003452 snd_hda_is_supported_format(codec, mout->dig_out_nid,
3453 format) &&
3454 !(codec->spdif_status & IEC958_AES0_NONAUDIO)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003455 mout->dig_out_used = HDA_DIG_ANALOG_DUP;
Takashi Iwai6b97eb42007-04-05 14:51:48 +02003456 setup_dig_out_stream(codec, mout->dig_out_nid,
3457 stream_tag, format);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003458 } else {
3459 mout->dig_out_used = 0;
Takashi Iwai2f728532008-09-25 16:32:41 +02003460 cleanup_dig_out_stream(codec, mout->dig_out_nid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003461 }
3462 }
Ingo Molnar62932df2006-01-16 16:34:20 +01003463 mutex_unlock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003464
3465 /* front */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003466 snd_hda_codec_setup_stream(codec, nids[HDA_FRONT], stream_tag,
3467 0, format);
Takashi Iwaid29240c2007-10-26 12:35:56 +02003468 if (!mout->no_share_stream &&
3469 mout->hp_nid && mout->hp_nid != nids[HDA_FRONT])
Linus Torvalds1da177e2005-04-16 15:20:36 -07003470 /* headphone out will just decode front left/right (stereo) */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003471 snd_hda_codec_setup_stream(codec, mout->hp_nid, stream_tag,
3472 0, format);
Takashi Iwai82bc9552006-03-21 11:24:42 +01003473 /* extra outputs copied from front */
3474 for (i = 0; i < ARRAY_SIZE(mout->extra_out_nid); i++)
Takashi Iwaid29240c2007-10-26 12:35:56 +02003475 if (!mout->no_share_stream && mout->extra_out_nid[i])
Takashi Iwai82bc9552006-03-21 11:24:42 +01003476 snd_hda_codec_setup_stream(codec,
3477 mout->extra_out_nid[i],
3478 stream_tag, 0, format);
3479
Linus Torvalds1da177e2005-04-16 15:20:36 -07003480 /* surrounds */
3481 for (i = 1; i < mout->num_dacs; i++) {
Takashi Iwai4b3acaf2005-06-10 19:48:10 +02003482 if (chs >= (i + 1) * 2) /* independent out */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003483 snd_hda_codec_setup_stream(codec, nids[i], stream_tag,
3484 i * 2, format);
Takashi Iwaid29240c2007-10-26 12:35:56 +02003485 else if (!mout->no_share_stream) /* copy front */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003486 snd_hda_codec_setup_stream(codec, nids[i], stream_tag,
3487 0, format);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003488 }
3489 return 0;
3490}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003491EXPORT_SYMBOL_HDA(snd_hda_multi_out_analog_prepare);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003492
3493/*
3494 * clean up the setting for analog out
3495 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003496int snd_hda_multi_out_analog_cleanup(struct hda_codec *codec,
3497 struct hda_multi_out *mout)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003498{
3499 hda_nid_t *nids = mout->dac_nids;
3500 int i;
3501
3502 for (i = 0; i < mout->num_dacs; i++)
Takashi Iwai888afa12008-03-18 09:57:50 +01003503 snd_hda_codec_cleanup_stream(codec, nids[i]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003504 if (mout->hp_nid)
Takashi Iwai888afa12008-03-18 09:57:50 +01003505 snd_hda_codec_cleanup_stream(codec, mout->hp_nid);
Takashi Iwai82bc9552006-03-21 11:24:42 +01003506 for (i = 0; i < ARRAY_SIZE(mout->extra_out_nid); i++)
3507 if (mout->extra_out_nid[i])
Takashi Iwai888afa12008-03-18 09:57:50 +01003508 snd_hda_codec_cleanup_stream(codec,
3509 mout->extra_out_nid[i]);
Ingo Molnar62932df2006-01-16 16:34:20 +01003510 mutex_lock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003511 if (mout->dig_out_nid && mout->dig_out_used == HDA_DIG_ANALOG_DUP) {
Takashi Iwai2f728532008-09-25 16:32:41 +02003512 cleanup_dig_out_stream(codec, mout->dig_out_nid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003513 mout->dig_out_used = 0;
3514 }
Ingo Molnar62932df2006-01-16 16:34:20 +01003515 mutex_unlock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003516 return 0;
3517}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003518EXPORT_SYMBOL_HDA(snd_hda_multi_out_analog_cleanup);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003519
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003520/*
Wu Fengguang6b345002008-10-07 14:21:41 +08003521 * Helper for automatic pin configuration
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003522 */
Kailang Yangdf694da2005-12-05 19:42:22 +01003523
Takashi Iwai12f288b2007-08-02 15:51:59 +02003524static int is_in_nid_list(hda_nid_t nid, hda_nid_t *list)
Kailang Yangdf694da2005-12-05 19:42:22 +01003525{
3526 for (; *list; list++)
3527 if (*list == nid)
3528 return 1;
3529 return 0;
3530}
3531
Steve Longerbeam81937d32007-05-08 15:33:03 +02003532
3533/*
3534 * Sort an associated group of pins according to their sequence numbers.
3535 */
3536static void sort_pins_by_sequence(hda_nid_t * pins, short * sequences,
3537 int num_pins)
3538{
3539 int i, j;
3540 short seq;
3541 hda_nid_t nid;
3542
3543 for (i = 0; i < num_pins; i++) {
3544 for (j = i + 1; j < num_pins; j++) {
3545 if (sequences[i] > sequences[j]) {
3546 seq = sequences[i];
3547 sequences[i] = sequences[j];
3548 sequences[j] = seq;
3549 nid = pins[i];
3550 pins[i] = pins[j];
3551 pins[j] = nid;
3552 }
3553 }
3554 }
3555}
3556
3557
Takashi Iwai82bc9552006-03-21 11:24:42 +01003558/*
3559 * Parse all pin widgets and store the useful pin nids to cfg
3560 *
3561 * The number of line-outs or any primary output is stored in line_outs,
3562 * and the corresponding output pins are assigned to line_out_pins[],
3563 * in the order of front, rear, CLFE, side, ...
3564 *
3565 * If more extra outputs (speaker and headphone) are found, the pins are
Takashi Iwaieb06ed82006-09-20 17:10:27 +02003566 * assisnged to hp_pins[] and speaker_pins[], respectively. If no line-out jack
Takashi Iwai82bc9552006-03-21 11:24:42 +01003567 * is detected, one of speaker of HP pins is assigned as the primary
3568 * output, i.e. to line_out_pins[0]. So, line_outs is always positive
3569 * if any analog output exists.
3570 *
3571 * The analog input pins are assigned to input_pins array.
3572 * The digital input/output pins are assigned to dig_in_pin and dig_out_pin,
3573 * respectively.
3574 */
Takashi Iwai12f288b2007-08-02 15:51:59 +02003575int snd_hda_parse_pin_def_config(struct hda_codec *codec,
3576 struct auto_pin_cfg *cfg,
3577 hda_nid_t *ignore_nids)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003578{
Takashi Iwai0ef6ce72008-01-22 15:35:37 +01003579 hda_nid_t nid, end_nid;
Steve Longerbeam81937d32007-05-08 15:33:03 +02003580 short seq, assoc_line_out, assoc_speaker;
3581 short sequences_line_out[ARRAY_SIZE(cfg->line_out_pins)];
3582 short sequences_speaker[ARRAY_SIZE(cfg->speaker_pins)];
Takashi Iwaif889fa92007-10-31 15:49:32 +01003583 short sequences_hp[ARRAY_SIZE(cfg->hp_pins)];
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003584
3585 memset(cfg, 0, sizeof(*cfg));
3586
Steve Longerbeam81937d32007-05-08 15:33:03 +02003587 memset(sequences_line_out, 0, sizeof(sequences_line_out));
3588 memset(sequences_speaker, 0, sizeof(sequences_speaker));
Takashi Iwaif889fa92007-10-31 15:49:32 +01003589 memset(sequences_hp, 0, sizeof(sequences_hp));
Steve Longerbeam81937d32007-05-08 15:33:03 +02003590 assoc_line_out = assoc_speaker = 0;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003591
Takashi Iwai0ef6ce72008-01-22 15:35:37 +01003592 end_nid = codec->start_nid + codec->num_nodes;
3593 for (nid = codec->start_nid; nid < end_nid; nid++) {
Takashi Iwai54d17402005-11-21 16:33:22 +01003594 unsigned int wid_caps = get_wcaps(codec, nid);
Takashi Iwai0ba21762007-04-16 11:29:14 +02003595 unsigned int wid_type =
3596 (wid_caps & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003597 unsigned int def_conf;
3598 short assoc, loc;
3599
3600 /* read all default configuration for pin complex */
3601 if (wid_type != AC_WID_PIN)
3602 continue;
Kailang Yangdf694da2005-12-05 19:42:22 +01003603 /* ignore the given nids (e.g. pc-beep returns error) */
3604 if (ignore_nids && is_in_nid_list(nid, ignore_nids))
3605 continue;
3606
Takashi Iwaic17a1ab2009-02-23 09:28:12 +01003607 def_conf = snd_hda_codec_get_pincfg(codec, nid);
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003608 if (get_defcfg_connect(def_conf) == AC_JACK_PORT_NONE)
3609 continue;
3610 loc = get_defcfg_location(def_conf);
3611 switch (get_defcfg_device(def_conf)) {
3612 case AC_JACK_LINE_OUT:
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003613 seq = get_defcfg_sequence(def_conf);
3614 assoc = get_defcfg_association(def_conf);
Matthew Ranostay90da78b2008-01-24 11:48:01 +01003615
3616 if (!(wid_caps & AC_WCAP_STEREO))
3617 if (!cfg->mono_out_pin)
3618 cfg->mono_out_pin = nid;
Takashi Iwai0ba21762007-04-16 11:29:14 +02003619 if (!assoc)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003620 continue;
Takashi Iwai0ba21762007-04-16 11:29:14 +02003621 if (!assoc_line_out)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003622 assoc_line_out = assoc;
3623 else if (assoc_line_out != assoc)
3624 continue;
3625 if (cfg->line_outs >= ARRAY_SIZE(cfg->line_out_pins))
3626 continue;
3627 cfg->line_out_pins[cfg->line_outs] = nid;
Steve Longerbeam81937d32007-05-08 15:33:03 +02003628 sequences_line_out[cfg->line_outs] = seq;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003629 cfg->line_outs++;
3630 break;
Takashi Iwai8d88bc32005-11-17 11:09:23 +01003631 case AC_JACK_SPEAKER:
Steve Longerbeam81937d32007-05-08 15:33:03 +02003632 seq = get_defcfg_sequence(def_conf);
3633 assoc = get_defcfg_association(def_conf);
3634 if (! assoc)
3635 continue;
3636 if (! assoc_speaker)
3637 assoc_speaker = assoc;
3638 else if (assoc_speaker != assoc)
3639 continue;
Takashi Iwai82bc9552006-03-21 11:24:42 +01003640 if (cfg->speaker_outs >= ARRAY_SIZE(cfg->speaker_pins))
3641 continue;
3642 cfg->speaker_pins[cfg->speaker_outs] = nid;
Steve Longerbeam81937d32007-05-08 15:33:03 +02003643 sequences_speaker[cfg->speaker_outs] = seq;
Takashi Iwai82bc9552006-03-21 11:24:42 +01003644 cfg->speaker_outs++;
Takashi Iwai8d88bc32005-11-17 11:09:23 +01003645 break;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003646 case AC_JACK_HP_OUT:
Takashi Iwaif889fa92007-10-31 15:49:32 +01003647 seq = get_defcfg_sequence(def_conf);
3648 assoc = get_defcfg_association(def_conf);
Takashi Iwaieb06ed82006-09-20 17:10:27 +02003649 if (cfg->hp_outs >= ARRAY_SIZE(cfg->hp_pins))
3650 continue;
3651 cfg->hp_pins[cfg->hp_outs] = nid;
Takashi Iwaif889fa92007-10-31 15:49:32 +01003652 sequences_hp[cfg->hp_outs] = (assoc << 4) | seq;
Takashi Iwaieb06ed82006-09-20 17:10:27 +02003653 cfg->hp_outs++;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003654 break;
Takashi Iwai314634b2006-09-21 11:56:18 +02003655 case AC_JACK_MIC_IN: {
3656 int preferred, alt;
3657 if (loc == AC_JACK_LOC_FRONT) {
3658 preferred = AUTO_PIN_FRONT_MIC;
3659 alt = AUTO_PIN_MIC;
3660 } else {
3661 preferred = AUTO_PIN_MIC;
3662 alt = AUTO_PIN_FRONT_MIC;
3663 }
3664 if (!cfg->input_pins[preferred])
3665 cfg->input_pins[preferred] = nid;
3666 else if (!cfg->input_pins[alt])
3667 cfg->input_pins[alt] = nid;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003668 break;
Takashi Iwai314634b2006-09-21 11:56:18 +02003669 }
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003670 case AC_JACK_LINE_IN:
3671 if (loc == AC_JACK_LOC_FRONT)
3672 cfg->input_pins[AUTO_PIN_FRONT_LINE] = nid;
3673 else
3674 cfg->input_pins[AUTO_PIN_LINE] = nid;
3675 break;
3676 case AC_JACK_CD:
3677 cfg->input_pins[AUTO_PIN_CD] = nid;
3678 break;
3679 case AC_JACK_AUX:
3680 cfg->input_pins[AUTO_PIN_AUX] = nid;
3681 break;
3682 case AC_JACK_SPDIF_OUT:
Takashi Iwai1b52ae72009-01-20 17:17:29 +01003683 case AC_JACK_DIG_OTHER_OUT:
Takashi Iwai0852d7a2009-02-11 11:35:15 +01003684 if (cfg->dig_outs >= ARRAY_SIZE(cfg->dig_out_pins))
3685 continue;
3686 cfg->dig_out_pins[cfg->dig_outs] = nid;
3687 cfg->dig_out_type[cfg->dig_outs] =
3688 (loc == AC_JACK_LOC_HDMI) ?
3689 HDA_PCM_TYPE_HDMI : HDA_PCM_TYPE_SPDIF;
3690 cfg->dig_outs++;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003691 break;
3692 case AC_JACK_SPDIF_IN:
Takashi Iwai1b52ae72009-01-20 17:17:29 +01003693 case AC_JACK_DIG_OTHER_IN:
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003694 cfg->dig_in_pin = nid;
Takashi Iwai2297bd62009-01-20 18:24:13 +01003695 if (loc == AC_JACK_LOC_HDMI)
3696 cfg->dig_in_type = HDA_PCM_TYPE_HDMI;
3697 else
3698 cfg->dig_in_type = HDA_PCM_TYPE_SPDIF;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003699 break;
3700 }
3701 }
3702
Takashi Iwai5832fcf2008-02-12 18:30:12 +01003703 /* FIX-UP:
3704 * If no line-out is defined but multiple HPs are found,
3705 * some of them might be the real line-outs.
3706 */
3707 if (!cfg->line_outs && cfg->hp_outs > 1) {
3708 int i = 0;
3709 while (i < cfg->hp_outs) {
3710 /* The real HPs should have the sequence 0x0f */
3711 if ((sequences_hp[i] & 0x0f) == 0x0f) {
3712 i++;
3713 continue;
3714 }
3715 /* Move it to the line-out table */
3716 cfg->line_out_pins[cfg->line_outs] = cfg->hp_pins[i];
3717 sequences_line_out[cfg->line_outs] = sequences_hp[i];
3718 cfg->line_outs++;
3719 cfg->hp_outs--;
3720 memmove(cfg->hp_pins + i, cfg->hp_pins + i + 1,
3721 sizeof(cfg->hp_pins[0]) * (cfg->hp_outs - i));
3722 memmove(sequences_hp + i - 1, sequences_hp + i,
3723 sizeof(sequences_hp[0]) * (cfg->hp_outs - i));
3724 }
3725 }
3726
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003727 /* sort by sequence */
Steve Longerbeam81937d32007-05-08 15:33:03 +02003728 sort_pins_by_sequence(cfg->line_out_pins, sequences_line_out,
3729 cfg->line_outs);
3730 sort_pins_by_sequence(cfg->speaker_pins, sequences_speaker,
3731 cfg->speaker_outs);
Takashi Iwaif889fa92007-10-31 15:49:32 +01003732 sort_pins_by_sequence(cfg->hp_pins, sequences_hp,
3733 cfg->hp_outs);
Steve Longerbeam81937d32007-05-08 15:33:03 +02003734
Takashi Iwaif889fa92007-10-31 15:49:32 +01003735 /* if we have only one mic, make it AUTO_PIN_MIC */
3736 if (!cfg->input_pins[AUTO_PIN_MIC] &&
3737 cfg->input_pins[AUTO_PIN_FRONT_MIC]) {
3738 cfg->input_pins[AUTO_PIN_MIC] =
3739 cfg->input_pins[AUTO_PIN_FRONT_MIC];
3740 cfg->input_pins[AUTO_PIN_FRONT_MIC] = 0;
3741 }
3742 /* ditto for line-in */
3743 if (!cfg->input_pins[AUTO_PIN_LINE] &&
3744 cfg->input_pins[AUTO_PIN_FRONT_LINE]) {
3745 cfg->input_pins[AUTO_PIN_LINE] =
3746 cfg->input_pins[AUTO_PIN_FRONT_LINE];
3747 cfg->input_pins[AUTO_PIN_FRONT_LINE] = 0;
3748 }
3749
Steve Longerbeam81937d32007-05-08 15:33:03 +02003750 /*
3751 * FIX-UP: if no line-outs are detected, try to use speaker or HP pin
3752 * as a primary output
3753 */
3754 if (!cfg->line_outs) {
3755 if (cfg->speaker_outs) {
3756 cfg->line_outs = cfg->speaker_outs;
3757 memcpy(cfg->line_out_pins, cfg->speaker_pins,
3758 sizeof(cfg->speaker_pins));
3759 cfg->speaker_outs = 0;
3760 memset(cfg->speaker_pins, 0, sizeof(cfg->speaker_pins));
3761 cfg->line_out_type = AUTO_PIN_SPEAKER_OUT;
3762 } else if (cfg->hp_outs) {
3763 cfg->line_outs = cfg->hp_outs;
3764 memcpy(cfg->line_out_pins, cfg->hp_pins,
3765 sizeof(cfg->hp_pins));
3766 cfg->hp_outs = 0;
3767 memset(cfg->hp_pins, 0, sizeof(cfg->hp_pins));
3768 cfg->line_out_type = AUTO_PIN_HP_OUT;
3769 }
3770 }
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003771
Takashi Iwaicb8e2f82005-07-29 11:54:32 +02003772 /* Reorder the surround channels
3773 * ALSA sequence is front/surr/clfe/side
3774 * HDA sequence is:
3775 * 4-ch: front/surr => OK as it is
3776 * 6-ch: front/clfe/surr
Takashi Iwai9422db42007-04-20 16:11:43 +02003777 * 8-ch: front/clfe/rear/side|fc
Takashi Iwaicb8e2f82005-07-29 11:54:32 +02003778 */
3779 switch (cfg->line_outs) {
3780 case 3:
Takashi Iwaicb8e2f82005-07-29 11:54:32 +02003781 case 4:
3782 nid = cfg->line_out_pins[1];
Takashi Iwai9422db42007-04-20 16:11:43 +02003783 cfg->line_out_pins[1] = cfg->line_out_pins[2];
Takashi Iwaicb8e2f82005-07-29 11:54:32 +02003784 cfg->line_out_pins[2] = nid;
3785 break;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003786 }
3787
Takashi Iwai82bc9552006-03-21 11:24:42 +01003788 /*
3789 * debug prints of the parsed results
3790 */
3791 snd_printd("autoconfig: line_outs=%d (0x%x/0x%x/0x%x/0x%x/0x%x)\n",
3792 cfg->line_outs, cfg->line_out_pins[0], cfg->line_out_pins[1],
3793 cfg->line_out_pins[2], cfg->line_out_pins[3],
3794 cfg->line_out_pins[4]);
3795 snd_printd(" speaker_outs=%d (0x%x/0x%x/0x%x/0x%x/0x%x)\n",
3796 cfg->speaker_outs, cfg->speaker_pins[0],
3797 cfg->speaker_pins[1], cfg->speaker_pins[2],
3798 cfg->speaker_pins[3], cfg->speaker_pins[4]);
Takashi Iwaieb06ed82006-09-20 17:10:27 +02003799 snd_printd(" hp_outs=%d (0x%x/0x%x/0x%x/0x%x/0x%x)\n",
3800 cfg->hp_outs, cfg->hp_pins[0],
3801 cfg->hp_pins[1], cfg->hp_pins[2],
3802 cfg->hp_pins[3], cfg->hp_pins[4]);
Matthew Ranostay90da78b2008-01-24 11:48:01 +01003803 snd_printd(" mono: mono_out=0x%x\n", cfg->mono_out_pin);
Takashi Iwai0852d7a2009-02-11 11:35:15 +01003804 if (cfg->dig_outs)
3805 snd_printd(" dig-out=0x%x/0x%x\n",
3806 cfg->dig_out_pins[0], cfg->dig_out_pins[1]);
Takashi Iwai82bc9552006-03-21 11:24:42 +01003807 snd_printd(" inputs: mic=0x%x, fmic=0x%x, line=0x%x, fline=0x%x,"
3808 " cd=0x%x, aux=0x%x\n",
3809 cfg->input_pins[AUTO_PIN_MIC],
3810 cfg->input_pins[AUTO_PIN_FRONT_MIC],
3811 cfg->input_pins[AUTO_PIN_LINE],
3812 cfg->input_pins[AUTO_PIN_FRONT_LINE],
3813 cfg->input_pins[AUTO_PIN_CD],
3814 cfg->input_pins[AUTO_PIN_AUX]);
Takashi Iwai32d2c7f2009-02-11 11:33:13 +01003815 if (cfg->dig_in_pin)
Takashi Iwai89ce9e82009-01-20 17:15:57 +01003816 snd_printd(" dig-in=0x%x\n", cfg->dig_in_pin);
Takashi Iwai82bc9552006-03-21 11:24:42 +01003817
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003818 return 0;
3819}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003820EXPORT_SYMBOL_HDA(snd_hda_parse_pin_def_config);
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003821
Takashi Iwai4a471b72005-12-07 13:56:29 +01003822/* labels for input pins */
3823const char *auto_pin_cfg_labels[AUTO_PIN_LAST] = {
3824 "Mic", "Front Mic", "Line", "Front Line", "CD", "Aux"
3825};
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003826EXPORT_SYMBOL_HDA(auto_pin_cfg_labels);
Takashi Iwai4a471b72005-12-07 13:56:29 +01003827
3828
Linus Torvalds1da177e2005-04-16 15:20:36 -07003829#ifdef CONFIG_PM
3830/*
3831 * power management
3832 */
3833
3834/**
3835 * snd_hda_suspend - suspend the codecs
3836 * @bus: the HDA bus
3837 * @state: suspsend state
3838 *
3839 * Returns 0 if successful.
3840 */
3841int snd_hda_suspend(struct hda_bus *bus, pm_message_t state)
3842{
Takashi Iwai0ba21762007-04-16 11:29:14 +02003843 struct hda_codec *codec;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003844
Takashi Iwai0ba21762007-04-16 11:29:14 +02003845 list_for_each_entry(codec, &bus->codec_list, list) {
Takashi Iwai0b7a2e92007-08-14 15:18:26 +02003846#ifdef CONFIG_SND_HDA_POWER_SAVE
3847 if (!codec->power_on)
3848 continue;
3849#endif
Takashi Iwaicb53c622007-08-10 17:21:45 +02003850 hda_call_codec_suspend(codec);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003851 }
3852 return 0;
3853}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003854EXPORT_SYMBOL_HDA(snd_hda_suspend);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003855
3856/**
3857 * snd_hda_resume - resume the codecs
3858 * @bus: the HDA bus
Linus Torvalds1da177e2005-04-16 15:20:36 -07003859 *
3860 * Returns 0 if successful.
Takashi Iwaicb53c622007-08-10 17:21:45 +02003861 *
3862 * This fucntion is defined only when POWER_SAVE isn't set.
3863 * In the power-save mode, the codec is resumed dynamically.
Linus Torvalds1da177e2005-04-16 15:20:36 -07003864 */
3865int snd_hda_resume(struct hda_bus *bus)
3866{
Takashi Iwai0ba21762007-04-16 11:29:14 +02003867 struct hda_codec *codec;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003868
Takashi Iwai0ba21762007-04-16 11:29:14 +02003869 list_for_each_entry(codec, &bus->codec_list, list) {
Maxim Levitskyd804ad92007-09-03 15:28:04 +02003870 if (snd_hda_codec_needs_resume(codec))
3871 hda_call_codec_resume(codec);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003872 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003873 return 0;
3874}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003875EXPORT_SYMBOL_HDA(snd_hda_resume);
Takashi Iwai1289e9e2008-11-27 15:47:11 +01003876#endif /* CONFIG_PM */
Takashi Iwaib2e18592008-07-30 15:01:44 +02003877
3878/*
3879 * generic arrays
3880 */
3881
3882/* get a new element from the given array
3883 * if it exceeds the pre-allocated array size, re-allocate the array
3884 */
3885void *snd_array_new(struct snd_array *array)
3886{
3887 if (array->used >= array->alloced) {
3888 int num = array->alloced + array->alloc_align;
Takashi Iwaib910d9a2008-11-07 00:26:52 +01003889 void *nlist;
3890 if (snd_BUG_ON(num >= 4096))
3891 return NULL;
3892 nlist = kcalloc(num + 1, array->elem_size, GFP_KERNEL);
Takashi Iwaib2e18592008-07-30 15:01:44 +02003893 if (!nlist)
3894 return NULL;
3895 if (array->list) {
3896 memcpy(nlist, array->list,
3897 array->elem_size * array->alloced);
3898 kfree(array->list);
3899 }
3900 array->list = nlist;
3901 array->alloced = num;
3902 }
Takashi Iwaif43aa022008-11-10 16:24:26 +01003903 return snd_array_elem(array, array->used++);
Takashi Iwaib2e18592008-07-30 15:01:44 +02003904}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003905EXPORT_SYMBOL_HDA(snd_array_new);
Takashi Iwaib2e18592008-07-30 15:01:44 +02003906
3907/* free the given array elements */
3908void snd_array_free(struct snd_array *array)
3909{
3910 kfree(array->list);
3911 array->used = 0;
3912 array->alloced = 0;
3913 array->list = NULL;
3914}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003915EXPORT_SYMBOL_HDA(snd_array_free);
Takashi Iwaib2022262008-11-21 21:24:03 +01003916
3917/*
3918 * used by hda_proc.c and hda_eld.c
3919 */
3920void snd_print_pcm_rates(int pcm, char *buf, int buflen)
3921{
3922 static unsigned int rates[] = {
3923 8000, 11025, 16000, 22050, 32000, 44100, 48000, 88200,
3924 96000, 176400, 192000, 384000
3925 };
3926 int i, j;
3927
3928 for (i = 0, j = 0; i < ARRAY_SIZE(rates); i++)
3929 if (pcm & (1 << i))
3930 j += snprintf(buf + j, buflen - j, " %d", rates[i]);
3931
3932 buf[j] = '\0'; /* necessary when j == 0 */
3933}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003934EXPORT_SYMBOL_HDA(snd_print_pcm_rates);
Takashi Iwaib2022262008-11-21 21:24:03 +01003935
3936void snd_print_pcm_bits(int pcm, char *buf, int buflen)
3937{
3938 static unsigned int bits[] = { 8, 16, 20, 24, 32 };
3939 int i, j;
3940
3941 for (i = 0, j = 0; i < ARRAY_SIZE(bits); i++)
3942 if (pcm & (AC_SUPPCM_BITS_8 << i))
3943 j += snprintf(buf + j, buflen - j, " %d", bits[i]);
3944
3945 buf[j] = '\0'; /* necessary when j == 0 */
3946}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003947EXPORT_SYMBOL_HDA(snd_print_pcm_bits);
Takashi Iwai1289e9e2008-11-27 15:47:11 +01003948
3949MODULE_DESCRIPTION("HDA codec core");
3950MODULE_LICENSE("GPL");