blob: 48f0cea7df14a44cf1ee1a46c8ede639a053f1cc [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 Iwai18cb7102009-04-16 10:22:24 +02001434 if (snd_BUG_ON(strlen(name) >= sizeof(id.name)))
1435 return NULL;
Takashi Iwai2134ea42008-01-10 16:53:55 +01001436 strcpy(id.name, name);
1437 return snd_ctl_find_id(codec->bus->card, &id);
1438}
1439
Takashi Iwai09f99702008-02-04 12:31:13 +01001440struct snd_kcontrol *snd_hda_find_mixer_ctl(struct hda_codec *codec,
1441 const char *name)
1442{
1443 return _snd_hda_find_mixer_ctl(codec, name, 0);
1444}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001445EXPORT_SYMBOL_HDA(snd_hda_find_mixer_ctl);
Takashi Iwai09f99702008-02-04 12:31:13 +01001446
Takashi Iwaid13bd412008-07-30 15:01:45 +02001447/* Add a control element and assign to the codec */
1448int snd_hda_ctl_add(struct hda_codec *codec, struct snd_kcontrol *kctl)
1449{
1450 int err;
1451 struct snd_kcontrol **knewp;
1452
1453 err = snd_ctl_add(codec->bus->card, kctl);
1454 if (err < 0)
1455 return err;
1456 knewp = snd_array_new(&codec->mixers);
1457 if (!knewp)
1458 return -ENOMEM;
1459 *knewp = kctl;
1460 return 0;
1461}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001462EXPORT_SYMBOL_HDA(snd_hda_ctl_add);
Takashi Iwaid13bd412008-07-30 15:01:45 +02001463
1464/* Clear all controls assigned to the given codec */
1465void snd_hda_ctls_clear(struct hda_codec *codec)
1466{
1467 int i;
1468 struct snd_kcontrol **kctls = codec->mixers.list;
1469 for (i = 0; i < codec->mixers.used; i++)
1470 snd_ctl_remove(codec->bus->card, kctls[i]);
1471 snd_array_free(&codec->mixers);
1472}
1473
Takashi Iwaia65d6292009-02-23 16:57:04 +01001474/* pseudo device locking
1475 * toggle card->shutdown to allow/disallow the device access (as a hack)
1476 */
1477static int hda_lock_devices(struct snd_card *card)
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001478{
Takashi Iwaia65d6292009-02-23 16:57:04 +01001479 spin_lock(&card->files_lock);
1480 if (card->shutdown) {
1481 spin_unlock(&card->files_lock);
1482 return -EINVAL;
1483 }
1484 card->shutdown = 1;
1485 spin_unlock(&card->files_lock);
1486 return 0;
1487}
1488
1489static void hda_unlock_devices(struct snd_card *card)
1490{
1491 spin_lock(&card->files_lock);
1492 card->shutdown = 0;
1493 spin_unlock(&card->files_lock);
1494}
1495
1496int snd_hda_codec_reset(struct hda_codec *codec)
1497{
1498 struct snd_card *card = codec->bus->card;
1499 int i, pcm;
1500
1501 if (hda_lock_devices(card) < 0)
1502 return -EBUSY;
1503 /* check whether the codec isn't used by any mixer or PCM streams */
1504 if (!list_empty(&card->ctl_files)) {
1505 hda_unlock_devices(card);
1506 return -EBUSY;
1507 }
1508 for (pcm = 0; pcm < codec->num_pcms; pcm++) {
1509 struct hda_pcm *cpcm = &codec->pcm_info[pcm];
1510 if (!cpcm->pcm)
1511 continue;
1512 if (cpcm->pcm->streams[0].substream_opened ||
1513 cpcm->pcm->streams[1].substream_opened) {
1514 hda_unlock_devices(card);
1515 return -EBUSY;
1516 }
1517 }
1518
1519 /* OK, let it free */
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001520
1521#ifdef CONFIG_SND_HDA_POWER_SAVE
1522 cancel_delayed_work(&codec->power_work);
Takashi Iwai6acaed32009-01-12 10:09:24 +01001523 flush_workqueue(codec->bus->workq);
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001524#endif
1525 snd_hda_ctls_clear(codec);
1526 /* relase PCMs */
1527 for (i = 0; i < codec->num_pcms; i++) {
Takashi Iwai529bd6c2008-11-27 14:17:01 +01001528 if (codec->pcm_info[i].pcm) {
Takashi Iwaia65d6292009-02-23 16:57:04 +01001529 snd_device_free(card, codec->pcm_info[i].pcm);
Takashi Iwai529bd6c2008-11-27 14:17:01 +01001530 clear_bit(codec->pcm_info[i].device,
1531 codec->bus->pcm_dev_bits);
1532 }
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001533 }
1534 if (codec->patch_ops.free)
1535 codec->patch_ops.free(codec);
Takashi Iwai56d17712008-11-28 14:36:23 +01001536 codec->proc_widget_hook = NULL;
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001537 codec->spec = NULL;
1538 free_hda_cache(&codec->amp_cache);
1539 free_hda_cache(&codec->cmd_cache);
Takashi Iwai827057f2008-12-19 10:12:02 +01001540 init_hda_cache(&codec->amp_cache, sizeof(struct hda_amp_info));
1541 init_hda_cache(&codec->cmd_cache, sizeof(struct hda_cache_head));
Takashi Iwai346ff702009-02-23 09:42:57 +01001542 /* free only driver_pins so that init_pins + user_pins are restored */
1543 snd_array_free(&codec->driver_pins);
Takashi Iwai3be14142009-02-20 14:11:16 +01001544 restore_pincfgs(codec);
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001545 codec->num_pcms = 0;
1546 codec->pcm_info = NULL;
1547 codec->preset = NULL;
Takashi Iwaid1f1af22009-03-02 10:35:29 +01001548 memset(&codec->patch_ops, 0, sizeof(codec->patch_ops));
1549 codec->slave_dig_outs = NULL;
1550 codec->spdif_status_reset = 0;
Takashi Iwai1289e9e2008-11-27 15:47:11 +01001551 module_put(codec->owner);
1552 codec->owner = NULL;
Takashi Iwaia65d6292009-02-23 16:57:04 +01001553
1554 /* allow device access again */
1555 hda_unlock_devices(card);
1556 return 0;
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001557}
1558
Takashi Iwai2134ea42008-01-10 16:53:55 +01001559/* create a virtual master control and add slaves */
1560int snd_hda_add_vmaster(struct hda_codec *codec, char *name,
1561 unsigned int *tlv, const char **slaves)
1562{
1563 struct snd_kcontrol *kctl;
1564 const char **s;
1565 int err;
1566
Takashi Iwai2f085542008-02-22 18:43:50 +01001567 for (s = slaves; *s && !snd_hda_find_mixer_ctl(codec, *s); s++)
1568 ;
1569 if (!*s) {
1570 snd_printdd("No slave found for %s\n", name);
1571 return 0;
1572 }
Takashi Iwai2134ea42008-01-10 16:53:55 +01001573 kctl = snd_ctl_make_virtual_master(name, tlv);
1574 if (!kctl)
1575 return -ENOMEM;
Takashi Iwaid13bd412008-07-30 15:01:45 +02001576 err = snd_hda_ctl_add(codec, kctl);
Takashi Iwai2134ea42008-01-10 16:53:55 +01001577 if (err < 0)
1578 return err;
1579
1580 for (s = slaves; *s; s++) {
1581 struct snd_kcontrol *sctl;
Takashi Iwai7a411ee2009-03-06 10:08:14 +01001582 int i = 0;
1583 for (;;) {
1584 sctl = _snd_hda_find_mixer_ctl(codec, *s, i);
1585 if (!sctl) {
1586 if (!i)
1587 snd_printdd("Cannot find slave %s, "
1588 "skipped\n", *s);
1589 break;
1590 }
1591 err = snd_ctl_add_slave(kctl, sctl);
1592 if (err < 0)
1593 return err;
1594 i++;
Takashi Iwai2134ea42008-01-10 16:53:55 +01001595 }
Takashi Iwai2134ea42008-01-10 16:53:55 +01001596 }
1597 return 0;
1598}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001599EXPORT_SYMBOL_HDA(snd_hda_add_vmaster);
Takashi Iwai2134ea42008-01-10 16:53:55 +01001600
Linus Torvalds1da177e2005-04-16 15:20:36 -07001601/* switch */
Takashi Iwai0ba21762007-04-16 11:29:14 +02001602int snd_hda_mixer_amp_switch_info(struct snd_kcontrol *kcontrol,
1603 struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001604{
1605 int chs = get_amp_channels(kcontrol);
1606
1607 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
1608 uinfo->count = chs == 3 ? 2 : 1;
1609 uinfo->value.integer.min = 0;
1610 uinfo->value.integer.max = 1;
1611 return 0;
1612}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001613EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_switch_info);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001614
Takashi Iwai0ba21762007-04-16 11:29:14 +02001615int snd_hda_mixer_amp_switch_get(struct snd_kcontrol *kcontrol,
1616 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001617{
1618 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1619 hda_nid_t nid = get_amp_nid(kcontrol);
1620 int chs = get_amp_channels(kcontrol);
1621 int dir = get_amp_direction(kcontrol);
1622 int idx = get_amp_index(kcontrol);
1623 long *valp = ucontrol->value.integer.value;
1624
1625 if (chs & 1)
Takashi Iwai0ba21762007-04-16 11:29:14 +02001626 *valp++ = (snd_hda_codec_amp_read(codec, nid, 0, dir, idx) &
Takashi Iwai47fd8302007-08-10 17:11:07 +02001627 HDA_AMP_MUTE) ? 0 : 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001628 if (chs & 2)
Takashi Iwai0ba21762007-04-16 11:29:14 +02001629 *valp = (snd_hda_codec_amp_read(codec, nid, 1, dir, idx) &
Takashi Iwai47fd8302007-08-10 17:11:07 +02001630 HDA_AMP_MUTE) ? 0 : 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001631 return 0;
1632}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001633EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_switch_get);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001634
Takashi Iwai0ba21762007-04-16 11:29:14 +02001635int snd_hda_mixer_amp_switch_put(struct snd_kcontrol *kcontrol,
1636 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001637{
1638 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1639 hda_nid_t nid = get_amp_nid(kcontrol);
1640 int chs = get_amp_channels(kcontrol);
1641 int dir = get_amp_direction(kcontrol);
1642 int idx = get_amp_index(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001643 long *valp = ucontrol->value.integer.value;
1644 int change = 0;
1645
Takashi Iwaicb53c622007-08-10 17:21:45 +02001646 snd_hda_power_up(codec);
Nicolas Grazianob9f5a892005-07-29 12:17:20 +02001647 if (chs & 1) {
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001648 change = snd_hda_codec_amp_update(codec, nid, 0, dir, idx,
Takashi Iwai47fd8302007-08-10 17:11:07 +02001649 HDA_AMP_MUTE,
1650 *valp ? 0 : HDA_AMP_MUTE);
Nicolas Grazianob9f5a892005-07-29 12:17:20 +02001651 valp++;
1652 }
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001653 if (chs & 2)
1654 change |= snd_hda_codec_amp_update(codec, nid, 1, dir, idx,
Takashi Iwai47fd8302007-08-10 17:11:07 +02001655 HDA_AMP_MUTE,
1656 *valp ? 0 : HDA_AMP_MUTE);
Takashi Iwaicb53c622007-08-10 17:21:45 +02001657#ifdef CONFIG_SND_HDA_POWER_SAVE
1658 if (codec->patch_ops.check_power_status)
1659 codec->patch_ops.check_power_status(codec, nid);
1660#endif
1661 snd_hda_power_down(codec);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001662 return change;
1663}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001664EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_switch_put);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001665
1666/*
Takashi Iwai985be542005-11-02 18:26:49 +01001667 * bound volume controls
1668 *
1669 * bind multiple volumes (# indices, from 0)
1670 */
1671
1672#define AMP_VAL_IDX_SHIFT 19
1673#define AMP_VAL_IDX_MASK (0x0f<<19)
1674
Takashi Iwai0ba21762007-04-16 11:29:14 +02001675int snd_hda_mixer_bind_switch_get(struct snd_kcontrol *kcontrol,
1676 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai985be542005-11-02 18:26:49 +01001677{
1678 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1679 unsigned long pval;
1680 int err;
1681
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001682 mutex_lock(&codec->control_mutex);
Takashi Iwai985be542005-11-02 18:26:49 +01001683 pval = kcontrol->private_value;
1684 kcontrol->private_value = pval & ~AMP_VAL_IDX_MASK; /* index 0 */
1685 err = snd_hda_mixer_amp_switch_get(kcontrol, ucontrol);
1686 kcontrol->private_value = pval;
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001687 mutex_unlock(&codec->control_mutex);
Takashi Iwai985be542005-11-02 18:26:49 +01001688 return err;
1689}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001690EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_switch_get);
Takashi Iwai985be542005-11-02 18:26:49 +01001691
Takashi Iwai0ba21762007-04-16 11:29:14 +02001692int snd_hda_mixer_bind_switch_put(struct snd_kcontrol *kcontrol,
1693 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai985be542005-11-02 18:26:49 +01001694{
1695 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1696 unsigned long pval;
1697 int i, indices, err = 0, change = 0;
1698
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001699 mutex_lock(&codec->control_mutex);
Takashi Iwai985be542005-11-02 18:26:49 +01001700 pval = kcontrol->private_value;
1701 indices = (pval & AMP_VAL_IDX_MASK) >> AMP_VAL_IDX_SHIFT;
1702 for (i = 0; i < indices; i++) {
Takashi Iwai0ba21762007-04-16 11:29:14 +02001703 kcontrol->private_value = (pval & ~AMP_VAL_IDX_MASK) |
1704 (i << AMP_VAL_IDX_SHIFT);
Takashi Iwai985be542005-11-02 18:26:49 +01001705 err = snd_hda_mixer_amp_switch_put(kcontrol, ucontrol);
1706 if (err < 0)
1707 break;
1708 change |= err;
1709 }
1710 kcontrol->private_value = pval;
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001711 mutex_unlock(&codec->control_mutex);
Takashi Iwai985be542005-11-02 18:26:49 +01001712 return err < 0 ? err : change;
1713}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001714EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_switch_put);
Takashi Iwai985be542005-11-02 18:26:49 +01001715
1716/*
Takashi Iwai532d5382007-07-27 19:02:40 +02001717 * generic bound volume/swtich controls
1718 */
1719int snd_hda_mixer_bind_ctls_info(struct snd_kcontrol *kcontrol,
1720 struct snd_ctl_elem_info *uinfo)
1721{
1722 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1723 struct hda_bind_ctls *c;
1724 int err;
1725
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001726 mutex_lock(&codec->control_mutex);
Serge A. Suchkov14c65f92008-02-22 18:43:16 +01001727 c = (struct hda_bind_ctls *)kcontrol->private_value;
Takashi Iwai532d5382007-07-27 19:02:40 +02001728 kcontrol->private_value = *c->values;
1729 err = c->ops->info(kcontrol, uinfo);
1730 kcontrol->private_value = (long)c;
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001731 mutex_unlock(&codec->control_mutex);
Takashi Iwai532d5382007-07-27 19:02:40 +02001732 return err;
1733}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001734EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_ctls_info);
Takashi Iwai532d5382007-07-27 19:02:40 +02001735
1736int snd_hda_mixer_bind_ctls_get(struct snd_kcontrol *kcontrol,
1737 struct snd_ctl_elem_value *ucontrol)
1738{
1739 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1740 struct hda_bind_ctls *c;
1741 int err;
1742
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001743 mutex_lock(&codec->control_mutex);
Serge A. Suchkov14c65f92008-02-22 18:43:16 +01001744 c = (struct hda_bind_ctls *)kcontrol->private_value;
Takashi Iwai532d5382007-07-27 19:02:40 +02001745 kcontrol->private_value = *c->values;
1746 err = c->ops->get(kcontrol, ucontrol);
1747 kcontrol->private_value = (long)c;
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001748 mutex_unlock(&codec->control_mutex);
Takashi Iwai532d5382007-07-27 19:02:40 +02001749 return err;
1750}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001751EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_ctls_get);
Takashi Iwai532d5382007-07-27 19:02:40 +02001752
1753int snd_hda_mixer_bind_ctls_put(struct snd_kcontrol *kcontrol,
1754 struct snd_ctl_elem_value *ucontrol)
1755{
1756 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1757 struct hda_bind_ctls *c;
1758 unsigned long *vals;
1759 int err = 0, change = 0;
1760
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001761 mutex_lock(&codec->control_mutex);
Serge A. Suchkov14c65f92008-02-22 18:43:16 +01001762 c = (struct hda_bind_ctls *)kcontrol->private_value;
Takashi Iwai532d5382007-07-27 19:02:40 +02001763 for (vals = c->values; *vals; vals++) {
1764 kcontrol->private_value = *vals;
1765 err = c->ops->put(kcontrol, ucontrol);
1766 if (err < 0)
1767 break;
1768 change |= err;
1769 }
1770 kcontrol->private_value = (long)c;
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001771 mutex_unlock(&codec->control_mutex);
Takashi Iwai532d5382007-07-27 19:02:40 +02001772 return err < 0 ? err : change;
1773}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001774EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_ctls_put);
Takashi Iwai532d5382007-07-27 19:02:40 +02001775
1776int snd_hda_mixer_bind_tlv(struct snd_kcontrol *kcontrol, int op_flag,
1777 unsigned int size, unsigned int __user *tlv)
1778{
1779 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1780 struct hda_bind_ctls *c;
1781 int err;
1782
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001783 mutex_lock(&codec->control_mutex);
Serge A. Suchkov14c65f92008-02-22 18:43:16 +01001784 c = (struct hda_bind_ctls *)kcontrol->private_value;
Takashi Iwai532d5382007-07-27 19:02:40 +02001785 kcontrol->private_value = *c->values;
1786 err = c->ops->tlv(kcontrol, op_flag, size, tlv);
1787 kcontrol->private_value = (long)c;
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001788 mutex_unlock(&codec->control_mutex);
Takashi Iwai532d5382007-07-27 19:02:40 +02001789 return err;
1790}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001791EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_tlv);
Takashi Iwai532d5382007-07-27 19:02:40 +02001792
1793struct hda_ctl_ops snd_hda_bind_vol = {
1794 .info = snd_hda_mixer_amp_volume_info,
1795 .get = snd_hda_mixer_amp_volume_get,
1796 .put = snd_hda_mixer_amp_volume_put,
1797 .tlv = snd_hda_mixer_amp_tlv
1798};
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001799EXPORT_SYMBOL_HDA(snd_hda_bind_vol);
Takashi Iwai532d5382007-07-27 19:02:40 +02001800
1801struct hda_ctl_ops snd_hda_bind_sw = {
1802 .info = snd_hda_mixer_amp_switch_info,
1803 .get = snd_hda_mixer_amp_switch_get,
1804 .put = snd_hda_mixer_amp_switch_put,
1805 .tlv = snd_hda_mixer_amp_tlv
1806};
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001807EXPORT_SYMBOL_HDA(snd_hda_bind_sw);
Takashi Iwai532d5382007-07-27 19:02:40 +02001808
1809/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07001810 * SPDIF out controls
1811 */
1812
Takashi Iwai0ba21762007-04-16 11:29:14 +02001813static int snd_hda_spdif_mask_info(struct snd_kcontrol *kcontrol,
1814 struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001815{
1816 uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
1817 uinfo->count = 1;
1818 return 0;
1819}
1820
Takashi Iwai0ba21762007-04-16 11:29:14 +02001821static int snd_hda_spdif_cmask_get(struct snd_kcontrol *kcontrol,
1822 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001823{
1824 ucontrol->value.iec958.status[0] = IEC958_AES0_PROFESSIONAL |
1825 IEC958_AES0_NONAUDIO |
1826 IEC958_AES0_CON_EMPHASIS_5015 |
1827 IEC958_AES0_CON_NOT_COPYRIGHT;
1828 ucontrol->value.iec958.status[1] = IEC958_AES1_CON_CATEGORY |
1829 IEC958_AES1_CON_ORIGINAL;
1830 return 0;
1831}
1832
Takashi Iwai0ba21762007-04-16 11:29:14 +02001833static int snd_hda_spdif_pmask_get(struct snd_kcontrol *kcontrol,
1834 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001835{
1836 ucontrol->value.iec958.status[0] = IEC958_AES0_PROFESSIONAL |
1837 IEC958_AES0_NONAUDIO |
1838 IEC958_AES0_PRO_EMPHASIS_5015;
1839 return 0;
1840}
1841
Takashi Iwai0ba21762007-04-16 11:29:14 +02001842static int snd_hda_spdif_default_get(struct snd_kcontrol *kcontrol,
1843 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001844{
1845 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1846
1847 ucontrol->value.iec958.status[0] = codec->spdif_status & 0xff;
1848 ucontrol->value.iec958.status[1] = (codec->spdif_status >> 8) & 0xff;
1849 ucontrol->value.iec958.status[2] = (codec->spdif_status >> 16) & 0xff;
1850 ucontrol->value.iec958.status[3] = (codec->spdif_status >> 24) & 0xff;
1851
1852 return 0;
1853}
1854
1855/* convert from SPDIF status bits to HDA SPDIF bits
1856 * bit 0 (DigEn) is always set zero (to be filled later)
1857 */
1858static unsigned short convert_from_spdif_status(unsigned int sbits)
1859{
1860 unsigned short val = 0;
1861
1862 if (sbits & IEC958_AES0_PROFESSIONAL)
Takashi Iwai0ba21762007-04-16 11:29:14 +02001863 val |= AC_DIG1_PROFESSIONAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001864 if (sbits & IEC958_AES0_NONAUDIO)
Takashi Iwai0ba21762007-04-16 11:29:14 +02001865 val |= AC_DIG1_NONAUDIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001866 if (sbits & IEC958_AES0_PROFESSIONAL) {
Takashi Iwai0ba21762007-04-16 11:29:14 +02001867 if ((sbits & IEC958_AES0_PRO_EMPHASIS) ==
1868 IEC958_AES0_PRO_EMPHASIS_5015)
1869 val |= AC_DIG1_EMPHASIS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001870 } else {
Takashi Iwai0ba21762007-04-16 11:29:14 +02001871 if ((sbits & IEC958_AES0_CON_EMPHASIS) ==
1872 IEC958_AES0_CON_EMPHASIS_5015)
1873 val |= AC_DIG1_EMPHASIS;
1874 if (!(sbits & IEC958_AES0_CON_NOT_COPYRIGHT))
1875 val |= AC_DIG1_COPYRIGHT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001876 if (sbits & (IEC958_AES1_CON_ORIGINAL << 8))
Takashi Iwai0ba21762007-04-16 11:29:14 +02001877 val |= AC_DIG1_LEVEL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001878 val |= sbits & (IEC958_AES1_CON_CATEGORY << 8);
1879 }
1880 return val;
1881}
1882
1883/* convert to SPDIF status bits from HDA SPDIF bits
1884 */
1885static unsigned int convert_to_spdif_status(unsigned short val)
1886{
1887 unsigned int sbits = 0;
1888
Takashi Iwai0ba21762007-04-16 11:29:14 +02001889 if (val & AC_DIG1_NONAUDIO)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001890 sbits |= IEC958_AES0_NONAUDIO;
Takashi Iwai0ba21762007-04-16 11:29:14 +02001891 if (val & AC_DIG1_PROFESSIONAL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001892 sbits |= IEC958_AES0_PROFESSIONAL;
1893 if (sbits & IEC958_AES0_PROFESSIONAL) {
Takashi Iwai0ba21762007-04-16 11:29:14 +02001894 if (sbits & AC_DIG1_EMPHASIS)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001895 sbits |= IEC958_AES0_PRO_EMPHASIS_5015;
1896 } else {
Takashi Iwai0ba21762007-04-16 11:29:14 +02001897 if (val & AC_DIG1_EMPHASIS)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001898 sbits |= IEC958_AES0_CON_EMPHASIS_5015;
Takashi Iwai0ba21762007-04-16 11:29:14 +02001899 if (!(val & AC_DIG1_COPYRIGHT))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001900 sbits |= IEC958_AES0_CON_NOT_COPYRIGHT;
Takashi Iwai0ba21762007-04-16 11:29:14 +02001901 if (val & AC_DIG1_LEVEL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001902 sbits |= (IEC958_AES1_CON_ORIGINAL << 8);
1903 sbits |= val & (0x7f << 8);
1904 }
1905 return sbits;
1906}
1907
Takashi Iwai2f728532008-09-25 16:32:41 +02001908/* set digital convert verbs both for the given NID and its slaves */
1909static void set_dig_out(struct hda_codec *codec, hda_nid_t nid,
1910 int verb, int val)
1911{
1912 hda_nid_t *d;
1913
Takashi Iwai9e976972008-11-25 08:17:20 +01001914 snd_hda_codec_write_cache(codec, nid, 0, verb, val);
Takashi Iwai2f728532008-09-25 16:32:41 +02001915 d = codec->slave_dig_outs;
1916 if (!d)
1917 return;
1918 for (; *d; d++)
Takashi Iwai9e976972008-11-25 08:17:20 +01001919 snd_hda_codec_write_cache(codec, *d, 0, verb, val);
Takashi Iwai2f728532008-09-25 16:32:41 +02001920}
1921
1922static inline void set_dig_out_convert(struct hda_codec *codec, hda_nid_t nid,
1923 int dig1, int dig2)
1924{
1925 if (dig1 != -1)
1926 set_dig_out(codec, nid, AC_VERB_SET_DIGI_CONVERT_1, dig1);
1927 if (dig2 != -1)
1928 set_dig_out(codec, nid, AC_VERB_SET_DIGI_CONVERT_2, dig2);
1929}
1930
Takashi Iwai0ba21762007-04-16 11:29:14 +02001931static int snd_hda_spdif_default_put(struct snd_kcontrol *kcontrol,
1932 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001933{
1934 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1935 hda_nid_t nid = kcontrol->private_value;
1936 unsigned short val;
1937 int change;
1938
Ingo Molnar62932df2006-01-16 16:34:20 +01001939 mutex_lock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001940 codec->spdif_status = ucontrol->value.iec958.status[0] |
1941 ((unsigned int)ucontrol->value.iec958.status[1] << 8) |
1942 ((unsigned int)ucontrol->value.iec958.status[2] << 16) |
1943 ((unsigned int)ucontrol->value.iec958.status[3] << 24);
1944 val = convert_from_spdif_status(codec->spdif_status);
1945 val |= codec->spdif_ctls & 1;
1946 change = codec->spdif_ctls != val;
1947 codec->spdif_ctls = val;
1948
Takashi Iwai2f728532008-09-25 16:32:41 +02001949 if (change)
1950 set_dig_out_convert(codec, nid, val & 0xff, (val >> 8) & 0xff);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001951
Ingo Molnar62932df2006-01-16 16:34:20 +01001952 mutex_unlock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001953 return change;
1954}
1955
Takashi Iwaia5ce8892007-07-23 15:42:26 +02001956#define snd_hda_spdif_out_switch_info snd_ctl_boolean_mono_info
Linus Torvalds1da177e2005-04-16 15:20:36 -07001957
Takashi Iwai0ba21762007-04-16 11:29:14 +02001958static int snd_hda_spdif_out_switch_get(struct snd_kcontrol *kcontrol,
1959 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001960{
1961 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1962
Takashi Iwai0ba21762007-04-16 11:29:14 +02001963 ucontrol->value.integer.value[0] = codec->spdif_ctls & AC_DIG1_ENABLE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001964 return 0;
1965}
1966
Takashi Iwai0ba21762007-04-16 11:29:14 +02001967static int snd_hda_spdif_out_switch_put(struct snd_kcontrol *kcontrol,
1968 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001969{
1970 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1971 hda_nid_t nid = kcontrol->private_value;
1972 unsigned short val;
1973 int change;
1974
Ingo Molnar62932df2006-01-16 16:34:20 +01001975 mutex_lock(&codec->spdif_mutex);
Takashi Iwai0ba21762007-04-16 11:29:14 +02001976 val = codec->spdif_ctls & ~AC_DIG1_ENABLE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001977 if (ucontrol->value.integer.value[0])
Takashi Iwai0ba21762007-04-16 11:29:14 +02001978 val |= AC_DIG1_ENABLE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001979 change = codec->spdif_ctls != val;
Takashi Iwai82beb8f2007-08-10 17:09:26 +02001980 if (change) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001981 codec->spdif_ctls = val;
Takashi Iwai2f728532008-09-25 16:32:41 +02001982 set_dig_out_convert(codec, nid, val & 0xff, -1);
Takashi Iwai0ba21762007-04-16 11:29:14 +02001983 /* unmute amp switch (if any) */
1984 if ((get_wcaps(codec, nid) & AC_WCAP_OUT_AMP) &&
Takashi Iwai47fd8302007-08-10 17:11:07 +02001985 (val & AC_DIG1_ENABLE))
1986 snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0,
1987 HDA_AMP_MUTE, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001988 }
Ingo Molnar62932df2006-01-16 16:34:20 +01001989 mutex_unlock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001990 return change;
1991}
1992
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01001993static struct snd_kcontrol_new dig_mixes[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001994 {
1995 .access = SNDRV_CTL_ELEM_ACCESS_READ,
1996 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1997 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,CON_MASK),
1998 .info = snd_hda_spdif_mask_info,
1999 .get = snd_hda_spdif_cmask_get,
2000 },
2001 {
2002 .access = SNDRV_CTL_ELEM_ACCESS_READ,
2003 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2004 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,PRO_MASK),
2005 .info = snd_hda_spdif_mask_info,
2006 .get = snd_hda_spdif_pmask_get,
2007 },
2008 {
2009 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2010 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT),
2011 .info = snd_hda_spdif_mask_info,
2012 .get = snd_hda_spdif_default_get,
2013 .put = snd_hda_spdif_default_put,
2014 },
2015 {
2016 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2017 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,SWITCH),
2018 .info = snd_hda_spdif_out_switch_info,
2019 .get = snd_hda_spdif_out_switch_get,
2020 .put = snd_hda_spdif_out_switch_put,
2021 },
2022 { } /* end */
2023};
2024
Takashi Iwai09f99702008-02-04 12:31:13 +01002025#define SPDIF_MAX_IDX 4 /* 4 instances should be enough to probe */
2026
Linus Torvalds1da177e2005-04-16 15:20:36 -07002027/**
2028 * snd_hda_create_spdif_out_ctls - create Output SPDIF-related controls
2029 * @codec: the HDA codec
2030 * @nid: audio out widget NID
2031 *
2032 * Creates controls related with the SPDIF output.
2033 * Called from each patch supporting the SPDIF out.
2034 *
2035 * Returns 0 if successful, or a negative error code.
2036 */
Takashi Iwai12f288b2007-08-02 15:51:59 +02002037int snd_hda_create_spdif_out_ctls(struct hda_codec *codec, hda_nid_t nid)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002038{
2039 int err;
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01002040 struct snd_kcontrol *kctl;
2041 struct snd_kcontrol_new *dig_mix;
Takashi Iwai09f99702008-02-04 12:31:13 +01002042 int idx;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002043
Takashi Iwai09f99702008-02-04 12:31:13 +01002044 for (idx = 0; idx < SPDIF_MAX_IDX; idx++) {
2045 if (!_snd_hda_find_mixer_ctl(codec, "IEC958 Playback Switch",
2046 idx))
2047 break;
2048 }
2049 if (idx >= SPDIF_MAX_IDX) {
2050 printk(KERN_ERR "hda_codec: too many IEC958 outputs\n");
2051 return -EBUSY;
2052 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002053 for (dig_mix = dig_mixes; dig_mix->name; dig_mix++) {
2054 kctl = snd_ctl_new1(dig_mix, codec);
Takashi Iwaib91f0802008-11-04 08:43:08 +01002055 if (!kctl)
2056 return -ENOMEM;
Takashi Iwai09f99702008-02-04 12:31:13 +01002057 kctl->id.index = idx;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002058 kctl->private_value = nid;
Takashi Iwaid13bd412008-07-30 15:01:45 +02002059 err = snd_hda_ctl_add(codec, kctl);
Takashi Iwai0ba21762007-04-16 11:29:14 +02002060 if (err < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002061 return err;
2062 }
Takashi Iwai0ba21762007-04-16 11:29:14 +02002063 codec->spdif_ctls =
Andrew Paprocki3982d172007-12-19 12:13:44 +01002064 snd_hda_codec_read(codec, nid, 0,
2065 AC_VERB_GET_DIGI_CONVERT_1, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002066 codec->spdif_status = convert_to_spdif_status(codec->spdif_ctls);
2067 return 0;
2068}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002069EXPORT_SYMBOL_HDA(snd_hda_create_spdif_out_ctls);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002070
2071/*
Takashi Iwai9a081602008-02-12 18:37:26 +01002072 * SPDIF sharing with analog output
2073 */
2074static int spdif_share_sw_get(struct snd_kcontrol *kcontrol,
2075 struct snd_ctl_elem_value *ucontrol)
2076{
2077 struct hda_multi_out *mout = snd_kcontrol_chip(kcontrol);
2078 ucontrol->value.integer.value[0] = mout->share_spdif;
2079 return 0;
2080}
2081
2082static int spdif_share_sw_put(struct snd_kcontrol *kcontrol,
2083 struct snd_ctl_elem_value *ucontrol)
2084{
2085 struct hda_multi_out *mout = snd_kcontrol_chip(kcontrol);
2086 mout->share_spdif = !!ucontrol->value.integer.value[0];
2087 return 0;
2088}
2089
2090static struct snd_kcontrol_new spdif_share_sw = {
2091 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2092 .name = "IEC958 Default PCM Playback Switch",
2093 .info = snd_ctl_boolean_mono_info,
2094 .get = spdif_share_sw_get,
2095 .put = spdif_share_sw_put,
2096};
2097
2098int snd_hda_create_spdif_share_sw(struct hda_codec *codec,
2099 struct hda_multi_out *mout)
2100{
2101 if (!mout->dig_out_nid)
2102 return 0;
2103 /* ATTENTION: here mout is passed as private_data, instead of codec */
Takashi Iwaid13bd412008-07-30 15:01:45 +02002104 return snd_hda_ctl_add(codec,
Takashi Iwai9a081602008-02-12 18:37:26 +01002105 snd_ctl_new1(&spdif_share_sw, mout));
2106}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002107EXPORT_SYMBOL_HDA(snd_hda_create_spdif_share_sw);
Takashi Iwai9a081602008-02-12 18:37:26 +01002108
2109/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002110 * SPDIF input
2111 */
2112
2113#define snd_hda_spdif_in_switch_info snd_hda_spdif_out_switch_info
2114
Takashi Iwai0ba21762007-04-16 11:29:14 +02002115static int snd_hda_spdif_in_switch_get(struct snd_kcontrol *kcontrol,
2116 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002117{
2118 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2119
2120 ucontrol->value.integer.value[0] = codec->spdif_in_enable;
2121 return 0;
2122}
2123
Takashi Iwai0ba21762007-04-16 11:29:14 +02002124static int snd_hda_spdif_in_switch_put(struct snd_kcontrol *kcontrol,
2125 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002126{
2127 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2128 hda_nid_t nid = kcontrol->private_value;
2129 unsigned int val = !!ucontrol->value.integer.value[0];
2130 int change;
2131
Ingo Molnar62932df2006-01-16 16:34:20 +01002132 mutex_lock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002133 change = codec->spdif_in_enable != val;
Takashi Iwai82beb8f2007-08-10 17:09:26 +02002134 if (change) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002135 codec->spdif_in_enable = val;
Takashi Iwai82beb8f2007-08-10 17:09:26 +02002136 snd_hda_codec_write_cache(codec, nid, 0,
2137 AC_VERB_SET_DIGI_CONVERT_1, val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002138 }
Ingo Molnar62932df2006-01-16 16:34:20 +01002139 mutex_unlock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002140 return change;
2141}
2142
Takashi Iwai0ba21762007-04-16 11:29:14 +02002143static int snd_hda_spdif_in_status_get(struct snd_kcontrol *kcontrol,
2144 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002145{
2146 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2147 hda_nid_t nid = kcontrol->private_value;
2148 unsigned short val;
2149 unsigned int sbits;
2150
Andrew Paprocki3982d172007-12-19 12:13:44 +01002151 val = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_DIGI_CONVERT_1, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002152 sbits = convert_to_spdif_status(val);
2153 ucontrol->value.iec958.status[0] = sbits;
2154 ucontrol->value.iec958.status[1] = sbits >> 8;
2155 ucontrol->value.iec958.status[2] = sbits >> 16;
2156 ucontrol->value.iec958.status[3] = sbits >> 24;
2157 return 0;
2158}
2159
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01002160static struct snd_kcontrol_new dig_in_ctls[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002161 {
2162 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2163 .name = SNDRV_CTL_NAME_IEC958("",CAPTURE,SWITCH),
2164 .info = snd_hda_spdif_in_switch_info,
2165 .get = snd_hda_spdif_in_switch_get,
2166 .put = snd_hda_spdif_in_switch_put,
2167 },
2168 {
2169 .access = SNDRV_CTL_ELEM_ACCESS_READ,
2170 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2171 .name = SNDRV_CTL_NAME_IEC958("",CAPTURE,DEFAULT),
2172 .info = snd_hda_spdif_mask_info,
2173 .get = snd_hda_spdif_in_status_get,
2174 },
2175 { } /* end */
2176};
2177
2178/**
2179 * snd_hda_create_spdif_in_ctls - create Input SPDIF-related controls
2180 * @codec: the HDA codec
2181 * @nid: audio in widget NID
2182 *
2183 * Creates controls related with the SPDIF input.
2184 * Called from each patch supporting the SPDIF in.
2185 *
2186 * Returns 0 if successful, or a negative error code.
2187 */
Takashi Iwai12f288b2007-08-02 15:51:59 +02002188int snd_hda_create_spdif_in_ctls(struct hda_codec *codec, hda_nid_t nid)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002189{
2190 int err;
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01002191 struct snd_kcontrol *kctl;
2192 struct snd_kcontrol_new *dig_mix;
Takashi Iwai09f99702008-02-04 12:31:13 +01002193 int idx;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002194
Takashi Iwai09f99702008-02-04 12:31:13 +01002195 for (idx = 0; idx < SPDIF_MAX_IDX; idx++) {
2196 if (!_snd_hda_find_mixer_ctl(codec, "IEC958 Capture Switch",
2197 idx))
2198 break;
2199 }
2200 if (idx >= SPDIF_MAX_IDX) {
2201 printk(KERN_ERR "hda_codec: too many IEC958 inputs\n");
2202 return -EBUSY;
2203 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002204 for (dig_mix = dig_in_ctls; dig_mix->name; dig_mix++) {
2205 kctl = snd_ctl_new1(dig_mix, codec);
Takashi Iwaic8dcdf82009-02-06 16:21:20 +01002206 if (!kctl)
2207 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002208 kctl->private_value = nid;
Takashi Iwaid13bd412008-07-30 15:01:45 +02002209 err = snd_hda_ctl_add(codec, kctl);
Takashi Iwai0ba21762007-04-16 11:29:14 +02002210 if (err < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002211 return err;
2212 }
Takashi Iwai0ba21762007-04-16 11:29:14 +02002213 codec->spdif_in_enable =
Andrew Paprocki3982d172007-12-19 12:13:44 +01002214 snd_hda_codec_read(codec, nid, 0,
2215 AC_VERB_GET_DIGI_CONVERT_1, 0) &
Takashi Iwai0ba21762007-04-16 11:29:14 +02002216 AC_DIG1_ENABLE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002217 return 0;
2218}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002219EXPORT_SYMBOL_HDA(snd_hda_create_spdif_in_ctls);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002220
Takashi Iwaicb53c622007-08-10 17:21:45 +02002221#ifdef SND_HDA_NEEDS_RESUME
Takashi Iwai82beb8f2007-08-10 17:09:26 +02002222/*
2223 * command cache
2224 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002225
Takashi Iwaib3ac5632007-08-10 17:03:40 +02002226/* build a 32bit cache key with the widget id and the command parameter */
2227#define build_cmd_cache_key(nid, verb) ((verb << 8) | nid)
2228#define get_cmd_cache_nid(key) ((key) & 0xff)
2229#define get_cmd_cache_cmd(key) (((key) >> 8) & 0xffff)
2230
2231/**
2232 * snd_hda_codec_write_cache - send a single command with caching
2233 * @codec: the HDA codec
2234 * @nid: NID to send the command
2235 * @direct: direct flag
2236 * @verb: the verb to send
2237 * @parm: the parameter for the verb
2238 *
2239 * Send a single command without waiting for response.
2240 *
2241 * Returns 0 if successful, or a negative error code.
2242 */
2243int snd_hda_codec_write_cache(struct hda_codec *codec, hda_nid_t nid,
2244 int direct, unsigned int verb, unsigned int parm)
2245{
Takashi Iwai33fa35e2008-11-06 16:50:40 +01002246 struct hda_bus *bus = codec->bus;
2247 unsigned int res;
Takashi Iwaib3ac5632007-08-10 17:03:40 +02002248 int err;
Takashi Iwai33fa35e2008-11-06 16:50:40 +01002249
2250 res = make_codec_cmd(codec, nid, direct, verb, parm);
Takashi Iwaicb53c622007-08-10 17:21:45 +02002251 snd_hda_power_up(codec);
Takashi Iwai33fa35e2008-11-06 16:50:40 +01002252 mutex_lock(&bus->cmd_mutex);
2253 err = bus->ops.command(bus, res);
Takashi Iwaib3ac5632007-08-10 17:03:40 +02002254 if (!err) {
2255 struct hda_cache_head *c;
Takashi Iwaifcad94a2009-04-15 17:48:35 +02002256 u32 key;
2257 /* parm may contain the verb stuff for get/set amp */
2258 verb = verb | (parm >> 8);
2259 parm &= 0xff;
2260 key = build_cmd_cache_key(nid, verb);
Takashi Iwaib3ac5632007-08-10 17:03:40 +02002261 c = get_alloc_hash(&codec->cmd_cache, key);
2262 if (c)
2263 c->val = parm;
2264 }
Takashi Iwai33fa35e2008-11-06 16:50:40 +01002265 mutex_unlock(&bus->cmd_mutex);
Takashi Iwaicb53c622007-08-10 17:21:45 +02002266 snd_hda_power_down(codec);
Takashi Iwaib3ac5632007-08-10 17:03:40 +02002267 return err;
2268}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002269EXPORT_SYMBOL_HDA(snd_hda_codec_write_cache);
Takashi Iwaib3ac5632007-08-10 17:03:40 +02002270
2271/* resume the all commands from the cache */
2272void snd_hda_codec_resume_cache(struct hda_codec *codec)
2273{
Takashi Iwai603c4012008-07-30 15:01:44 +02002274 struct hda_cache_head *buffer = codec->cmd_cache.buf.list;
Takashi Iwaib3ac5632007-08-10 17:03:40 +02002275 int i;
2276
Takashi Iwai603c4012008-07-30 15:01:44 +02002277 for (i = 0; i < codec->cmd_cache.buf.used; i++, buffer++) {
Takashi Iwaib3ac5632007-08-10 17:03:40 +02002278 u32 key = buffer->key;
2279 if (!key)
2280 continue;
2281 snd_hda_codec_write(codec, get_cmd_cache_nid(key), 0,
2282 get_cmd_cache_cmd(key), buffer->val);
2283 }
2284}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002285EXPORT_SYMBOL_HDA(snd_hda_codec_resume_cache);
Takashi Iwaib3ac5632007-08-10 17:03:40 +02002286
2287/**
2288 * snd_hda_sequence_write_cache - sequence writes with caching
2289 * @codec: the HDA codec
2290 * @seq: VERB array to send
2291 *
2292 * Send the commands sequentially from the given array.
2293 * Thte commands are recorded on cache for power-save and resume.
2294 * The array must be terminated with NID=0.
2295 */
2296void snd_hda_sequence_write_cache(struct hda_codec *codec,
2297 const struct hda_verb *seq)
2298{
2299 for (; seq->nid; seq++)
2300 snd_hda_codec_write_cache(codec, seq->nid, 0, seq->verb,
2301 seq->param);
2302}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002303EXPORT_SYMBOL_HDA(snd_hda_sequence_write_cache);
Takashi Iwaicb53c622007-08-10 17:21:45 +02002304#endif /* SND_HDA_NEEDS_RESUME */
Takashi Iwaib3ac5632007-08-10 17:03:40 +02002305
Takashi Iwai54d17402005-11-21 16:33:22 +01002306/*
2307 * set power state of the codec
2308 */
2309static void hda_set_power_state(struct hda_codec *codec, hda_nid_t fg,
2310 unsigned int power_state)
2311{
Takashi Iwaicb53c622007-08-10 17:21:45 +02002312 hda_nid_t nid;
2313 int i;
Takashi Iwai54d17402005-11-21 16:33:22 +01002314
2315 snd_hda_codec_write(codec, fg, 0, AC_VERB_SET_POWER_STATE,
2316 power_state);
Marc Boucherd2595d82008-01-22 15:23:30 +01002317 msleep(10); /* partial workaround for "azx_get_response timeout" */
Takashi Iwai54d17402005-11-21 16:33:22 +01002318
Takashi Iwaicb53c622007-08-10 17:21:45 +02002319 nid = codec->start_nid;
2320 for (i = 0; i < codec->num_nodes; i++, nid++) {
Takashi Iwai7eba5c92007-11-14 14:53:42 +01002321 unsigned int wcaps = get_wcaps(codec, nid);
2322 if (wcaps & AC_WCAP_POWER) {
2323 unsigned int wid_type = (wcaps & AC_WCAP_TYPE) >>
2324 AC_WCAP_TYPE_SHIFT;
2325 if (wid_type == AC_WID_PIN) {
2326 unsigned int pincap;
2327 /*
2328 * don't power down the widget if it controls
2329 * eapd and EAPD_BTLENABLE is set.
2330 */
Takashi Iwai14bafe32009-03-23 16:35:39 +01002331 pincap = snd_hda_query_pin_caps(codec, nid);
Takashi Iwai7eba5c92007-11-14 14:53:42 +01002332 if (pincap & AC_PINCAP_EAPD) {
2333 int eapd = snd_hda_codec_read(codec,
2334 nid, 0,
2335 AC_VERB_GET_EAPD_BTLENABLE, 0);
2336 eapd &= 0x02;
2337 if (power_state == AC_PWRST_D3 && eapd)
2338 continue;
2339 }
Takashi Iwai1194b5b2007-10-10 10:04:26 +02002340 }
Takashi Iwai54d17402005-11-21 16:33:22 +01002341 snd_hda_codec_write(codec, nid, 0,
2342 AC_VERB_SET_POWER_STATE,
2343 power_state);
Takashi Iwai1194b5b2007-10-10 10:04:26 +02002344 }
Takashi Iwai54d17402005-11-21 16:33:22 +01002345 }
2346
Takashi Iwaicb53c622007-08-10 17:21:45 +02002347 if (power_state == AC_PWRST_D0) {
2348 unsigned long end_time;
2349 int state;
Takashi Iwai54d17402005-11-21 16:33:22 +01002350 msleep(10);
Takashi Iwaicb53c622007-08-10 17:21:45 +02002351 /* wait until the codec reachs to D0 */
2352 end_time = jiffies + msecs_to_jiffies(500);
2353 do {
2354 state = snd_hda_codec_read(codec, fg, 0,
2355 AC_VERB_GET_POWER_STATE, 0);
2356 if (state == power_state)
2357 break;
2358 msleep(1);
2359 } while (time_after_eq(end_time, jiffies));
2360 }
Takashi Iwai54d17402005-11-21 16:33:22 +01002361}
2362
Takashi Iwai11aeff02008-07-30 15:01:46 +02002363#ifdef CONFIG_SND_HDA_HWDEP
2364/* execute additional init verbs */
2365static void hda_exec_init_verbs(struct hda_codec *codec)
2366{
2367 if (codec->init_verbs.list)
2368 snd_hda_sequence_write(codec, codec->init_verbs.list);
2369}
2370#else
2371static inline void hda_exec_init_verbs(struct hda_codec *codec) {}
2372#endif
2373
Takashi Iwaicb53c622007-08-10 17:21:45 +02002374#ifdef SND_HDA_NEEDS_RESUME
2375/*
2376 * call suspend and power-down; used both from PM and power-save
2377 */
2378static void hda_call_codec_suspend(struct hda_codec *codec)
2379{
2380 if (codec->patch_ops.suspend)
2381 codec->patch_ops.suspend(codec, PMSG_SUSPEND);
2382 hda_set_power_state(codec,
2383 codec->afg ? codec->afg : codec->mfg,
2384 AC_PWRST_D3);
2385#ifdef CONFIG_SND_HDA_POWER_SAVE
2386 cancel_delayed_work(&codec->power_work);
Takashi Iwai95e99fd2007-08-13 15:29:04 +02002387 codec->power_on = 0;
Takashi Iwaia221e282007-08-16 16:35:33 +02002388 codec->power_transition = 0;
Takashi Iwaicb53c622007-08-10 17:21:45 +02002389#endif
2390}
2391
2392/*
2393 * kick up codec; used both from PM and power-save
2394 */
2395static void hda_call_codec_resume(struct hda_codec *codec)
2396{
2397 hda_set_power_state(codec,
2398 codec->afg ? codec->afg : codec->mfg,
2399 AC_PWRST_D0);
Takashi Iwai3be14142009-02-20 14:11:16 +01002400 restore_pincfgs(codec); /* restore all current pin configs */
Takashi Iwai11aeff02008-07-30 15:01:46 +02002401 hda_exec_init_verbs(codec);
Takashi Iwaicb53c622007-08-10 17:21:45 +02002402 if (codec->patch_ops.resume)
2403 codec->patch_ops.resume(codec);
2404 else {
Takashi Iwai9d99f312007-08-14 15:15:52 +02002405 if (codec->patch_ops.init)
2406 codec->patch_ops.init(codec);
Takashi Iwaicb53c622007-08-10 17:21:45 +02002407 snd_hda_codec_resume_amp(codec);
2408 snd_hda_codec_resume_cache(codec);
2409 }
2410}
2411#endif /* SND_HDA_NEEDS_RESUME */
2412
Takashi Iwai54d17402005-11-21 16:33:22 +01002413
Linus Torvalds1da177e2005-04-16 15:20:36 -07002414/**
2415 * snd_hda_build_controls - build mixer controls
2416 * @bus: the BUS
2417 *
2418 * Creates mixer controls for each codec included in the bus.
2419 *
2420 * Returns 0 if successful, otherwise a negative error code.
2421 */
Takashi Iwai1289e9e2008-11-27 15:47:11 +01002422int /*__devinit*/ snd_hda_build_controls(struct hda_bus *bus)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002423{
Takashi Iwai0ba21762007-04-16 11:29:14 +02002424 struct hda_codec *codec;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002425
Takashi Iwai0ba21762007-04-16 11:29:14 +02002426 list_for_each_entry(codec, &bus->codec_list, list) {
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02002427 int err = snd_hda_codec_build_controls(codec);
Takashi Iwaif93d4612009-03-02 10:44:15 +01002428 if (err < 0) {
2429 printk(KERN_ERR "hda_codec: cannot build controls"
2430 "for #%d (error %d)\n", codec->addr, err);
2431 err = snd_hda_codec_reset(codec);
2432 if (err < 0) {
2433 printk(KERN_ERR
2434 "hda_codec: cannot revert codec\n");
2435 return err;
2436 }
2437 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002438 }
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02002439 return 0;
2440}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002441EXPORT_SYMBOL_HDA(snd_hda_build_controls);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002442
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02002443int snd_hda_codec_build_controls(struct hda_codec *codec)
2444{
2445 int err = 0;
Takashi Iwai11aeff02008-07-30 15:01:46 +02002446 hda_exec_init_verbs(codec);
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02002447 /* continue to initialize... */
2448 if (codec->patch_ops.init)
2449 err = codec->patch_ops.init(codec);
2450 if (!err && codec->patch_ops.build_controls)
2451 err = codec->patch_ops.build_controls(codec);
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02002452 if (err < 0)
2453 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002454 return 0;
2455}
2456
Linus Torvalds1da177e2005-04-16 15:20:36 -07002457/*
2458 * stream formats
2459 */
Takashi Iwaibefdf312005-08-22 13:57:55 +02002460struct hda_rate_tbl {
2461 unsigned int hz;
2462 unsigned int alsa_bits;
2463 unsigned int hda_fmt;
2464};
2465
2466static struct hda_rate_tbl rate_bits[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002467 /* rate in Hz, ALSA rate bitmask, HDA format value */
Nicolas Graziano9d8f53f2005-08-22 13:47:16 +02002468
2469 /* autodetected value used in snd_hda_query_supported_pcm */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002470 { 8000, SNDRV_PCM_RATE_8000, 0x0500 }, /* 1/6 x 48 */
2471 { 11025, SNDRV_PCM_RATE_11025, 0x4300 }, /* 1/4 x 44 */
2472 { 16000, SNDRV_PCM_RATE_16000, 0x0200 }, /* 1/3 x 48 */
2473 { 22050, SNDRV_PCM_RATE_22050, 0x4100 }, /* 1/2 x 44 */
2474 { 32000, SNDRV_PCM_RATE_32000, 0x0a00 }, /* 2/3 x 48 */
2475 { 44100, SNDRV_PCM_RATE_44100, 0x4000 }, /* 44 */
2476 { 48000, SNDRV_PCM_RATE_48000, 0x0000 }, /* 48 */
2477 { 88200, SNDRV_PCM_RATE_88200, 0x4800 }, /* 2 x 44 */
2478 { 96000, SNDRV_PCM_RATE_96000, 0x0800 }, /* 2 x 48 */
2479 { 176400, SNDRV_PCM_RATE_176400, 0x5800 },/* 4 x 44 */
2480 { 192000, SNDRV_PCM_RATE_192000, 0x1800 }, /* 4 x 48 */
Takashi Iwaia961f9f2007-04-12 13:08:09 +02002481#define AC_PAR_PCM_RATE_BITS 11
2482 /* up to bits 10, 384kHZ isn't supported properly */
2483
2484 /* not autodetected value */
2485 { 9600, SNDRV_PCM_RATE_KNOT, 0x0400 }, /* 1/5 x 48 */
Nicolas Graziano9d8f53f2005-08-22 13:47:16 +02002486
Takashi Iwaibefdf312005-08-22 13:57:55 +02002487 { 0 } /* terminator */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002488};
2489
2490/**
2491 * snd_hda_calc_stream_format - calculate format bitset
2492 * @rate: the sample rate
2493 * @channels: the number of channels
2494 * @format: the PCM format (SNDRV_PCM_FORMAT_XXX)
2495 * @maxbps: the max. bps
2496 *
2497 * Calculate the format bitset from the given rate, channels and th PCM format.
2498 *
2499 * Return zero if invalid.
2500 */
2501unsigned int snd_hda_calc_stream_format(unsigned int rate,
2502 unsigned int channels,
2503 unsigned int format,
2504 unsigned int maxbps)
2505{
2506 int i;
2507 unsigned int val = 0;
2508
Takashi Iwaibefdf312005-08-22 13:57:55 +02002509 for (i = 0; rate_bits[i].hz; i++)
2510 if (rate_bits[i].hz == rate) {
2511 val = rate_bits[i].hda_fmt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002512 break;
2513 }
Takashi Iwai0ba21762007-04-16 11:29:14 +02002514 if (!rate_bits[i].hz) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002515 snd_printdd("invalid rate %d\n", rate);
2516 return 0;
2517 }
2518
2519 if (channels == 0 || channels > 8) {
2520 snd_printdd("invalid channels %d\n", channels);
2521 return 0;
2522 }
2523 val |= channels - 1;
2524
2525 switch (snd_pcm_format_width(format)) {
2526 case 8: val |= 0x00; break;
2527 case 16: val |= 0x10; break;
2528 case 20:
2529 case 24:
2530 case 32:
2531 if (maxbps >= 32)
2532 val |= 0x40;
2533 else if (maxbps >= 24)
2534 val |= 0x30;
2535 else
2536 val |= 0x20;
2537 break;
2538 default:
Takashi Iwai0ba21762007-04-16 11:29:14 +02002539 snd_printdd("invalid format width %d\n",
2540 snd_pcm_format_width(format));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002541 return 0;
2542 }
2543
2544 return val;
2545}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002546EXPORT_SYMBOL_HDA(snd_hda_calc_stream_format);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002547
2548/**
2549 * snd_hda_query_supported_pcm - query the supported PCM rates and formats
2550 * @codec: the HDA codec
2551 * @nid: NID to query
2552 * @ratesp: the pointer to store the detected rate bitflags
2553 * @formatsp: the pointer to store the detected formats
2554 * @bpsp: the pointer to store the detected format widths
2555 *
2556 * Queries the supported PCM rates and formats. The NULL @ratesp, @formatsp
2557 * or @bsps argument is ignored.
2558 *
2559 * Returns 0 if successful, otherwise a negative error code.
2560 */
Takashi Iwai986862bd2008-11-27 12:40:13 +01002561static int snd_hda_query_supported_pcm(struct hda_codec *codec, hda_nid_t nid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002562 u32 *ratesp, u64 *formatsp, unsigned int *bpsp)
2563{
Jaroslav Kyselaee504712009-03-17 14:30:31 +01002564 unsigned int i, val, wcaps;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002565
2566 val = 0;
Jaroslav Kyselaee504712009-03-17 14:30:31 +01002567 wcaps = get_wcaps(codec, nid);
2568 if (nid != codec->afg && (wcaps & AC_WCAP_FORMAT_OVRD)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002569 val = snd_hda_param_read(codec, nid, AC_PAR_PCM);
2570 if (val == -1)
2571 return -EIO;
2572 }
Takashi Iwai0ba21762007-04-16 11:29:14 +02002573 if (!val)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002574 val = snd_hda_param_read(codec, codec->afg, AC_PAR_PCM);
2575
2576 if (ratesp) {
2577 u32 rates = 0;
Takashi Iwaia961f9f2007-04-12 13:08:09 +02002578 for (i = 0; i < AC_PAR_PCM_RATE_BITS; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002579 if (val & (1 << i))
Takashi Iwaibefdf312005-08-22 13:57:55 +02002580 rates |= rate_bits[i].alsa_bits;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002581 }
Jaroslav Kyselaee504712009-03-17 14:30:31 +01002582 if (rates == 0) {
2583 snd_printk(KERN_ERR "hda_codec: rates == 0 "
2584 "(nid=0x%x, val=0x%x, ovrd=%i)\n",
2585 nid, val,
2586 (wcaps & AC_WCAP_FORMAT_OVRD) ? 1 : 0);
2587 return -EIO;
2588 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002589 *ratesp = rates;
2590 }
2591
2592 if (formatsp || bpsp) {
2593 u64 formats = 0;
Jaroslav Kyselaee504712009-03-17 14:30:31 +01002594 unsigned int streams, bps;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002595
Linus Torvalds1da177e2005-04-16 15:20:36 -07002596 streams = snd_hda_param_read(codec, nid, AC_PAR_STREAM);
2597 if (streams == -1)
2598 return -EIO;
Takashi Iwai0ba21762007-04-16 11:29:14 +02002599 if (!streams) {
2600 streams = snd_hda_param_read(codec, codec->afg,
2601 AC_PAR_STREAM);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002602 if (streams == -1)
2603 return -EIO;
2604 }
2605
2606 bps = 0;
2607 if (streams & AC_SUPFMT_PCM) {
2608 if (val & AC_SUPPCM_BITS_8) {
2609 formats |= SNDRV_PCM_FMTBIT_U8;
2610 bps = 8;
2611 }
2612 if (val & AC_SUPPCM_BITS_16) {
2613 formats |= SNDRV_PCM_FMTBIT_S16_LE;
2614 bps = 16;
2615 }
2616 if (wcaps & AC_WCAP_DIGITAL) {
2617 if (val & AC_SUPPCM_BITS_32)
2618 formats |= SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_LE;
2619 if (val & (AC_SUPPCM_BITS_20|AC_SUPPCM_BITS_24))
2620 formats |= SNDRV_PCM_FMTBIT_S32_LE;
2621 if (val & AC_SUPPCM_BITS_24)
2622 bps = 24;
2623 else if (val & AC_SUPPCM_BITS_20)
2624 bps = 20;
Takashi Iwai0ba21762007-04-16 11:29:14 +02002625 } else if (val & (AC_SUPPCM_BITS_20|AC_SUPPCM_BITS_24|
2626 AC_SUPPCM_BITS_32)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002627 formats |= SNDRV_PCM_FMTBIT_S32_LE;
2628 if (val & AC_SUPPCM_BITS_32)
2629 bps = 32;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002630 else if (val & AC_SUPPCM_BITS_24)
2631 bps = 24;
Nicolas Graziano33ef76512006-09-19 14:23:14 +02002632 else if (val & AC_SUPPCM_BITS_20)
2633 bps = 20;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002634 }
2635 }
Takashi Iwai0ba21762007-04-16 11:29:14 +02002636 else if (streams == AC_SUPFMT_FLOAT32) {
2637 /* should be exclusive */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002638 formats |= SNDRV_PCM_FMTBIT_FLOAT_LE;
2639 bps = 32;
Takashi Iwai0ba21762007-04-16 11:29:14 +02002640 } else if (streams == AC_SUPFMT_AC3) {
2641 /* should be exclusive */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002642 /* temporary hack: we have still no proper support
2643 * for the direct AC3 stream...
2644 */
2645 formats |= SNDRV_PCM_FMTBIT_U8;
2646 bps = 8;
2647 }
Jaroslav Kyselaee504712009-03-17 14:30:31 +01002648 if (formats == 0) {
2649 snd_printk(KERN_ERR "hda_codec: formats == 0 "
2650 "(nid=0x%x, val=0x%x, ovrd=%i, "
2651 "streams=0x%x)\n",
2652 nid, val,
2653 (wcaps & AC_WCAP_FORMAT_OVRD) ? 1 : 0,
2654 streams);
2655 return -EIO;
2656 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002657 if (formatsp)
2658 *formatsp = formats;
2659 if (bpsp)
2660 *bpsp = bps;
2661 }
2662
2663 return 0;
2664}
2665
2666/**
Takashi Iwai0ba21762007-04-16 11:29:14 +02002667 * snd_hda_is_supported_format - check whether the given node supports
2668 * the format val
Linus Torvalds1da177e2005-04-16 15:20:36 -07002669 *
2670 * Returns 1 if supported, 0 if not.
2671 */
2672int snd_hda_is_supported_format(struct hda_codec *codec, hda_nid_t nid,
2673 unsigned int format)
2674{
2675 int i;
2676 unsigned int val = 0, rate, stream;
2677
2678 if (nid != codec->afg &&
Takashi Iwai54d17402005-11-21 16:33:22 +01002679 (get_wcaps(codec, nid) & AC_WCAP_FORMAT_OVRD)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002680 val = snd_hda_param_read(codec, nid, AC_PAR_PCM);
2681 if (val == -1)
2682 return 0;
2683 }
Takashi Iwai0ba21762007-04-16 11:29:14 +02002684 if (!val) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002685 val = snd_hda_param_read(codec, codec->afg, AC_PAR_PCM);
2686 if (val == -1)
2687 return 0;
2688 }
2689
2690 rate = format & 0xff00;
Takashi Iwaia961f9f2007-04-12 13:08:09 +02002691 for (i = 0; i < AC_PAR_PCM_RATE_BITS; i++)
Takashi Iwaibefdf312005-08-22 13:57:55 +02002692 if (rate_bits[i].hda_fmt == rate) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002693 if (val & (1 << i))
2694 break;
2695 return 0;
2696 }
Takashi Iwaia961f9f2007-04-12 13:08:09 +02002697 if (i >= AC_PAR_PCM_RATE_BITS)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002698 return 0;
2699
2700 stream = snd_hda_param_read(codec, nid, AC_PAR_STREAM);
2701 if (stream == -1)
2702 return 0;
Takashi Iwai0ba21762007-04-16 11:29:14 +02002703 if (!stream && nid != codec->afg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002704 stream = snd_hda_param_read(codec, codec->afg, AC_PAR_STREAM);
Takashi Iwai0ba21762007-04-16 11:29:14 +02002705 if (!stream || stream == -1)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002706 return 0;
2707
2708 if (stream & AC_SUPFMT_PCM) {
2709 switch (format & 0xf0) {
2710 case 0x00:
Takashi Iwai0ba21762007-04-16 11:29:14 +02002711 if (!(val & AC_SUPPCM_BITS_8))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002712 return 0;
2713 break;
2714 case 0x10:
Takashi Iwai0ba21762007-04-16 11:29:14 +02002715 if (!(val & AC_SUPPCM_BITS_16))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002716 return 0;
2717 break;
2718 case 0x20:
Takashi Iwai0ba21762007-04-16 11:29:14 +02002719 if (!(val & AC_SUPPCM_BITS_20))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002720 return 0;
2721 break;
2722 case 0x30:
Takashi Iwai0ba21762007-04-16 11:29:14 +02002723 if (!(val & AC_SUPPCM_BITS_24))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002724 return 0;
2725 break;
2726 case 0x40:
Takashi Iwai0ba21762007-04-16 11:29:14 +02002727 if (!(val & AC_SUPPCM_BITS_32))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002728 return 0;
2729 break;
2730 default:
2731 return 0;
2732 }
2733 } else {
2734 /* FIXME: check for float32 and AC3? */
2735 }
2736
2737 return 1;
2738}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002739EXPORT_SYMBOL_HDA(snd_hda_is_supported_format);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002740
2741/*
2742 * PCM stuff
2743 */
2744static int hda_pcm_default_open_close(struct hda_pcm_stream *hinfo,
2745 struct hda_codec *codec,
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01002746 struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002747{
2748 return 0;
2749}
2750
2751static int hda_pcm_default_prepare(struct hda_pcm_stream *hinfo,
2752 struct hda_codec *codec,
2753 unsigned int stream_tag,
2754 unsigned int format,
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01002755 struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002756{
2757 snd_hda_codec_setup_stream(codec, hinfo->nid, stream_tag, 0, format);
2758 return 0;
2759}
2760
2761static int hda_pcm_default_cleanup(struct hda_pcm_stream *hinfo,
2762 struct hda_codec *codec,
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01002763 struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002764{
Takashi Iwai888afa12008-03-18 09:57:50 +01002765 snd_hda_codec_cleanup_stream(codec, hinfo->nid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002766 return 0;
2767}
2768
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02002769static int set_pcm_default_values(struct hda_codec *codec,
2770 struct hda_pcm_stream *info)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002771{
Jaroslav Kyselaee504712009-03-17 14:30:31 +01002772 int err;
2773
Takashi Iwai0ba21762007-04-16 11:29:14 +02002774 /* query support PCM information from the given NID */
2775 if (info->nid && (!info->rates || !info->formats)) {
Jaroslav Kyselaee504712009-03-17 14:30:31 +01002776 err = snd_hda_query_supported_pcm(codec, info->nid,
Takashi Iwai0ba21762007-04-16 11:29:14 +02002777 info->rates ? NULL : &info->rates,
2778 info->formats ? NULL : &info->formats,
2779 info->maxbps ? NULL : &info->maxbps);
Jaroslav Kyselaee504712009-03-17 14:30:31 +01002780 if (err < 0)
2781 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002782 }
2783 if (info->ops.open == NULL)
2784 info->ops.open = hda_pcm_default_open_close;
2785 if (info->ops.close == NULL)
2786 info->ops.close = hda_pcm_default_open_close;
2787 if (info->ops.prepare == NULL) {
Takashi Iwaida3cec32008-08-08 17:12:14 +02002788 if (snd_BUG_ON(!info->nid))
2789 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002790 info->ops.prepare = hda_pcm_default_prepare;
2791 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002792 if (info->ops.cleanup == NULL) {
Takashi Iwaida3cec32008-08-08 17:12:14 +02002793 if (snd_BUG_ON(!info->nid))
2794 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002795 info->ops.cleanup = hda_pcm_default_cleanup;
2796 }
2797 return 0;
2798}
2799
Takashi Iwai176d5332008-07-30 15:01:44 +02002800/*
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002801 * get the empty PCM device number to assign
2802 */
2803static int get_empty_pcm_device(struct hda_bus *bus, int type)
2804{
2805 static const char *dev_name[HDA_PCM_NTYPES] = {
2806 "Audio", "SPDIF", "HDMI", "Modem"
2807 };
2808 /* starting device index for each PCM type */
2809 static int dev_idx[HDA_PCM_NTYPES] = {
2810 [HDA_PCM_TYPE_AUDIO] = 0,
2811 [HDA_PCM_TYPE_SPDIF] = 1,
2812 [HDA_PCM_TYPE_HDMI] = 3,
2813 [HDA_PCM_TYPE_MODEM] = 6
2814 };
2815 /* normal audio device indices; not linear to keep compatibility */
2816 static int audio_idx[4] = { 0, 2, 4, 5 };
2817 int i, dev;
2818
2819 switch (type) {
2820 case HDA_PCM_TYPE_AUDIO:
2821 for (i = 0; i < ARRAY_SIZE(audio_idx); i++) {
2822 dev = audio_idx[i];
2823 if (!test_bit(dev, bus->pcm_dev_bits))
Takashi Iwai82ad39f2009-03-03 15:00:35 +01002824 goto ok;
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002825 }
Takashi Iwai82ad39f2009-03-03 15:00:35 +01002826 snd_printk(KERN_WARNING "Too many audio devices\n");
2827 return -EAGAIN;
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002828 case HDA_PCM_TYPE_SPDIF:
2829 case HDA_PCM_TYPE_HDMI:
2830 case HDA_PCM_TYPE_MODEM:
2831 dev = dev_idx[type];
2832 if (test_bit(dev, bus->pcm_dev_bits)) {
2833 snd_printk(KERN_WARNING "%s already defined\n",
2834 dev_name[type]);
2835 return -EAGAIN;
2836 }
2837 break;
2838 default:
2839 snd_printk(KERN_WARNING "Invalid PCM type %d\n", type);
2840 return -EINVAL;
2841 }
Takashi Iwai82ad39f2009-03-03 15:00:35 +01002842 ok:
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002843 set_bit(dev, bus->pcm_dev_bits);
2844 return dev;
2845}
2846
2847/*
Takashi Iwai176d5332008-07-30 15:01:44 +02002848 * attach a new PCM stream
2849 */
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002850static int snd_hda_attach_pcm(struct hda_codec *codec, struct hda_pcm *pcm)
Takashi Iwai176d5332008-07-30 15:01:44 +02002851{
Takashi Iwai33fa35e2008-11-06 16:50:40 +01002852 struct hda_bus *bus = codec->bus;
Takashi Iwai176d5332008-07-30 15:01:44 +02002853 struct hda_pcm_stream *info;
2854 int stream, err;
2855
Takashi Iwaib91f0802008-11-04 08:43:08 +01002856 if (snd_BUG_ON(!pcm->name))
Takashi Iwai176d5332008-07-30 15:01:44 +02002857 return -EINVAL;
2858 for (stream = 0; stream < 2; stream++) {
2859 info = &pcm->stream[stream];
2860 if (info->substreams) {
2861 err = set_pcm_default_values(codec, info);
2862 if (err < 0)
2863 return err;
2864 }
2865 }
Takashi Iwai33fa35e2008-11-06 16:50:40 +01002866 return bus->ops.attach_pcm(bus, codec, pcm);
Takashi Iwai176d5332008-07-30 15:01:44 +02002867}
2868
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002869/* assign all PCMs of the given codec */
2870int snd_hda_codec_build_pcms(struct hda_codec *codec)
2871{
2872 unsigned int pcm;
2873 int err;
2874
2875 if (!codec->num_pcms) {
2876 if (!codec->patch_ops.build_pcms)
2877 return 0;
2878 err = codec->patch_ops.build_pcms(codec);
Takashi Iwai6e655bf2009-03-02 10:46:03 +01002879 if (err < 0) {
2880 printk(KERN_ERR "hda_codec: cannot build PCMs"
2881 "for #%d (error %d)\n", codec->addr, err);
2882 err = snd_hda_codec_reset(codec);
2883 if (err < 0) {
2884 printk(KERN_ERR
2885 "hda_codec: cannot revert codec\n");
2886 return err;
2887 }
2888 }
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002889 }
2890 for (pcm = 0; pcm < codec->num_pcms; pcm++) {
2891 struct hda_pcm *cpcm = &codec->pcm_info[pcm];
2892 int dev;
2893
2894 if (!cpcm->stream[0].substreams && !cpcm->stream[1].substreams)
Takashi Iwai41b5b012009-01-20 18:21:23 +01002895 continue; /* no substreams assigned */
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002896
2897 if (!cpcm->pcm) {
2898 dev = get_empty_pcm_device(codec->bus, cpcm->pcm_type);
2899 if (dev < 0)
Takashi Iwai6e655bf2009-03-02 10:46:03 +01002900 continue; /* no fatal error */
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002901 cpcm->device = dev;
2902 err = snd_hda_attach_pcm(codec, cpcm);
Takashi Iwai6e655bf2009-03-02 10:46:03 +01002903 if (err < 0) {
2904 printk(KERN_ERR "hda_codec: cannot attach "
2905 "PCM stream %d for codec #%d\n",
2906 dev, codec->addr);
2907 continue; /* no fatal error */
2908 }
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002909 }
2910 }
2911 return 0;
2912}
2913
Linus Torvalds1da177e2005-04-16 15:20:36 -07002914/**
2915 * snd_hda_build_pcms - build PCM information
2916 * @bus: the BUS
2917 *
2918 * Create PCM information for each codec included in the bus.
2919 *
2920 * The build_pcms codec patch is requested to set up codec->num_pcms and
2921 * codec->pcm_info properly. The array is referred by the top-level driver
2922 * to create its PCM instances.
2923 * The allocated codec->pcm_info should be released in codec->patch_ops.free
2924 * callback.
2925 *
2926 * At least, substreams, channels_min and channels_max must be filled for
2927 * each stream. substreams = 0 indicates that the stream doesn't exist.
2928 * When rates and/or formats are zero, the supported values are queried
2929 * from the given nid. The nid is used also by the default ops.prepare
2930 * and ops.cleanup callbacks.
2931 *
2932 * The driver needs to call ops.open in its open callback. Similarly,
2933 * ops.close is supposed to be called in the close callback.
2934 * ops.prepare should be called in the prepare or hw_params callback
2935 * with the proper parameters for set up.
2936 * ops.cleanup should be called in hw_free for clean up of streams.
2937 *
2938 * This function returns 0 if successfull, or a negative error code.
2939 */
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002940int __devinit snd_hda_build_pcms(struct hda_bus *bus)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002941{
Takashi Iwai0ba21762007-04-16 11:29:14 +02002942 struct hda_codec *codec;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002943
Takashi Iwai0ba21762007-04-16 11:29:14 +02002944 list_for_each_entry(codec, &bus->codec_list, list) {
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002945 int err = snd_hda_codec_build_pcms(codec);
2946 if (err < 0)
2947 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002948 }
2949 return 0;
2950}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002951EXPORT_SYMBOL_HDA(snd_hda_build_pcms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002952
Linus Torvalds1da177e2005-04-16 15:20:36 -07002953/**
2954 * snd_hda_check_board_config - compare the current codec with the config table
2955 * @codec: the HDA codec
Takashi Iwaif5fcc132006-11-24 17:07:44 +01002956 * @num_configs: number of config enums
2957 * @models: array of model name strings
Linus Torvalds1da177e2005-04-16 15:20:36 -07002958 * @tbl: configuration table, terminated by null entries
2959 *
2960 * Compares the modelname or PCI subsystem id of the current codec with the
2961 * given configuration table. If a matching entry is found, returns its
2962 * config value (supposed to be 0 or positive).
2963 *
2964 * If no entries are matching, the function returns a negative value.
2965 */
Takashi Iwai12f288b2007-08-02 15:51:59 +02002966int snd_hda_check_board_config(struct hda_codec *codec,
2967 int num_configs, const char **models,
2968 const struct snd_pci_quirk *tbl)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002969{
Takashi Iwaif44ac832008-07-30 15:01:45 +02002970 if (codec->modelname && models) {
Takashi Iwaif5fcc132006-11-24 17:07:44 +01002971 int i;
2972 for (i = 0; i < num_configs; i++) {
2973 if (models[i] &&
Takashi Iwaif44ac832008-07-30 15:01:45 +02002974 !strcmp(codec->modelname, models[i])) {
Takashi Iwaif5fcc132006-11-24 17:07:44 +01002975 snd_printd(KERN_INFO "hda_codec: model '%s' is "
2976 "selected\n", models[i]);
2977 return i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002978 }
2979 }
2980 }
2981
Takashi Iwaif5fcc132006-11-24 17:07:44 +01002982 if (!codec->bus->pci || !tbl)
2983 return -1;
2984
2985 tbl = snd_pci_quirk_lookup(codec->bus->pci, tbl);
2986 if (!tbl)
2987 return -1;
2988 if (tbl->value >= 0 && tbl->value < num_configs) {
Takashi Iwai62cf8722008-05-20 12:15:15 +02002989#ifdef CONFIG_SND_DEBUG_VERBOSE
Takashi Iwaif5fcc132006-11-24 17:07:44 +01002990 char tmp[10];
2991 const char *model = NULL;
2992 if (models)
2993 model = models[tbl->value];
2994 if (!model) {
2995 sprintf(tmp, "#%d", tbl->value);
2996 model = tmp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002997 }
Takashi Iwaif5fcc132006-11-24 17:07:44 +01002998 snd_printdd(KERN_INFO "hda_codec: model '%s' is selected "
2999 "for config %x:%x (%s)\n",
3000 model, tbl->subvendor, tbl->subdevice,
3001 (tbl->name ? tbl->name : "Unknown device"));
3002#endif
3003 return tbl->value;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003004 }
3005 return -1;
3006}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003007EXPORT_SYMBOL_HDA(snd_hda_check_board_config);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003008
3009/**
Mauro Carvalho Chehab2eda3442008-08-11 10:18:39 +02003010 * snd_hda_check_board_codec_sid_config - compare the current codec
3011 subsystem ID with the
3012 config table
3013
3014 This is important for Gateway notebooks with SB450 HDA Audio
3015 where the vendor ID of the PCI device is:
3016 ATI Technologies Inc SB450 HDA Audio [1002:437b]
3017 and the vendor/subvendor are found only at the codec.
3018
3019 * @codec: the HDA codec
3020 * @num_configs: number of config enums
3021 * @models: array of model name strings
3022 * @tbl: configuration table, terminated by null entries
3023 *
3024 * Compares the modelname or PCI subsystem id of the current codec with the
3025 * given configuration table. If a matching entry is found, returns its
3026 * config value (supposed to be 0 or positive).
3027 *
3028 * If no entries are matching, the function returns a negative value.
3029 */
3030int snd_hda_check_board_codec_sid_config(struct hda_codec *codec,
3031 int num_configs, const char **models,
3032 const struct snd_pci_quirk *tbl)
3033{
3034 const struct snd_pci_quirk *q;
3035
3036 /* Search for codec ID */
3037 for (q = tbl; q->subvendor; q++) {
3038 unsigned long vendorid = (q->subdevice) | (q->subvendor << 16);
3039
3040 if (vendorid == codec->subsystem_id)
3041 break;
3042 }
3043
3044 if (!q->subvendor)
3045 return -1;
3046
3047 tbl = q;
3048
3049 if (tbl->value >= 0 && tbl->value < num_configs) {
3050#ifdef CONFIG_SND_DEBUG_DETECT
3051 char tmp[10];
3052 const char *model = NULL;
3053 if (models)
3054 model = models[tbl->value];
3055 if (!model) {
3056 sprintf(tmp, "#%d", tbl->value);
3057 model = tmp;
3058 }
3059 snd_printdd(KERN_INFO "hda_codec: model '%s' is selected "
3060 "for config %x:%x (%s)\n",
3061 model, tbl->subvendor, tbl->subdevice,
3062 (tbl->name ? tbl->name : "Unknown device"));
3063#endif
3064 return tbl->value;
3065 }
3066 return -1;
3067}
3068EXPORT_SYMBOL_HDA(snd_hda_check_board_codec_sid_config);
3069
3070/**
Linus Torvalds1da177e2005-04-16 15:20:36 -07003071 * snd_hda_add_new_ctls - create controls from the array
3072 * @codec: the HDA codec
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01003073 * @knew: the array of struct snd_kcontrol_new
Linus Torvalds1da177e2005-04-16 15:20:36 -07003074 *
3075 * This helper function creates and add new controls in the given array.
3076 * The array must be terminated with an empty entry as terminator.
3077 *
3078 * Returns 0 if successful, or a negative error code.
3079 */
Takashi Iwai12f288b2007-08-02 15:51:59 +02003080int snd_hda_add_new_ctls(struct hda_codec *codec, struct snd_kcontrol_new *knew)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003081{
Takashi Iwaicb53c622007-08-10 17:21:45 +02003082 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003083
3084 for (; knew->name; knew++) {
Takashi Iwai54d17402005-11-21 16:33:22 +01003085 struct snd_kcontrol *kctl;
3086 kctl = snd_ctl_new1(knew, codec);
Takashi Iwai0ba21762007-04-16 11:29:14 +02003087 if (!kctl)
Takashi Iwai54d17402005-11-21 16:33:22 +01003088 return -ENOMEM;
Takashi Iwaid13bd412008-07-30 15:01:45 +02003089 err = snd_hda_ctl_add(codec, kctl);
Takashi Iwai54d17402005-11-21 16:33:22 +01003090 if (err < 0) {
Takashi Iwai0ba21762007-04-16 11:29:14 +02003091 if (!codec->addr)
Takashi Iwai54d17402005-11-21 16:33:22 +01003092 return err;
3093 kctl = snd_ctl_new1(knew, codec);
Takashi Iwai0ba21762007-04-16 11:29:14 +02003094 if (!kctl)
Takashi Iwai54d17402005-11-21 16:33:22 +01003095 return -ENOMEM;
3096 kctl->id.device = codec->addr;
Takashi Iwaid13bd412008-07-30 15:01:45 +02003097 err = snd_hda_ctl_add(codec, kctl);
Takashi Iwai0ba21762007-04-16 11:29:14 +02003098 if (err < 0)
Takashi Iwai54d17402005-11-21 16:33:22 +01003099 return err;
3100 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003101 }
3102 return 0;
3103}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003104EXPORT_SYMBOL_HDA(snd_hda_add_new_ctls);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003105
Takashi Iwaicb53c622007-08-10 17:21:45 +02003106#ifdef CONFIG_SND_HDA_POWER_SAVE
3107static void hda_set_power_state(struct hda_codec *codec, hda_nid_t fg,
3108 unsigned int power_state);
3109
3110static void hda_power_work(struct work_struct *work)
3111{
3112 struct hda_codec *codec =
3113 container_of(work, struct hda_codec, power_work.work);
Takashi Iwai33fa35e2008-11-06 16:50:40 +01003114 struct hda_bus *bus = codec->bus;
Takashi Iwaicb53c622007-08-10 17:21:45 +02003115
Maxim Levitsky2e492462007-09-03 15:26:57 +02003116 if (!codec->power_on || codec->power_count) {
3117 codec->power_transition = 0;
Takashi Iwaicb53c622007-08-10 17:21:45 +02003118 return;
Maxim Levitsky2e492462007-09-03 15:26:57 +02003119 }
Takashi Iwaicb53c622007-08-10 17:21:45 +02003120
3121 hda_call_codec_suspend(codec);
Takashi Iwai33fa35e2008-11-06 16:50:40 +01003122 if (bus->ops.pm_notify)
3123 bus->ops.pm_notify(bus);
Takashi Iwaicb53c622007-08-10 17:21:45 +02003124}
3125
3126static void hda_keep_power_on(struct hda_codec *codec)
3127{
3128 codec->power_count++;
3129 codec->power_on = 1;
3130}
3131
3132void snd_hda_power_up(struct hda_codec *codec)
3133{
Takashi Iwai33fa35e2008-11-06 16:50:40 +01003134 struct hda_bus *bus = codec->bus;
3135
Takashi Iwaicb53c622007-08-10 17:21:45 +02003136 codec->power_count++;
Takashi Iwaia221e282007-08-16 16:35:33 +02003137 if (codec->power_on || codec->power_transition)
Takashi Iwaicb53c622007-08-10 17:21:45 +02003138 return;
3139
3140 codec->power_on = 1;
Takashi Iwai33fa35e2008-11-06 16:50:40 +01003141 if (bus->ops.pm_notify)
3142 bus->ops.pm_notify(bus);
Takashi Iwaicb53c622007-08-10 17:21:45 +02003143 hda_call_codec_resume(codec);
3144 cancel_delayed_work(&codec->power_work);
Takashi Iwaia221e282007-08-16 16:35:33 +02003145 codec->power_transition = 0;
Takashi Iwaicb53c622007-08-10 17:21:45 +02003146}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003147EXPORT_SYMBOL_HDA(snd_hda_power_up);
Takashi Iwai1289e9e2008-11-27 15:47:11 +01003148
3149#define power_save(codec) \
3150 ((codec)->bus->power_save ? *(codec)->bus->power_save : 0)
Takashi Iwaicb53c622007-08-10 17:21:45 +02003151
Takashi Iwaifee2fba2008-11-27 12:43:28 +01003152#define power_save(codec) \
3153 ((codec)->bus->power_save ? *(codec)->bus->power_save : 0)
3154
Takashi Iwaicb53c622007-08-10 17:21:45 +02003155void snd_hda_power_down(struct hda_codec *codec)
3156{
3157 --codec->power_count;
Takashi Iwaia221e282007-08-16 16:35:33 +02003158 if (!codec->power_on || codec->power_count || codec->power_transition)
Takashi Iwaicb53c622007-08-10 17:21:45 +02003159 return;
Takashi Iwaifee2fba2008-11-27 12:43:28 +01003160 if (power_save(codec)) {
Takashi Iwaia221e282007-08-16 16:35:33 +02003161 codec->power_transition = 1; /* avoid reentrance */
Takashi Iwaic107b412009-01-13 17:46:37 +01003162 queue_delayed_work(codec->bus->workq, &codec->power_work,
Takashi Iwaifee2fba2008-11-27 12:43:28 +01003163 msecs_to_jiffies(power_save(codec) * 1000));
Takashi Iwaia221e282007-08-16 16:35:33 +02003164 }
Takashi Iwaicb53c622007-08-10 17:21:45 +02003165}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003166EXPORT_SYMBOL_HDA(snd_hda_power_down);
Takashi Iwaicb53c622007-08-10 17:21:45 +02003167
3168int snd_hda_check_amp_list_power(struct hda_codec *codec,
3169 struct hda_loopback_check *check,
3170 hda_nid_t nid)
3171{
3172 struct hda_amp_list *p;
3173 int ch, v;
3174
3175 if (!check->amplist)
3176 return 0;
3177 for (p = check->amplist; p->nid; p++) {
3178 if (p->nid == nid)
3179 break;
3180 }
3181 if (!p->nid)
3182 return 0; /* nothing changed */
3183
3184 for (p = check->amplist; p->nid; p++) {
3185 for (ch = 0; ch < 2; ch++) {
3186 v = snd_hda_codec_amp_read(codec, p->nid, ch, p->dir,
3187 p->idx);
3188 if (!(v & HDA_AMP_MUTE) && v > 0) {
3189 if (!check->power_on) {
3190 check->power_on = 1;
3191 snd_hda_power_up(codec);
3192 }
3193 return 1;
3194 }
3195 }
3196 }
3197 if (check->power_on) {
3198 check->power_on = 0;
3199 snd_hda_power_down(codec);
3200 }
3201 return 0;
3202}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003203EXPORT_SYMBOL_HDA(snd_hda_check_amp_list_power);
Takashi Iwaicb53c622007-08-10 17:21:45 +02003204#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07003205
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01003206/*
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01003207 * Channel mode helper
3208 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003209int snd_hda_ch_mode_info(struct hda_codec *codec,
3210 struct snd_ctl_elem_info *uinfo,
3211 const struct hda_channel_mode *chmode,
3212 int num_chmodes)
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01003213{
3214 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
3215 uinfo->count = 1;
3216 uinfo->value.enumerated.items = num_chmodes;
3217 if (uinfo->value.enumerated.item >= num_chmodes)
3218 uinfo->value.enumerated.item = num_chmodes - 1;
3219 sprintf(uinfo->value.enumerated.name, "%dch",
3220 chmode[uinfo->value.enumerated.item].channels);
3221 return 0;
3222}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003223EXPORT_SYMBOL_HDA(snd_hda_ch_mode_info);
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01003224
Takashi Iwai0ba21762007-04-16 11:29:14 +02003225int snd_hda_ch_mode_get(struct hda_codec *codec,
3226 struct snd_ctl_elem_value *ucontrol,
3227 const struct hda_channel_mode *chmode,
3228 int num_chmodes,
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01003229 int max_channels)
3230{
3231 int i;
3232
3233 for (i = 0; i < num_chmodes; i++) {
3234 if (max_channels == chmode[i].channels) {
3235 ucontrol->value.enumerated.item[0] = i;
3236 break;
3237 }
3238 }
3239 return 0;
3240}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003241EXPORT_SYMBOL_HDA(snd_hda_ch_mode_get);
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01003242
Takashi Iwai0ba21762007-04-16 11:29:14 +02003243int snd_hda_ch_mode_put(struct hda_codec *codec,
3244 struct snd_ctl_elem_value *ucontrol,
3245 const struct hda_channel_mode *chmode,
3246 int num_chmodes,
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01003247 int *max_channelsp)
3248{
3249 unsigned int mode;
3250
3251 mode = ucontrol->value.enumerated.item[0];
Takashi Iwai68ea7b22007-11-15 15:54:38 +01003252 if (mode >= num_chmodes)
3253 return -EINVAL;
Takashi Iwai82beb8f2007-08-10 17:09:26 +02003254 if (*max_channelsp == chmode[mode].channels)
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01003255 return 0;
3256 /* change the current channel setting */
3257 *max_channelsp = chmode[mode].channels;
3258 if (chmode[mode].sequence)
Takashi Iwai82beb8f2007-08-10 17:09:26 +02003259 snd_hda_sequence_write_cache(codec, chmode[mode].sequence);
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01003260 return 1;
3261}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003262EXPORT_SYMBOL_HDA(snd_hda_ch_mode_put);
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01003263
Linus Torvalds1da177e2005-04-16 15:20:36 -07003264/*
3265 * input MUX helper
3266 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003267int snd_hda_input_mux_info(const struct hda_input_mux *imux,
3268 struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003269{
3270 unsigned int index;
3271
3272 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
3273 uinfo->count = 1;
3274 uinfo->value.enumerated.items = imux->num_items;
Takashi Iwai5513b0c2007-10-09 11:58:41 +02003275 if (!imux->num_items)
3276 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003277 index = uinfo->value.enumerated.item;
3278 if (index >= imux->num_items)
3279 index = imux->num_items - 1;
3280 strcpy(uinfo->value.enumerated.name, imux->items[index].label);
3281 return 0;
3282}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003283EXPORT_SYMBOL_HDA(snd_hda_input_mux_info);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003284
Takashi Iwai0ba21762007-04-16 11:29:14 +02003285int snd_hda_input_mux_put(struct hda_codec *codec,
3286 const struct hda_input_mux *imux,
3287 struct snd_ctl_elem_value *ucontrol,
3288 hda_nid_t nid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003289 unsigned int *cur_val)
3290{
3291 unsigned int idx;
3292
Takashi Iwai5513b0c2007-10-09 11:58:41 +02003293 if (!imux->num_items)
3294 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003295 idx = ucontrol->value.enumerated.item[0];
3296 if (idx >= imux->num_items)
3297 idx = imux->num_items - 1;
Takashi Iwai82beb8f2007-08-10 17:09:26 +02003298 if (*cur_val == idx)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003299 return 0;
Takashi Iwai82beb8f2007-08-10 17:09:26 +02003300 snd_hda_codec_write_cache(codec, nid, 0, AC_VERB_SET_CONNECT_SEL,
3301 imux->items[idx].index);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003302 *cur_val = idx;
3303 return 1;
3304}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003305EXPORT_SYMBOL_HDA(snd_hda_input_mux_put);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003306
3307
3308/*
3309 * Multi-channel / digital-out PCM helper functions
3310 */
3311
Takashi Iwai6b97eb42007-04-05 14:51:48 +02003312/* setup SPDIF output stream */
3313static void setup_dig_out_stream(struct hda_codec *codec, hda_nid_t nid,
3314 unsigned int stream_tag, unsigned int format)
3315{
3316 /* turn off SPDIF once; otherwise the IEC958 bits won't be updated */
Takashi Iwai2f728532008-09-25 16:32:41 +02003317 if (codec->spdif_status_reset && (codec->spdif_ctls & AC_DIG1_ENABLE))
3318 set_dig_out_convert(codec, nid,
3319 codec->spdif_ctls & ~AC_DIG1_ENABLE & 0xff,
3320 -1);
Takashi Iwai6b97eb42007-04-05 14:51:48 +02003321 snd_hda_codec_setup_stream(codec, nid, stream_tag, 0, format);
Takashi Iwai2f728532008-09-25 16:32:41 +02003322 if (codec->slave_dig_outs) {
3323 hda_nid_t *d;
3324 for (d = codec->slave_dig_outs; *d; d++)
3325 snd_hda_codec_setup_stream(codec, *d, stream_tag, 0,
3326 format);
Matthew Ranostayde51ca12008-09-07 14:31:40 -04003327 }
Takashi Iwai2f728532008-09-25 16:32:41 +02003328 /* turn on again (if needed) */
3329 if (codec->spdif_status_reset && (codec->spdif_ctls & AC_DIG1_ENABLE))
3330 set_dig_out_convert(codec, nid,
3331 codec->spdif_ctls & 0xff, -1);
3332}
Matthew Ranostayde51ca12008-09-07 14:31:40 -04003333
Takashi Iwai2f728532008-09-25 16:32:41 +02003334static void cleanup_dig_out_stream(struct hda_codec *codec, hda_nid_t nid)
3335{
3336 snd_hda_codec_cleanup_stream(codec, nid);
3337 if (codec->slave_dig_outs) {
3338 hda_nid_t *d;
3339 for (d = codec->slave_dig_outs; *d; d++)
3340 snd_hda_codec_cleanup_stream(codec, *d);
3341 }
Takashi Iwai6b97eb42007-04-05 14:51:48 +02003342}
3343
Linus Torvalds1da177e2005-04-16 15:20:36 -07003344/*
3345 * open the digital out in the exclusive mode
3346 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003347int snd_hda_multi_out_dig_open(struct hda_codec *codec,
3348 struct hda_multi_out *mout)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003349{
Ingo Molnar62932df2006-01-16 16:34:20 +01003350 mutex_lock(&codec->spdif_mutex);
Takashi Iwai5930ca42007-04-16 11:23:56 +02003351 if (mout->dig_out_used == HDA_DIG_ANALOG_DUP)
3352 /* already opened as analog dup; reset it once */
Takashi Iwai2f728532008-09-25 16:32:41 +02003353 cleanup_dig_out_stream(codec, mout->dig_out_nid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003354 mout->dig_out_used = HDA_DIG_EXCLUSIVE;
Ingo Molnar62932df2006-01-16 16:34:20 +01003355 mutex_unlock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003356 return 0;
3357}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003358EXPORT_SYMBOL_HDA(snd_hda_multi_out_dig_open);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003359
Takashi Iwai6b97eb42007-04-05 14:51:48 +02003360int snd_hda_multi_out_dig_prepare(struct hda_codec *codec,
3361 struct hda_multi_out *mout,
3362 unsigned int stream_tag,
3363 unsigned int format,
3364 struct snd_pcm_substream *substream)
3365{
3366 mutex_lock(&codec->spdif_mutex);
3367 setup_dig_out_stream(codec, mout->dig_out_nid, stream_tag, format);
3368 mutex_unlock(&codec->spdif_mutex);
3369 return 0;
3370}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003371EXPORT_SYMBOL_HDA(snd_hda_multi_out_dig_prepare);
Takashi Iwai6b97eb42007-04-05 14:51:48 +02003372
Takashi Iwai9411e212009-02-13 11:32:28 +01003373int snd_hda_multi_out_dig_cleanup(struct hda_codec *codec,
3374 struct hda_multi_out *mout)
3375{
3376 mutex_lock(&codec->spdif_mutex);
3377 cleanup_dig_out_stream(codec, mout->dig_out_nid);
3378 mutex_unlock(&codec->spdif_mutex);
3379 return 0;
3380}
3381EXPORT_SYMBOL_HDA(snd_hda_multi_out_dig_cleanup);
3382
Linus Torvalds1da177e2005-04-16 15:20:36 -07003383/*
3384 * release the digital out
3385 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003386int snd_hda_multi_out_dig_close(struct hda_codec *codec,
3387 struct hda_multi_out *mout)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003388{
Ingo Molnar62932df2006-01-16 16:34:20 +01003389 mutex_lock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003390 mout->dig_out_used = 0;
Ingo Molnar62932df2006-01-16 16:34:20 +01003391 mutex_unlock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003392 return 0;
3393}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003394EXPORT_SYMBOL_HDA(snd_hda_multi_out_dig_close);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003395
3396/*
3397 * set up more restrictions for analog out
3398 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003399int snd_hda_multi_out_analog_open(struct hda_codec *codec,
3400 struct hda_multi_out *mout,
Takashi Iwai9a081602008-02-12 18:37:26 +01003401 struct snd_pcm_substream *substream,
3402 struct hda_pcm_stream *hinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003403{
Takashi Iwai9a081602008-02-12 18:37:26 +01003404 struct snd_pcm_runtime *runtime = substream->runtime;
3405 runtime->hw.channels_max = mout->max_channels;
3406 if (mout->dig_out_nid) {
3407 if (!mout->analog_rates) {
3408 mout->analog_rates = hinfo->rates;
3409 mout->analog_formats = hinfo->formats;
3410 mout->analog_maxbps = hinfo->maxbps;
3411 } else {
3412 runtime->hw.rates = mout->analog_rates;
3413 runtime->hw.formats = mout->analog_formats;
3414 hinfo->maxbps = mout->analog_maxbps;
3415 }
3416 if (!mout->spdif_rates) {
3417 snd_hda_query_supported_pcm(codec, mout->dig_out_nid,
3418 &mout->spdif_rates,
3419 &mout->spdif_formats,
3420 &mout->spdif_maxbps);
3421 }
3422 mutex_lock(&codec->spdif_mutex);
3423 if (mout->share_spdif) {
3424 runtime->hw.rates &= mout->spdif_rates;
3425 runtime->hw.formats &= mout->spdif_formats;
3426 if (mout->spdif_maxbps < hinfo->maxbps)
3427 hinfo->maxbps = mout->spdif_maxbps;
3428 }
Frederik Deweerdteaa99852008-04-14 13:11:44 +02003429 mutex_unlock(&codec->spdif_mutex);
Takashi Iwai9a081602008-02-12 18:37:26 +01003430 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003431 return snd_pcm_hw_constraint_step(substream->runtime, 0,
3432 SNDRV_PCM_HW_PARAM_CHANNELS, 2);
3433}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003434EXPORT_SYMBOL_HDA(snd_hda_multi_out_analog_open);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003435
3436/*
3437 * set up the i/o for analog out
3438 * when the digital out is available, copy the front out to digital out, too.
3439 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003440int snd_hda_multi_out_analog_prepare(struct hda_codec *codec,
3441 struct hda_multi_out *mout,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003442 unsigned int stream_tag,
3443 unsigned int format,
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01003444 struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003445{
3446 hda_nid_t *nids = mout->dac_nids;
3447 int chs = substream->runtime->channels;
3448 int i;
3449
Ingo Molnar62932df2006-01-16 16:34:20 +01003450 mutex_lock(&codec->spdif_mutex);
Takashi Iwai9a081602008-02-12 18:37:26 +01003451 if (mout->dig_out_nid && mout->share_spdif &&
3452 mout->dig_out_used != HDA_DIG_EXCLUSIVE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003453 if (chs == 2 &&
Takashi Iwai0ba21762007-04-16 11:29:14 +02003454 snd_hda_is_supported_format(codec, mout->dig_out_nid,
3455 format) &&
3456 !(codec->spdif_status & IEC958_AES0_NONAUDIO)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003457 mout->dig_out_used = HDA_DIG_ANALOG_DUP;
Takashi Iwai6b97eb42007-04-05 14:51:48 +02003458 setup_dig_out_stream(codec, mout->dig_out_nid,
3459 stream_tag, format);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003460 } else {
3461 mout->dig_out_used = 0;
Takashi Iwai2f728532008-09-25 16:32:41 +02003462 cleanup_dig_out_stream(codec, mout->dig_out_nid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003463 }
3464 }
Ingo Molnar62932df2006-01-16 16:34:20 +01003465 mutex_unlock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003466
3467 /* front */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003468 snd_hda_codec_setup_stream(codec, nids[HDA_FRONT], stream_tag,
3469 0, format);
Takashi Iwaid29240c2007-10-26 12:35:56 +02003470 if (!mout->no_share_stream &&
3471 mout->hp_nid && mout->hp_nid != nids[HDA_FRONT])
Linus Torvalds1da177e2005-04-16 15:20:36 -07003472 /* headphone out will just decode front left/right (stereo) */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003473 snd_hda_codec_setup_stream(codec, mout->hp_nid, stream_tag,
3474 0, format);
Takashi Iwai82bc9552006-03-21 11:24:42 +01003475 /* extra outputs copied from front */
3476 for (i = 0; i < ARRAY_SIZE(mout->extra_out_nid); i++)
Takashi Iwaid29240c2007-10-26 12:35:56 +02003477 if (!mout->no_share_stream && mout->extra_out_nid[i])
Takashi Iwai82bc9552006-03-21 11:24:42 +01003478 snd_hda_codec_setup_stream(codec,
3479 mout->extra_out_nid[i],
3480 stream_tag, 0, format);
3481
Linus Torvalds1da177e2005-04-16 15:20:36 -07003482 /* surrounds */
3483 for (i = 1; i < mout->num_dacs; i++) {
Takashi Iwai4b3acaf2005-06-10 19:48:10 +02003484 if (chs >= (i + 1) * 2) /* independent out */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003485 snd_hda_codec_setup_stream(codec, nids[i], stream_tag,
3486 i * 2, format);
Takashi Iwaid29240c2007-10-26 12:35:56 +02003487 else if (!mout->no_share_stream) /* copy front */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003488 snd_hda_codec_setup_stream(codec, nids[i], stream_tag,
3489 0, format);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003490 }
3491 return 0;
3492}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003493EXPORT_SYMBOL_HDA(snd_hda_multi_out_analog_prepare);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003494
3495/*
3496 * clean up the setting for analog out
3497 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003498int snd_hda_multi_out_analog_cleanup(struct hda_codec *codec,
3499 struct hda_multi_out *mout)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003500{
3501 hda_nid_t *nids = mout->dac_nids;
3502 int i;
3503
3504 for (i = 0; i < mout->num_dacs; i++)
Takashi Iwai888afa12008-03-18 09:57:50 +01003505 snd_hda_codec_cleanup_stream(codec, nids[i]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003506 if (mout->hp_nid)
Takashi Iwai888afa12008-03-18 09:57:50 +01003507 snd_hda_codec_cleanup_stream(codec, mout->hp_nid);
Takashi Iwai82bc9552006-03-21 11:24:42 +01003508 for (i = 0; i < ARRAY_SIZE(mout->extra_out_nid); i++)
3509 if (mout->extra_out_nid[i])
Takashi Iwai888afa12008-03-18 09:57:50 +01003510 snd_hda_codec_cleanup_stream(codec,
3511 mout->extra_out_nid[i]);
Ingo Molnar62932df2006-01-16 16:34:20 +01003512 mutex_lock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003513 if (mout->dig_out_nid && mout->dig_out_used == HDA_DIG_ANALOG_DUP) {
Takashi Iwai2f728532008-09-25 16:32:41 +02003514 cleanup_dig_out_stream(codec, mout->dig_out_nid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003515 mout->dig_out_used = 0;
3516 }
Ingo Molnar62932df2006-01-16 16:34:20 +01003517 mutex_unlock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003518 return 0;
3519}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003520EXPORT_SYMBOL_HDA(snd_hda_multi_out_analog_cleanup);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003521
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003522/*
Wu Fengguang6b345002008-10-07 14:21:41 +08003523 * Helper for automatic pin configuration
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003524 */
Kailang Yangdf694da2005-12-05 19:42:22 +01003525
Takashi Iwai12f288b2007-08-02 15:51:59 +02003526static int is_in_nid_list(hda_nid_t nid, hda_nid_t *list)
Kailang Yangdf694da2005-12-05 19:42:22 +01003527{
3528 for (; *list; list++)
3529 if (*list == nid)
3530 return 1;
3531 return 0;
3532}
3533
Steve Longerbeam81937d32007-05-08 15:33:03 +02003534
3535/*
3536 * Sort an associated group of pins according to their sequence numbers.
3537 */
3538static void sort_pins_by_sequence(hda_nid_t * pins, short * sequences,
3539 int num_pins)
3540{
3541 int i, j;
3542 short seq;
3543 hda_nid_t nid;
3544
3545 for (i = 0; i < num_pins; i++) {
3546 for (j = i + 1; j < num_pins; j++) {
3547 if (sequences[i] > sequences[j]) {
3548 seq = sequences[i];
3549 sequences[i] = sequences[j];
3550 sequences[j] = seq;
3551 nid = pins[i];
3552 pins[i] = pins[j];
3553 pins[j] = nid;
3554 }
3555 }
3556 }
3557}
3558
3559
Takashi Iwai82bc9552006-03-21 11:24:42 +01003560/*
3561 * Parse all pin widgets and store the useful pin nids to cfg
3562 *
3563 * The number of line-outs or any primary output is stored in line_outs,
3564 * and the corresponding output pins are assigned to line_out_pins[],
3565 * in the order of front, rear, CLFE, side, ...
3566 *
3567 * If more extra outputs (speaker and headphone) are found, the pins are
Takashi Iwaieb06ed82006-09-20 17:10:27 +02003568 * assisnged to hp_pins[] and speaker_pins[], respectively. If no line-out jack
Takashi Iwai82bc9552006-03-21 11:24:42 +01003569 * is detected, one of speaker of HP pins is assigned as the primary
3570 * output, i.e. to line_out_pins[0]. So, line_outs is always positive
3571 * if any analog output exists.
3572 *
3573 * The analog input pins are assigned to input_pins array.
3574 * The digital input/output pins are assigned to dig_in_pin and dig_out_pin,
3575 * respectively.
3576 */
Takashi Iwai12f288b2007-08-02 15:51:59 +02003577int snd_hda_parse_pin_def_config(struct hda_codec *codec,
3578 struct auto_pin_cfg *cfg,
3579 hda_nid_t *ignore_nids)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003580{
Takashi Iwai0ef6ce72008-01-22 15:35:37 +01003581 hda_nid_t nid, end_nid;
Steve Longerbeam81937d32007-05-08 15:33:03 +02003582 short seq, assoc_line_out, assoc_speaker;
3583 short sequences_line_out[ARRAY_SIZE(cfg->line_out_pins)];
3584 short sequences_speaker[ARRAY_SIZE(cfg->speaker_pins)];
Takashi Iwaif889fa92007-10-31 15:49:32 +01003585 short sequences_hp[ARRAY_SIZE(cfg->hp_pins)];
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003586
3587 memset(cfg, 0, sizeof(*cfg));
3588
Steve Longerbeam81937d32007-05-08 15:33:03 +02003589 memset(sequences_line_out, 0, sizeof(sequences_line_out));
3590 memset(sequences_speaker, 0, sizeof(sequences_speaker));
Takashi Iwaif889fa92007-10-31 15:49:32 +01003591 memset(sequences_hp, 0, sizeof(sequences_hp));
Steve Longerbeam81937d32007-05-08 15:33:03 +02003592 assoc_line_out = assoc_speaker = 0;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003593
Takashi Iwai0ef6ce72008-01-22 15:35:37 +01003594 end_nid = codec->start_nid + codec->num_nodes;
3595 for (nid = codec->start_nid; nid < end_nid; nid++) {
Takashi Iwai54d17402005-11-21 16:33:22 +01003596 unsigned int wid_caps = get_wcaps(codec, nid);
Takashi Iwai0ba21762007-04-16 11:29:14 +02003597 unsigned int wid_type =
3598 (wid_caps & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003599 unsigned int def_conf;
3600 short assoc, loc;
3601
3602 /* read all default configuration for pin complex */
3603 if (wid_type != AC_WID_PIN)
3604 continue;
Kailang Yangdf694da2005-12-05 19:42:22 +01003605 /* ignore the given nids (e.g. pc-beep returns error) */
3606 if (ignore_nids && is_in_nid_list(nid, ignore_nids))
3607 continue;
3608
Takashi Iwaic17a1ab2009-02-23 09:28:12 +01003609 def_conf = snd_hda_codec_get_pincfg(codec, nid);
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003610 if (get_defcfg_connect(def_conf) == AC_JACK_PORT_NONE)
3611 continue;
3612 loc = get_defcfg_location(def_conf);
3613 switch (get_defcfg_device(def_conf)) {
3614 case AC_JACK_LINE_OUT:
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003615 seq = get_defcfg_sequence(def_conf);
3616 assoc = get_defcfg_association(def_conf);
Matthew Ranostay90da78b2008-01-24 11:48:01 +01003617
3618 if (!(wid_caps & AC_WCAP_STEREO))
3619 if (!cfg->mono_out_pin)
3620 cfg->mono_out_pin = nid;
Takashi Iwai0ba21762007-04-16 11:29:14 +02003621 if (!assoc)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003622 continue;
Takashi Iwai0ba21762007-04-16 11:29:14 +02003623 if (!assoc_line_out)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003624 assoc_line_out = assoc;
3625 else if (assoc_line_out != assoc)
3626 continue;
3627 if (cfg->line_outs >= ARRAY_SIZE(cfg->line_out_pins))
3628 continue;
3629 cfg->line_out_pins[cfg->line_outs] = nid;
Steve Longerbeam81937d32007-05-08 15:33:03 +02003630 sequences_line_out[cfg->line_outs] = seq;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003631 cfg->line_outs++;
3632 break;
Takashi Iwai8d88bc32005-11-17 11:09:23 +01003633 case AC_JACK_SPEAKER:
Steve Longerbeam81937d32007-05-08 15:33:03 +02003634 seq = get_defcfg_sequence(def_conf);
3635 assoc = get_defcfg_association(def_conf);
3636 if (! assoc)
3637 continue;
3638 if (! assoc_speaker)
3639 assoc_speaker = assoc;
3640 else if (assoc_speaker != assoc)
3641 continue;
Takashi Iwai82bc9552006-03-21 11:24:42 +01003642 if (cfg->speaker_outs >= ARRAY_SIZE(cfg->speaker_pins))
3643 continue;
3644 cfg->speaker_pins[cfg->speaker_outs] = nid;
Steve Longerbeam81937d32007-05-08 15:33:03 +02003645 sequences_speaker[cfg->speaker_outs] = seq;
Takashi Iwai82bc9552006-03-21 11:24:42 +01003646 cfg->speaker_outs++;
Takashi Iwai8d88bc32005-11-17 11:09:23 +01003647 break;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003648 case AC_JACK_HP_OUT:
Takashi Iwaif889fa92007-10-31 15:49:32 +01003649 seq = get_defcfg_sequence(def_conf);
3650 assoc = get_defcfg_association(def_conf);
Takashi Iwaieb06ed82006-09-20 17:10:27 +02003651 if (cfg->hp_outs >= ARRAY_SIZE(cfg->hp_pins))
3652 continue;
3653 cfg->hp_pins[cfg->hp_outs] = nid;
Takashi Iwaif889fa92007-10-31 15:49:32 +01003654 sequences_hp[cfg->hp_outs] = (assoc << 4) | seq;
Takashi Iwaieb06ed82006-09-20 17:10:27 +02003655 cfg->hp_outs++;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003656 break;
Takashi Iwai314634b2006-09-21 11:56:18 +02003657 case AC_JACK_MIC_IN: {
3658 int preferred, alt;
3659 if (loc == AC_JACK_LOC_FRONT) {
3660 preferred = AUTO_PIN_FRONT_MIC;
3661 alt = AUTO_PIN_MIC;
3662 } else {
3663 preferred = AUTO_PIN_MIC;
3664 alt = AUTO_PIN_FRONT_MIC;
3665 }
3666 if (!cfg->input_pins[preferred])
3667 cfg->input_pins[preferred] = nid;
3668 else if (!cfg->input_pins[alt])
3669 cfg->input_pins[alt] = nid;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003670 break;
Takashi Iwai314634b2006-09-21 11:56:18 +02003671 }
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003672 case AC_JACK_LINE_IN:
3673 if (loc == AC_JACK_LOC_FRONT)
3674 cfg->input_pins[AUTO_PIN_FRONT_LINE] = nid;
3675 else
3676 cfg->input_pins[AUTO_PIN_LINE] = nid;
3677 break;
3678 case AC_JACK_CD:
3679 cfg->input_pins[AUTO_PIN_CD] = nid;
3680 break;
3681 case AC_JACK_AUX:
3682 cfg->input_pins[AUTO_PIN_AUX] = nid;
3683 break;
3684 case AC_JACK_SPDIF_OUT:
Takashi Iwai1b52ae72009-01-20 17:17:29 +01003685 case AC_JACK_DIG_OTHER_OUT:
Takashi Iwai0852d7a2009-02-11 11:35:15 +01003686 if (cfg->dig_outs >= ARRAY_SIZE(cfg->dig_out_pins))
3687 continue;
3688 cfg->dig_out_pins[cfg->dig_outs] = nid;
3689 cfg->dig_out_type[cfg->dig_outs] =
3690 (loc == AC_JACK_LOC_HDMI) ?
3691 HDA_PCM_TYPE_HDMI : HDA_PCM_TYPE_SPDIF;
3692 cfg->dig_outs++;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003693 break;
3694 case AC_JACK_SPDIF_IN:
Takashi Iwai1b52ae72009-01-20 17:17:29 +01003695 case AC_JACK_DIG_OTHER_IN:
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003696 cfg->dig_in_pin = nid;
Takashi Iwai2297bd62009-01-20 18:24:13 +01003697 if (loc == AC_JACK_LOC_HDMI)
3698 cfg->dig_in_type = HDA_PCM_TYPE_HDMI;
3699 else
3700 cfg->dig_in_type = HDA_PCM_TYPE_SPDIF;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003701 break;
3702 }
3703 }
3704
Takashi Iwai5832fcf2008-02-12 18:30:12 +01003705 /* FIX-UP:
3706 * If no line-out is defined but multiple HPs are found,
3707 * some of them might be the real line-outs.
3708 */
3709 if (!cfg->line_outs && cfg->hp_outs > 1) {
3710 int i = 0;
3711 while (i < cfg->hp_outs) {
3712 /* The real HPs should have the sequence 0x0f */
3713 if ((sequences_hp[i] & 0x0f) == 0x0f) {
3714 i++;
3715 continue;
3716 }
3717 /* Move it to the line-out table */
3718 cfg->line_out_pins[cfg->line_outs] = cfg->hp_pins[i];
3719 sequences_line_out[cfg->line_outs] = sequences_hp[i];
3720 cfg->line_outs++;
3721 cfg->hp_outs--;
3722 memmove(cfg->hp_pins + i, cfg->hp_pins + i + 1,
3723 sizeof(cfg->hp_pins[0]) * (cfg->hp_outs - i));
3724 memmove(sequences_hp + i - 1, sequences_hp + i,
3725 sizeof(sequences_hp[0]) * (cfg->hp_outs - i));
3726 }
3727 }
3728
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003729 /* sort by sequence */
Steve Longerbeam81937d32007-05-08 15:33:03 +02003730 sort_pins_by_sequence(cfg->line_out_pins, sequences_line_out,
3731 cfg->line_outs);
3732 sort_pins_by_sequence(cfg->speaker_pins, sequences_speaker,
3733 cfg->speaker_outs);
Takashi Iwaif889fa92007-10-31 15:49:32 +01003734 sort_pins_by_sequence(cfg->hp_pins, sequences_hp,
3735 cfg->hp_outs);
Steve Longerbeam81937d32007-05-08 15:33:03 +02003736
Takashi Iwaif889fa92007-10-31 15:49:32 +01003737 /* if we have only one mic, make it AUTO_PIN_MIC */
3738 if (!cfg->input_pins[AUTO_PIN_MIC] &&
3739 cfg->input_pins[AUTO_PIN_FRONT_MIC]) {
3740 cfg->input_pins[AUTO_PIN_MIC] =
3741 cfg->input_pins[AUTO_PIN_FRONT_MIC];
3742 cfg->input_pins[AUTO_PIN_FRONT_MIC] = 0;
3743 }
3744 /* ditto for line-in */
3745 if (!cfg->input_pins[AUTO_PIN_LINE] &&
3746 cfg->input_pins[AUTO_PIN_FRONT_LINE]) {
3747 cfg->input_pins[AUTO_PIN_LINE] =
3748 cfg->input_pins[AUTO_PIN_FRONT_LINE];
3749 cfg->input_pins[AUTO_PIN_FRONT_LINE] = 0;
3750 }
3751
Steve Longerbeam81937d32007-05-08 15:33:03 +02003752 /*
3753 * FIX-UP: if no line-outs are detected, try to use speaker or HP pin
3754 * as a primary output
3755 */
3756 if (!cfg->line_outs) {
3757 if (cfg->speaker_outs) {
3758 cfg->line_outs = cfg->speaker_outs;
3759 memcpy(cfg->line_out_pins, cfg->speaker_pins,
3760 sizeof(cfg->speaker_pins));
3761 cfg->speaker_outs = 0;
3762 memset(cfg->speaker_pins, 0, sizeof(cfg->speaker_pins));
3763 cfg->line_out_type = AUTO_PIN_SPEAKER_OUT;
3764 } else if (cfg->hp_outs) {
3765 cfg->line_outs = cfg->hp_outs;
3766 memcpy(cfg->line_out_pins, cfg->hp_pins,
3767 sizeof(cfg->hp_pins));
3768 cfg->hp_outs = 0;
3769 memset(cfg->hp_pins, 0, sizeof(cfg->hp_pins));
3770 cfg->line_out_type = AUTO_PIN_HP_OUT;
3771 }
3772 }
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003773
Takashi Iwaicb8e2f82005-07-29 11:54:32 +02003774 /* Reorder the surround channels
3775 * ALSA sequence is front/surr/clfe/side
3776 * HDA sequence is:
3777 * 4-ch: front/surr => OK as it is
3778 * 6-ch: front/clfe/surr
Takashi Iwai9422db42007-04-20 16:11:43 +02003779 * 8-ch: front/clfe/rear/side|fc
Takashi Iwaicb8e2f82005-07-29 11:54:32 +02003780 */
3781 switch (cfg->line_outs) {
3782 case 3:
Takashi Iwaicb8e2f82005-07-29 11:54:32 +02003783 case 4:
3784 nid = cfg->line_out_pins[1];
Takashi Iwai9422db42007-04-20 16:11:43 +02003785 cfg->line_out_pins[1] = cfg->line_out_pins[2];
Takashi Iwaicb8e2f82005-07-29 11:54:32 +02003786 cfg->line_out_pins[2] = nid;
3787 break;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003788 }
3789
Takashi Iwai82bc9552006-03-21 11:24:42 +01003790 /*
3791 * debug prints of the parsed results
3792 */
3793 snd_printd("autoconfig: line_outs=%d (0x%x/0x%x/0x%x/0x%x/0x%x)\n",
3794 cfg->line_outs, cfg->line_out_pins[0], cfg->line_out_pins[1],
3795 cfg->line_out_pins[2], cfg->line_out_pins[3],
3796 cfg->line_out_pins[4]);
3797 snd_printd(" speaker_outs=%d (0x%x/0x%x/0x%x/0x%x/0x%x)\n",
3798 cfg->speaker_outs, cfg->speaker_pins[0],
3799 cfg->speaker_pins[1], cfg->speaker_pins[2],
3800 cfg->speaker_pins[3], cfg->speaker_pins[4]);
Takashi Iwaieb06ed82006-09-20 17:10:27 +02003801 snd_printd(" hp_outs=%d (0x%x/0x%x/0x%x/0x%x/0x%x)\n",
3802 cfg->hp_outs, cfg->hp_pins[0],
3803 cfg->hp_pins[1], cfg->hp_pins[2],
3804 cfg->hp_pins[3], cfg->hp_pins[4]);
Matthew Ranostay90da78b2008-01-24 11:48:01 +01003805 snd_printd(" mono: mono_out=0x%x\n", cfg->mono_out_pin);
Takashi Iwai0852d7a2009-02-11 11:35:15 +01003806 if (cfg->dig_outs)
3807 snd_printd(" dig-out=0x%x/0x%x\n",
3808 cfg->dig_out_pins[0], cfg->dig_out_pins[1]);
Takashi Iwai82bc9552006-03-21 11:24:42 +01003809 snd_printd(" inputs: mic=0x%x, fmic=0x%x, line=0x%x, fline=0x%x,"
3810 " cd=0x%x, aux=0x%x\n",
3811 cfg->input_pins[AUTO_PIN_MIC],
3812 cfg->input_pins[AUTO_PIN_FRONT_MIC],
3813 cfg->input_pins[AUTO_PIN_LINE],
3814 cfg->input_pins[AUTO_PIN_FRONT_LINE],
3815 cfg->input_pins[AUTO_PIN_CD],
3816 cfg->input_pins[AUTO_PIN_AUX]);
Takashi Iwai32d2c7f2009-02-11 11:33:13 +01003817 if (cfg->dig_in_pin)
Takashi Iwai89ce9e82009-01-20 17:15:57 +01003818 snd_printd(" dig-in=0x%x\n", cfg->dig_in_pin);
Takashi Iwai82bc9552006-03-21 11:24:42 +01003819
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003820 return 0;
3821}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003822EXPORT_SYMBOL_HDA(snd_hda_parse_pin_def_config);
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003823
Takashi Iwai4a471b72005-12-07 13:56:29 +01003824/* labels for input pins */
3825const char *auto_pin_cfg_labels[AUTO_PIN_LAST] = {
3826 "Mic", "Front Mic", "Line", "Front Line", "CD", "Aux"
3827};
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003828EXPORT_SYMBOL_HDA(auto_pin_cfg_labels);
Takashi Iwai4a471b72005-12-07 13:56:29 +01003829
3830
Linus Torvalds1da177e2005-04-16 15:20:36 -07003831#ifdef CONFIG_PM
3832/*
3833 * power management
3834 */
3835
3836/**
3837 * snd_hda_suspend - suspend the codecs
3838 * @bus: the HDA bus
3839 * @state: suspsend state
3840 *
3841 * Returns 0 if successful.
3842 */
3843int snd_hda_suspend(struct hda_bus *bus, pm_message_t state)
3844{
Takashi Iwai0ba21762007-04-16 11:29:14 +02003845 struct hda_codec *codec;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003846
Takashi Iwai0ba21762007-04-16 11:29:14 +02003847 list_for_each_entry(codec, &bus->codec_list, list) {
Takashi Iwai0b7a2e92007-08-14 15:18:26 +02003848#ifdef CONFIG_SND_HDA_POWER_SAVE
3849 if (!codec->power_on)
3850 continue;
3851#endif
Takashi Iwaicb53c622007-08-10 17:21:45 +02003852 hda_call_codec_suspend(codec);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003853 }
3854 return 0;
3855}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003856EXPORT_SYMBOL_HDA(snd_hda_suspend);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003857
3858/**
3859 * snd_hda_resume - resume the codecs
3860 * @bus: the HDA bus
Linus Torvalds1da177e2005-04-16 15:20:36 -07003861 *
3862 * Returns 0 if successful.
Takashi Iwaicb53c622007-08-10 17:21:45 +02003863 *
3864 * This fucntion is defined only when POWER_SAVE isn't set.
3865 * In the power-save mode, the codec is resumed dynamically.
Linus Torvalds1da177e2005-04-16 15:20:36 -07003866 */
3867int snd_hda_resume(struct hda_bus *bus)
3868{
Takashi Iwai0ba21762007-04-16 11:29:14 +02003869 struct hda_codec *codec;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003870
Takashi Iwai0ba21762007-04-16 11:29:14 +02003871 list_for_each_entry(codec, &bus->codec_list, list) {
Maxim Levitskyd804ad92007-09-03 15:28:04 +02003872 if (snd_hda_codec_needs_resume(codec))
3873 hda_call_codec_resume(codec);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003874 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003875 return 0;
3876}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003877EXPORT_SYMBOL_HDA(snd_hda_resume);
Takashi Iwai1289e9e2008-11-27 15:47:11 +01003878#endif /* CONFIG_PM */
Takashi Iwaib2e18592008-07-30 15:01:44 +02003879
3880/*
3881 * generic arrays
3882 */
3883
3884/* get a new element from the given array
3885 * if it exceeds the pre-allocated array size, re-allocate the array
3886 */
3887void *snd_array_new(struct snd_array *array)
3888{
3889 if (array->used >= array->alloced) {
3890 int num = array->alloced + array->alloc_align;
Takashi Iwaib910d9a2008-11-07 00:26:52 +01003891 void *nlist;
3892 if (snd_BUG_ON(num >= 4096))
3893 return NULL;
3894 nlist = kcalloc(num + 1, array->elem_size, GFP_KERNEL);
Takashi Iwaib2e18592008-07-30 15:01:44 +02003895 if (!nlist)
3896 return NULL;
3897 if (array->list) {
3898 memcpy(nlist, array->list,
3899 array->elem_size * array->alloced);
3900 kfree(array->list);
3901 }
3902 array->list = nlist;
3903 array->alloced = num;
3904 }
Takashi Iwaif43aa022008-11-10 16:24:26 +01003905 return snd_array_elem(array, array->used++);
Takashi Iwaib2e18592008-07-30 15:01:44 +02003906}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003907EXPORT_SYMBOL_HDA(snd_array_new);
Takashi Iwaib2e18592008-07-30 15:01:44 +02003908
3909/* free the given array elements */
3910void snd_array_free(struct snd_array *array)
3911{
3912 kfree(array->list);
3913 array->used = 0;
3914 array->alloced = 0;
3915 array->list = NULL;
3916}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003917EXPORT_SYMBOL_HDA(snd_array_free);
Takashi Iwaib2022262008-11-21 21:24:03 +01003918
3919/*
3920 * used by hda_proc.c and hda_eld.c
3921 */
3922void snd_print_pcm_rates(int pcm, char *buf, int buflen)
3923{
3924 static unsigned int rates[] = {
3925 8000, 11025, 16000, 22050, 32000, 44100, 48000, 88200,
3926 96000, 176400, 192000, 384000
3927 };
3928 int i, j;
3929
3930 for (i = 0, j = 0; i < ARRAY_SIZE(rates); i++)
3931 if (pcm & (1 << i))
3932 j += snprintf(buf + j, buflen - j, " %d", rates[i]);
3933
3934 buf[j] = '\0'; /* necessary when j == 0 */
3935}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003936EXPORT_SYMBOL_HDA(snd_print_pcm_rates);
Takashi Iwaib2022262008-11-21 21:24:03 +01003937
3938void snd_print_pcm_bits(int pcm, char *buf, int buflen)
3939{
3940 static unsigned int bits[] = { 8, 16, 20, 24, 32 };
3941 int i, j;
3942
3943 for (i = 0, j = 0; i < ARRAY_SIZE(bits); i++)
3944 if (pcm & (AC_SUPPCM_BITS_8 << i))
3945 j += snprintf(buf + j, buflen - j, " %d", bits[i]);
3946
3947 buf[j] = '\0'; /* necessary when j == 0 */
3948}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003949EXPORT_SYMBOL_HDA(snd_print_pcm_bits);
Takashi Iwai1289e9e2008-11-27 15:47:11 +01003950
3951MODULE_DESCRIPTION("HDA codec core");
3952MODULE_LICENSE("GPL");