blob: aa0e1c18b606ace798eb6827f4f16a4b7751846c [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
Takashi Iwaiaa2936f2009-05-26 16:07:57 +0200161/*
162 * Send and receive a verb
163 */
164static int codec_exec_verb(struct hda_codec *codec, unsigned int cmd,
165 unsigned int *res)
166{
167 struct hda_bus *bus = codec->bus;
Takashi Iwai8dd78332009-06-02 01:16:07 +0200168 int err;
Takashi Iwaiaa2936f2009-05-26 16:07:57 +0200169
170 if (res)
171 *res = -1;
Takashi Iwai8dd78332009-06-02 01:16:07 +0200172 again:
Takashi Iwaiaa2936f2009-05-26 16:07:57 +0200173 snd_hda_power_up(codec);
174 mutex_lock(&bus->cmd_mutex);
Takashi Iwaiaa2936f2009-05-26 16:07:57 +0200175 err = bus->ops.command(bus, cmd);
Takashi Iwai8dd78332009-06-02 01:16:07 +0200176 if (!err && res)
177 *res = bus->ops.get_response(bus);
Takashi Iwaiaa2936f2009-05-26 16:07:57 +0200178 mutex_unlock(&bus->cmd_mutex);
179 snd_hda_power_down(codec);
Takashi Iwai8dd78332009-06-02 01:16:07 +0200180 if (res && *res == -1 && bus->rirb_error) {
181 if (bus->response_reset) {
182 snd_printd("hda_codec: resetting BUS due to "
183 "fatal communication error\n");
184 bus->ops.bus_reset(bus);
185 }
186 goto again;
187 }
188 /* clear reset-flag when the communication gets recovered */
189 if (!err)
190 bus->response_reset = 0;
Takashi Iwaiaa2936f2009-05-26 16:07:57 +0200191 return err;
192}
193
Linus Torvalds1da177e2005-04-16 15:20:36 -0700194/**
195 * snd_hda_codec_read - send a command and get the response
196 * @codec: the HDA codec
197 * @nid: NID to send the command
198 * @direct: direct flag
199 * @verb: the verb to send
200 * @parm: the parameter for the verb
201 *
202 * Send a single command and read the corresponding response.
203 *
204 * Returns the obtained response value, or -1 for an error.
205 */
Takashi Iwai0ba21762007-04-16 11:29:14 +0200206unsigned int snd_hda_codec_read(struct hda_codec *codec, hda_nid_t nid,
207 int direct,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700208 unsigned int verb, unsigned int parm)
209{
Takashi Iwaiaa2936f2009-05-26 16:07:57 +0200210 unsigned cmd = make_codec_cmd(codec, nid, direct, verb, parm);
211 unsigned int res;
212 codec_exec_verb(codec, cmd, &res);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700213 return res;
214}
Takashi Iwaiff7a3262008-11-28 15:17:06 +0100215EXPORT_SYMBOL_HDA(snd_hda_codec_read);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700216
Takashi Iwaiaa2936f2009-05-26 16:07:57 +0200217/* Define the below to send and receive verbs synchronously.
218 * If you often get any codec communication errors, this is worth to try.
219 */
220/* #define SND_HDA_SUPPORT_SYNC_WRITE */
221
Linus Torvalds1da177e2005-04-16 15:20:36 -0700222/**
223 * snd_hda_codec_write - send a single command without waiting for response
224 * @codec: the HDA codec
225 * @nid: NID to send the command
226 * @direct: direct flag
227 * @verb: the verb to send
228 * @parm: the parameter for the verb
229 *
230 * Send a single command without waiting for response.
231 *
232 * Returns 0 if successful, or a negative error code.
233 */
234int snd_hda_codec_write(struct hda_codec *codec, hda_nid_t nid, int direct,
235 unsigned int verb, unsigned int parm)
236{
Takashi Iwaiaa2936f2009-05-26 16:07:57 +0200237 unsigned int cmd = make_codec_cmd(codec, nid, direct, verb, parm);
238#ifdef SND_HDA_SUPPORT_SYNC_WRITE
Takashi Iwai33fa35e2008-11-06 16:50:40 +0100239 unsigned int res;
Takashi Iwaiaa2936f2009-05-26 16:07:57 +0200240 return codec_exec_verb(codec, cmd, &res);
241#else
242 return codec_exec_verb(codec, cmd, NULL);
243#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700244}
Takashi Iwaiff7a3262008-11-28 15:17:06 +0100245EXPORT_SYMBOL_HDA(snd_hda_codec_write);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700246
247/**
248 * snd_hda_sequence_write - sequence writes
249 * @codec: the HDA codec
250 * @seq: VERB array to send
251 *
252 * Send the commands sequentially from the given array.
253 * The array must be terminated with NID=0.
254 */
255void snd_hda_sequence_write(struct hda_codec *codec, const struct hda_verb *seq)
256{
257 for (; seq->nid; seq++)
258 snd_hda_codec_write(codec, seq->nid, 0, seq->verb, seq->param);
259}
Takashi Iwaiff7a3262008-11-28 15:17:06 +0100260EXPORT_SYMBOL_HDA(snd_hda_sequence_write);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700261
262/**
263 * snd_hda_get_sub_nodes - get the range of sub nodes
264 * @codec: the HDA codec
265 * @nid: NID to parse
266 * @start_id: the pointer to store the start NID
267 *
268 * Parse the NID and store the start NID of its sub-nodes.
269 * Returns the number of sub-nodes.
270 */
Takashi Iwai0ba21762007-04-16 11:29:14 +0200271int snd_hda_get_sub_nodes(struct hda_codec *codec, hda_nid_t nid,
272 hda_nid_t *start_id)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700273{
274 unsigned int parm;
275
276 parm = snd_hda_param_read(codec, nid, AC_PAR_NODE_COUNT);
Danny Tholene8a7f132007-09-11 21:41:56 +0200277 if (parm == -1)
278 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700279 *start_id = (parm >> 16) & 0x7fff;
280 return (int)(parm & 0x7fff);
281}
Takashi Iwaiff7a3262008-11-28 15:17:06 +0100282EXPORT_SYMBOL_HDA(snd_hda_get_sub_nodes);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700283
284/**
285 * snd_hda_get_connections - get connection list
286 * @codec: the HDA codec
287 * @nid: NID to parse
288 * @conn_list: connection list array
289 * @max_conns: max. number of connections to store
290 *
291 * Parses the connection list of the given widget and stores the list
292 * of NIDs.
293 *
294 * Returns the number of connections, or a negative error code.
295 */
296int snd_hda_get_connections(struct hda_codec *codec, hda_nid_t nid,
297 hda_nid_t *conn_list, int max_conns)
298{
299 unsigned int parm;
Takashi Iwai54d17402005-11-21 16:33:22 +0100300 int i, conn_len, conns;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700301 unsigned int shift, num_elems, mask;
Takashi Iwai54d17402005-11-21 16:33:22 +0100302 hda_nid_t prev_nid;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700303
Takashi Iwaida3cec32008-08-08 17:12:14 +0200304 if (snd_BUG_ON(!conn_list || max_conns <= 0))
305 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700306
307 parm = snd_hda_param_read(codec, nid, AC_PAR_CONNLIST_LEN);
308 if (parm & AC_CLIST_LONG) {
309 /* long form */
310 shift = 16;
311 num_elems = 2;
312 } else {
313 /* short form */
314 shift = 8;
315 num_elems = 4;
316 }
317 conn_len = parm & AC_CLIST_LENGTH;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700318 mask = (1 << (shift-1)) - 1;
319
Takashi Iwai0ba21762007-04-16 11:29:14 +0200320 if (!conn_len)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700321 return 0; /* no connection */
322
323 if (conn_len == 1) {
324 /* single connection */
Takashi Iwai0ba21762007-04-16 11:29:14 +0200325 parm = snd_hda_codec_read(codec, nid, 0,
326 AC_VERB_GET_CONNECT_LIST, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700327 conn_list[0] = parm & mask;
328 return 1;
329 }
330
331 /* multi connection */
332 conns = 0;
Takashi Iwai54d17402005-11-21 16:33:22 +0100333 prev_nid = 0;
334 for (i = 0; i < conn_len; i++) {
335 int range_val;
336 hda_nid_t val, n;
337
338 if (i % num_elems == 0)
339 parm = snd_hda_codec_read(codec, nid, 0,
340 AC_VERB_GET_CONNECT_LIST, i);
Takashi Iwai0ba21762007-04-16 11:29:14 +0200341 range_val = !!(parm & (1 << (shift-1))); /* ranges */
Takashi Iwai54d17402005-11-21 16:33:22 +0100342 val = parm & mask;
343 parm >>= shift;
344 if (range_val) {
345 /* ranges between the previous and this one */
Takashi Iwai0ba21762007-04-16 11:29:14 +0200346 if (!prev_nid || prev_nid >= val) {
347 snd_printk(KERN_WARNING "hda_codec: "
348 "invalid dep_range_val %x:%x\n",
349 prev_nid, val);
Takashi Iwai54d17402005-11-21 16:33:22 +0100350 continue;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700351 }
Takashi Iwai54d17402005-11-21 16:33:22 +0100352 for (n = prev_nid + 1; n <= val; n++) {
353 if (conns >= max_conns) {
Takashi Iwai0ba21762007-04-16 11:29:14 +0200354 snd_printk(KERN_ERR
355 "Too many connections\n");
Takashi Iwai54d17402005-11-21 16:33:22 +0100356 return -EINVAL;
357 }
358 conn_list[conns++] = n;
359 }
360 } else {
361 if (conns >= max_conns) {
362 snd_printk(KERN_ERR "Too many connections\n");
363 return -EINVAL;
364 }
365 conn_list[conns++] = val;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700366 }
Takashi Iwai54d17402005-11-21 16:33:22 +0100367 prev_nid = val;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700368 }
369 return conns;
370}
Takashi Iwaiff7a3262008-11-28 15:17:06 +0100371EXPORT_SYMBOL_HDA(snd_hda_get_connections);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700372
373
374/**
375 * snd_hda_queue_unsol_event - add an unsolicited event to queue
376 * @bus: the BUS
377 * @res: unsolicited event (lower 32bit of RIRB entry)
378 * @res_ex: codec addr and flags (upper 32bit or RIRB entry)
379 *
380 * Adds the given event to the queue. The events are processed in
381 * the workqueue asynchronously. Call this function in the interrupt
382 * hanlder when RIRB receives an unsolicited event.
383 *
384 * Returns 0 if successful, or a negative error code.
385 */
386int snd_hda_queue_unsol_event(struct hda_bus *bus, u32 res, u32 res_ex)
387{
388 struct hda_bus_unsolicited *unsol;
389 unsigned int wp;
390
Takashi Iwai0ba21762007-04-16 11:29:14 +0200391 unsol = bus->unsol;
392 if (!unsol)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700393 return 0;
394
395 wp = (unsol->wp + 1) % HDA_UNSOL_QUEUE_SIZE;
396 unsol->wp = wp;
397
398 wp <<= 1;
399 unsol->queue[wp] = res;
400 unsol->queue[wp + 1] = res_ex;
401
Takashi Iwai6acaed32009-01-12 10:09:24 +0100402 queue_work(bus->workq, &unsol->work);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700403
404 return 0;
405}
Takashi Iwaiff7a3262008-11-28 15:17:06 +0100406EXPORT_SYMBOL_HDA(snd_hda_queue_unsol_event);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700407
408/*
Wu Fengguang5c1d1a92008-10-07 14:17:53 +0800409 * process queued unsolicited events
Linus Torvalds1da177e2005-04-16 15:20:36 -0700410 */
David Howellsc4028952006-11-22 14:57:56 +0000411static void process_unsol_events(struct work_struct *work)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700412{
David Howellsc4028952006-11-22 14:57:56 +0000413 struct hda_bus_unsolicited *unsol =
414 container_of(work, struct hda_bus_unsolicited, work);
415 struct hda_bus *bus = unsol->bus;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700416 struct hda_codec *codec;
417 unsigned int rp, caddr, res;
418
419 while (unsol->rp != unsol->wp) {
420 rp = (unsol->rp + 1) % HDA_UNSOL_QUEUE_SIZE;
421 unsol->rp = rp;
422 rp <<= 1;
423 res = unsol->queue[rp];
424 caddr = unsol->queue[rp + 1];
Takashi Iwai0ba21762007-04-16 11:29:14 +0200425 if (!(caddr & (1 << 4))) /* no unsolicited event? */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700426 continue;
427 codec = bus->caddr_tbl[caddr & 0x0f];
428 if (codec && codec->patch_ops.unsol_event)
429 codec->patch_ops.unsol_event(codec, res);
430 }
431}
432
433/*
434 * initialize unsolicited queue
435 */
Takashi Iwai6c1f45e2008-07-30 15:01:45 +0200436static int init_unsol_queue(struct hda_bus *bus)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700437{
438 struct hda_bus_unsolicited *unsol;
439
Takashi Iwai9f146bb2005-11-17 11:07:49 +0100440 if (bus->unsol) /* already initialized */
441 return 0;
442
Takashi Iwaie560d8d2005-09-09 14:21:46 +0200443 unsol = kzalloc(sizeof(*unsol), GFP_KERNEL);
Takashi Iwai0ba21762007-04-16 11:29:14 +0200444 if (!unsol) {
445 snd_printk(KERN_ERR "hda_codec: "
446 "can't allocate unsolicited queue\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700447 return -ENOMEM;
448 }
David Howellsc4028952006-11-22 14:57:56 +0000449 INIT_WORK(&unsol->work, process_unsol_events);
450 unsol->bus = bus;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700451 bus->unsol = unsol;
452 return 0;
453}
454
455/*
456 * destructor
457 */
458static void snd_hda_codec_free(struct hda_codec *codec);
459
460static int snd_hda_bus_free(struct hda_bus *bus)
461{
Takashi Iwai0ba21762007-04-16 11:29:14 +0200462 struct hda_codec *codec, *n;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700463
Takashi Iwai0ba21762007-04-16 11:29:14 +0200464 if (!bus)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700465 return 0;
Takashi Iwai6acaed32009-01-12 10:09:24 +0100466 if (bus->workq)
467 flush_workqueue(bus->workq);
468 if (bus->unsol)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700469 kfree(bus->unsol);
Takashi Iwai0ba21762007-04-16 11:29:14 +0200470 list_for_each_entry_safe(codec, n, &bus->codec_list, list) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700471 snd_hda_codec_free(codec);
472 }
473 if (bus->ops.private_free)
474 bus->ops.private_free(bus);
Takashi Iwai6acaed32009-01-12 10:09:24 +0100475 if (bus->workq)
476 destroy_workqueue(bus->workq);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700477 kfree(bus);
478 return 0;
479}
480
Takashi Iwaic8b6bf92005-11-17 14:57:47 +0100481static int snd_hda_bus_dev_free(struct snd_device *device)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700482{
483 struct hda_bus *bus = device->device_data;
Takashi Iwaib94d35392008-11-21 09:08:06 +0100484 bus->shutdown = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700485 return snd_hda_bus_free(bus);
486}
487
Takashi Iwaid7ffba12008-07-30 15:01:46 +0200488#ifdef CONFIG_SND_HDA_HWDEP
489static int snd_hda_bus_dev_register(struct snd_device *device)
490{
491 struct hda_bus *bus = device->device_data;
492 struct hda_codec *codec;
493 list_for_each_entry(codec, &bus->codec_list, list) {
494 snd_hda_hwdep_add_sysfs(codec);
495 }
496 return 0;
497}
498#else
499#define snd_hda_bus_dev_register NULL
500#endif
501
Linus Torvalds1da177e2005-04-16 15:20:36 -0700502/**
503 * snd_hda_bus_new - create a HDA bus
504 * @card: the card entry
505 * @temp: the template for hda_bus information
506 * @busp: the pointer to store the created bus instance
507 *
508 * Returns 0 if successful, or a negative error code.
509 */
Takashi Iwai1289e9e2008-11-27 15:47:11 +0100510int /*__devinit*/ snd_hda_bus_new(struct snd_card *card,
Takashi Iwai756e2b02007-04-16 11:27:07 +0200511 const struct hda_bus_template *temp,
512 struct hda_bus **busp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700513{
514 struct hda_bus *bus;
515 int err;
Takashi Iwaic8b6bf92005-11-17 14:57:47 +0100516 static struct snd_device_ops dev_ops = {
Takashi Iwaid7ffba12008-07-30 15:01:46 +0200517 .dev_register = snd_hda_bus_dev_register,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700518 .dev_free = snd_hda_bus_dev_free,
519 };
520
Takashi Iwaida3cec32008-08-08 17:12:14 +0200521 if (snd_BUG_ON(!temp))
522 return -EINVAL;
523 if (snd_BUG_ON(!temp->ops.command || !temp->ops.get_response))
524 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700525
526 if (busp)
527 *busp = NULL;
528
Takashi Iwaie560d8d2005-09-09 14:21:46 +0200529 bus = kzalloc(sizeof(*bus), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700530 if (bus == NULL) {
531 snd_printk(KERN_ERR "can't allocate struct hda_bus\n");
532 return -ENOMEM;
533 }
534
535 bus->card = card;
536 bus->private_data = temp->private_data;
537 bus->pci = temp->pci;
538 bus->modelname = temp->modelname;
Takashi Iwaifee2fba2008-11-27 12:43:28 +0100539 bus->power_save = temp->power_save;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700540 bus->ops = temp->ops;
541
Ingo Molnar62932df2006-01-16 16:34:20 +0100542 mutex_init(&bus->cmd_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700543 INIT_LIST_HEAD(&bus->codec_list);
544
Takashi Iwaie8c0ee52009-02-05 07:34:28 +0100545 snprintf(bus->workq_name, sizeof(bus->workq_name),
546 "hd-audio%d", card->number);
547 bus->workq = create_singlethread_workqueue(bus->workq_name);
Takashi Iwai6acaed32009-01-12 10:09:24 +0100548 if (!bus->workq) {
Takashi Iwaie8c0ee52009-02-05 07:34:28 +0100549 snd_printk(KERN_ERR "cannot create workqueue %s\n",
550 bus->workq_name);
Takashi Iwai6acaed32009-01-12 10:09:24 +0100551 kfree(bus);
552 return -ENOMEM;
553 }
554
Takashi Iwai0ba21762007-04-16 11:29:14 +0200555 err = snd_device_new(card, SNDRV_DEV_BUS, bus, &dev_ops);
556 if (err < 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700557 snd_hda_bus_free(bus);
558 return err;
559 }
560 if (busp)
561 *busp = bus;
562 return 0;
563}
Takashi Iwaiff7a3262008-11-28 15:17:06 +0100564EXPORT_SYMBOL_HDA(snd_hda_bus_new);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700565
Takashi Iwai82467612007-07-27 19:15:54 +0200566#ifdef CONFIG_SND_HDA_GENERIC
567#define is_generic_config(codec) \
Takashi Iwaif44ac832008-07-30 15:01:45 +0200568 (codec->modelname && !strcmp(codec->modelname, "generic"))
Takashi Iwai82467612007-07-27 19:15:54 +0200569#else
570#define is_generic_config(codec) 0
571#endif
572
Takashi Iwai645f10c2008-11-28 15:07:37 +0100573#ifdef MODULE
Takashi Iwai1289e9e2008-11-27 15:47:11 +0100574#define HDA_MODREQ_MAX_COUNT 2 /* two request_modules()'s */
575#else
Takashi Iwai645f10c2008-11-28 15:07:37 +0100576#define HDA_MODREQ_MAX_COUNT 0 /* all presets are statically linked */
Takashi Iwai1289e9e2008-11-27 15:47:11 +0100577#endif
578
Linus Torvalds1da177e2005-04-16 15:20:36 -0700579/*
580 * find a matching codec preset
581 */
Takashi Iwai6c1f45e2008-07-30 15:01:45 +0200582static const struct hda_codec_preset *
Takashi Iwai756e2b02007-04-16 11:27:07 +0200583find_codec_preset(struct hda_codec *codec)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700584{
Takashi Iwai1289e9e2008-11-27 15:47:11 +0100585 struct hda_codec_preset_list *tbl;
586 const struct hda_codec_preset *preset;
587 int mod_requested = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700588
Takashi Iwai82467612007-07-27 19:15:54 +0200589 if (is_generic_config(codec))
Takashi Iwaid5ad6302007-03-07 15:55:59 +0100590 return NULL; /* use the generic parser */
591
Takashi Iwai1289e9e2008-11-27 15:47:11 +0100592 again:
593 mutex_lock(&preset_mutex);
594 list_for_each_entry(tbl, &hda_preset_tables, list) {
595 if (!try_module_get(tbl->owner)) {
596 snd_printk(KERN_ERR "hda_codec: cannot module_get\n");
597 continue;
598 }
599 for (preset = tbl->preset; preset->id; preset++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700600 u32 mask = preset->mask;
Marc Boucherca7cfae2008-01-22 15:32:25 +0100601 if (preset->afg && preset->afg != codec->afg)
602 continue;
603 if (preset->mfg && preset->mfg != codec->mfg)
604 continue;
Takashi Iwai0ba21762007-04-16 11:29:14 +0200605 if (!mask)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700606 mask = ~0;
Takashi Iwai9c7f8522006-06-28 15:08:22 +0200607 if (preset->id == (codec->vendor_id & mask) &&
Takashi Iwai0ba21762007-04-16 11:29:14 +0200608 (!preset->rev ||
Takashi Iwai1289e9e2008-11-27 15:47:11 +0100609 preset->rev == codec->revision_id)) {
610 mutex_unlock(&preset_mutex);
611 codec->owner = tbl->owner;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700612 return preset;
Takashi Iwai1289e9e2008-11-27 15:47:11 +0100613 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700614 }
Takashi Iwai1289e9e2008-11-27 15:47:11 +0100615 module_put(tbl->owner);
616 }
617 mutex_unlock(&preset_mutex);
618
619 if (mod_requested < HDA_MODREQ_MAX_COUNT) {
620 char name[32];
621 if (!mod_requested)
622 snprintf(name, sizeof(name), "snd-hda-codec-id:%08x",
623 codec->vendor_id);
624 else
625 snprintf(name, sizeof(name), "snd-hda-codec-id:%04x*",
626 (codec->vendor_id >> 16) & 0xffff);
627 request_module(name);
628 mod_requested++;
629 goto again;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700630 }
631 return NULL;
632}
633
634/*
Takashi Iwaif44ac832008-07-30 15:01:45 +0200635 * get_codec_name - store the codec name
Linus Torvalds1da177e2005-04-16 15:20:36 -0700636 */
Takashi Iwaif44ac832008-07-30 15:01:45 +0200637static int get_codec_name(struct hda_codec *codec)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700638{
639 const struct hda_vendor_id *c;
640 const char *vendor = NULL;
641 u16 vendor_id = codec->vendor_id >> 16;
Takashi Iwai812a2cc2009-05-16 10:00:49 +0200642 char tmp[16];
643
644 if (codec->vendor_name)
645 goto get_chip_name;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700646
647 for (c = hda_vendor_ids; c->id; c++) {
648 if (c->id == vendor_id) {
649 vendor = c->name;
650 break;
651 }
652 }
Takashi Iwai0ba21762007-04-16 11:29:14 +0200653 if (!vendor) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700654 sprintf(tmp, "Generic %04x", vendor_id);
655 vendor = tmp;
656 }
Takashi Iwai812a2cc2009-05-16 10:00:49 +0200657 codec->vendor_name = kstrdup(vendor, GFP_KERNEL);
658 if (!codec->vendor_name)
659 return -ENOMEM;
660
661 get_chip_name:
662 if (codec->chip_name)
663 return 0;
664
Linus Torvalds1da177e2005-04-16 15:20:36 -0700665 if (codec->preset && codec->preset->name)
Takashi Iwai812a2cc2009-05-16 10:00:49 +0200666 codec->chip_name = kstrdup(codec->preset->name, GFP_KERNEL);
667 else {
668 sprintf(tmp, "ID %x", codec->vendor_id & 0xffff);
669 codec->chip_name = kstrdup(tmp, GFP_KERNEL);
670 }
671 if (!codec->chip_name)
Takashi Iwaif44ac832008-07-30 15:01:45 +0200672 return -ENOMEM;
673 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700674}
675
676/*
Sasha Khapyorsky673b6832005-08-11 11:00:16 +0200677 * look for an AFG and MFG nodes
Linus Torvalds1da177e2005-04-16 15:20:36 -0700678 */
Takashi Iwai1289e9e2008-11-27 15:47:11 +0100679static void /*__devinit*/ setup_fg_nodes(struct hda_codec *codec)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700680{
Takashi Iwai93e82ae2009-04-17 18:04:41 +0200681 int i, total_nodes, function_id;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700682 hda_nid_t nid;
683
684 total_nodes = snd_hda_get_sub_nodes(codec, AC_NODE_ROOT, &nid);
685 for (i = 0; i < total_nodes; i++, nid++) {
Takashi Iwai93e82ae2009-04-17 18:04:41 +0200686 function_id = snd_hda_param_read(codec, nid,
Pascal de Bruijn234b4342009-03-23 11:15:59 +0100687 AC_PAR_FUNCTION_TYPE) & 0xff;
Takashi Iwai93e82ae2009-04-17 18:04:41 +0200688 switch (function_id) {
Sasha Khapyorsky673b6832005-08-11 11:00:16 +0200689 case AC_GRP_AUDIO_FUNCTION:
690 codec->afg = nid;
Takashi Iwai93e82ae2009-04-17 18:04:41 +0200691 codec->function_id = function_id;
Sasha Khapyorsky673b6832005-08-11 11:00:16 +0200692 break;
693 case AC_GRP_MODEM_FUNCTION:
694 codec->mfg = nid;
Takashi Iwai93e82ae2009-04-17 18:04:41 +0200695 codec->function_id = function_id;
Sasha Khapyorsky673b6832005-08-11 11:00:16 +0200696 break;
697 default:
698 break;
699 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700700 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700701}
702
703/*
Takashi Iwai54d17402005-11-21 16:33:22 +0100704 * read widget caps for each widget and store in cache
705 */
706static int read_widget_caps(struct hda_codec *codec, hda_nid_t fg_node)
707{
708 int i;
709 hda_nid_t nid;
710
711 codec->num_nodes = snd_hda_get_sub_nodes(codec, fg_node,
712 &codec->start_nid);
713 codec->wcaps = kmalloc(codec->num_nodes * 4, GFP_KERNEL);
Takashi Iwai0ba21762007-04-16 11:29:14 +0200714 if (!codec->wcaps)
Takashi Iwai54d17402005-11-21 16:33:22 +0100715 return -ENOMEM;
716 nid = codec->start_nid;
717 for (i = 0; i < codec->num_nodes; i++, nid++)
718 codec->wcaps[i] = snd_hda_param_read(codec, nid,
719 AC_PAR_AUDIO_WIDGET_CAP);
720 return 0;
721}
722
Takashi Iwai3be14142009-02-20 14:11:16 +0100723/* read all pin default configurations and save codec->init_pins */
724static int read_pin_defaults(struct hda_codec *codec)
725{
726 int i;
727 hda_nid_t nid = codec->start_nid;
728
729 for (i = 0; i < codec->num_nodes; i++, nid++) {
730 struct hda_pincfg *pin;
731 unsigned int wcaps = get_wcaps(codec, nid);
732 unsigned int wid_type = (wcaps & AC_WCAP_TYPE) >>
733 AC_WCAP_TYPE_SHIFT;
734 if (wid_type != AC_WID_PIN)
735 continue;
736 pin = snd_array_new(&codec->init_pins);
737 if (!pin)
738 return -ENOMEM;
739 pin->nid = nid;
740 pin->cfg = snd_hda_codec_read(codec, nid, 0,
741 AC_VERB_GET_CONFIG_DEFAULT, 0);
742 }
743 return 0;
744}
745
746/* look up the given pin config list and return the item matching with NID */
747static struct hda_pincfg *look_up_pincfg(struct hda_codec *codec,
748 struct snd_array *array,
749 hda_nid_t nid)
750{
751 int i;
752 for (i = 0; i < array->used; i++) {
753 struct hda_pincfg *pin = snd_array_elem(array, i);
754 if (pin->nid == nid)
755 return pin;
756 }
757 return NULL;
758}
759
760/* write a config value for the given NID */
761static void set_pincfg(struct hda_codec *codec, hda_nid_t nid,
762 unsigned int cfg)
763{
764 int i;
765 for (i = 0; i < 4; i++) {
766 snd_hda_codec_write(codec, nid, 0,
767 AC_VERB_SET_CONFIG_DEFAULT_BYTES_0 + i,
768 cfg & 0xff);
769 cfg >>= 8;
770 }
771}
772
773/* set the current pin config value for the given NID.
774 * the value is cached, and read via snd_hda_codec_get_pincfg()
775 */
776int snd_hda_add_pincfg(struct hda_codec *codec, struct snd_array *list,
777 hda_nid_t nid, unsigned int cfg)
778{
779 struct hda_pincfg *pin;
Takashi Iwai5e7b8e02009-02-23 09:45:59 +0100780 unsigned int oldcfg;
Takashi Iwai3be14142009-02-20 14:11:16 +0100781
Takashi Iwai5e7b8e02009-02-23 09:45:59 +0100782 oldcfg = snd_hda_codec_get_pincfg(codec, nid);
Takashi Iwai3be14142009-02-20 14:11:16 +0100783 pin = look_up_pincfg(codec, list, nid);
784 if (!pin) {
785 pin = snd_array_new(list);
786 if (!pin)
787 return -ENOMEM;
788 pin->nid = nid;
789 }
790 pin->cfg = cfg;
Takashi Iwai5e7b8e02009-02-23 09:45:59 +0100791
792 /* change only when needed; e.g. if the pincfg is already present
793 * in user_pins[], don't write it
794 */
795 cfg = snd_hda_codec_get_pincfg(codec, nid);
796 if (oldcfg != cfg)
797 set_pincfg(codec, nid, cfg);
Takashi Iwai3be14142009-02-20 14:11:16 +0100798 return 0;
799}
800
801int snd_hda_codec_set_pincfg(struct hda_codec *codec,
802 hda_nid_t nid, unsigned int cfg)
803{
Takashi Iwai346ff702009-02-23 09:42:57 +0100804 return snd_hda_add_pincfg(codec, &codec->driver_pins, nid, cfg);
Takashi Iwai3be14142009-02-20 14:11:16 +0100805}
806EXPORT_SYMBOL_HDA(snd_hda_codec_set_pincfg);
807
808/* get the current pin config value of the given pin NID */
809unsigned int snd_hda_codec_get_pincfg(struct hda_codec *codec, hda_nid_t nid)
810{
811 struct hda_pincfg *pin;
812
Takashi Iwai3be14142009-02-20 14:11:16 +0100813#ifdef CONFIG_SND_HDA_HWDEP
Takashi Iwai346ff702009-02-23 09:42:57 +0100814 pin = look_up_pincfg(codec, &codec->user_pins, nid);
Takashi Iwai3be14142009-02-20 14:11:16 +0100815 if (pin)
816 return pin->cfg;
817#endif
Takashi Iwai5e7b8e02009-02-23 09:45:59 +0100818 pin = look_up_pincfg(codec, &codec->driver_pins, nid);
819 if (pin)
820 return pin->cfg;
Takashi Iwai3be14142009-02-20 14:11:16 +0100821 pin = look_up_pincfg(codec, &codec->init_pins, nid);
822 if (pin)
823 return pin->cfg;
824 return 0;
825}
826EXPORT_SYMBOL_HDA(snd_hda_codec_get_pincfg);
827
828/* restore all current pin configs */
829static void restore_pincfgs(struct hda_codec *codec)
830{
831 int i;
832 for (i = 0; i < codec->init_pins.used; i++) {
833 struct hda_pincfg *pin = snd_array_elem(&codec->init_pins, i);
834 set_pincfg(codec, pin->nid,
835 snd_hda_codec_get_pincfg(codec, pin->nid));
836 }
837}
Takashi Iwai54d17402005-11-21 16:33:22 +0100838
Takashi Iwai01751f52007-08-10 16:59:39 +0200839static void init_hda_cache(struct hda_cache_rec *cache,
840 unsigned int record_size);
Takashi Iwai1fcaee62007-08-23 00:01:09 +0200841static void free_hda_cache(struct hda_cache_rec *cache);
Takashi Iwai01751f52007-08-10 16:59:39 +0200842
Takashi Iwai3be14142009-02-20 14:11:16 +0100843/* restore the initial pin cfgs and release all pincfg lists */
844static void restore_init_pincfgs(struct hda_codec *codec)
845{
Takashi Iwai346ff702009-02-23 09:42:57 +0100846 /* first free driver_pins and user_pins, then call restore_pincfg
Takashi Iwai3be14142009-02-20 14:11:16 +0100847 * so that only the values in init_pins are restored
848 */
Takashi Iwai346ff702009-02-23 09:42:57 +0100849 snd_array_free(&codec->driver_pins);
Takashi Iwai3be14142009-02-20 14:11:16 +0100850#ifdef CONFIG_SND_HDA_HWDEP
Takashi Iwai346ff702009-02-23 09:42:57 +0100851 snd_array_free(&codec->user_pins);
Takashi Iwai3be14142009-02-20 14:11:16 +0100852#endif
853 restore_pincfgs(codec);
854 snd_array_free(&codec->init_pins);
855}
856
Takashi Iwai54d17402005-11-21 16:33:22 +0100857/*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700858 * codec destructor
859 */
860static void snd_hda_codec_free(struct hda_codec *codec)
861{
Takashi Iwai0ba21762007-04-16 11:29:14 +0200862 if (!codec)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700863 return;
Takashi Iwai3be14142009-02-20 14:11:16 +0100864 restore_init_pincfgs(codec);
Takashi Iwaicb53c622007-08-10 17:21:45 +0200865#ifdef CONFIG_SND_HDA_POWER_SAVE
866 cancel_delayed_work(&codec->power_work);
Takashi Iwai6acaed32009-01-12 10:09:24 +0100867 flush_workqueue(codec->bus->workq);
Takashi Iwaicb53c622007-08-10 17:21:45 +0200868#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700869 list_del(&codec->list);
Takashi Iwaid13bd412008-07-30 15:01:45 +0200870 snd_array_free(&codec->mixers);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700871 codec->bus->caddr_tbl[codec->addr] = NULL;
872 if (codec->patch_ops.free)
873 codec->patch_ops.free(codec);
Takashi Iwai1289e9e2008-11-27 15:47:11 +0100874 module_put(codec->owner);
Takashi Iwai01751f52007-08-10 16:59:39 +0200875 free_hda_cache(&codec->amp_cache);
Takashi Iwaib3ac5632007-08-10 17:03:40 +0200876 free_hda_cache(&codec->cmd_cache);
Takashi Iwai812a2cc2009-05-16 10:00:49 +0200877 kfree(codec->vendor_name);
878 kfree(codec->chip_name);
Takashi Iwaif44ac832008-07-30 15:01:45 +0200879 kfree(codec->modelname);
Takashi Iwai54d17402005-11-21 16:33:22 +0100880 kfree(codec->wcaps);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700881 kfree(codec);
882}
883
Takashi Iwaibb6ac722009-03-13 09:02:42 +0100884static void hda_set_power_state(struct hda_codec *codec, hda_nid_t fg,
885 unsigned int power_state);
886
Linus Torvalds1da177e2005-04-16 15:20:36 -0700887/**
888 * snd_hda_codec_new - create a HDA codec
889 * @bus: the bus to assign
890 * @codec_addr: the codec address
891 * @codecp: the pointer to store the generated codec
892 *
893 * Returns 0 if successful, or a negative error code.
894 */
Takashi Iwai1289e9e2008-11-27 15:47:11 +0100895int /*__devinit*/ snd_hda_codec_new(struct hda_bus *bus, unsigned int codec_addr,
Takashi Iwaid4d9cd032008-12-19 15:19:11 +0100896 int do_init, struct hda_codec **codecp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700897{
898 struct hda_codec *codec;
Jaroslav Kyselaba443682008-08-13 20:55:32 +0200899 char component[31];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700900 int err;
901
Takashi Iwaida3cec32008-08-08 17:12:14 +0200902 if (snd_BUG_ON(!bus))
903 return -EINVAL;
904 if (snd_BUG_ON(codec_addr > HDA_MAX_CODEC_ADDRESS))
905 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700906
907 if (bus->caddr_tbl[codec_addr]) {
Takashi Iwai0ba21762007-04-16 11:29:14 +0200908 snd_printk(KERN_ERR "hda_codec: "
909 "address 0x%x is already occupied\n", codec_addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700910 return -EBUSY;
911 }
912
Takashi Iwaie560d8d2005-09-09 14:21:46 +0200913 codec = kzalloc(sizeof(*codec), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700914 if (codec == NULL) {
915 snd_printk(KERN_ERR "can't allocate struct hda_codec\n");
916 return -ENOMEM;
917 }
918
919 codec->bus = bus;
920 codec->addr = codec_addr;
Ingo Molnar62932df2006-01-16 16:34:20 +0100921 mutex_init(&codec->spdif_mutex);
Wu Fengguang5a9e02e2009-01-09 16:45:24 +0800922 mutex_init(&codec->control_mutex);
Takashi Iwai01751f52007-08-10 16:59:39 +0200923 init_hda_cache(&codec->amp_cache, sizeof(struct hda_amp_info));
Takashi Iwaib3ac5632007-08-10 17:03:40 +0200924 init_hda_cache(&codec->cmd_cache, sizeof(struct hda_cache_head));
Takashi Iwaid13bd412008-07-30 15:01:45 +0200925 snd_array_init(&codec->mixers, sizeof(struct snd_kcontrol *), 32);
Takashi Iwai3be14142009-02-20 14:11:16 +0100926 snd_array_init(&codec->init_pins, sizeof(struct hda_pincfg), 16);
Takashi Iwai346ff702009-02-23 09:42:57 +0100927 snd_array_init(&codec->driver_pins, sizeof(struct hda_pincfg), 16);
Takashi Iwai6c1f45e2008-07-30 15:01:45 +0200928 if (codec->bus->modelname) {
929 codec->modelname = kstrdup(codec->bus->modelname, GFP_KERNEL);
930 if (!codec->modelname) {
931 snd_hda_codec_free(codec);
932 return -ENODEV;
933 }
934 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700935
Takashi Iwaicb53c622007-08-10 17:21:45 +0200936#ifdef CONFIG_SND_HDA_POWER_SAVE
937 INIT_DELAYED_WORK(&codec->power_work, hda_power_work);
938 /* snd_hda_codec_new() marks the codec as power-up, and leave it as is.
939 * the caller has to power down appropriatley after initialization
940 * phase.
941 */
942 hda_keep_power_on(codec);
943#endif
944
Linus Torvalds1da177e2005-04-16 15:20:36 -0700945 list_add_tail(&codec->list, &bus->codec_list);
946 bus->caddr_tbl[codec_addr] = codec;
947
Takashi Iwai0ba21762007-04-16 11:29:14 +0200948 codec->vendor_id = snd_hda_param_read(codec, AC_NODE_ROOT,
949 AC_PAR_VENDOR_ID);
Takashi Iwai111d3af2006-02-16 18:17:58 +0100950 if (codec->vendor_id == -1)
951 /* read again, hopefully the access method was corrected
952 * in the last read...
953 */
954 codec->vendor_id = snd_hda_param_read(codec, AC_NODE_ROOT,
955 AC_PAR_VENDOR_ID);
Takashi Iwai0ba21762007-04-16 11:29:14 +0200956 codec->subsystem_id = snd_hda_param_read(codec, AC_NODE_ROOT,
957 AC_PAR_SUBSYSTEM_ID);
958 codec->revision_id = snd_hda_param_read(codec, AC_NODE_ROOT,
959 AC_PAR_REV_ID);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700960
Sasha Khapyorsky673b6832005-08-11 11:00:16 +0200961 setup_fg_nodes(codec);
Takashi Iwai0ba21762007-04-16 11:29:14 +0200962 if (!codec->afg && !codec->mfg) {
Sasha Khapyorsky673b6832005-08-11 11:00:16 +0200963 snd_printdd("hda_codec: no AFG or MFG node found\n");
Takashi Iwai3be14142009-02-20 14:11:16 +0100964 err = -ENODEV;
965 goto error;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700966 }
967
Takashi Iwai3be14142009-02-20 14:11:16 +0100968 err = read_widget_caps(codec, codec->afg ? codec->afg : codec->mfg);
969 if (err < 0) {
Takashi Iwai54d17402005-11-21 16:33:22 +0100970 snd_printk(KERN_ERR "hda_codec: cannot malloc\n");
Takashi Iwai3be14142009-02-20 14:11:16 +0100971 goto error;
Takashi Iwai54d17402005-11-21 16:33:22 +0100972 }
Takashi Iwai3be14142009-02-20 14:11:16 +0100973 err = read_pin_defaults(codec);
974 if (err < 0)
975 goto error;
Takashi Iwai54d17402005-11-21 16:33:22 +0100976
Takashi Iwai0ba21762007-04-16 11:29:14 +0200977 if (!codec->subsystem_id) {
Takashi Iwai86284e42005-10-11 15:05:54 +0200978 hda_nid_t nid = codec->afg ? codec->afg : codec->mfg;
Takashi Iwai0ba21762007-04-16 11:29:14 +0200979 codec->subsystem_id =
980 snd_hda_codec_read(codec, nid, 0,
981 AC_VERB_GET_SUBSYSTEM_ID, 0);
Takashi Iwai86284e42005-10-11 15:05:54 +0200982 }
Takashi Iwaif44ac832008-07-30 15:01:45 +0200983 if (bus->modelname)
984 codec->modelname = kstrdup(bus->modelname, GFP_KERNEL);
Takashi Iwai86284e42005-10-11 15:05:54 +0200985
Takashi Iwaibb6ac722009-03-13 09:02:42 +0100986 /* power-up all before initialization */
987 hda_set_power_state(codec,
988 codec->afg ? codec->afg : codec->mfg,
989 AC_PWRST_D0);
990
Takashi Iwaid4d9cd032008-12-19 15:19:11 +0100991 if (do_init) {
992 err = snd_hda_codec_configure(codec);
Takashi Iwai3be14142009-02-20 14:11:16 +0100993 if (err < 0)
994 goto error;
Takashi Iwai6c1f45e2008-07-30 15:01:45 +0200995 }
996 snd_hda_codec_proc_new(codec);
997
Takashi Iwai6c1f45e2008-07-30 15:01:45 +0200998 snd_hda_create_hwdep(codec);
Takashi Iwai6c1f45e2008-07-30 15:01:45 +0200999
1000 sprintf(component, "HDA:%08x,%08x,%08x", codec->vendor_id,
1001 codec->subsystem_id, codec->revision_id);
1002 snd_component_add(codec->bus->card, component);
1003
1004 if (codecp)
1005 *codecp = codec;
1006 return 0;
Takashi Iwai3be14142009-02-20 14:11:16 +01001007
1008 error:
1009 snd_hda_codec_free(codec);
1010 return err;
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001011}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001012EXPORT_SYMBOL_HDA(snd_hda_codec_new);
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001013
1014int snd_hda_codec_configure(struct hda_codec *codec)
1015{
1016 int err;
1017
Takashi Iwaid5ad6302007-03-07 15:55:59 +01001018 codec->preset = find_codec_preset(codec);
Takashi Iwai812a2cc2009-05-16 10:00:49 +02001019 if (!codec->vendor_name || !codec->chip_name) {
Takashi Iwaif44ac832008-07-30 15:01:45 +02001020 err = get_codec_name(codec);
1021 if (err < 0)
1022 return err;
1023 }
Takashi Iwai43ea1d42007-04-26 19:12:08 +02001024 /* audio codec should override the mixer name */
Takashi Iwaif44ac832008-07-30 15:01:45 +02001025 if (codec->afg || !*codec->bus->card->mixername)
Takashi Iwai812a2cc2009-05-16 10:00:49 +02001026 snprintf(codec->bus->card->mixername,
1027 sizeof(codec->bus->card->mixername),
1028 "%s %s", codec->vendor_name, codec->chip_name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001029
Takashi Iwai82467612007-07-27 19:15:54 +02001030 if (is_generic_config(codec)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001031 err = snd_hda_parse_generic_codec(codec);
Takashi Iwai82467612007-07-27 19:15:54 +02001032 goto patched;
1033 }
Takashi Iwai82467612007-07-27 19:15:54 +02001034 if (codec->preset && codec->preset->patch) {
1035 err = codec->preset->patch(codec);
1036 goto patched;
1037 }
1038
1039 /* call the default parser */
Takashi Iwai82467612007-07-27 19:15:54 +02001040 err = snd_hda_parse_generic_codec(codec);
Takashi Iwai35a1e0c2007-10-19 08:13:40 +02001041 if (err < 0)
1042 printk(KERN_ERR "hda-codec: No codec parser is available\n");
Takashi Iwai82467612007-07-27 19:15:54 +02001043
1044 patched:
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001045 if (!err && codec->patch_ops.unsol_event)
1046 err = init_unsol_queue(codec->bus);
1047 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001048}
1049
1050/**
1051 * snd_hda_codec_setup_stream - set up the codec for streaming
1052 * @codec: the CODEC to set up
1053 * @nid: the NID to set up
1054 * @stream_tag: stream tag to pass, it's between 0x1 and 0xf.
1055 * @channel_id: channel id to pass, zero based.
1056 * @format: stream format.
1057 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02001058void snd_hda_codec_setup_stream(struct hda_codec *codec, hda_nid_t nid,
1059 u32 stream_tag,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001060 int channel_id, int format)
1061{
Takashi Iwai0ba21762007-04-16 11:29:14 +02001062 if (!nid)
Takashi Iwaid21b37e2005-04-20 13:45:55 +02001063 return;
1064
Takashi Iwai0ba21762007-04-16 11:29:14 +02001065 snd_printdd("hda_codec_setup_stream: "
1066 "NID=0x%x, stream=0x%x, channel=%d, format=0x%x\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07001067 nid, stream_tag, channel_id, format);
1068 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CHANNEL_STREAMID,
1069 (stream_tag << 4) | channel_id);
1070 msleep(1);
1071 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_STREAM_FORMAT, format);
1072}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001073EXPORT_SYMBOL_HDA(snd_hda_codec_setup_stream);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001074
Takashi Iwai888afa12008-03-18 09:57:50 +01001075void snd_hda_codec_cleanup_stream(struct hda_codec *codec, hda_nid_t nid)
1076{
1077 if (!nid)
1078 return;
1079
1080 snd_printdd("hda_codec_cleanup_stream: NID=0x%x\n", nid);
1081 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CHANNEL_STREAMID, 0);
1082#if 0 /* keep the format */
1083 msleep(1);
1084 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_STREAM_FORMAT, 0);
1085#endif
1086}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001087EXPORT_SYMBOL_HDA(snd_hda_codec_cleanup_stream);
Takashi Iwai888afa12008-03-18 09:57:50 +01001088
Linus Torvalds1da177e2005-04-16 15:20:36 -07001089/*
1090 * amp access functions
1091 */
1092
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001093/* FIXME: more better hash key? */
1094#define HDA_HASH_KEY(nid,dir,idx) (u32)((nid) + ((idx) << 16) + ((dir) << 24))
Takashi Iwai1327a322009-03-23 13:07:47 +01001095#define HDA_HASH_PINCAP_KEY(nid) (u32)((nid) + (0x02 << 24))
Takashi Iwai92c7c8a2009-03-24 07:32:14 +01001096#define HDA_HASH_PARPCM_KEY(nid) (u32)((nid) + (0x03 << 24))
1097#define HDA_HASH_PARSTR_KEY(nid) (u32)((nid) + (0x04 << 24))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001098#define INFO_AMP_CAPS (1<<0)
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001099#define INFO_AMP_VOL(ch) (1 << (1 + (ch)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001100
1101/* initialize the hash table */
Takashi Iwai1289e9e2008-11-27 15:47:11 +01001102static void /*__devinit*/ init_hda_cache(struct hda_cache_rec *cache,
Takashi Iwai01751f52007-08-10 16:59:39 +02001103 unsigned int record_size)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001104{
Takashi Iwai01751f52007-08-10 16:59:39 +02001105 memset(cache, 0, sizeof(*cache));
1106 memset(cache->hash, 0xff, sizeof(cache->hash));
Takashi Iwai603c4012008-07-30 15:01:44 +02001107 snd_array_init(&cache->buf, record_size, 64);
Takashi Iwai01751f52007-08-10 16:59:39 +02001108}
1109
Takashi Iwai1fcaee62007-08-23 00:01:09 +02001110static void free_hda_cache(struct hda_cache_rec *cache)
Takashi Iwai01751f52007-08-10 16:59:39 +02001111{
Takashi Iwai603c4012008-07-30 15:01:44 +02001112 snd_array_free(&cache->buf);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001113}
1114
1115/* query the hash. allocate an entry if not found. */
Takashi Iwai01751f52007-08-10 16:59:39 +02001116static struct hda_cache_head *get_alloc_hash(struct hda_cache_rec *cache,
1117 u32 key)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001118{
Takashi Iwai01751f52007-08-10 16:59:39 +02001119 u16 idx = key % (u16)ARRAY_SIZE(cache->hash);
1120 u16 cur = cache->hash[idx];
1121 struct hda_cache_head *info;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001122
1123 while (cur != 0xffff) {
Takashi Iwaif43aa022008-11-10 16:24:26 +01001124 info = snd_array_elem(&cache->buf, cur);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001125 if (info->key == key)
1126 return info;
1127 cur = info->next;
1128 }
1129
1130 /* add a new hash entry */
Takashi Iwai603c4012008-07-30 15:01:44 +02001131 info = snd_array_new(&cache->buf);
Takashi Iwaic2174292008-11-07 00:23:30 +01001132 if (!info)
1133 return NULL;
Takashi Iwaif43aa022008-11-10 16:24:26 +01001134 cur = snd_array_index(&cache->buf, info);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001135 info->key = key;
Takashi Iwai01751f52007-08-10 16:59:39 +02001136 info->val = 0;
1137 info->next = cache->hash[idx];
1138 cache->hash[idx] = cur;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001139
1140 return info;
1141}
1142
Takashi Iwai01751f52007-08-10 16:59:39 +02001143/* query and allocate an amp hash entry */
1144static inline struct hda_amp_info *
1145get_alloc_amp_hash(struct hda_codec *codec, u32 key)
1146{
1147 return (struct hda_amp_info *)get_alloc_hash(&codec->amp_cache, key);
1148}
1149
Linus Torvalds1da177e2005-04-16 15:20:36 -07001150/*
1151 * query AMP capabilities for the given widget and direction
1152 */
Matthew Ranostay09a99952008-01-24 11:49:21 +01001153u32 query_amp_caps(struct hda_codec *codec, hda_nid_t nid, int direction)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001154{
Takashi Iwai0ba21762007-04-16 11:29:14 +02001155 struct hda_amp_info *info;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001156
Takashi Iwai0ba21762007-04-16 11:29:14 +02001157 info = get_alloc_amp_hash(codec, HDA_HASH_KEY(nid, direction, 0));
1158 if (!info)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001159 return 0;
Takashi Iwai01751f52007-08-10 16:59:39 +02001160 if (!(info->head.val & INFO_AMP_CAPS)) {
Takashi Iwai0ba21762007-04-16 11:29:14 +02001161 if (!(get_wcaps(codec, nid) & AC_WCAP_AMP_OVRD))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001162 nid = codec->afg;
Takashi Iwai0ba21762007-04-16 11:29:14 +02001163 info->amp_caps = snd_hda_param_read(codec, nid,
1164 direction == HDA_OUTPUT ?
1165 AC_PAR_AMP_OUT_CAP :
1166 AC_PAR_AMP_IN_CAP);
Takashi Iwaib75e53f2007-05-10 16:56:09 +02001167 if (info->amp_caps)
Takashi Iwai01751f52007-08-10 16:59:39 +02001168 info->head.val |= INFO_AMP_CAPS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001169 }
1170 return info->amp_caps;
1171}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001172EXPORT_SYMBOL_HDA(query_amp_caps);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001173
Takashi Iwai897cc182007-05-29 19:01:37 +02001174int snd_hda_override_amp_caps(struct hda_codec *codec, hda_nid_t nid, int dir,
1175 unsigned int caps)
1176{
1177 struct hda_amp_info *info;
1178
1179 info = get_alloc_amp_hash(codec, HDA_HASH_KEY(nid, dir, 0));
1180 if (!info)
1181 return -EINVAL;
1182 info->amp_caps = caps;
Takashi Iwai01751f52007-08-10 16:59:39 +02001183 info->head.val |= INFO_AMP_CAPS;
Takashi Iwai897cc182007-05-29 19:01:37 +02001184 return 0;
1185}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001186EXPORT_SYMBOL_HDA(snd_hda_override_amp_caps);
Takashi Iwai897cc182007-05-29 19:01:37 +02001187
Takashi Iwai92c7c8a2009-03-24 07:32:14 +01001188static unsigned int
1189query_caps_hash(struct hda_codec *codec, hda_nid_t nid, u32 key,
1190 unsigned int (*func)(struct hda_codec *, hda_nid_t))
Takashi Iwai1327a322009-03-23 13:07:47 +01001191{
1192 struct hda_amp_info *info;
1193
Takashi Iwai92c7c8a2009-03-24 07:32:14 +01001194 info = get_alloc_amp_hash(codec, key);
Takashi Iwai1327a322009-03-23 13:07:47 +01001195 if (!info)
1196 return 0;
1197 if (!info->head.val) {
Takashi Iwai1327a322009-03-23 13:07:47 +01001198 info->head.val |= INFO_AMP_CAPS;
Takashi Iwai92c7c8a2009-03-24 07:32:14 +01001199 info->amp_caps = func(codec, nid);
Takashi Iwai1327a322009-03-23 13:07:47 +01001200 }
1201 return info->amp_caps;
1202}
Takashi Iwai92c7c8a2009-03-24 07:32:14 +01001203
1204static unsigned int read_pin_cap(struct hda_codec *codec, hda_nid_t nid)
1205{
1206 return snd_hda_param_read(codec, nid, AC_PAR_PIN_CAP);
1207}
1208
1209u32 snd_hda_query_pin_caps(struct hda_codec *codec, hda_nid_t nid)
1210{
1211 return query_caps_hash(codec, nid, HDA_HASH_PINCAP_KEY(nid),
1212 read_pin_cap);
1213}
Takashi Iwai1327a322009-03-23 13:07:47 +01001214EXPORT_SYMBOL_HDA(snd_hda_query_pin_caps);
1215
Linus Torvalds1da177e2005-04-16 15:20:36 -07001216/*
1217 * read the current volume to info
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001218 * if the cache exists, read the cache value.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001219 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02001220static unsigned int get_vol_mute(struct hda_codec *codec,
1221 struct hda_amp_info *info, hda_nid_t nid,
1222 int ch, int direction, int index)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001223{
1224 u32 val, parm;
1225
Takashi Iwai01751f52007-08-10 16:59:39 +02001226 if (info->head.val & INFO_AMP_VOL(ch))
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001227 return info->vol[ch];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001228
1229 parm = ch ? AC_AMP_GET_RIGHT : AC_AMP_GET_LEFT;
1230 parm |= direction == HDA_OUTPUT ? AC_AMP_GET_OUTPUT : AC_AMP_GET_INPUT;
1231 parm |= index;
Takashi Iwai0ba21762007-04-16 11:29:14 +02001232 val = snd_hda_codec_read(codec, nid, 0,
1233 AC_VERB_GET_AMP_GAIN_MUTE, parm);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001234 info->vol[ch] = val & 0xff;
Takashi Iwai01751f52007-08-10 16:59:39 +02001235 info->head.val |= INFO_AMP_VOL(ch);
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001236 return info->vol[ch];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001237}
1238
1239/*
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001240 * write the current volume in info to the h/w and update the cache
Linus Torvalds1da177e2005-04-16 15:20:36 -07001241 */
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001242static void put_vol_mute(struct hda_codec *codec, struct hda_amp_info *info,
Takashi Iwai0ba21762007-04-16 11:29:14 +02001243 hda_nid_t nid, int ch, int direction, int index,
1244 int val)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001245{
1246 u32 parm;
1247
1248 parm = ch ? AC_AMP_SET_RIGHT : AC_AMP_SET_LEFT;
1249 parm |= direction == HDA_OUTPUT ? AC_AMP_SET_OUTPUT : AC_AMP_SET_INPUT;
1250 parm |= index << AC_AMP_SET_INDEX_SHIFT;
1251 parm |= val;
1252 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, parm);
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001253 info->vol[ch] = val;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001254}
1255
1256/*
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001257 * read AMP value. The volume is between 0 to 0x7f, 0x80 = mute bit.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001258 */
Takashi Iwai834be882006-03-01 14:16:17 +01001259int snd_hda_codec_amp_read(struct hda_codec *codec, hda_nid_t nid, int ch,
1260 int direction, int index)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001261{
Takashi Iwai0ba21762007-04-16 11:29:14 +02001262 struct hda_amp_info *info;
1263 info = get_alloc_amp_hash(codec, HDA_HASH_KEY(nid, direction, index));
1264 if (!info)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001265 return 0;
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001266 return get_vol_mute(codec, info, nid, ch, direction, index);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001267}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001268EXPORT_SYMBOL_HDA(snd_hda_codec_amp_read);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001269
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001270/*
1271 * update the AMP value, mask = bit mask to set, val = the value
1272 */
Takashi Iwai834be882006-03-01 14:16:17 +01001273int snd_hda_codec_amp_update(struct hda_codec *codec, hda_nid_t nid, int ch,
1274 int direction, int idx, int mask, int val)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001275{
Takashi Iwai0ba21762007-04-16 11:29:14 +02001276 struct hda_amp_info *info;
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001277
Takashi Iwai0ba21762007-04-16 11:29:14 +02001278 info = get_alloc_amp_hash(codec, HDA_HASH_KEY(nid, direction, idx));
1279 if (!info)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001280 return 0;
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001281 val &= mask;
1282 val |= get_vol_mute(codec, info, nid, ch, direction, idx) & ~mask;
Takashi Iwai82beb8f2007-08-10 17:09:26 +02001283 if (info->vol[ch] == val)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001284 return 0;
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001285 put_vol_mute(codec, info, nid, ch, direction, idx, val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001286 return 1;
1287}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001288EXPORT_SYMBOL_HDA(snd_hda_codec_amp_update);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001289
Takashi Iwai47fd8302007-08-10 17:11:07 +02001290/*
1291 * update the AMP stereo with the same mask and value
1292 */
1293int snd_hda_codec_amp_stereo(struct hda_codec *codec, hda_nid_t nid,
1294 int direction, int idx, int mask, int val)
1295{
1296 int ch, ret = 0;
1297 for (ch = 0; ch < 2; ch++)
1298 ret |= snd_hda_codec_amp_update(codec, nid, ch, direction,
1299 idx, mask, val);
1300 return ret;
1301}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001302EXPORT_SYMBOL_HDA(snd_hda_codec_amp_stereo);
Takashi Iwai47fd8302007-08-10 17:11:07 +02001303
Takashi Iwaicb53c622007-08-10 17:21:45 +02001304#ifdef SND_HDA_NEEDS_RESUME
Takashi Iwaib3ac5632007-08-10 17:03:40 +02001305/* resume the all amp commands from the cache */
1306void snd_hda_codec_resume_amp(struct hda_codec *codec)
1307{
Takashi Iwai603c4012008-07-30 15:01:44 +02001308 struct hda_amp_info *buffer = codec->amp_cache.buf.list;
Takashi Iwaib3ac5632007-08-10 17:03:40 +02001309 int i;
1310
Takashi Iwai603c4012008-07-30 15:01:44 +02001311 for (i = 0; i < codec->amp_cache.buf.used; i++, buffer++) {
Takashi Iwaib3ac5632007-08-10 17:03:40 +02001312 u32 key = buffer->head.key;
1313 hda_nid_t nid;
1314 unsigned int idx, dir, ch;
1315 if (!key)
1316 continue;
1317 nid = key & 0xff;
1318 idx = (key >> 16) & 0xff;
1319 dir = (key >> 24) & 0xff;
1320 for (ch = 0; ch < 2; ch++) {
1321 if (!(buffer->head.val & INFO_AMP_VOL(ch)))
1322 continue;
1323 put_vol_mute(codec, buffer, nid, ch, dir, idx,
1324 buffer->vol[ch]);
1325 }
1326 }
1327}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001328EXPORT_SYMBOL_HDA(snd_hda_codec_resume_amp);
Takashi Iwaicb53c622007-08-10 17:21:45 +02001329#endif /* SND_HDA_NEEDS_RESUME */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001330
Linus Torvalds1da177e2005-04-16 15:20:36 -07001331/* volume */
Takashi Iwai0ba21762007-04-16 11:29:14 +02001332int snd_hda_mixer_amp_volume_info(struct snd_kcontrol *kcontrol,
1333 struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001334{
1335 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1336 u16 nid = get_amp_nid(kcontrol);
1337 u8 chs = get_amp_channels(kcontrol);
1338 int dir = get_amp_direction(kcontrol);
Takashi Iwai29fdbec2009-01-20 13:07:55 +01001339 unsigned int ofs = get_amp_offset(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001340 u32 caps;
1341
1342 caps = query_amp_caps(codec, nid, dir);
Takashi Iwai0ba21762007-04-16 11:29:14 +02001343 /* num steps */
1344 caps = (caps & AC_AMPCAP_NUM_STEPS) >> AC_AMPCAP_NUM_STEPS_SHIFT;
1345 if (!caps) {
1346 printk(KERN_WARNING "hda_codec: "
Takashi Iwai9c8f2ab2008-01-11 16:12:23 +01001347 "num_steps = 0 for NID=0x%x (ctl = %s)\n", nid,
1348 kcontrol->id.name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001349 return -EINVAL;
1350 }
Takashi Iwai29fdbec2009-01-20 13:07:55 +01001351 if (ofs < caps)
1352 caps -= ofs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001353 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
1354 uinfo->count = chs == 3 ? 2 : 1;
1355 uinfo->value.integer.min = 0;
1356 uinfo->value.integer.max = caps;
1357 return 0;
1358}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001359EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_volume_info);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001360
Takashi Iwai29fdbec2009-01-20 13:07:55 +01001361
1362static inline unsigned int
1363read_amp_value(struct hda_codec *codec, hda_nid_t nid,
1364 int ch, int dir, int idx, unsigned int ofs)
1365{
1366 unsigned int val;
1367 val = snd_hda_codec_amp_read(codec, nid, ch, dir, idx);
1368 val &= HDA_AMP_VOLMASK;
1369 if (val >= ofs)
1370 val -= ofs;
1371 else
1372 val = 0;
1373 return val;
1374}
1375
1376static inline int
1377update_amp_value(struct hda_codec *codec, hda_nid_t nid,
1378 int ch, int dir, int idx, unsigned int ofs,
1379 unsigned int val)
1380{
1381 if (val > 0)
1382 val += ofs;
1383 return snd_hda_codec_amp_update(codec, nid, ch, dir, idx,
1384 HDA_AMP_VOLMASK, val);
1385}
1386
Takashi Iwai0ba21762007-04-16 11:29:14 +02001387int snd_hda_mixer_amp_volume_get(struct snd_kcontrol *kcontrol,
1388 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001389{
1390 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1391 hda_nid_t nid = get_amp_nid(kcontrol);
1392 int chs = get_amp_channels(kcontrol);
1393 int dir = get_amp_direction(kcontrol);
1394 int idx = get_amp_index(kcontrol);
Takashi Iwai29fdbec2009-01-20 13:07:55 +01001395 unsigned int ofs = get_amp_offset(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001396 long *valp = ucontrol->value.integer.value;
1397
1398 if (chs & 1)
Takashi Iwai29fdbec2009-01-20 13:07:55 +01001399 *valp++ = read_amp_value(codec, nid, 0, dir, idx, ofs);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001400 if (chs & 2)
Takashi Iwai29fdbec2009-01-20 13:07:55 +01001401 *valp = read_amp_value(codec, nid, 1, dir, idx, ofs);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001402 return 0;
1403}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001404EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_volume_get);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001405
Takashi Iwai0ba21762007-04-16 11:29:14 +02001406int snd_hda_mixer_amp_volume_put(struct snd_kcontrol *kcontrol,
1407 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001408{
1409 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1410 hda_nid_t nid = get_amp_nid(kcontrol);
1411 int chs = get_amp_channels(kcontrol);
1412 int dir = get_amp_direction(kcontrol);
1413 int idx = get_amp_index(kcontrol);
Takashi Iwai29fdbec2009-01-20 13:07:55 +01001414 unsigned int ofs = get_amp_offset(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001415 long *valp = ucontrol->value.integer.value;
1416 int change = 0;
1417
Takashi Iwaicb53c622007-08-10 17:21:45 +02001418 snd_hda_power_up(codec);
Nicolas Grazianob9f5a892005-07-29 12:17:20 +02001419 if (chs & 1) {
Takashi Iwai29fdbec2009-01-20 13:07:55 +01001420 change = update_amp_value(codec, nid, 0, dir, idx, ofs, *valp);
Nicolas Grazianob9f5a892005-07-29 12:17:20 +02001421 valp++;
1422 }
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001423 if (chs & 2)
Takashi Iwai29fdbec2009-01-20 13:07:55 +01001424 change |= update_amp_value(codec, nid, 1, dir, idx, ofs, *valp);
Takashi Iwaicb53c622007-08-10 17:21:45 +02001425 snd_hda_power_down(codec);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001426 return change;
1427}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001428EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_volume_put);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001429
Jaroslav Kysela302e9c52006-07-05 17:39:49 +02001430int snd_hda_mixer_amp_tlv(struct snd_kcontrol *kcontrol, int op_flag,
1431 unsigned int size, unsigned int __user *_tlv)
1432{
1433 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1434 hda_nid_t nid = get_amp_nid(kcontrol);
1435 int dir = get_amp_direction(kcontrol);
Takashi Iwai29fdbec2009-01-20 13:07:55 +01001436 unsigned int ofs = get_amp_offset(kcontrol);
Jaroslav Kysela302e9c52006-07-05 17:39:49 +02001437 u32 caps, val1, val2;
1438
1439 if (size < 4 * sizeof(unsigned int))
1440 return -ENOMEM;
1441 caps = query_amp_caps(codec, nid, dir);
Takashi Iwai0ba21762007-04-16 11:29:14 +02001442 val2 = (caps & AC_AMPCAP_STEP_SIZE) >> AC_AMPCAP_STEP_SIZE_SHIFT;
1443 val2 = (val2 + 1) * 25;
Jaroslav Kysela302e9c52006-07-05 17:39:49 +02001444 val1 = -((caps & AC_AMPCAP_OFFSET) >> AC_AMPCAP_OFFSET_SHIFT);
Takashi Iwai29fdbec2009-01-20 13:07:55 +01001445 val1 += ofs;
Jaroslav Kysela302e9c52006-07-05 17:39:49 +02001446 val1 = ((int)val1) * ((int)val2);
Jaroslav Kysela302e9c52006-07-05 17:39:49 +02001447 if (put_user(SNDRV_CTL_TLVT_DB_SCALE, _tlv))
1448 return -EFAULT;
1449 if (put_user(2 * sizeof(unsigned int), _tlv + 1))
1450 return -EFAULT;
1451 if (put_user(val1, _tlv + 2))
1452 return -EFAULT;
1453 if (put_user(val2, _tlv + 3))
1454 return -EFAULT;
1455 return 0;
1456}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001457EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_tlv);
Jaroslav Kysela302e9c52006-07-05 17:39:49 +02001458
Takashi Iwai2134ea42008-01-10 16:53:55 +01001459/*
1460 * set (static) TLV for virtual master volume; recalculated as max 0dB
1461 */
1462void snd_hda_set_vmaster_tlv(struct hda_codec *codec, hda_nid_t nid, int dir,
1463 unsigned int *tlv)
1464{
1465 u32 caps;
1466 int nums, step;
1467
1468 caps = query_amp_caps(codec, nid, dir);
1469 nums = (caps & AC_AMPCAP_NUM_STEPS) >> AC_AMPCAP_NUM_STEPS_SHIFT;
1470 step = (caps & AC_AMPCAP_STEP_SIZE) >> AC_AMPCAP_STEP_SIZE_SHIFT;
1471 step = (step + 1) * 25;
1472 tlv[0] = SNDRV_CTL_TLVT_DB_SCALE;
1473 tlv[1] = 2 * sizeof(unsigned int);
1474 tlv[2] = -nums * step;
1475 tlv[3] = step;
1476}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001477EXPORT_SYMBOL_HDA(snd_hda_set_vmaster_tlv);
Takashi Iwai2134ea42008-01-10 16:53:55 +01001478
1479/* find a mixer control element with the given name */
Takashi Iwai09f99702008-02-04 12:31:13 +01001480static struct snd_kcontrol *
1481_snd_hda_find_mixer_ctl(struct hda_codec *codec,
1482 const char *name, int idx)
Takashi Iwai2134ea42008-01-10 16:53:55 +01001483{
1484 struct snd_ctl_elem_id id;
1485 memset(&id, 0, sizeof(id));
1486 id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
Takashi Iwai09f99702008-02-04 12:31:13 +01001487 id.index = idx;
Takashi Iwai18cb7102009-04-16 10:22:24 +02001488 if (snd_BUG_ON(strlen(name) >= sizeof(id.name)))
1489 return NULL;
Takashi Iwai2134ea42008-01-10 16:53:55 +01001490 strcpy(id.name, name);
1491 return snd_ctl_find_id(codec->bus->card, &id);
1492}
1493
Takashi Iwai09f99702008-02-04 12:31:13 +01001494struct snd_kcontrol *snd_hda_find_mixer_ctl(struct hda_codec *codec,
1495 const char *name)
1496{
1497 return _snd_hda_find_mixer_ctl(codec, name, 0);
1498}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001499EXPORT_SYMBOL_HDA(snd_hda_find_mixer_ctl);
Takashi Iwai09f99702008-02-04 12:31:13 +01001500
Takashi Iwaid13bd412008-07-30 15:01:45 +02001501/* Add a control element and assign to the codec */
1502int snd_hda_ctl_add(struct hda_codec *codec, struct snd_kcontrol *kctl)
1503{
1504 int err;
1505 struct snd_kcontrol **knewp;
1506
1507 err = snd_ctl_add(codec->bus->card, kctl);
1508 if (err < 0)
1509 return err;
1510 knewp = snd_array_new(&codec->mixers);
1511 if (!knewp)
1512 return -ENOMEM;
1513 *knewp = kctl;
1514 return 0;
1515}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001516EXPORT_SYMBOL_HDA(snd_hda_ctl_add);
Takashi Iwaid13bd412008-07-30 15:01:45 +02001517
1518/* Clear all controls assigned to the given codec */
1519void snd_hda_ctls_clear(struct hda_codec *codec)
1520{
1521 int i;
1522 struct snd_kcontrol **kctls = codec->mixers.list;
1523 for (i = 0; i < codec->mixers.used; i++)
1524 snd_ctl_remove(codec->bus->card, kctls[i]);
1525 snd_array_free(&codec->mixers);
1526}
1527
Takashi Iwaia65d6292009-02-23 16:57:04 +01001528/* pseudo device locking
1529 * toggle card->shutdown to allow/disallow the device access (as a hack)
1530 */
1531static int hda_lock_devices(struct snd_card *card)
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001532{
Takashi Iwaia65d6292009-02-23 16:57:04 +01001533 spin_lock(&card->files_lock);
1534 if (card->shutdown) {
1535 spin_unlock(&card->files_lock);
1536 return -EINVAL;
1537 }
1538 card->shutdown = 1;
1539 spin_unlock(&card->files_lock);
1540 return 0;
1541}
1542
1543static void hda_unlock_devices(struct snd_card *card)
1544{
1545 spin_lock(&card->files_lock);
1546 card->shutdown = 0;
1547 spin_unlock(&card->files_lock);
1548}
1549
1550int snd_hda_codec_reset(struct hda_codec *codec)
1551{
1552 struct snd_card *card = codec->bus->card;
1553 int i, pcm;
1554
1555 if (hda_lock_devices(card) < 0)
1556 return -EBUSY;
1557 /* check whether the codec isn't used by any mixer or PCM streams */
1558 if (!list_empty(&card->ctl_files)) {
1559 hda_unlock_devices(card);
1560 return -EBUSY;
1561 }
1562 for (pcm = 0; pcm < codec->num_pcms; pcm++) {
1563 struct hda_pcm *cpcm = &codec->pcm_info[pcm];
1564 if (!cpcm->pcm)
1565 continue;
1566 if (cpcm->pcm->streams[0].substream_opened ||
1567 cpcm->pcm->streams[1].substream_opened) {
1568 hda_unlock_devices(card);
1569 return -EBUSY;
1570 }
1571 }
1572
1573 /* OK, let it free */
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001574
1575#ifdef CONFIG_SND_HDA_POWER_SAVE
1576 cancel_delayed_work(&codec->power_work);
Takashi Iwai6acaed32009-01-12 10:09:24 +01001577 flush_workqueue(codec->bus->workq);
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001578#endif
1579 snd_hda_ctls_clear(codec);
1580 /* relase PCMs */
1581 for (i = 0; i < codec->num_pcms; i++) {
Takashi Iwai529bd6c2008-11-27 14:17:01 +01001582 if (codec->pcm_info[i].pcm) {
Takashi Iwaia65d6292009-02-23 16:57:04 +01001583 snd_device_free(card, codec->pcm_info[i].pcm);
Takashi Iwai529bd6c2008-11-27 14:17:01 +01001584 clear_bit(codec->pcm_info[i].device,
1585 codec->bus->pcm_dev_bits);
1586 }
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001587 }
1588 if (codec->patch_ops.free)
1589 codec->patch_ops.free(codec);
Takashi Iwai56d17712008-11-28 14:36:23 +01001590 codec->proc_widget_hook = NULL;
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001591 codec->spec = NULL;
1592 free_hda_cache(&codec->amp_cache);
1593 free_hda_cache(&codec->cmd_cache);
Takashi Iwai827057f2008-12-19 10:12:02 +01001594 init_hda_cache(&codec->amp_cache, sizeof(struct hda_amp_info));
1595 init_hda_cache(&codec->cmd_cache, sizeof(struct hda_cache_head));
Takashi Iwai346ff702009-02-23 09:42:57 +01001596 /* free only driver_pins so that init_pins + user_pins are restored */
1597 snd_array_free(&codec->driver_pins);
Takashi Iwai3be14142009-02-20 14:11:16 +01001598 restore_pincfgs(codec);
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001599 codec->num_pcms = 0;
1600 codec->pcm_info = NULL;
1601 codec->preset = NULL;
Takashi Iwaid1f1af22009-03-02 10:35:29 +01001602 memset(&codec->patch_ops, 0, sizeof(codec->patch_ops));
1603 codec->slave_dig_outs = NULL;
1604 codec->spdif_status_reset = 0;
Takashi Iwai1289e9e2008-11-27 15:47:11 +01001605 module_put(codec->owner);
1606 codec->owner = NULL;
Takashi Iwaia65d6292009-02-23 16:57:04 +01001607
1608 /* allow device access again */
1609 hda_unlock_devices(card);
1610 return 0;
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001611}
1612
Takashi Iwai2134ea42008-01-10 16:53:55 +01001613/* create a virtual master control and add slaves */
1614int snd_hda_add_vmaster(struct hda_codec *codec, char *name,
1615 unsigned int *tlv, const char **slaves)
1616{
1617 struct snd_kcontrol *kctl;
1618 const char **s;
1619 int err;
1620
Takashi Iwai2f085542008-02-22 18:43:50 +01001621 for (s = slaves; *s && !snd_hda_find_mixer_ctl(codec, *s); s++)
1622 ;
1623 if (!*s) {
1624 snd_printdd("No slave found for %s\n", name);
1625 return 0;
1626 }
Takashi Iwai2134ea42008-01-10 16:53:55 +01001627 kctl = snd_ctl_make_virtual_master(name, tlv);
1628 if (!kctl)
1629 return -ENOMEM;
Takashi Iwaid13bd412008-07-30 15:01:45 +02001630 err = snd_hda_ctl_add(codec, kctl);
Takashi Iwai2134ea42008-01-10 16:53:55 +01001631 if (err < 0)
1632 return err;
1633
1634 for (s = slaves; *s; s++) {
1635 struct snd_kcontrol *sctl;
Takashi Iwai7a411ee2009-03-06 10:08:14 +01001636 int i = 0;
1637 for (;;) {
1638 sctl = _snd_hda_find_mixer_ctl(codec, *s, i);
1639 if (!sctl) {
1640 if (!i)
1641 snd_printdd("Cannot find slave %s, "
1642 "skipped\n", *s);
1643 break;
1644 }
1645 err = snd_ctl_add_slave(kctl, sctl);
1646 if (err < 0)
1647 return err;
1648 i++;
Takashi Iwai2134ea42008-01-10 16:53:55 +01001649 }
Takashi Iwai2134ea42008-01-10 16:53:55 +01001650 }
1651 return 0;
1652}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001653EXPORT_SYMBOL_HDA(snd_hda_add_vmaster);
Takashi Iwai2134ea42008-01-10 16:53:55 +01001654
Linus Torvalds1da177e2005-04-16 15:20:36 -07001655/* switch */
Takashi Iwai0ba21762007-04-16 11:29:14 +02001656int snd_hda_mixer_amp_switch_info(struct snd_kcontrol *kcontrol,
1657 struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001658{
1659 int chs = get_amp_channels(kcontrol);
1660
1661 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
1662 uinfo->count = chs == 3 ? 2 : 1;
1663 uinfo->value.integer.min = 0;
1664 uinfo->value.integer.max = 1;
1665 return 0;
1666}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001667EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_switch_info);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001668
Takashi Iwai0ba21762007-04-16 11:29:14 +02001669int snd_hda_mixer_amp_switch_get(struct snd_kcontrol *kcontrol,
1670 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001671{
1672 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1673 hda_nid_t nid = get_amp_nid(kcontrol);
1674 int chs = get_amp_channels(kcontrol);
1675 int dir = get_amp_direction(kcontrol);
1676 int idx = get_amp_index(kcontrol);
1677 long *valp = ucontrol->value.integer.value;
1678
1679 if (chs & 1)
Takashi Iwai0ba21762007-04-16 11:29:14 +02001680 *valp++ = (snd_hda_codec_amp_read(codec, nid, 0, dir, idx) &
Takashi Iwai47fd8302007-08-10 17:11:07 +02001681 HDA_AMP_MUTE) ? 0 : 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001682 if (chs & 2)
Takashi Iwai0ba21762007-04-16 11:29:14 +02001683 *valp = (snd_hda_codec_amp_read(codec, nid, 1, dir, idx) &
Takashi Iwai47fd8302007-08-10 17:11:07 +02001684 HDA_AMP_MUTE) ? 0 : 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001685 return 0;
1686}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001687EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_switch_get);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001688
Takashi Iwai0ba21762007-04-16 11:29:14 +02001689int snd_hda_mixer_amp_switch_put(struct snd_kcontrol *kcontrol,
1690 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001691{
1692 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1693 hda_nid_t nid = get_amp_nid(kcontrol);
1694 int chs = get_amp_channels(kcontrol);
1695 int dir = get_amp_direction(kcontrol);
1696 int idx = get_amp_index(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001697 long *valp = ucontrol->value.integer.value;
1698 int change = 0;
1699
Takashi Iwaicb53c622007-08-10 17:21:45 +02001700 snd_hda_power_up(codec);
Nicolas Grazianob9f5a892005-07-29 12:17:20 +02001701 if (chs & 1) {
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001702 change = snd_hda_codec_amp_update(codec, nid, 0, dir, idx,
Takashi Iwai47fd8302007-08-10 17:11:07 +02001703 HDA_AMP_MUTE,
1704 *valp ? 0 : HDA_AMP_MUTE);
Nicolas Grazianob9f5a892005-07-29 12:17:20 +02001705 valp++;
1706 }
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001707 if (chs & 2)
1708 change |= snd_hda_codec_amp_update(codec, nid, 1, dir, idx,
Takashi Iwai47fd8302007-08-10 17:11:07 +02001709 HDA_AMP_MUTE,
1710 *valp ? 0 : HDA_AMP_MUTE);
Takashi Iwaicb53c622007-08-10 17:21:45 +02001711#ifdef CONFIG_SND_HDA_POWER_SAVE
1712 if (codec->patch_ops.check_power_status)
1713 codec->patch_ops.check_power_status(codec, nid);
1714#endif
1715 snd_hda_power_down(codec);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001716 return change;
1717}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001718EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_switch_put);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001719
1720/*
Takashi Iwai985be542005-11-02 18:26:49 +01001721 * bound volume controls
1722 *
1723 * bind multiple volumes (# indices, from 0)
1724 */
1725
1726#define AMP_VAL_IDX_SHIFT 19
1727#define AMP_VAL_IDX_MASK (0x0f<<19)
1728
Takashi Iwai0ba21762007-04-16 11:29:14 +02001729int snd_hda_mixer_bind_switch_get(struct snd_kcontrol *kcontrol,
1730 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai985be542005-11-02 18:26:49 +01001731{
1732 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1733 unsigned long pval;
1734 int err;
1735
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001736 mutex_lock(&codec->control_mutex);
Takashi Iwai985be542005-11-02 18:26:49 +01001737 pval = kcontrol->private_value;
1738 kcontrol->private_value = pval & ~AMP_VAL_IDX_MASK; /* index 0 */
1739 err = snd_hda_mixer_amp_switch_get(kcontrol, ucontrol);
1740 kcontrol->private_value = pval;
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001741 mutex_unlock(&codec->control_mutex);
Takashi Iwai985be542005-11-02 18:26:49 +01001742 return err;
1743}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001744EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_switch_get);
Takashi Iwai985be542005-11-02 18:26:49 +01001745
Takashi Iwai0ba21762007-04-16 11:29:14 +02001746int snd_hda_mixer_bind_switch_put(struct snd_kcontrol *kcontrol,
1747 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai985be542005-11-02 18:26:49 +01001748{
1749 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1750 unsigned long pval;
1751 int i, indices, err = 0, change = 0;
1752
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001753 mutex_lock(&codec->control_mutex);
Takashi Iwai985be542005-11-02 18:26:49 +01001754 pval = kcontrol->private_value;
1755 indices = (pval & AMP_VAL_IDX_MASK) >> AMP_VAL_IDX_SHIFT;
1756 for (i = 0; i < indices; i++) {
Takashi Iwai0ba21762007-04-16 11:29:14 +02001757 kcontrol->private_value = (pval & ~AMP_VAL_IDX_MASK) |
1758 (i << AMP_VAL_IDX_SHIFT);
Takashi Iwai985be542005-11-02 18:26:49 +01001759 err = snd_hda_mixer_amp_switch_put(kcontrol, ucontrol);
1760 if (err < 0)
1761 break;
1762 change |= err;
1763 }
1764 kcontrol->private_value = pval;
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001765 mutex_unlock(&codec->control_mutex);
Takashi Iwai985be542005-11-02 18:26:49 +01001766 return err < 0 ? err : change;
1767}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001768EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_switch_put);
Takashi Iwai985be542005-11-02 18:26:49 +01001769
1770/*
Takashi Iwai532d5382007-07-27 19:02:40 +02001771 * generic bound volume/swtich controls
1772 */
1773int snd_hda_mixer_bind_ctls_info(struct snd_kcontrol *kcontrol,
1774 struct snd_ctl_elem_info *uinfo)
1775{
1776 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1777 struct hda_bind_ctls *c;
1778 int err;
1779
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001780 mutex_lock(&codec->control_mutex);
Serge A. Suchkov14c65f92008-02-22 18:43:16 +01001781 c = (struct hda_bind_ctls *)kcontrol->private_value;
Takashi Iwai532d5382007-07-27 19:02:40 +02001782 kcontrol->private_value = *c->values;
1783 err = c->ops->info(kcontrol, uinfo);
1784 kcontrol->private_value = (long)c;
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001785 mutex_unlock(&codec->control_mutex);
Takashi Iwai532d5382007-07-27 19:02:40 +02001786 return err;
1787}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001788EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_ctls_info);
Takashi Iwai532d5382007-07-27 19:02:40 +02001789
1790int snd_hda_mixer_bind_ctls_get(struct snd_kcontrol *kcontrol,
1791 struct snd_ctl_elem_value *ucontrol)
1792{
1793 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1794 struct hda_bind_ctls *c;
1795 int err;
1796
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001797 mutex_lock(&codec->control_mutex);
Serge A. Suchkov14c65f92008-02-22 18:43:16 +01001798 c = (struct hda_bind_ctls *)kcontrol->private_value;
Takashi Iwai532d5382007-07-27 19:02:40 +02001799 kcontrol->private_value = *c->values;
1800 err = c->ops->get(kcontrol, ucontrol);
1801 kcontrol->private_value = (long)c;
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001802 mutex_unlock(&codec->control_mutex);
Takashi Iwai532d5382007-07-27 19:02:40 +02001803 return err;
1804}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001805EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_ctls_get);
Takashi Iwai532d5382007-07-27 19:02:40 +02001806
1807int snd_hda_mixer_bind_ctls_put(struct snd_kcontrol *kcontrol,
1808 struct snd_ctl_elem_value *ucontrol)
1809{
1810 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1811 struct hda_bind_ctls *c;
1812 unsigned long *vals;
1813 int err = 0, change = 0;
1814
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001815 mutex_lock(&codec->control_mutex);
Serge A. Suchkov14c65f92008-02-22 18:43:16 +01001816 c = (struct hda_bind_ctls *)kcontrol->private_value;
Takashi Iwai532d5382007-07-27 19:02:40 +02001817 for (vals = c->values; *vals; vals++) {
1818 kcontrol->private_value = *vals;
1819 err = c->ops->put(kcontrol, ucontrol);
1820 if (err < 0)
1821 break;
1822 change |= err;
1823 }
1824 kcontrol->private_value = (long)c;
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001825 mutex_unlock(&codec->control_mutex);
Takashi Iwai532d5382007-07-27 19:02:40 +02001826 return err < 0 ? err : change;
1827}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001828EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_ctls_put);
Takashi Iwai532d5382007-07-27 19:02:40 +02001829
1830int snd_hda_mixer_bind_tlv(struct snd_kcontrol *kcontrol, int op_flag,
1831 unsigned int size, unsigned int __user *tlv)
1832{
1833 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1834 struct hda_bind_ctls *c;
1835 int err;
1836
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001837 mutex_lock(&codec->control_mutex);
Serge A. Suchkov14c65f92008-02-22 18:43:16 +01001838 c = (struct hda_bind_ctls *)kcontrol->private_value;
Takashi Iwai532d5382007-07-27 19:02:40 +02001839 kcontrol->private_value = *c->values;
1840 err = c->ops->tlv(kcontrol, op_flag, size, tlv);
1841 kcontrol->private_value = (long)c;
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001842 mutex_unlock(&codec->control_mutex);
Takashi Iwai532d5382007-07-27 19:02:40 +02001843 return err;
1844}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001845EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_tlv);
Takashi Iwai532d5382007-07-27 19:02:40 +02001846
1847struct hda_ctl_ops snd_hda_bind_vol = {
1848 .info = snd_hda_mixer_amp_volume_info,
1849 .get = snd_hda_mixer_amp_volume_get,
1850 .put = snd_hda_mixer_amp_volume_put,
1851 .tlv = snd_hda_mixer_amp_tlv
1852};
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001853EXPORT_SYMBOL_HDA(snd_hda_bind_vol);
Takashi Iwai532d5382007-07-27 19:02:40 +02001854
1855struct hda_ctl_ops snd_hda_bind_sw = {
1856 .info = snd_hda_mixer_amp_switch_info,
1857 .get = snd_hda_mixer_amp_switch_get,
1858 .put = snd_hda_mixer_amp_switch_put,
1859 .tlv = snd_hda_mixer_amp_tlv
1860};
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001861EXPORT_SYMBOL_HDA(snd_hda_bind_sw);
Takashi Iwai532d5382007-07-27 19:02:40 +02001862
1863/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07001864 * SPDIF out controls
1865 */
1866
Takashi Iwai0ba21762007-04-16 11:29:14 +02001867static int snd_hda_spdif_mask_info(struct snd_kcontrol *kcontrol,
1868 struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001869{
1870 uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
1871 uinfo->count = 1;
1872 return 0;
1873}
1874
Takashi Iwai0ba21762007-04-16 11:29:14 +02001875static int snd_hda_spdif_cmask_get(struct snd_kcontrol *kcontrol,
1876 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001877{
1878 ucontrol->value.iec958.status[0] = IEC958_AES0_PROFESSIONAL |
1879 IEC958_AES0_NONAUDIO |
1880 IEC958_AES0_CON_EMPHASIS_5015 |
1881 IEC958_AES0_CON_NOT_COPYRIGHT;
1882 ucontrol->value.iec958.status[1] = IEC958_AES1_CON_CATEGORY |
1883 IEC958_AES1_CON_ORIGINAL;
1884 return 0;
1885}
1886
Takashi Iwai0ba21762007-04-16 11:29:14 +02001887static int snd_hda_spdif_pmask_get(struct snd_kcontrol *kcontrol,
1888 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001889{
1890 ucontrol->value.iec958.status[0] = IEC958_AES0_PROFESSIONAL |
1891 IEC958_AES0_NONAUDIO |
1892 IEC958_AES0_PRO_EMPHASIS_5015;
1893 return 0;
1894}
1895
Takashi Iwai0ba21762007-04-16 11:29:14 +02001896static int snd_hda_spdif_default_get(struct snd_kcontrol *kcontrol,
1897 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001898{
1899 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1900
1901 ucontrol->value.iec958.status[0] = codec->spdif_status & 0xff;
1902 ucontrol->value.iec958.status[1] = (codec->spdif_status >> 8) & 0xff;
1903 ucontrol->value.iec958.status[2] = (codec->spdif_status >> 16) & 0xff;
1904 ucontrol->value.iec958.status[3] = (codec->spdif_status >> 24) & 0xff;
1905
1906 return 0;
1907}
1908
1909/* convert from SPDIF status bits to HDA SPDIF bits
1910 * bit 0 (DigEn) is always set zero (to be filled later)
1911 */
1912static unsigned short convert_from_spdif_status(unsigned int sbits)
1913{
1914 unsigned short val = 0;
1915
1916 if (sbits & IEC958_AES0_PROFESSIONAL)
Takashi Iwai0ba21762007-04-16 11:29:14 +02001917 val |= AC_DIG1_PROFESSIONAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001918 if (sbits & IEC958_AES0_NONAUDIO)
Takashi Iwai0ba21762007-04-16 11:29:14 +02001919 val |= AC_DIG1_NONAUDIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001920 if (sbits & IEC958_AES0_PROFESSIONAL) {
Takashi Iwai0ba21762007-04-16 11:29:14 +02001921 if ((sbits & IEC958_AES0_PRO_EMPHASIS) ==
1922 IEC958_AES0_PRO_EMPHASIS_5015)
1923 val |= AC_DIG1_EMPHASIS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001924 } else {
Takashi Iwai0ba21762007-04-16 11:29:14 +02001925 if ((sbits & IEC958_AES0_CON_EMPHASIS) ==
1926 IEC958_AES0_CON_EMPHASIS_5015)
1927 val |= AC_DIG1_EMPHASIS;
1928 if (!(sbits & IEC958_AES0_CON_NOT_COPYRIGHT))
1929 val |= AC_DIG1_COPYRIGHT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001930 if (sbits & (IEC958_AES1_CON_ORIGINAL << 8))
Takashi Iwai0ba21762007-04-16 11:29:14 +02001931 val |= AC_DIG1_LEVEL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001932 val |= sbits & (IEC958_AES1_CON_CATEGORY << 8);
1933 }
1934 return val;
1935}
1936
1937/* convert to SPDIF status bits from HDA SPDIF bits
1938 */
1939static unsigned int convert_to_spdif_status(unsigned short val)
1940{
1941 unsigned int sbits = 0;
1942
Takashi Iwai0ba21762007-04-16 11:29:14 +02001943 if (val & AC_DIG1_NONAUDIO)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001944 sbits |= IEC958_AES0_NONAUDIO;
Takashi Iwai0ba21762007-04-16 11:29:14 +02001945 if (val & AC_DIG1_PROFESSIONAL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001946 sbits |= IEC958_AES0_PROFESSIONAL;
1947 if (sbits & IEC958_AES0_PROFESSIONAL) {
Takashi Iwai0ba21762007-04-16 11:29:14 +02001948 if (sbits & AC_DIG1_EMPHASIS)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001949 sbits |= IEC958_AES0_PRO_EMPHASIS_5015;
1950 } else {
Takashi Iwai0ba21762007-04-16 11:29:14 +02001951 if (val & AC_DIG1_EMPHASIS)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001952 sbits |= IEC958_AES0_CON_EMPHASIS_5015;
Takashi Iwai0ba21762007-04-16 11:29:14 +02001953 if (!(val & AC_DIG1_COPYRIGHT))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001954 sbits |= IEC958_AES0_CON_NOT_COPYRIGHT;
Takashi Iwai0ba21762007-04-16 11:29:14 +02001955 if (val & AC_DIG1_LEVEL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001956 sbits |= (IEC958_AES1_CON_ORIGINAL << 8);
1957 sbits |= val & (0x7f << 8);
1958 }
1959 return sbits;
1960}
1961
Takashi Iwai2f728532008-09-25 16:32:41 +02001962/* set digital convert verbs both for the given NID and its slaves */
1963static void set_dig_out(struct hda_codec *codec, hda_nid_t nid,
1964 int verb, int val)
1965{
1966 hda_nid_t *d;
1967
Takashi Iwai9e976972008-11-25 08:17:20 +01001968 snd_hda_codec_write_cache(codec, nid, 0, verb, val);
Takashi Iwai2f728532008-09-25 16:32:41 +02001969 d = codec->slave_dig_outs;
1970 if (!d)
1971 return;
1972 for (; *d; d++)
Takashi Iwai9e976972008-11-25 08:17:20 +01001973 snd_hda_codec_write_cache(codec, *d, 0, verb, val);
Takashi Iwai2f728532008-09-25 16:32:41 +02001974}
1975
1976static inline void set_dig_out_convert(struct hda_codec *codec, hda_nid_t nid,
1977 int dig1, int dig2)
1978{
1979 if (dig1 != -1)
1980 set_dig_out(codec, nid, AC_VERB_SET_DIGI_CONVERT_1, dig1);
1981 if (dig2 != -1)
1982 set_dig_out(codec, nid, AC_VERB_SET_DIGI_CONVERT_2, dig2);
1983}
1984
Takashi Iwai0ba21762007-04-16 11:29:14 +02001985static int snd_hda_spdif_default_put(struct snd_kcontrol *kcontrol,
1986 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001987{
1988 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1989 hda_nid_t nid = kcontrol->private_value;
1990 unsigned short val;
1991 int change;
1992
Ingo Molnar62932df2006-01-16 16:34:20 +01001993 mutex_lock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001994 codec->spdif_status = ucontrol->value.iec958.status[0] |
1995 ((unsigned int)ucontrol->value.iec958.status[1] << 8) |
1996 ((unsigned int)ucontrol->value.iec958.status[2] << 16) |
1997 ((unsigned int)ucontrol->value.iec958.status[3] << 24);
1998 val = convert_from_spdif_status(codec->spdif_status);
1999 val |= codec->spdif_ctls & 1;
2000 change = codec->spdif_ctls != val;
2001 codec->spdif_ctls = val;
2002
Takashi Iwai2f728532008-09-25 16:32:41 +02002003 if (change)
2004 set_dig_out_convert(codec, nid, val & 0xff, (val >> 8) & 0xff);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002005
Ingo Molnar62932df2006-01-16 16:34:20 +01002006 mutex_unlock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002007 return change;
2008}
2009
Takashi Iwaia5ce8892007-07-23 15:42:26 +02002010#define snd_hda_spdif_out_switch_info snd_ctl_boolean_mono_info
Linus Torvalds1da177e2005-04-16 15:20:36 -07002011
Takashi Iwai0ba21762007-04-16 11:29:14 +02002012static int snd_hda_spdif_out_switch_get(struct snd_kcontrol *kcontrol,
2013 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002014{
2015 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2016
Takashi Iwai0ba21762007-04-16 11:29:14 +02002017 ucontrol->value.integer.value[0] = codec->spdif_ctls & AC_DIG1_ENABLE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002018 return 0;
2019}
2020
Takashi Iwai0ba21762007-04-16 11:29:14 +02002021static int snd_hda_spdif_out_switch_put(struct snd_kcontrol *kcontrol,
2022 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002023{
2024 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2025 hda_nid_t nid = kcontrol->private_value;
2026 unsigned short val;
2027 int change;
2028
Ingo Molnar62932df2006-01-16 16:34:20 +01002029 mutex_lock(&codec->spdif_mutex);
Takashi Iwai0ba21762007-04-16 11:29:14 +02002030 val = codec->spdif_ctls & ~AC_DIG1_ENABLE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002031 if (ucontrol->value.integer.value[0])
Takashi Iwai0ba21762007-04-16 11:29:14 +02002032 val |= AC_DIG1_ENABLE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002033 change = codec->spdif_ctls != val;
Takashi Iwai82beb8f2007-08-10 17:09:26 +02002034 if (change) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002035 codec->spdif_ctls = val;
Takashi Iwai2f728532008-09-25 16:32:41 +02002036 set_dig_out_convert(codec, nid, val & 0xff, -1);
Takashi Iwai0ba21762007-04-16 11:29:14 +02002037 /* unmute amp switch (if any) */
2038 if ((get_wcaps(codec, nid) & AC_WCAP_OUT_AMP) &&
Takashi Iwai47fd8302007-08-10 17:11:07 +02002039 (val & AC_DIG1_ENABLE))
2040 snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0,
2041 HDA_AMP_MUTE, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002042 }
Ingo Molnar62932df2006-01-16 16:34:20 +01002043 mutex_unlock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002044 return change;
2045}
2046
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01002047static struct snd_kcontrol_new dig_mixes[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002048 {
2049 .access = SNDRV_CTL_ELEM_ACCESS_READ,
2050 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2051 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,CON_MASK),
2052 .info = snd_hda_spdif_mask_info,
2053 .get = snd_hda_spdif_cmask_get,
2054 },
2055 {
2056 .access = SNDRV_CTL_ELEM_ACCESS_READ,
2057 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2058 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,PRO_MASK),
2059 .info = snd_hda_spdif_mask_info,
2060 .get = snd_hda_spdif_pmask_get,
2061 },
2062 {
2063 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2064 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT),
2065 .info = snd_hda_spdif_mask_info,
2066 .get = snd_hda_spdif_default_get,
2067 .put = snd_hda_spdif_default_put,
2068 },
2069 {
2070 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2071 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,SWITCH),
2072 .info = snd_hda_spdif_out_switch_info,
2073 .get = snd_hda_spdif_out_switch_get,
2074 .put = snd_hda_spdif_out_switch_put,
2075 },
2076 { } /* end */
2077};
2078
Takashi Iwai09f99702008-02-04 12:31:13 +01002079#define SPDIF_MAX_IDX 4 /* 4 instances should be enough to probe */
2080
Linus Torvalds1da177e2005-04-16 15:20:36 -07002081/**
2082 * snd_hda_create_spdif_out_ctls - create Output SPDIF-related controls
2083 * @codec: the HDA codec
2084 * @nid: audio out widget NID
2085 *
2086 * Creates controls related with the SPDIF output.
2087 * Called from each patch supporting the SPDIF out.
2088 *
2089 * Returns 0 if successful, or a negative error code.
2090 */
Takashi Iwai12f288b2007-08-02 15:51:59 +02002091int snd_hda_create_spdif_out_ctls(struct hda_codec *codec, hda_nid_t nid)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002092{
2093 int err;
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01002094 struct snd_kcontrol *kctl;
2095 struct snd_kcontrol_new *dig_mix;
Takashi Iwai09f99702008-02-04 12:31:13 +01002096 int idx;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002097
Takashi Iwai09f99702008-02-04 12:31:13 +01002098 for (idx = 0; idx < SPDIF_MAX_IDX; idx++) {
2099 if (!_snd_hda_find_mixer_ctl(codec, "IEC958 Playback Switch",
2100 idx))
2101 break;
2102 }
2103 if (idx >= SPDIF_MAX_IDX) {
2104 printk(KERN_ERR "hda_codec: too many IEC958 outputs\n");
2105 return -EBUSY;
2106 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002107 for (dig_mix = dig_mixes; dig_mix->name; dig_mix++) {
2108 kctl = snd_ctl_new1(dig_mix, codec);
Takashi Iwaib91f0802008-11-04 08:43:08 +01002109 if (!kctl)
2110 return -ENOMEM;
Takashi Iwai09f99702008-02-04 12:31:13 +01002111 kctl->id.index = idx;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002112 kctl->private_value = nid;
Takashi Iwaid13bd412008-07-30 15:01:45 +02002113 err = snd_hda_ctl_add(codec, kctl);
Takashi Iwai0ba21762007-04-16 11:29:14 +02002114 if (err < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002115 return err;
2116 }
Takashi Iwai0ba21762007-04-16 11:29:14 +02002117 codec->spdif_ctls =
Andrew Paprocki3982d172007-12-19 12:13:44 +01002118 snd_hda_codec_read(codec, nid, 0,
2119 AC_VERB_GET_DIGI_CONVERT_1, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002120 codec->spdif_status = convert_to_spdif_status(codec->spdif_ctls);
2121 return 0;
2122}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002123EXPORT_SYMBOL_HDA(snd_hda_create_spdif_out_ctls);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002124
2125/*
Takashi Iwai9a081602008-02-12 18:37:26 +01002126 * SPDIF sharing with analog output
2127 */
2128static int spdif_share_sw_get(struct snd_kcontrol *kcontrol,
2129 struct snd_ctl_elem_value *ucontrol)
2130{
2131 struct hda_multi_out *mout = snd_kcontrol_chip(kcontrol);
2132 ucontrol->value.integer.value[0] = mout->share_spdif;
2133 return 0;
2134}
2135
2136static int spdif_share_sw_put(struct snd_kcontrol *kcontrol,
2137 struct snd_ctl_elem_value *ucontrol)
2138{
2139 struct hda_multi_out *mout = snd_kcontrol_chip(kcontrol);
2140 mout->share_spdif = !!ucontrol->value.integer.value[0];
2141 return 0;
2142}
2143
2144static struct snd_kcontrol_new spdif_share_sw = {
2145 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2146 .name = "IEC958 Default PCM Playback Switch",
2147 .info = snd_ctl_boolean_mono_info,
2148 .get = spdif_share_sw_get,
2149 .put = spdif_share_sw_put,
2150};
2151
2152int snd_hda_create_spdif_share_sw(struct hda_codec *codec,
2153 struct hda_multi_out *mout)
2154{
2155 if (!mout->dig_out_nid)
2156 return 0;
2157 /* ATTENTION: here mout is passed as private_data, instead of codec */
Takashi Iwaid13bd412008-07-30 15:01:45 +02002158 return snd_hda_ctl_add(codec,
Takashi Iwai9a081602008-02-12 18:37:26 +01002159 snd_ctl_new1(&spdif_share_sw, mout));
2160}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002161EXPORT_SYMBOL_HDA(snd_hda_create_spdif_share_sw);
Takashi Iwai9a081602008-02-12 18:37:26 +01002162
2163/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002164 * SPDIF input
2165 */
2166
2167#define snd_hda_spdif_in_switch_info snd_hda_spdif_out_switch_info
2168
Takashi Iwai0ba21762007-04-16 11:29:14 +02002169static int snd_hda_spdif_in_switch_get(struct snd_kcontrol *kcontrol,
2170 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002171{
2172 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2173
2174 ucontrol->value.integer.value[0] = codec->spdif_in_enable;
2175 return 0;
2176}
2177
Takashi Iwai0ba21762007-04-16 11:29:14 +02002178static int snd_hda_spdif_in_switch_put(struct snd_kcontrol *kcontrol,
2179 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002180{
2181 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2182 hda_nid_t nid = kcontrol->private_value;
2183 unsigned int val = !!ucontrol->value.integer.value[0];
2184 int change;
2185
Ingo Molnar62932df2006-01-16 16:34:20 +01002186 mutex_lock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002187 change = codec->spdif_in_enable != val;
Takashi Iwai82beb8f2007-08-10 17:09:26 +02002188 if (change) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002189 codec->spdif_in_enable = val;
Takashi Iwai82beb8f2007-08-10 17:09:26 +02002190 snd_hda_codec_write_cache(codec, nid, 0,
2191 AC_VERB_SET_DIGI_CONVERT_1, val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002192 }
Ingo Molnar62932df2006-01-16 16:34:20 +01002193 mutex_unlock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002194 return change;
2195}
2196
Takashi Iwai0ba21762007-04-16 11:29:14 +02002197static int snd_hda_spdif_in_status_get(struct snd_kcontrol *kcontrol,
2198 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002199{
2200 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2201 hda_nid_t nid = kcontrol->private_value;
2202 unsigned short val;
2203 unsigned int sbits;
2204
Andrew Paprocki3982d172007-12-19 12:13:44 +01002205 val = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_DIGI_CONVERT_1, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002206 sbits = convert_to_spdif_status(val);
2207 ucontrol->value.iec958.status[0] = sbits;
2208 ucontrol->value.iec958.status[1] = sbits >> 8;
2209 ucontrol->value.iec958.status[2] = sbits >> 16;
2210 ucontrol->value.iec958.status[3] = sbits >> 24;
2211 return 0;
2212}
2213
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01002214static struct snd_kcontrol_new dig_in_ctls[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002215 {
2216 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2217 .name = SNDRV_CTL_NAME_IEC958("",CAPTURE,SWITCH),
2218 .info = snd_hda_spdif_in_switch_info,
2219 .get = snd_hda_spdif_in_switch_get,
2220 .put = snd_hda_spdif_in_switch_put,
2221 },
2222 {
2223 .access = SNDRV_CTL_ELEM_ACCESS_READ,
2224 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2225 .name = SNDRV_CTL_NAME_IEC958("",CAPTURE,DEFAULT),
2226 .info = snd_hda_spdif_mask_info,
2227 .get = snd_hda_spdif_in_status_get,
2228 },
2229 { } /* end */
2230};
2231
2232/**
2233 * snd_hda_create_spdif_in_ctls - create Input SPDIF-related controls
2234 * @codec: the HDA codec
2235 * @nid: audio in widget NID
2236 *
2237 * Creates controls related with the SPDIF input.
2238 * Called from each patch supporting the SPDIF in.
2239 *
2240 * Returns 0 if successful, or a negative error code.
2241 */
Takashi Iwai12f288b2007-08-02 15:51:59 +02002242int snd_hda_create_spdif_in_ctls(struct hda_codec *codec, hda_nid_t nid)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002243{
2244 int err;
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01002245 struct snd_kcontrol *kctl;
2246 struct snd_kcontrol_new *dig_mix;
Takashi Iwai09f99702008-02-04 12:31:13 +01002247 int idx;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002248
Takashi Iwai09f99702008-02-04 12:31:13 +01002249 for (idx = 0; idx < SPDIF_MAX_IDX; idx++) {
2250 if (!_snd_hda_find_mixer_ctl(codec, "IEC958 Capture Switch",
2251 idx))
2252 break;
2253 }
2254 if (idx >= SPDIF_MAX_IDX) {
2255 printk(KERN_ERR "hda_codec: too many IEC958 inputs\n");
2256 return -EBUSY;
2257 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002258 for (dig_mix = dig_in_ctls; dig_mix->name; dig_mix++) {
2259 kctl = snd_ctl_new1(dig_mix, codec);
Takashi Iwaic8dcdf82009-02-06 16:21:20 +01002260 if (!kctl)
2261 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002262 kctl->private_value = nid;
Takashi Iwaid13bd412008-07-30 15:01:45 +02002263 err = snd_hda_ctl_add(codec, kctl);
Takashi Iwai0ba21762007-04-16 11:29:14 +02002264 if (err < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002265 return err;
2266 }
Takashi Iwai0ba21762007-04-16 11:29:14 +02002267 codec->spdif_in_enable =
Andrew Paprocki3982d172007-12-19 12:13:44 +01002268 snd_hda_codec_read(codec, nid, 0,
2269 AC_VERB_GET_DIGI_CONVERT_1, 0) &
Takashi Iwai0ba21762007-04-16 11:29:14 +02002270 AC_DIG1_ENABLE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002271 return 0;
2272}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002273EXPORT_SYMBOL_HDA(snd_hda_create_spdif_in_ctls);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002274
Takashi Iwaicb53c622007-08-10 17:21:45 +02002275#ifdef SND_HDA_NEEDS_RESUME
Takashi Iwai82beb8f2007-08-10 17:09:26 +02002276/*
2277 * command cache
2278 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002279
Takashi Iwaib3ac5632007-08-10 17:03:40 +02002280/* build a 32bit cache key with the widget id and the command parameter */
2281#define build_cmd_cache_key(nid, verb) ((verb << 8) | nid)
2282#define get_cmd_cache_nid(key) ((key) & 0xff)
2283#define get_cmd_cache_cmd(key) (((key) >> 8) & 0xffff)
2284
2285/**
2286 * snd_hda_codec_write_cache - send a single command with caching
2287 * @codec: the HDA codec
2288 * @nid: NID to send the command
2289 * @direct: direct flag
2290 * @verb: the verb to send
2291 * @parm: the parameter for the verb
2292 *
2293 * Send a single command without waiting for response.
2294 *
2295 * Returns 0 if successful, or a negative error code.
2296 */
2297int snd_hda_codec_write_cache(struct hda_codec *codec, hda_nid_t nid,
2298 int direct, unsigned int verb, unsigned int parm)
2299{
Takashi Iwaiaa2936f2009-05-26 16:07:57 +02002300 int err = snd_hda_codec_write(codec, nid, direct, verb, parm);
2301 struct hda_cache_head *c;
2302 u32 key;
Takashi Iwai33fa35e2008-11-06 16:50:40 +01002303
Takashi Iwaiaa2936f2009-05-26 16:07:57 +02002304 if (err < 0)
2305 return err;
2306 /* parm may contain the verb stuff for get/set amp */
2307 verb = verb | (parm >> 8);
2308 parm &= 0xff;
2309 key = build_cmd_cache_key(nid, verb);
2310 mutex_lock(&codec->bus->cmd_mutex);
2311 c = get_alloc_hash(&codec->cmd_cache, key);
2312 if (c)
2313 c->val = parm;
2314 mutex_unlock(&codec->bus->cmd_mutex);
2315 return 0;
Takashi Iwaib3ac5632007-08-10 17:03:40 +02002316}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002317EXPORT_SYMBOL_HDA(snd_hda_codec_write_cache);
Takashi Iwaib3ac5632007-08-10 17:03:40 +02002318
2319/* resume the all commands from the cache */
2320void snd_hda_codec_resume_cache(struct hda_codec *codec)
2321{
Takashi Iwai603c4012008-07-30 15:01:44 +02002322 struct hda_cache_head *buffer = codec->cmd_cache.buf.list;
Takashi Iwaib3ac5632007-08-10 17:03:40 +02002323 int i;
2324
Takashi Iwai603c4012008-07-30 15:01:44 +02002325 for (i = 0; i < codec->cmd_cache.buf.used; i++, buffer++) {
Takashi Iwaib3ac5632007-08-10 17:03:40 +02002326 u32 key = buffer->key;
2327 if (!key)
2328 continue;
2329 snd_hda_codec_write(codec, get_cmd_cache_nid(key), 0,
2330 get_cmd_cache_cmd(key), buffer->val);
2331 }
2332}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002333EXPORT_SYMBOL_HDA(snd_hda_codec_resume_cache);
Takashi Iwaib3ac5632007-08-10 17:03:40 +02002334
2335/**
2336 * snd_hda_sequence_write_cache - sequence writes with caching
2337 * @codec: the HDA codec
2338 * @seq: VERB array to send
2339 *
2340 * Send the commands sequentially from the given array.
2341 * Thte commands are recorded on cache for power-save and resume.
2342 * The array must be terminated with NID=0.
2343 */
2344void snd_hda_sequence_write_cache(struct hda_codec *codec,
2345 const struct hda_verb *seq)
2346{
2347 for (; seq->nid; seq++)
2348 snd_hda_codec_write_cache(codec, seq->nid, 0, seq->verb,
2349 seq->param);
2350}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002351EXPORT_SYMBOL_HDA(snd_hda_sequence_write_cache);
Takashi Iwaicb53c622007-08-10 17:21:45 +02002352#endif /* SND_HDA_NEEDS_RESUME */
Takashi Iwaib3ac5632007-08-10 17:03:40 +02002353
Takashi Iwai54d17402005-11-21 16:33:22 +01002354/*
2355 * set power state of the codec
2356 */
2357static void hda_set_power_state(struct hda_codec *codec, hda_nid_t fg,
2358 unsigned int power_state)
2359{
Takashi Iwaicb53c622007-08-10 17:21:45 +02002360 hda_nid_t nid;
2361 int i;
Takashi Iwai54d17402005-11-21 16:33:22 +01002362
2363 snd_hda_codec_write(codec, fg, 0, AC_VERB_SET_POWER_STATE,
2364 power_state);
Marc Boucherd2595d82008-01-22 15:23:30 +01002365 msleep(10); /* partial workaround for "azx_get_response timeout" */
Takashi Iwai54d17402005-11-21 16:33:22 +01002366
Takashi Iwaicb53c622007-08-10 17:21:45 +02002367 nid = codec->start_nid;
2368 for (i = 0; i < codec->num_nodes; i++, nid++) {
Takashi Iwai7eba5c92007-11-14 14:53:42 +01002369 unsigned int wcaps = get_wcaps(codec, nid);
2370 if (wcaps & AC_WCAP_POWER) {
2371 unsigned int wid_type = (wcaps & AC_WCAP_TYPE) >>
2372 AC_WCAP_TYPE_SHIFT;
Takashi Iwaia3b48c82009-04-21 13:37:29 +02002373 if (power_state == AC_PWRST_D3 &&
2374 wid_type == AC_WID_PIN) {
Takashi Iwai7eba5c92007-11-14 14:53:42 +01002375 unsigned int pincap;
2376 /*
2377 * don't power down the widget if it controls
2378 * eapd and EAPD_BTLENABLE is set.
2379 */
Takashi Iwai14bafe32009-03-23 16:35:39 +01002380 pincap = snd_hda_query_pin_caps(codec, nid);
Takashi Iwai7eba5c92007-11-14 14:53:42 +01002381 if (pincap & AC_PINCAP_EAPD) {
2382 int eapd = snd_hda_codec_read(codec,
2383 nid, 0,
2384 AC_VERB_GET_EAPD_BTLENABLE, 0);
2385 eapd &= 0x02;
Takashi Iwaia3b48c82009-04-21 13:37:29 +02002386 if (eapd)
Takashi Iwai7eba5c92007-11-14 14:53:42 +01002387 continue;
2388 }
Takashi Iwai1194b5b2007-10-10 10:04:26 +02002389 }
Takashi Iwai54d17402005-11-21 16:33:22 +01002390 snd_hda_codec_write(codec, nid, 0,
2391 AC_VERB_SET_POWER_STATE,
2392 power_state);
Takashi Iwai1194b5b2007-10-10 10:04:26 +02002393 }
Takashi Iwai54d17402005-11-21 16:33:22 +01002394 }
2395
Takashi Iwaicb53c622007-08-10 17:21:45 +02002396 if (power_state == AC_PWRST_D0) {
2397 unsigned long end_time;
2398 int state;
Takashi Iwai54d17402005-11-21 16:33:22 +01002399 msleep(10);
Takashi Iwaicb53c622007-08-10 17:21:45 +02002400 /* wait until the codec reachs to D0 */
2401 end_time = jiffies + msecs_to_jiffies(500);
2402 do {
2403 state = snd_hda_codec_read(codec, fg, 0,
2404 AC_VERB_GET_POWER_STATE, 0);
2405 if (state == power_state)
2406 break;
2407 msleep(1);
2408 } while (time_after_eq(end_time, jiffies));
2409 }
Takashi Iwai54d17402005-11-21 16:33:22 +01002410}
2411
Takashi Iwai11aeff02008-07-30 15:01:46 +02002412#ifdef CONFIG_SND_HDA_HWDEP
2413/* execute additional init verbs */
2414static void hda_exec_init_verbs(struct hda_codec *codec)
2415{
2416 if (codec->init_verbs.list)
2417 snd_hda_sequence_write(codec, codec->init_verbs.list);
2418}
2419#else
2420static inline void hda_exec_init_verbs(struct hda_codec *codec) {}
2421#endif
2422
Takashi Iwaicb53c622007-08-10 17:21:45 +02002423#ifdef SND_HDA_NEEDS_RESUME
2424/*
2425 * call suspend and power-down; used both from PM and power-save
2426 */
2427static void hda_call_codec_suspend(struct hda_codec *codec)
2428{
2429 if (codec->patch_ops.suspend)
2430 codec->patch_ops.suspend(codec, PMSG_SUSPEND);
2431 hda_set_power_state(codec,
2432 codec->afg ? codec->afg : codec->mfg,
2433 AC_PWRST_D3);
2434#ifdef CONFIG_SND_HDA_POWER_SAVE
2435 cancel_delayed_work(&codec->power_work);
Takashi Iwai95e99fd2007-08-13 15:29:04 +02002436 codec->power_on = 0;
Takashi Iwaia221e282007-08-16 16:35:33 +02002437 codec->power_transition = 0;
Takashi Iwaicb53c622007-08-10 17:21:45 +02002438#endif
2439}
2440
2441/*
2442 * kick up codec; used both from PM and power-save
2443 */
2444static void hda_call_codec_resume(struct hda_codec *codec)
2445{
2446 hda_set_power_state(codec,
2447 codec->afg ? codec->afg : codec->mfg,
2448 AC_PWRST_D0);
Takashi Iwai3be14142009-02-20 14:11:16 +01002449 restore_pincfgs(codec); /* restore all current pin configs */
Takashi Iwai11aeff02008-07-30 15:01:46 +02002450 hda_exec_init_verbs(codec);
Takashi Iwaicb53c622007-08-10 17:21:45 +02002451 if (codec->patch_ops.resume)
2452 codec->patch_ops.resume(codec);
2453 else {
Takashi Iwai9d99f312007-08-14 15:15:52 +02002454 if (codec->patch_ops.init)
2455 codec->patch_ops.init(codec);
Takashi Iwaicb53c622007-08-10 17:21:45 +02002456 snd_hda_codec_resume_amp(codec);
2457 snd_hda_codec_resume_cache(codec);
2458 }
2459}
2460#endif /* SND_HDA_NEEDS_RESUME */
2461
Takashi Iwai54d17402005-11-21 16:33:22 +01002462
Linus Torvalds1da177e2005-04-16 15:20:36 -07002463/**
2464 * snd_hda_build_controls - build mixer controls
2465 * @bus: the BUS
2466 *
2467 * Creates mixer controls for each codec included in the bus.
2468 *
2469 * Returns 0 if successful, otherwise a negative error code.
2470 */
Takashi Iwai1289e9e2008-11-27 15:47:11 +01002471int /*__devinit*/ snd_hda_build_controls(struct hda_bus *bus)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002472{
Takashi Iwai0ba21762007-04-16 11:29:14 +02002473 struct hda_codec *codec;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002474
Takashi Iwai0ba21762007-04-16 11:29:14 +02002475 list_for_each_entry(codec, &bus->codec_list, list) {
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02002476 int err = snd_hda_codec_build_controls(codec);
Takashi Iwaif93d4612009-03-02 10:44:15 +01002477 if (err < 0) {
2478 printk(KERN_ERR "hda_codec: cannot build controls"
2479 "for #%d (error %d)\n", codec->addr, err);
2480 err = snd_hda_codec_reset(codec);
2481 if (err < 0) {
2482 printk(KERN_ERR
2483 "hda_codec: cannot revert codec\n");
2484 return err;
2485 }
2486 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002487 }
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02002488 return 0;
2489}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002490EXPORT_SYMBOL_HDA(snd_hda_build_controls);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002491
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02002492int snd_hda_codec_build_controls(struct hda_codec *codec)
2493{
2494 int err = 0;
Takashi Iwai11aeff02008-07-30 15:01:46 +02002495 hda_exec_init_verbs(codec);
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02002496 /* continue to initialize... */
2497 if (codec->patch_ops.init)
2498 err = codec->patch_ops.init(codec);
2499 if (!err && codec->patch_ops.build_controls)
2500 err = codec->patch_ops.build_controls(codec);
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02002501 if (err < 0)
2502 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002503 return 0;
2504}
2505
Linus Torvalds1da177e2005-04-16 15:20:36 -07002506/*
2507 * stream formats
2508 */
Takashi Iwaibefdf312005-08-22 13:57:55 +02002509struct hda_rate_tbl {
2510 unsigned int hz;
2511 unsigned int alsa_bits;
2512 unsigned int hda_fmt;
2513};
2514
2515static struct hda_rate_tbl rate_bits[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002516 /* rate in Hz, ALSA rate bitmask, HDA format value */
Nicolas Graziano9d8f53f2005-08-22 13:47:16 +02002517
2518 /* autodetected value used in snd_hda_query_supported_pcm */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002519 { 8000, SNDRV_PCM_RATE_8000, 0x0500 }, /* 1/6 x 48 */
2520 { 11025, SNDRV_PCM_RATE_11025, 0x4300 }, /* 1/4 x 44 */
2521 { 16000, SNDRV_PCM_RATE_16000, 0x0200 }, /* 1/3 x 48 */
2522 { 22050, SNDRV_PCM_RATE_22050, 0x4100 }, /* 1/2 x 44 */
2523 { 32000, SNDRV_PCM_RATE_32000, 0x0a00 }, /* 2/3 x 48 */
2524 { 44100, SNDRV_PCM_RATE_44100, 0x4000 }, /* 44 */
2525 { 48000, SNDRV_PCM_RATE_48000, 0x0000 }, /* 48 */
2526 { 88200, SNDRV_PCM_RATE_88200, 0x4800 }, /* 2 x 44 */
2527 { 96000, SNDRV_PCM_RATE_96000, 0x0800 }, /* 2 x 48 */
2528 { 176400, SNDRV_PCM_RATE_176400, 0x5800 },/* 4 x 44 */
2529 { 192000, SNDRV_PCM_RATE_192000, 0x1800 }, /* 4 x 48 */
Takashi Iwaia961f9f2007-04-12 13:08:09 +02002530#define AC_PAR_PCM_RATE_BITS 11
2531 /* up to bits 10, 384kHZ isn't supported properly */
2532
2533 /* not autodetected value */
2534 { 9600, SNDRV_PCM_RATE_KNOT, 0x0400 }, /* 1/5 x 48 */
Nicolas Graziano9d8f53f2005-08-22 13:47:16 +02002535
Takashi Iwaibefdf312005-08-22 13:57:55 +02002536 { 0 } /* terminator */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002537};
2538
2539/**
2540 * snd_hda_calc_stream_format - calculate format bitset
2541 * @rate: the sample rate
2542 * @channels: the number of channels
2543 * @format: the PCM format (SNDRV_PCM_FORMAT_XXX)
2544 * @maxbps: the max. bps
2545 *
2546 * Calculate the format bitset from the given rate, channels and th PCM format.
2547 *
2548 * Return zero if invalid.
2549 */
2550unsigned int snd_hda_calc_stream_format(unsigned int rate,
2551 unsigned int channels,
2552 unsigned int format,
2553 unsigned int maxbps)
2554{
2555 int i;
2556 unsigned int val = 0;
2557
Takashi Iwaibefdf312005-08-22 13:57:55 +02002558 for (i = 0; rate_bits[i].hz; i++)
2559 if (rate_bits[i].hz == rate) {
2560 val = rate_bits[i].hda_fmt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002561 break;
2562 }
Takashi Iwai0ba21762007-04-16 11:29:14 +02002563 if (!rate_bits[i].hz) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002564 snd_printdd("invalid rate %d\n", rate);
2565 return 0;
2566 }
2567
2568 if (channels == 0 || channels > 8) {
2569 snd_printdd("invalid channels %d\n", channels);
2570 return 0;
2571 }
2572 val |= channels - 1;
2573
2574 switch (snd_pcm_format_width(format)) {
2575 case 8: val |= 0x00; break;
2576 case 16: val |= 0x10; break;
2577 case 20:
2578 case 24:
2579 case 32:
2580 if (maxbps >= 32)
2581 val |= 0x40;
2582 else if (maxbps >= 24)
2583 val |= 0x30;
2584 else
2585 val |= 0x20;
2586 break;
2587 default:
Takashi Iwai0ba21762007-04-16 11:29:14 +02002588 snd_printdd("invalid format width %d\n",
2589 snd_pcm_format_width(format));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002590 return 0;
2591 }
2592
2593 return val;
2594}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002595EXPORT_SYMBOL_HDA(snd_hda_calc_stream_format);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002596
Takashi Iwai92c7c8a2009-03-24 07:32:14 +01002597static unsigned int get_pcm_param(struct hda_codec *codec, hda_nid_t nid)
2598{
2599 unsigned int val = 0;
2600 if (nid != codec->afg &&
2601 (get_wcaps(codec, nid) & AC_WCAP_FORMAT_OVRD))
2602 val = snd_hda_param_read(codec, nid, AC_PAR_PCM);
2603 if (!val || val == -1)
2604 val = snd_hda_param_read(codec, codec->afg, AC_PAR_PCM);
2605 if (!val || val == -1)
2606 return 0;
2607 return val;
2608}
2609
2610static unsigned int query_pcm_param(struct hda_codec *codec, hda_nid_t nid)
2611{
2612 return query_caps_hash(codec, nid, HDA_HASH_PARPCM_KEY(nid),
2613 get_pcm_param);
2614}
2615
2616static unsigned int get_stream_param(struct hda_codec *codec, hda_nid_t nid)
2617{
2618 unsigned int streams = snd_hda_param_read(codec, nid, AC_PAR_STREAM);
2619 if (!streams || streams == -1)
2620 streams = snd_hda_param_read(codec, codec->afg, AC_PAR_STREAM);
2621 if (!streams || streams == -1)
2622 return 0;
2623 return streams;
2624}
2625
2626static unsigned int query_stream_param(struct hda_codec *codec, hda_nid_t nid)
2627{
2628 return query_caps_hash(codec, nid, HDA_HASH_PARSTR_KEY(nid),
2629 get_stream_param);
2630}
2631
Linus Torvalds1da177e2005-04-16 15:20:36 -07002632/**
2633 * snd_hda_query_supported_pcm - query the supported PCM rates and formats
2634 * @codec: the HDA codec
2635 * @nid: NID to query
2636 * @ratesp: the pointer to store the detected rate bitflags
2637 * @formatsp: the pointer to store the detected formats
2638 * @bpsp: the pointer to store the detected format widths
2639 *
2640 * Queries the supported PCM rates and formats. The NULL @ratesp, @formatsp
2641 * or @bsps argument is ignored.
2642 *
2643 * Returns 0 if successful, otherwise a negative error code.
2644 */
Takashi Iwai986862bd2008-11-27 12:40:13 +01002645static int snd_hda_query_supported_pcm(struct hda_codec *codec, hda_nid_t nid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002646 u32 *ratesp, u64 *formatsp, unsigned int *bpsp)
2647{
Jaroslav Kyselaee504712009-03-17 14:30:31 +01002648 unsigned int i, val, wcaps;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002649
Jaroslav Kyselaee504712009-03-17 14:30:31 +01002650 wcaps = get_wcaps(codec, nid);
Takashi Iwai92c7c8a2009-03-24 07:32:14 +01002651 val = query_pcm_param(codec, nid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002652
2653 if (ratesp) {
2654 u32 rates = 0;
Takashi Iwaia961f9f2007-04-12 13:08:09 +02002655 for (i = 0; i < AC_PAR_PCM_RATE_BITS; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002656 if (val & (1 << i))
Takashi Iwaibefdf312005-08-22 13:57:55 +02002657 rates |= rate_bits[i].alsa_bits;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002658 }
Jaroslav Kyselaee504712009-03-17 14:30:31 +01002659 if (rates == 0) {
2660 snd_printk(KERN_ERR "hda_codec: rates == 0 "
2661 "(nid=0x%x, val=0x%x, ovrd=%i)\n",
2662 nid, val,
2663 (wcaps & AC_WCAP_FORMAT_OVRD) ? 1 : 0);
2664 return -EIO;
2665 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002666 *ratesp = rates;
2667 }
2668
2669 if (formatsp || bpsp) {
2670 u64 formats = 0;
Jaroslav Kyselaee504712009-03-17 14:30:31 +01002671 unsigned int streams, bps;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002672
Takashi Iwai92c7c8a2009-03-24 07:32:14 +01002673 streams = query_stream_param(codec, nid);
2674 if (!streams)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002675 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002676
2677 bps = 0;
2678 if (streams & AC_SUPFMT_PCM) {
2679 if (val & AC_SUPPCM_BITS_8) {
2680 formats |= SNDRV_PCM_FMTBIT_U8;
2681 bps = 8;
2682 }
2683 if (val & AC_SUPPCM_BITS_16) {
2684 formats |= SNDRV_PCM_FMTBIT_S16_LE;
2685 bps = 16;
2686 }
2687 if (wcaps & AC_WCAP_DIGITAL) {
2688 if (val & AC_SUPPCM_BITS_32)
2689 formats |= SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_LE;
2690 if (val & (AC_SUPPCM_BITS_20|AC_SUPPCM_BITS_24))
2691 formats |= SNDRV_PCM_FMTBIT_S32_LE;
2692 if (val & AC_SUPPCM_BITS_24)
2693 bps = 24;
2694 else if (val & AC_SUPPCM_BITS_20)
2695 bps = 20;
Takashi Iwai0ba21762007-04-16 11:29:14 +02002696 } else if (val & (AC_SUPPCM_BITS_20|AC_SUPPCM_BITS_24|
2697 AC_SUPPCM_BITS_32)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002698 formats |= SNDRV_PCM_FMTBIT_S32_LE;
2699 if (val & AC_SUPPCM_BITS_32)
2700 bps = 32;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002701 else if (val & AC_SUPPCM_BITS_24)
2702 bps = 24;
Nicolas Graziano33ef76512006-09-19 14:23:14 +02002703 else if (val & AC_SUPPCM_BITS_20)
2704 bps = 20;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002705 }
2706 }
Takashi Iwai0ba21762007-04-16 11:29:14 +02002707 else if (streams == AC_SUPFMT_FLOAT32) {
2708 /* should be exclusive */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002709 formats |= SNDRV_PCM_FMTBIT_FLOAT_LE;
2710 bps = 32;
Takashi Iwai0ba21762007-04-16 11:29:14 +02002711 } else if (streams == AC_SUPFMT_AC3) {
2712 /* should be exclusive */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002713 /* temporary hack: we have still no proper support
2714 * for the direct AC3 stream...
2715 */
2716 formats |= SNDRV_PCM_FMTBIT_U8;
2717 bps = 8;
2718 }
Jaroslav Kyselaee504712009-03-17 14:30:31 +01002719 if (formats == 0) {
2720 snd_printk(KERN_ERR "hda_codec: formats == 0 "
2721 "(nid=0x%x, val=0x%x, ovrd=%i, "
2722 "streams=0x%x)\n",
2723 nid, val,
2724 (wcaps & AC_WCAP_FORMAT_OVRD) ? 1 : 0,
2725 streams);
2726 return -EIO;
2727 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002728 if (formatsp)
2729 *formatsp = formats;
2730 if (bpsp)
2731 *bpsp = bps;
2732 }
2733
2734 return 0;
2735}
2736
2737/**
Takashi Iwai0ba21762007-04-16 11:29:14 +02002738 * snd_hda_is_supported_format - check whether the given node supports
2739 * the format val
Linus Torvalds1da177e2005-04-16 15:20:36 -07002740 *
2741 * Returns 1 if supported, 0 if not.
2742 */
2743int snd_hda_is_supported_format(struct hda_codec *codec, hda_nid_t nid,
2744 unsigned int format)
2745{
2746 int i;
2747 unsigned int val = 0, rate, stream;
2748
Takashi Iwai92c7c8a2009-03-24 07:32:14 +01002749 val = query_pcm_param(codec, nid);
2750 if (!val)
2751 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002752
2753 rate = format & 0xff00;
Takashi Iwaia961f9f2007-04-12 13:08:09 +02002754 for (i = 0; i < AC_PAR_PCM_RATE_BITS; i++)
Takashi Iwaibefdf312005-08-22 13:57:55 +02002755 if (rate_bits[i].hda_fmt == rate) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002756 if (val & (1 << i))
2757 break;
2758 return 0;
2759 }
Takashi Iwaia961f9f2007-04-12 13:08:09 +02002760 if (i >= AC_PAR_PCM_RATE_BITS)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002761 return 0;
2762
Takashi Iwai92c7c8a2009-03-24 07:32:14 +01002763 stream = query_stream_param(codec, nid);
2764 if (!stream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002765 return 0;
2766
2767 if (stream & AC_SUPFMT_PCM) {
2768 switch (format & 0xf0) {
2769 case 0x00:
Takashi Iwai0ba21762007-04-16 11:29:14 +02002770 if (!(val & AC_SUPPCM_BITS_8))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002771 return 0;
2772 break;
2773 case 0x10:
Takashi Iwai0ba21762007-04-16 11:29:14 +02002774 if (!(val & AC_SUPPCM_BITS_16))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002775 return 0;
2776 break;
2777 case 0x20:
Takashi Iwai0ba21762007-04-16 11:29:14 +02002778 if (!(val & AC_SUPPCM_BITS_20))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002779 return 0;
2780 break;
2781 case 0x30:
Takashi Iwai0ba21762007-04-16 11:29:14 +02002782 if (!(val & AC_SUPPCM_BITS_24))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002783 return 0;
2784 break;
2785 case 0x40:
Takashi Iwai0ba21762007-04-16 11:29:14 +02002786 if (!(val & AC_SUPPCM_BITS_32))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002787 return 0;
2788 break;
2789 default:
2790 return 0;
2791 }
2792 } else {
2793 /* FIXME: check for float32 and AC3? */
2794 }
2795
2796 return 1;
2797}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002798EXPORT_SYMBOL_HDA(snd_hda_is_supported_format);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002799
2800/*
2801 * PCM stuff
2802 */
2803static int hda_pcm_default_open_close(struct hda_pcm_stream *hinfo,
2804 struct hda_codec *codec,
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01002805 struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002806{
2807 return 0;
2808}
2809
2810static int hda_pcm_default_prepare(struct hda_pcm_stream *hinfo,
2811 struct hda_codec *codec,
2812 unsigned int stream_tag,
2813 unsigned int format,
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01002814 struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002815{
2816 snd_hda_codec_setup_stream(codec, hinfo->nid, stream_tag, 0, format);
2817 return 0;
2818}
2819
2820static int hda_pcm_default_cleanup(struct hda_pcm_stream *hinfo,
2821 struct hda_codec *codec,
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01002822 struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002823{
Takashi Iwai888afa12008-03-18 09:57:50 +01002824 snd_hda_codec_cleanup_stream(codec, hinfo->nid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002825 return 0;
2826}
2827
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02002828static int set_pcm_default_values(struct hda_codec *codec,
2829 struct hda_pcm_stream *info)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002830{
Jaroslav Kyselaee504712009-03-17 14:30:31 +01002831 int err;
2832
Takashi Iwai0ba21762007-04-16 11:29:14 +02002833 /* query support PCM information from the given NID */
2834 if (info->nid && (!info->rates || !info->formats)) {
Jaroslav Kyselaee504712009-03-17 14:30:31 +01002835 err = snd_hda_query_supported_pcm(codec, info->nid,
Takashi Iwai0ba21762007-04-16 11:29:14 +02002836 info->rates ? NULL : &info->rates,
2837 info->formats ? NULL : &info->formats,
2838 info->maxbps ? NULL : &info->maxbps);
Jaroslav Kyselaee504712009-03-17 14:30:31 +01002839 if (err < 0)
2840 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002841 }
2842 if (info->ops.open == NULL)
2843 info->ops.open = hda_pcm_default_open_close;
2844 if (info->ops.close == NULL)
2845 info->ops.close = hda_pcm_default_open_close;
2846 if (info->ops.prepare == NULL) {
Takashi Iwaida3cec32008-08-08 17:12:14 +02002847 if (snd_BUG_ON(!info->nid))
2848 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002849 info->ops.prepare = hda_pcm_default_prepare;
2850 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002851 if (info->ops.cleanup == NULL) {
Takashi Iwaida3cec32008-08-08 17:12:14 +02002852 if (snd_BUG_ON(!info->nid))
2853 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002854 info->ops.cleanup = hda_pcm_default_cleanup;
2855 }
2856 return 0;
2857}
2858
Takashi Iwai176d5332008-07-30 15:01:44 +02002859/*
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002860 * get the empty PCM device number to assign
2861 */
2862static int get_empty_pcm_device(struct hda_bus *bus, int type)
2863{
2864 static const char *dev_name[HDA_PCM_NTYPES] = {
2865 "Audio", "SPDIF", "HDMI", "Modem"
2866 };
2867 /* starting device index for each PCM type */
2868 static int dev_idx[HDA_PCM_NTYPES] = {
2869 [HDA_PCM_TYPE_AUDIO] = 0,
2870 [HDA_PCM_TYPE_SPDIF] = 1,
2871 [HDA_PCM_TYPE_HDMI] = 3,
2872 [HDA_PCM_TYPE_MODEM] = 6
2873 };
2874 /* normal audio device indices; not linear to keep compatibility */
2875 static int audio_idx[4] = { 0, 2, 4, 5 };
2876 int i, dev;
2877
2878 switch (type) {
2879 case HDA_PCM_TYPE_AUDIO:
2880 for (i = 0; i < ARRAY_SIZE(audio_idx); i++) {
2881 dev = audio_idx[i];
2882 if (!test_bit(dev, bus->pcm_dev_bits))
Takashi Iwai82ad39f2009-03-03 15:00:35 +01002883 goto ok;
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002884 }
Takashi Iwai82ad39f2009-03-03 15:00:35 +01002885 snd_printk(KERN_WARNING "Too many audio devices\n");
2886 return -EAGAIN;
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002887 case HDA_PCM_TYPE_SPDIF:
2888 case HDA_PCM_TYPE_HDMI:
2889 case HDA_PCM_TYPE_MODEM:
2890 dev = dev_idx[type];
2891 if (test_bit(dev, bus->pcm_dev_bits)) {
2892 snd_printk(KERN_WARNING "%s already defined\n",
2893 dev_name[type]);
2894 return -EAGAIN;
2895 }
2896 break;
2897 default:
2898 snd_printk(KERN_WARNING "Invalid PCM type %d\n", type);
2899 return -EINVAL;
2900 }
Takashi Iwai82ad39f2009-03-03 15:00:35 +01002901 ok:
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002902 set_bit(dev, bus->pcm_dev_bits);
2903 return dev;
2904}
2905
2906/*
Takashi Iwai176d5332008-07-30 15:01:44 +02002907 * attach a new PCM stream
2908 */
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002909static int snd_hda_attach_pcm(struct hda_codec *codec, struct hda_pcm *pcm)
Takashi Iwai176d5332008-07-30 15:01:44 +02002910{
Takashi Iwai33fa35e2008-11-06 16:50:40 +01002911 struct hda_bus *bus = codec->bus;
Takashi Iwai176d5332008-07-30 15:01:44 +02002912 struct hda_pcm_stream *info;
2913 int stream, err;
2914
Takashi Iwaib91f0802008-11-04 08:43:08 +01002915 if (snd_BUG_ON(!pcm->name))
Takashi Iwai176d5332008-07-30 15:01:44 +02002916 return -EINVAL;
2917 for (stream = 0; stream < 2; stream++) {
2918 info = &pcm->stream[stream];
2919 if (info->substreams) {
2920 err = set_pcm_default_values(codec, info);
2921 if (err < 0)
2922 return err;
2923 }
2924 }
Takashi Iwai33fa35e2008-11-06 16:50:40 +01002925 return bus->ops.attach_pcm(bus, codec, pcm);
Takashi Iwai176d5332008-07-30 15:01:44 +02002926}
2927
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002928/* assign all PCMs of the given codec */
2929int snd_hda_codec_build_pcms(struct hda_codec *codec)
2930{
2931 unsigned int pcm;
2932 int err;
2933
2934 if (!codec->num_pcms) {
2935 if (!codec->patch_ops.build_pcms)
2936 return 0;
2937 err = codec->patch_ops.build_pcms(codec);
Takashi Iwai6e655bf2009-03-02 10:46:03 +01002938 if (err < 0) {
2939 printk(KERN_ERR "hda_codec: cannot build PCMs"
2940 "for #%d (error %d)\n", codec->addr, err);
2941 err = snd_hda_codec_reset(codec);
2942 if (err < 0) {
2943 printk(KERN_ERR
2944 "hda_codec: cannot revert codec\n");
2945 return err;
2946 }
2947 }
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002948 }
2949 for (pcm = 0; pcm < codec->num_pcms; pcm++) {
2950 struct hda_pcm *cpcm = &codec->pcm_info[pcm];
2951 int dev;
2952
2953 if (!cpcm->stream[0].substreams && !cpcm->stream[1].substreams)
Takashi Iwai41b5b012009-01-20 18:21:23 +01002954 continue; /* no substreams assigned */
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002955
2956 if (!cpcm->pcm) {
2957 dev = get_empty_pcm_device(codec->bus, cpcm->pcm_type);
2958 if (dev < 0)
Takashi Iwai6e655bf2009-03-02 10:46:03 +01002959 continue; /* no fatal error */
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002960 cpcm->device = dev;
2961 err = snd_hda_attach_pcm(codec, cpcm);
Takashi Iwai6e655bf2009-03-02 10:46:03 +01002962 if (err < 0) {
2963 printk(KERN_ERR "hda_codec: cannot attach "
2964 "PCM stream %d for codec #%d\n",
2965 dev, codec->addr);
2966 continue; /* no fatal error */
2967 }
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002968 }
2969 }
2970 return 0;
2971}
2972
Linus Torvalds1da177e2005-04-16 15:20:36 -07002973/**
2974 * snd_hda_build_pcms - build PCM information
2975 * @bus: the BUS
2976 *
2977 * Create PCM information for each codec included in the bus.
2978 *
2979 * The build_pcms codec patch is requested to set up codec->num_pcms and
2980 * codec->pcm_info properly. The array is referred by the top-level driver
2981 * to create its PCM instances.
2982 * The allocated codec->pcm_info should be released in codec->patch_ops.free
2983 * callback.
2984 *
2985 * At least, substreams, channels_min and channels_max must be filled for
2986 * each stream. substreams = 0 indicates that the stream doesn't exist.
2987 * When rates and/or formats are zero, the supported values are queried
2988 * from the given nid. The nid is used also by the default ops.prepare
2989 * and ops.cleanup callbacks.
2990 *
2991 * The driver needs to call ops.open in its open callback. Similarly,
2992 * ops.close is supposed to be called in the close callback.
2993 * ops.prepare should be called in the prepare or hw_params callback
2994 * with the proper parameters for set up.
2995 * ops.cleanup should be called in hw_free for clean up of streams.
2996 *
2997 * This function returns 0 if successfull, or a negative error code.
2998 */
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002999int __devinit snd_hda_build_pcms(struct hda_bus *bus)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003000{
Takashi Iwai0ba21762007-04-16 11:29:14 +02003001 struct hda_codec *codec;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003002
Takashi Iwai0ba21762007-04-16 11:29:14 +02003003 list_for_each_entry(codec, &bus->codec_list, list) {
Takashi Iwai529bd6c2008-11-27 14:17:01 +01003004 int err = snd_hda_codec_build_pcms(codec);
3005 if (err < 0)
3006 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003007 }
3008 return 0;
3009}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003010EXPORT_SYMBOL_HDA(snd_hda_build_pcms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003011
Linus Torvalds1da177e2005-04-16 15:20:36 -07003012/**
3013 * snd_hda_check_board_config - compare the current codec with the config table
3014 * @codec: the HDA codec
Takashi Iwaif5fcc132006-11-24 17:07:44 +01003015 * @num_configs: number of config enums
3016 * @models: array of model name strings
Linus Torvalds1da177e2005-04-16 15:20:36 -07003017 * @tbl: configuration table, terminated by null entries
3018 *
3019 * Compares the modelname or PCI subsystem id of the current codec with the
3020 * given configuration table. If a matching entry is found, returns its
3021 * config value (supposed to be 0 or positive).
3022 *
3023 * If no entries are matching, the function returns a negative value.
3024 */
Takashi Iwai12f288b2007-08-02 15:51:59 +02003025int snd_hda_check_board_config(struct hda_codec *codec,
3026 int num_configs, const char **models,
3027 const struct snd_pci_quirk *tbl)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003028{
Takashi Iwaif44ac832008-07-30 15:01:45 +02003029 if (codec->modelname && models) {
Takashi Iwaif5fcc132006-11-24 17:07:44 +01003030 int i;
3031 for (i = 0; i < num_configs; i++) {
3032 if (models[i] &&
Takashi Iwaif44ac832008-07-30 15:01:45 +02003033 !strcmp(codec->modelname, models[i])) {
Takashi Iwaif5fcc132006-11-24 17:07:44 +01003034 snd_printd(KERN_INFO "hda_codec: model '%s' is "
3035 "selected\n", models[i]);
3036 return i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003037 }
3038 }
3039 }
3040
Takashi Iwaif5fcc132006-11-24 17:07:44 +01003041 if (!codec->bus->pci || !tbl)
3042 return -1;
3043
3044 tbl = snd_pci_quirk_lookup(codec->bus->pci, tbl);
3045 if (!tbl)
3046 return -1;
3047 if (tbl->value >= 0 && tbl->value < num_configs) {
Takashi Iwai62cf8722008-05-20 12:15:15 +02003048#ifdef CONFIG_SND_DEBUG_VERBOSE
Takashi Iwaif5fcc132006-11-24 17:07:44 +01003049 char tmp[10];
3050 const char *model = NULL;
3051 if (models)
3052 model = models[tbl->value];
3053 if (!model) {
3054 sprintf(tmp, "#%d", tbl->value);
3055 model = tmp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003056 }
Takashi Iwaif5fcc132006-11-24 17:07:44 +01003057 snd_printdd(KERN_INFO "hda_codec: model '%s' is selected "
3058 "for config %x:%x (%s)\n",
3059 model, tbl->subvendor, tbl->subdevice,
3060 (tbl->name ? tbl->name : "Unknown device"));
3061#endif
3062 return tbl->value;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003063 }
3064 return -1;
3065}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003066EXPORT_SYMBOL_HDA(snd_hda_check_board_config);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003067
3068/**
Mauro Carvalho Chehab2eda3442008-08-11 10:18:39 +02003069 * snd_hda_check_board_codec_sid_config - compare the current codec
3070 subsystem ID with the
3071 config table
3072
3073 This is important for Gateway notebooks with SB450 HDA Audio
3074 where the vendor ID of the PCI device is:
3075 ATI Technologies Inc SB450 HDA Audio [1002:437b]
3076 and the vendor/subvendor are found only at the codec.
3077
3078 * @codec: the HDA codec
3079 * @num_configs: number of config enums
3080 * @models: array of model name strings
3081 * @tbl: configuration table, terminated by null entries
3082 *
3083 * Compares the modelname or PCI subsystem id of the current codec with the
3084 * given configuration table. If a matching entry is found, returns its
3085 * config value (supposed to be 0 or positive).
3086 *
3087 * If no entries are matching, the function returns a negative value.
3088 */
3089int snd_hda_check_board_codec_sid_config(struct hda_codec *codec,
3090 int num_configs, const char **models,
3091 const struct snd_pci_quirk *tbl)
3092{
3093 const struct snd_pci_quirk *q;
3094
3095 /* Search for codec ID */
3096 for (q = tbl; q->subvendor; q++) {
3097 unsigned long vendorid = (q->subdevice) | (q->subvendor << 16);
3098
3099 if (vendorid == codec->subsystem_id)
3100 break;
3101 }
3102
3103 if (!q->subvendor)
3104 return -1;
3105
3106 tbl = q;
3107
3108 if (tbl->value >= 0 && tbl->value < num_configs) {
3109#ifdef CONFIG_SND_DEBUG_DETECT
3110 char tmp[10];
3111 const char *model = NULL;
3112 if (models)
3113 model = models[tbl->value];
3114 if (!model) {
3115 sprintf(tmp, "#%d", tbl->value);
3116 model = tmp;
3117 }
3118 snd_printdd(KERN_INFO "hda_codec: model '%s' is selected "
3119 "for config %x:%x (%s)\n",
3120 model, tbl->subvendor, tbl->subdevice,
3121 (tbl->name ? tbl->name : "Unknown device"));
3122#endif
3123 return tbl->value;
3124 }
3125 return -1;
3126}
3127EXPORT_SYMBOL_HDA(snd_hda_check_board_codec_sid_config);
3128
3129/**
Linus Torvalds1da177e2005-04-16 15:20:36 -07003130 * snd_hda_add_new_ctls - create controls from the array
3131 * @codec: the HDA codec
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01003132 * @knew: the array of struct snd_kcontrol_new
Linus Torvalds1da177e2005-04-16 15:20:36 -07003133 *
3134 * This helper function creates and add new controls in the given array.
3135 * The array must be terminated with an empty entry as terminator.
3136 *
3137 * Returns 0 if successful, or a negative error code.
3138 */
Takashi Iwai12f288b2007-08-02 15:51:59 +02003139int snd_hda_add_new_ctls(struct hda_codec *codec, struct snd_kcontrol_new *knew)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003140{
Takashi Iwaicb53c622007-08-10 17:21:45 +02003141 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003142
3143 for (; knew->name; knew++) {
Takashi Iwai54d17402005-11-21 16:33:22 +01003144 struct snd_kcontrol *kctl;
3145 kctl = snd_ctl_new1(knew, codec);
Takashi Iwai0ba21762007-04-16 11:29:14 +02003146 if (!kctl)
Takashi Iwai54d17402005-11-21 16:33:22 +01003147 return -ENOMEM;
Takashi Iwaid13bd412008-07-30 15:01:45 +02003148 err = snd_hda_ctl_add(codec, kctl);
Takashi Iwai54d17402005-11-21 16:33:22 +01003149 if (err < 0) {
Takashi Iwai0ba21762007-04-16 11:29:14 +02003150 if (!codec->addr)
Takashi Iwai54d17402005-11-21 16:33:22 +01003151 return err;
3152 kctl = snd_ctl_new1(knew, codec);
Takashi Iwai0ba21762007-04-16 11:29:14 +02003153 if (!kctl)
Takashi Iwai54d17402005-11-21 16:33:22 +01003154 return -ENOMEM;
3155 kctl->id.device = codec->addr;
Takashi Iwaid13bd412008-07-30 15:01:45 +02003156 err = snd_hda_ctl_add(codec, kctl);
Takashi Iwai0ba21762007-04-16 11:29:14 +02003157 if (err < 0)
Takashi Iwai54d17402005-11-21 16:33:22 +01003158 return err;
3159 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003160 }
3161 return 0;
3162}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003163EXPORT_SYMBOL_HDA(snd_hda_add_new_ctls);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003164
Takashi Iwaicb53c622007-08-10 17:21:45 +02003165#ifdef CONFIG_SND_HDA_POWER_SAVE
3166static void hda_set_power_state(struct hda_codec *codec, hda_nid_t fg,
3167 unsigned int power_state);
3168
3169static void hda_power_work(struct work_struct *work)
3170{
3171 struct hda_codec *codec =
3172 container_of(work, struct hda_codec, power_work.work);
Takashi Iwai33fa35e2008-11-06 16:50:40 +01003173 struct hda_bus *bus = codec->bus;
Takashi Iwaicb53c622007-08-10 17:21:45 +02003174
Maxim Levitsky2e492462007-09-03 15:26:57 +02003175 if (!codec->power_on || codec->power_count) {
3176 codec->power_transition = 0;
Takashi Iwaicb53c622007-08-10 17:21:45 +02003177 return;
Maxim Levitsky2e492462007-09-03 15:26:57 +02003178 }
Takashi Iwaicb53c622007-08-10 17:21:45 +02003179
3180 hda_call_codec_suspend(codec);
Takashi Iwai33fa35e2008-11-06 16:50:40 +01003181 if (bus->ops.pm_notify)
3182 bus->ops.pm_notify(bus);
Takashi Iwaicb53c622007-08-10 17:21:45 +02003183}
3184
3185static void hda_keep_power_on(struct hda_codec *codec)
3186{
3187 codec->power_count++;
3188 codec->power_on = 1;
3189}
3190
3191void snd_hda_power_up(struct hda_codec *codec)
3192{
Takashi Iwai33fa35e2008-11-06 16:50:40 +01003193 struct hda_bus *bus = codec->bus;
3194
Takashi Iwaicb53c622007-08-10 17:21:45 +02003195 codec->power_count++;
Takashi Iwaia221e282007-08-16 16:35:33 +02003196 if (codec->power_on || codec->power_transition)
Takashi Iwaicb53c622007-08-10 17:21:45 +02003197 return;
3198
3199 codec->power_on = 1;
Takashi Iwai33fa35e2008-11-06 16:50:40 +01003200 if (bus->ops.pm_notify)
3201 bus->ops.pm_notify(bus);
Takashi Iwaicb53c622007-08-10 17:21:45 +02003202 hda_call_codec_resume(codec);
3203 cancel_delayed_work(&codec->power_work);
Takashi Iwaia221e282007-08-16 16:35:33 +02003204 codec->power_transition = 0;
Takashi Iwaicb53c622007-08-10 17:21:45 +02003205}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003206EXPORT_SYMBOL_HDA(snd_hda_power_up);
Takashi Iwai1289e9e2008-11-27 15:47:11 +01003207
3208#define power_save(codec) \
3209 ((codec)->bus->power_save ? *(codec)->bus->power_save : 0)
Takashi Iwaicb53c622007-08-10 17:21:45 +02003210
Takashi Iwaifee2fba2008-11-27 12:43:28 +01003211#define power_save(codec) \
3212 ((codec)->bus->power_save ? *(codec)->bus->power_save : 0)
3213
Takashi Iwaicb53c622007-08-10 17:21:45 +02003214void snd_hda_power_down(struct hda_codec *codec)
3215{
3216 --codec->power_count;
Takashi Iwaia221e282007-08-16 16:35:33 +02003217 if (!codec->power_on || codec->power_count || codec->power_transition)
Takashi Iwaicb53c622007-08-10 17:21:45 +02003218 return;
Takashi Iwaifee2fba2008-11-27 12:43:28 +01003219 if (power_save(codec)) {
Takashi Iwaia221e282007-08-16 16:35:33 +02003220 codec->power_transition = 1; /* avoid reentrance */
Takashi Iwaic107b412009-01-13 17:46:37 +01003221 queue_delayed_work(codec->bus->workq, &codec->power_work,
Takashi Iwaifee2fba2008-11-27 12:43:28 +01003222 msecs_to_jiffies(power_save(codec) * 1000));
Takashi Iwaia221e282007-08-16 16:35:33 +02003223 }
Takashi Iwaicb53c622007-08-10 17:21:45 +02003224}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003225EXPORT_SYMBOL_HDA(snd_hda_power_down);
Takashi Iwaicb53c622007-08-10 17:21:45 +02003226
3227int snd_hda_check_amp_list_power(struct hda_codec *codec,
3228 struct hda_loopback_check *check,
3229 hda_nid_t nid)
3230{
3231 struct hda_amp_list *p;
3232 int ch, v;
3233
3234 if (!check->amplist)
3235 return 0;
3236 for (p = check->amplist; p->nid; p++) {
3237 if (p->nid == nid)
3238 break;
3239 }
3240 if (!p->nid)
3241 return 0; /* nothing changed */
3242
3243 for (p = check->amplist; p->nid; p++) {
3244 for (ch = 0; ch < 2; ch++) {
3245 v = snd_hda_codec_amp_read(codec, p->nid, ch, p->dir,
3246 p->idx);
3247 if (!(v & HDA_AMP_MUTE) && v > 0) {
3248 if (!check->power_on) {
3249 check->power_on = 1;
3250 snd_hda_power_up(codec);
3251 }
3252 return 1;
3253 }
3254 }
3255 }
3256 if (check->power_on) {
3257 check->power_on = 0;
3258 snd_hda_power_down(codec);
3259 }
3260 return 0;
3261}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003262EXPORT_SYMBOL_HDA(snd_hda_check_amp_list_power);
Takashi Iwaicb53c622007-08-10 17:21:45 +02003263#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07003264
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01003265/*
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01003266 * Channel mode helper
3267 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003268int snd_hda_ch_mode_info(struct hda_codec *codec,
3269 struct snd_ctl_elem_info *uinfo,
3270 const struct hda_channel_mode *chmode,
3271 int num_chmodes)
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01003272{
3273 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
3274 uinfo->count = 1;
3275 uinfo->value.enumerated.items = num_chmodes;
3276 if (uinfo->value.enumerated.item >= num_chmodes)
3277 uinfo->value.enumerated.item = num_chmodes - 1;
3278 sprintf(uinfo->value.enumerated.name, "%dch",
3279 chmode[uinfo->value.enumerated.item].channels);
3280 return 0;
3281}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003282EXPORT_SYMBOL_HDA(snd_hda_ch_mode_info);
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01003283
Takashi Iwai0ba21762007-04-16 11:29:14 +02003284int snd_hda_ch_mode_get(struct hda_codec *codec,
3285 struct snd_ctl_elem_value *ucontrol,
3286 const struct hda_channel_mode *chmode,
3287 int num_chmodes,
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01003288 int max_channels)
3289{
3290 int i;
3291
3292 for (i = 0; i < num_chmodes; i++) {
3293 if (max_channels == chmode[i].channels) {
3294 ucontrol->value.enumerated.item[0] = i;
3295 break;
3296 }
3297 }
3298 return 0;
3299}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003300EXPORT_SYMBOL_HDA(snd_hda_ch_mode_get);
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01003301
Takashi Iwai0ba21762007-04-16 11:29:14 +02003302int snd_hda_ch_mode_put(struct hda_codec *codec,
3303 struct snd_ctl_elem_value *ucontrol,
3304 const struct hda_channel_mode *chmode,
3305 int num_chmodes,
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01003306 int *max_channelsp)
3307{
3308 unsigned int mode;
3309
3310 mode = ucontrol->value.enumerated.item[0];
Takashi Iwai68ea7b22007-11-15 15:54:38 +01003311 if (mode >= num_chmodes)
3312 return -EINVAL;
Takashi Iwai82beb8f2007-08-10 17:09:26 +02003313 if (*max_channelsp == chmode[mode].channels)
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01003314 return 0;
3315 /* change the current channel setting */
3316 *max_channelsp = chmode[mode].channels;
3317 if (chmode[mode].sequence)
Takashi Iwai82beb8f2007-08-10 17:09:26 +02003318 snd_hda_sequence_write_cache(codec, chmode[mode].sequence);
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01003319 return 1;
3320}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003321EXPORT_SYMBOL_HDA(snd_hda_ch_mode_put);
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01003322
Linus Torvalds1da177e2005-04-16 15:20:36 -07003323/*
3324 * input MUX helper
3325 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003326int snd_hda_input_mux_info(const struct hda_input_mux *imux,
3327 struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003328{
3329 unsigned int index;
3330
3331 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
3332 uinfo->count = 1;
3333 uinfo->value.enumerated.items = imux->num_items;
Takashi Iwai5513b0c2007-10-09 11:58:41 +02003334 if (!imux->num_items)
3335 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003336 index = uinfo->value.enumerated.item;
3337 if (index >= imux->num_items)
3338 index = imux->num_items - 1;
3339 strcpy(uinfo->value.enumerated.name, imux->items[index].label);
3340 return 0;
3341}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003342EXPORT_SYMBOL_HDA(snd_hda_input_mux_info);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003343
Takashi Iwai0ba21762007-04-16 11:29:14 +02003344int snd_hda_input_mux_put(struct hda_codec *codec,
3345 const struct hda_input_mux *imux,
3346 struct snd_ctl_elem_value *ucontrol,
3347 hda_nid_t nid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003348 unsigned int *cur_val)
3349{
3350 unsigned int idx;
3351
Takashi Iwai5513b0c2007-10-09 11:58:41 +02003352 if (!imux->num_items)
3353 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003354 idx = ucontrol->value.enumerated.item[0];
3355 if (idx >= imux->num_items)
3356 idx = imux->num_items - 1;
Takashi Iwai82beb8f2007-08-10 17:09:26 +02003357 if (*cur_val == idx)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003358 return 0;
Takashi Iwai82beb8f2007-08-10 17:09:26 +02003359 snd_hda_codec_write_cache(codec, nid, 0, AC_VERB_SET_CONNECT_SEL,
3360 imux->items[idx].index);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003361 *cur_val = idx;
3362 return 1;
3363}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003364EXPORT_SYMBOL_HDA(snd_hda_input_mux_put);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003365
3366
3367/*
3368 * Multi-channel / digital-out PCM helper functions
3369 */
3370
Takashi Iwai6b97eb42007-04-05 14:51:48 +02003371/* setup SPDIF output stream */
3372static void setup_dig_out_stream(struct hda_codec *codec, hda_nid_t nid,
3373 unsigned int stream_tag, unsigned int format)
3374{
3375 /* turn off SPDIF once; otherwise the IEC958 bits won't be updated */
Takashi Iwai2f728532008-09-25 16:32:41 +02003376 if (codec->spdif_status_reset && (codec->spdif_ctls & AC_DIG1_ENABLE))
3377 set_dig_out_convert(codec, nid,
3378 codec->spdif_ctls & ~AC_DIG1_ENABLE & 0xff,
3379 -1);
Takashi Iwai6b97eb42007-04-05 14:51:48 +02003380 snd_hda_codec_setup_stream(codec, nid, stream_tag, 0, format);
Takashi Iwai2f728532008-09-25 16:32:41 +02003381 if (codec->slave_dig_outs) {
3382 hda_nid_t *d;
3383 for (d = codec->slave_dig_outs; *d; d++)
3384 snd_hda_codec_setup_stream(codec, *d, stream_tag, 0,
3385 format);
Matthew Ranostayde51ca12008-09-07 14:31:40 -04003386 }
Takashi Iwai2f728532008-09-25 16:32:41 +02003387 /* turn on again (if needed) */
3388 if (codec->spdif_status_reset && (codec->spdif_ctls & AC_DIG1_ENABLE))
3389 set_dig_out_convert(codec, nid,
3390 codec->spdif_ctls & 0xff, -1);
3391}
Matthew Ranostayde51ca12008-09-07 14:31:40 -04003392
Takashi Iwai2f728532008-09-25 16:32:41 +02003393static void cleanup_dig_out_stream(struct hda_codec *codec, hda_nid_t nid)
3394{
3395 snd_hda_codec_cleanup_stream(codec, nid);
3396 if (codec->slave_dig_outs) {
3397 hda_nid_t *d;
3398 for (d = codec->slave_dig_outs; *d; d++)
3399 snd_hda_codec_cleanup_stream(codec, *d);
3400 }
Takashi Iwai6b97eb42007-04-05 14:51:48 +02003401}
3402
Linus Torvalds1da177e2005-04-16 15:20:36 -07003403/*
3404 * open the digital out in the exclusive mode
3405 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003406int snd_hda_multi_out_dig_open(struct hda_codec *codec,
3407 struct hda_multi_out *mout)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003408{
Ingo Molnar62932df2006-01-16 16:34:20 +01003409 mutex_lock(&codec->spdif_mutex);
Takashi Iwai5930ca42007-04-16 11:23:56 +02003410 if (mout->dig_out_used == HDA_DIG_ANALOG_DUP)
3411 /* already opened as analog dup; reset it once */
Takashi Iwai2f728532008-09-25 16:32:41 +02003412 cleanup_dig_out_stream(codec, mout->dig_out_nid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003413 mout->dig_out_used = HDA_DIG_EXCLUSIVE;
Ingo Molnar62932df2006-01-16 16:34:20 +01003414 mutex_unlock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003415 return 0;
3416}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003417EXPORT_SYMBOL_HDA(snd_hda_multi_out_dig_open);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003418
Takashi Iwai6b97eb42007-04-05 14:51:48 +02003419int snd_hda_multi_out_dig_prepare(struct hda_codec *codec,
3420 struct hda_multi_out *mout,
3421 unsigned int stream_tag,
3422 unsigned int format,
3423 struct snd_pcm_substream *substream)
3424{
3425 mutex_lock(&codec->spdif_mutex);
3426 setup_dig_out_stream(codec, mout->dig_out_nid, stream_tag, format);
3427 mutex_unlock(&codec->spdif_mutex);
3428 return 0;
3429}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003430EXPORT_SYMBOL_HDA(snd_hda_multi_out_dig_prepare);
Takashi Iwai6b97eb42007-04-05 14:51:48 +02003431
Takashi Iwai9411e212009-02-13 11:32:28 +01003432int snd_hda_multi_out_dig_cleanup(struct hda_codec *codec,
3433 struct hda_multi_out *mout)
3434{
3435 mutex_lock(&codec->spdif_mutex);
3436 cleanup_dig_out_stream(codec, mout->dig_out_nid);
3437 mutex_unlock(&codec->spdif_mutex);
3438 return 0;
3439}
3440EXPORT_SYMBOL_HDA(snd_hda_multi_out_dig_cleanup);
3441
Linus Torvalds1da177e2005-04-16 15:20:36 -07003442/*
3443 * release the digital out
3444 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003445int snd_hda_multi_out_dig_close(struct hda_codec *codec,
3446 struct hda_multi_out *mout)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003447{
Ingo Molnar62932df2006-01-16 16:34:20 +01003448 mutex_lock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003449 mout->dig_out_used = 0;
Ingo Molnar62932df2006-01-16 16:34:20 +01003450 mutex_unlock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003451 return 0;
3452}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003453EXPORT_SYMBOL_HDA(snd_hda_multi_out_dig_close);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003454
3455/*
3456 * set up more restrictions for analog out
3457 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003458int snd_hda_multi_out_analog_open(struct hda_codec *codec,
3459 struct hda_multi_out *mout,
Takashi Iwai9a081602008-02-12 18:37:26 +01003460 struct snd_pcm_substream *substream,
3461 struct hda_pcm_stream *hinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003462{
Takashi Iwai9a081602008-02-12 18:37:26 +01003463 struct snd_pcm_runtime *runtime = substream->runtime;
3464 runtime->hw.channels_max = mout->max_channels;
3465 if (mout->dig_out_nid) {
3466 if (!mout->analog_rates) {
3467 mout->analog_rates = hinfo->rates;
3468 mout->analog_formats = hinfo->formats;
3469 mout->analog_maxbps = hinfo->maxbps;
3470 } else {
3471 runtime->hw.rates = mout->analog_rates;
3472 runtime->hw.formats = mout->analog_formats;
3473 hinfo->maxbps = mout->analog_maxbps;
3474 }
3475 if (!mout->spdif_rates) {
3476 snd_hda_query_supported_pcm(codec, mout->dig_out_nid,
3477 &mout->spdif_rates,
3478 &mout->spdif_formats,
3479 &mout->spdif_maxbps);
3480 }
3481 mutex_lock(&codec->spdif_mutex);
3482 if (mout->share_spdif) {
3483 runtime->hw.rates &= mout->spdif_rates;
3484 runtime->hw.formats &= mout->spdif_formats;
3485 if (mout->spdif_maxbps < hinfo->maxbps)
3486 hinfo->maxbps = mout->spdif_maxbps;
3487 }
Frederik Deweerdteaa99852008-04-14 13:11:44 +02003488 mutex_unlock(&codec->spdif_mutex);
Takashi Iwai9a081602008-02-12 18:37:26 +01003489 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003490 return snd_pcm_hw_constraint_step(substream->runtime, 0,
3491 SNDRV_PCM_HW_PARAM_CHANNELS, 2);
3492}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003493EXPORT_SYMBOL_HDA(snd_hda_multi_out_analog_open);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003494
3495/*
3496 * set up the i/o for analog out
3497 * when the digital out is available, copy the front out to digital out, too.
3498 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003499int snd_hda_multi_out_analog_prepare(struct hda_codec *codec,
3500 struct hda_multi_out *mout,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003501 unsigned int stream_tag,
3502 unsigned int format,
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01003503 struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003504{
3505 hda_nid_t *nids = mout->dac_nids;
3506 int chs = substream->runtime->channels;
3507 int i;
3508
Ingo Molnar62932df2006-01-16 16:34:20 +01003509 mutex_lock(&codec->spdif_mutex);
Takashi Iwai9a081602008-02-12 18:37:26 +01003510 if (mout->dig_out_nid && mout->share_spdif &&
3511 mout->dig_out_used != HDA_DIG_EXCLUSIVE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003512 if (chs == 2 &&
Takashi Iwai0ba21762007-04-16 11:29:14 +02003513 snd_hda_is_supported_format(codec, mout->dig_out_nid,
3514 format) &&
3515 !(codec->spdif_status & IEC958_AES0_NONAUDIO)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003516 mout->dig_out_used = HDA_DIG_ANALOG_DUP;
Takashi Iwai6b97eb42007-04-05 14:51:48 +02003517 setup_dig_out_stream(codec, mout->dig_out_nid,
3518 stream_tag, format);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003519 } else {
3520 mout->dig_out_used = 0;
Takashi Iwai2f728532008-09-25 16:32:41 +02003521 cleanup_dig_out_stream(codec, mout->dig_out_nid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003522 }
3523 }
Ingo Molnar62932df2006-01-16 16:34:20 +01003524 mutex_unlock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003525
3526 /* front */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003527 snd_hda_codec_setup_stream(codec, nids[HDA_FRONT], stream_tag,
3528 0, format);
Takashi Iwaid29240c2007-10-26 12:35:56 +02003529 if (!mout->no_share_stream &&
3530 mout->hp_nid && mout->hp_nid != nids[HDA_FRONT])
Linus Torvalds1da177e2005-04-16 15:20:36 -07003531 /* headphone out will just decode front left/right (stereo) */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003532 snd_hda_codec_setup_stream(codec, mout->hp_nid, stream_tag,
3533 0, format);
Takashi Iwai82bc9552006-03-21 11:24:42 +01003534 /* extra outputs copied from front */
3535 for (i = 0; i < ARRAY_SIZE(mout->extra_out_nid); i++)
Takashi Iwaid29240c2007-10-26 12:35:56 +02003536 if (!mout->no_share_stream && mout->extra_out_nid[i])
Takashi Iwai82bc9552006-03-21 11:24:42 +01003537 snd_hda_codec_setup_stream(codec,
3538 mout->extra_out_nid[i],
3539 stream_tag, 0, format);
3540
Linus Torvalds1da177e2005-04-16 15:20:36 -07003541 /* surrounds */
3542 for (i = 1; i < mout->num_dacs; i++) {
Takashi Iwai4b3acaf2005-06-10 19:48:10 +02003543 if (chs >= (i + 1) * 2) /* independent out */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003544 snd_hda_codec_setup_stream(codec, nids[i], stream_tag,
3545 i * 2, format);
Takashi Iwaid29240c2007-10-26 12:35:56 +02003546 else if (!mout->no_share_stream) /* copy front */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003547 snd_hda_codec_setup_stream(codec, nids[i], stream_tag,
3548 0, format);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003549 }
3550 return 0;
3551}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003552EXPORT_SYMBOL_HDA(snd_hda_multi_out_analog_prepare);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003553
3554/*
3555 * clean up the setting for analog out
3556 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003557int snd_hda_multi_out_analog_cleanup(struct hda_codec *codec,
3558 struct hda_multi_out *mout)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003559{
3560 hda_nid_t *nids = mout->dac_nids;
3561 int i;
3562
3563 for (i = 0; i < mout->num_dacs; i++)
Takashi Iwai888afa12008-03-18 09:57:50 +01003564 snd_hda_codec_cleanup_stream(codec, nids[i]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003565 if (mout->hp_nid)
Takashi Iwai888afa12008-03-18 09:57:50 +01003566 snd_hda_codec_cleanup_stream(codec, mout->hp_nid);
Takashi Iwai82bc9552006-03-21 11:24:42 +01003567 for (i = 0; i < ARRAY_SIZE(mout->extra_out_nid); i++)
3568 if (mout->extra_out_nid[i])
Takashi Iwai888afa12008-03-18 09:57:50 +01003569 snd_hda_codec_cleanup_stream(codec,
3570 mout->extra_out_nid[i]);
Ingo Molnar62932df2006-01-16 16:34:20 +01003571 mutex_lock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003572 if (mout->dig_out_nid && mout->dig_out_used == HDA_DIG_ANALOG_DUP) {
Takashi Iwai2f728532008-09-25 16:32:41 +02003573 cleanup_dig_out_stream(codec, mout->dig_out_nid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003574 mout->dig_out_used = 0;
3575 }
Ingo Molnar62932df2006-01-16 16:34:20 +01003576 mutex_unlock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003577 return 0;
3578}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003579EXPORT_SYMBOL_HDA(snd_hda_multi_out_analog_cleanup);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003580
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003581/*
Wu Fengguang6b345002008-10-07 14:21:41 +08003582 * Helper for automatic pin configuration
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003583 */
Kailang Yangdf694da2005-12-05 19:42:22 +01003584
Takashi Iwai12f288b2007-08-02 15:51:59 +02003585static int is_in_nid_list(hda_nid_t nid, hda_nid_t *list)
Kailang Yangdf694da2005-12-05 19:42:22 +01003586{
3587 for (; *list; list++)
3588 if (*list == nid)
3589 return 1;
3590 return 0;
3591}
3592
Steve Longerbeam81937d32007-05-08 15:33:03 +02003593
3594/*
3595 * Sort an associated group of pins according to their sequence numbers.
3596 */
3597static void sort_pins_by_sequence(hda_nid_t * pins, short * sequences,
3598 int num_pins)
3599{
3600 int i, j;
3601 short seq;
3602 hda_nid_t nid;
3603
3604 for (i = 0; i < num_pins; i++) {
3605 for (j = i + 1; j < num_pins; j++) {
3606 if (sequences[i] > sequences[j]) {
3607 seq = sequences[i];
3608 sequences[i] = sequences[j];
3609 sequences[j] = seq;
3610 nid = pins[i];
3611 pins[i] = pins[j];
3612 pins[j] = nid;
3613 }
3614 }
3615 }
3616}
3617
3618
Takashi Iwai82bc9552006-03-21 11:24:42 +01003619/*
3620 * Parse all pin widgets and store the useful pin nids to cfg
3621 *
3622 * The number of line-outs or any primary output is stored in line_outs,
3623 * and the corresponding output pins are assigned to line_out_pins[],
3624 * in the order of front, rear, CLFE, side, ...
3625 *
3626 * If more extra outputs (speaker and headphone) are found, the pins are
Takashi Iwaieb06ed82006-09-20 17:10:27 +02003627 * assisnged to hp_pins[] and speaker_pins[], respectively. If no line-out jack
Takashi Iwai82bc9552006-03-21 11:24:42 +01003628 * is detected, one of speaker of HP pins is assigned as the primary
3629 * output, i.e. to line_out_pins[0]. So, line_outs is always positive
3630 * if any analog output exists.
3631 *
3632 * The analog input pins are assigned to input_pins array.
3633 * The digital input/output pins are assigned to dig_in_pin and dig_out_pin,
3634 * respectively.
3635 */
Takashi Iwai12f288b2007-08-02 15:51:59 +02003636int snd_hda_parse_pin_def_config(struct hda_codec *codec,
3637 struct auto_pin_cfg *cfg,
3638 hda_nid_t *ignore_nids)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003639{
Takashi Iwai0ef6ce72008-01-22 15:35:37 +01003640 hda_nid_t nid, end_nid;
Steve Longerbeam81937d32007-05-08 15:33:03 +02003641 short seq, assoc_line_out, assoc_speaker;
3642 short sequences_line_out[ARRAY_SIZE(cfg->line_out_pins)];
3643 short sequences_speaker[ARRAY_SIZE(cfg->speaker_pins)];
Takashi Iwaif889fa92007-10-31 15:49:32 +01003644 short sequences_hp[ARRAY_SIZE(cfg->hp_pins)];
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003645
3646 memset(cfg, 0, sizeof(*cfg));
3647
Steve Longerbeam81937d32007-05-08 15:33:03 +02003648 memset(sequences_line_out, 0, sizeof(sequences_line_out));
3649 memset(sequences_speaker, 0, sizeof(sequences_speaker));
Takashi Iwaif889fa92007-10-31 15:49:32 +01003650 memset(sequences_hp, 0, sizeof(sequences_hp));
Steve Longerbeam81937d32007-05-08 15:33:03 +02003651 assoc_line_out = assoc_speaker = 0;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003652
Takashi Iwai0ef6ce72008-01-22 15:35:37 +01003653 end_nid = codec->start_nid + codec->num_nodes;
3654 for (nid = codec->start_nid; nid < end_nid; nid++) {
Takashi Iwai54d17402005-11-21 16:33:22 +01003655 unsigned int wid_caps = get_wcaps(codec, nid);
Takashi Iwai0ba21762007-04-16 11:29:14 +02003656 unsigned int wid_type =
3657 (wid_caps & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003658 unsigned int def_conf;
3659 short assoc, loc;
3660
3661 /* read all default configuration for pin complex */
3662 if (wid_type != AC_WID_PIN)
3663 continue;
Kailang Yangdf694da2005-12-05 19:42:22 +01003664 /* ignore the given nids (e.g. pc-beep returns error) */
3665 if (ignore_nids && is_in_nid_list(nid, ignore_nids))
3666 continue;
3667
Takashi Iwaic17a1ab2009-02-23 09:28:12 +01003668 def_conf = snd_hda_codec_get_pincfg(codec, nid);
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003669 if (get_defcfg_connect(def_conf) == AC_JACK_PORT_NONE)
3670 continue;
3671 loc = get_defcfg_location(def_conf);
3672 switch (get_defcfg_device(def_conf)) {
3673 case AC_JACK_LINE_OUT:
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003674 seq = get_defcfg_sequence(def_conf);
3675 assoc = get_defcfg_association(def_conf);
Matthew Ranostay90da78b2008-01-24 11:48:01 +01003676
3677 if (!(wid_caps & AC_WCAP_STEREO))
3678 if (!cfg->mono_out_pin)
3679 cfg->mono_out_pin = nid;
Takashi Iwai0ba21762007-04-16 11:29:14 +02003680 if (!assoc)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003681 continue;
Takashi Iwai0ba21762007-04-16 11:29:14 +02003682 if (!assoc_line_out)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003683 assoc_line_out = assoc;
3684 else if (assoc_line_out != assoc)
3685 continue;
3686 if (cfg->line_outs >= ARRAY_SIZE(cfg->line_out_pins))
3687 continue;
3688 cfg->line_out_pins[cfg->line_outs] = nid;
Steve Longerbeam81937d32007-05-08 15:33:03 +02003689 sequences_line_out[cfg->line_outs] = seq;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003690 cfg->line_outs++;
3691 break;
Takashi Iwai8d88bc32005-11-17 11:09:23 +01003692 case AC_JACK_SPEAKER:
Steve Longerbeam81937d32007-05-08 15:33:03 +02003693 seq = get_defcfg_sequence(def_conf);
3694 assoc = get_defcfg_association(def_conf);
3695 if (! assoc)
3696 continue;
3697 if (! assoc_speaker)
3698 assoc_speaker = assoc;
3699 else if (assoc_speaker != assoc)
3700 continue;
Takashi Iwai82bc9552006-03-21 11:24:42 +01003701 if (cfg->speaker_outs >= ARRAY_SIZE(cfg->speaker_pins))
3702 continue;
3703 cfg->speaker_pins[cfg->speaker_outs] = nid;
Steve Longerbeam81937d32007-05-08 15:33:03 +02003704 sequences_speaker[cfg->speaker_outs] = seq;
Takashi Iwai82bc9552006-03-21 11:24:42 +01003705 cfg->speaker_outs++;
Takashi Iwai8d88bc32005-11-17 11:09:23 +01003706 break;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003707 case AC_JACK_HP_OUT:
Takashi Iwaif889fa92007-10-31 15:49:32 +01003708 seq = get_defcfg_sequence(def_conf);
3709 assoc = get_defcfg_association(def_conf);
Takashi Iwaieb06ed82006-09-20 17:10:27 +02003710 if (cfg->hp_outs >= ARRAY_SIZE(cfg->hp_pins))
3711 continue;
3712 cfg->hp_pins[cfg->hp_outs] = nid;
Takashi Iwaif889fa92007-10-31 15:49:32 +01003713 sequences_hp[cfg->hp_outs] = (assoc << 4) | seq;
Takashi Iwaieb06ed82006-09-20 17:10:27 +02003714 cfg->hp_outs++;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003715 break;
Takashi Iwai314634b2006-09-21 11:56:18 +02003716 case AC_JACK_MIC_IN: {
3717 int preferred, alt;
3718 if (loc == AC_JACK_LOC_FRONT) {
3719 preferred = AUTO_PIN_FRONT_MIC;
3720 alt = AUTO_PIN_MIC;
3721 } else {
3722 preferred = AUTO_PIN_MIC;
3723 alt = AUTO_PIN_FRONT_MIC;
3724 }
3725 if (!cfg->input_pins[preferred])
3726 cfg->input_pins[preferred] = nid;
3727 else if (!cfg->input_pins[alt])
3728 cfg->input_pins[alt] = nid;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003729 break;
Takashi Iwai314634b2006-09-21 11:56:18 +02003730 }
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003731 case AC_JACK_LINE_IN:
3732 if (loc == AC_JACK_LOC_FRONT)
3733 cfg->input_pins[AUTO_PIN_FRONT_LINE] = nid;
3734 else
3735 cfg->input_pins[AUTO_PIN_LINE] = nid;
3736 break;
3737 case AC_JACK_CD:
3738 cfg->input_pins[AUTO_PIN_CD] = nid;
3739 break;
3740 case AC_JACK_AUX:
3741 cfg->input_pins[AUTO_PIN_AUX] = nid;
3742 break;
3743 case AC_JACK_SPDIF_OUT:
Takashi Iwai1b52ae72009-01-20 17:17:29 +01003744 case AC_JACK_DIG_OTHER_OUT:
Takashi Iwai0852d7a2009-02-11 11:35:15 +01003745 if (cfg->dig_outs >= ARRAY_SIZE(cfg->dig_out_pins))
3746 continue;
3747 cfg->dig_out_pins[cfg->dig_outs] = nid;
3748 cfg->dig_out_type[cfg->dig_outs] =
3749 (loc == AC_JACK_LOC_HDMI) ?
3750 HDA_PCM_TYPE_HDMI : HDA_PCM_TYPE_SPDIF;
3751 cfg->dig_outs++;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003752 break;
3753 case AC_JACK_SPDIF_IN:
Takashi Iwai1b52ae72009-01-20 17:17:29 +01003754 case AC_JACK_DIG_OTHER_IN:
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003755 cfg->dig_in_pin = nid;
Takashi Iwai2297bd62009-01-20 18:24:13 +01003756 if (loc == AC_JACK_LOC_HDMI)
3757 cfg->dig_in_type = HDA_PCM_TYPE_HDMI;
3758 else
3759 cfg->dig_in_type = HDA_PCM_TYPE_SPDIF;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003760 break;
3761 }
3762 }
3763
Takashi Iwai5832fcf2008-02-12 18:30:12 +01003764 /* FIX-UP:
3765 * If no line-out is defined but multiple HPs are found,
3766 * some of them might be the real line-outs.
3767 */
3768 if (!cfg->line_outs && cfg->hp_outs > 1) {
3769 int i = 0;
3770 while (i < cfg->hp_outs) {
3771 /* The real HPs should have the sequence 0x0f */
3772 if ((sequences_hp[i] & 0x0f) == 0x0f) {
3773 i++;
3774 continue;
3775 }
3776 /* Move it to the line-out table */
3777 cfg->line_out_pins[cfg->line_outs] = cfg->hp_pins[i];
3778 sequences_line_out[cfg->line_outs] = sequences_hp[i];
3779 cfg->line_outs++;
3780 cfg->hp_outs--;
3781 memmove(cfg->hp_pins + i, cfg->hp_pins + i + 1,
3782 sizeof(cfg->hp_pins[0]) * (cfg->hp_outs - i));
3783 memmove(sequences_hp + i - 1, sequences_hp + i,
3784 sizeof(sequences_hp[0]) * (cfg->hp_outs - i));
3785 }
3786 }
3787
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003788 /* sort by sequence */
Steve Longerbeam81937d32007-05-08 15:33:03 +02003789 sort_pins_by_sequence(cfg->line_out_pins, sequences_line_out,
3790 cfg->line_outs);
3791 sort_pins_by_sequence(cfg->speaker_pins, sequences_speaker,
3792 cfg->speaker_outs);
Takashi Iwaif889fa92007-10-31 15:49:32 +01003793 sort_pins_by_sequence(cfg->hp_pins, sequences_hp,
3794 cfg->hp_outs);
Steve Longerbeam81937d32007-05-08 15:33:03 +02003795
Takashi Iwaif889fa92007-10-31 15:49:32 +01003796 /* if we have only one mic, make it AUTO_PIN_MIC */
3797 if (!cfg->input_pins[AUTO_PIN_MIC] &&
3798 cfg->input_pins[AUTO_PIN_FRONT_MIC]) {
3799 cfg->input_pins[AUTO_PIN_MIC] =
3800 cfg->input_pins[AUTO_PIN_FRONT_MIC];
3801 cfg->input_pins[AUTO_PIN_FRONT_MIC] = 0;
3802 }
3803 /* ditto for line-in */
3804 if (!cfg->input_pins[AUTO_PIN_LINE] &&
3805 cfg->input_pins[AUTO_PIN_FRONT_LINE]) {
3806 cfg->input_pins[AUTO_PIN_LINE] =
3807 cfg->input_pins[AUTO_PIN_FRONT_LINE];
3808 cfg->input_pins[AUTO_PIN_FRONT_LINE] = 0;
3809 }
3810
Steve Longerbeam81937d32007-05-08 15:33:03 +02003811 /*
3812 * FIX-UP: if no line-outs are detected, try to use speaker or HP pin
3813 * as a primary output
3814 */
3815 if (!cfg->line_outs) {
3816 if (cfg->speaker_outs) {
3817 cfg->line_outs = cfg->speaker_outs;
3818 memcpy(cfg->line_out_pins, cfg->speaker_pins,
3819 sizeof(cfg->speaker_pins));
3820 cfg->speaker_outs = 0;
3821 memset(cfg->speaker_pins, 0, sizeof(cfg->speaker_pins));
3822 cfg->line_out_type = AUTO_PIN_SPEAKER_OUT;
3823 } else if (cfg->hp_outs) {
3824 cfg->line_outs = cfg->hp_outs;
3825 memcpy(cfg->line_out_pins, cfg->hp_pins,
3826 sizeof(cfg->hp_pins));
3827 cfg->hp_outs = 0;
3828 memset(cfg->hp_pins, 0, sizeof(cfg->hp_pins));
3829 cfg->line_out_type = AUTO_PIN_HP_OUT;
3830 }
3831 }
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003832
Takashi Iwaicb8e2f82005-07-29 11:54:32 +02003833 /* Reorder the surround channels
3834 * ALSA sequence is front/surr/clfe/side
3835 * HDA sequence is:
3836 * 4-ch: front/surr => OK as it is
3837 * 6-ch: front/clfe/surr
Takashi Iwai9422db42007-04-20 16:11:43 +02003838 * 8-ch: front/clfe/rear/side|fc
Takashi Iwaicb8e2f82005-07-29 11:54:32 +02003839 */
3840 switch (cfg->line_outs) {
3841 case 3:
Takashi Iwaicb8e2f82005-07-29 11:54:32 +02003842 case 4:
3843 nid = cfg->line_out_pins[1];
Takashi Iwai9422db42007-04-20 16:11:43 +02003844 cfg->line_out_pins[1] = cfg->line_out_pins[2];
Takashi Iwaicb8e2f82005-07-29 11:54:32 +02003845 cfg->line_out_pins[2] = nid;
3846 break;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003847 }
3848
Takashi Iwai82bc9552006-03-21 11:24:42 +01003849 /*
3850 * debug prints of the parsed results
3851 */
3852 snd_printd("autoconfig: line_outs=%d (0x%x/0x%x/0x%x/0x%x/0x%x)\n",
3853 cfg->line_outs, cfg->line_out_pins[0], cfg->line_out_pins[1],
3854 cfg->line_out_pins[2], cfg->line_out_pins[3],
3855 cfg->line_out_pins[4]);
3856 snd_printd(" speaker_outs=%d (0x%x/0x%x/0x%x/0x%x/0x%x)\n",
3857 cfg->speaker_outs, cfg->speaker_pins[0],
3858 cfg->speaker_pins[1], cfg->speaker_pins[2],
3859 cfg->speaker_pins[3], cfg->speaker_pins[4]);
Takashi Iwaieb06ed82006-09-20 17:10:27 +02003860 snd_printd(" hp_outs=%d (0x%x/0x%x/0x%x/0x%x/0x%x)\n",
3861 cfg->hp_outs, cfg->hp_pins[0],
3862 cfg->hp_pins[1], cfg->hp_pins[2],
3863 cfg->hp_pins[3], cfg->hp_pins[4]);
Matthew Ranostay90da78b2008-01-24 11:48:01 +01003864 snd_printd(" mono: mono_out=0x%x\n", cfg->mono_out_pin);
Takashi Iwai0852d7a2009-02-11 11:35:15 +01003865 if (cfg->dig_outs)
3866 snd_printd(" dig-out=0x%x/0x%x\n",
3867 cfg->dig_out_pins[0], cfg->dig_out_pins[1]);
Takashi Iwai82bc9552006-03-21 11:24:42 +01003868 snd_printd(" inputs: mic=0x%x, fmic=0x%x, line=0x%x, fline=0x%x,"
3869 " cd=0x%x, aux=0x%x\n",
3870 cfg->input_pins[AUTO_PIN_MIC],
3871 cfg->input_pins[AUTO_PIN_FRONT_MIC],
3872 cfg->input_pins[AUTO_PIN_LINE],
3873 cfg->input_pins[AUTO_PIN_FRONT_LINE],
3874 cfg->input_pins[AUTO_PIN_CD],
3875 cfg->input_pins[AUTO_PIN_AUX]);
Takashi Iwai32d2c7f2009-02-11 11:33:13 +01003876 if (cfg->dig_in_pin)
Takashi Iwai89ce9e82009-01-20 17:15:57 +01003877 snd_printd(" dig-in=0x%x\n", cfg->dig_in_pin);
Takashi Iwai82bc9552006-03-21 11:24:42 +01003878
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003879 return 0;
3880}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003881EXPORT_SYMBOL_HDA(snd_hda_parse_pin_def_config);
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003882
Takashi Iwai4a471b72005-12-07 13:56:29 +01003883/* labels for input pins */
3884const char *auto_pin_cfg_labels[AUTO_PIN_LAST] = {
3885 "Mic", "Front Mic", "Line", "Front Line", "CD", "Aux"
3886};
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003887EXPORT_SYMBOL_HDA(auto_pin_cfg_labels);
Takashi Iwai4a471b72005-12-07 13:56:29 +01003888
3889
Linus Torvalds1da177e2005-04-16 15:20:36 -07003890#ifdef CONFIG_PM
3891/*
3892 * power management
3893 */
3894
3895/**
3896 * snd_hda_suspend - suspend the codecs
3897 * @bus: the HDA bus
Linus Torvalds1da177e2005-04-16 15:20:36 -07003898 *
3899 * Returns 0 if successful.
3900 */
Takashi Iwai8dd78332009-06-02 01:16:07 +02003901int snd_hda_suspend(struct hda_bus *bus)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003902{
Takashi Iwai0ba21762007-04-16 11:29:14 +02003903 struct hda_codec *codec;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003904
Takashi Iwai0ba21762007-04-16 11:29:14 +02003905 list_for_each_entry(codec, &bus->codec_list, list) {
Takashi Iwai0b7a2e92007-08-14 15:18:26 +02003906#ifdef CONFIG_SND_HDA_POWER_SAVE
3907 if (!codec->power_on)
3908 continue;
3909#endif
Takashi Iwaicb53c622007-08-10 17:21:45 +02003910 hda_call_codec_suspend(codec);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003911 }
3912 return 0;
3913}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003914EXPORT_SYMBOL_HDA(snd_hda_suspend);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003915
3916/**
3917 * snd_hda_resume - resume the codecs
3918 * @bus: the HDA bus
Linus Torvalds1da177e2005-04-16 15:20:36 -07003919 *
3920 * Returns 0 if successful.
Takashi Iwaicb53c622007-08-10 17:21:45 +02003921 *
3922 * This fucntion is defined only when POWER_SAVE isn't set.
3923 * In the power-save mode, the codec is resumed dynamically.
Linus Torvalds1da177e2005-04-16 15:20:36 -07003924 */
3925int snd_hda_resume(struct hda_bus *bus)
3926{
Takashi Iwai0ba21762007-04-16 11:29:14 +02003927 struct hda_codec *codec;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003928
Takashi Iwai0ba21762007-04-16 11:29:14 +02003929 list_for_each_entry(codec, &bus->codec_list, list) {
Maxim Levitskyd804ad92007-09-03 15:28:04 +02003930 if (snd_hda_codec_needs_resume(codec))
3931 hda_call_codec_resume(codec);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003932 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003933 return 0;
3934}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003935EXPORT_SYMBOL_HDA(snd_hda_resume);
Takashi Iwai1289e9e2008-11-27 15:47:11 +01003936#endif /* CONFIG_PM */
Takashi Iwaib2e18592008-07-30 15:01:44 +02003937
3938/*
3939 * generic arrays
3940 */
3941
3942/* get a new element from the given array
3943 * if it exceeds the pre-allocated array size, re-allocate the array
3944 */
3945void *snd_array_new(struct snd_array *array)
3946{
3947 if (array->used >= array->alloced) {
3948 int num = array->alloced + array->alloc_align;
Takashi Iwaib910d9a2008-11-07 00:26:52 +01003949 void *nlist;
3950 if (snd_BUG_ON(num >= 4096))
3951 return NULL;
3952 nlist = kcalloc(num + 1, array->elem_size, GFP_KERNEL);
Takashi Iwaib2e18592008-07-30 15:01:44 +02003953 if (!nlist)
3954 return NULL;
3955 if (array->list) {
3956 memcpy(nlist, array->list,
3957 array->elem_size * array->alloced);
3958 kfree(array->list);
3959 }
3960 array->list = nlist;
3961 array->alloced = num;
3962 }
Takashi Iwaif43aa022008-11-10 16:24:26 +01003963 return snd_array_elem(array, array->used++);
Takashi Iwaib2e18592008-07-30 15:01:44 +02003964}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003965EXPORT_SYMBOL_HDA(snd_array_new);
Takashi Iwaib2e18592008-07-30 15:01:44 +02003966
3967/* free the given array elements */
3968void snd_array_free(struct snd_array *array)
3969{
3970 kfree(array->list);
3971 array->used = 0;
3972 array->alloced = 0;
3973 array->list = NULL;
3974}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003975EXPORT_SYMBOL_HDA(snd_array_free);
Takashi Iwaib2022262008-11-21 21:24:03 +01003976
3977/*
3978 * used by hda_proc.c and hda_eld.c
3979 */
3980void snd_print_pcm_rates(int pcm, char *buf, int buflen)
3981{
3982 static unsigned int rates[] = {
3983 8000, 11025, 16000, 22050, 32000, 44100, 48000, 88200,
3984 96000, 176400, 192000, 384000
3985 };
3986 int i, j;
3987
3988 for (i = 0, j = 0; i < ARRAY_SIZE(rates); i++)
3989 if (pcm & (1 << i))
3990 j += snprintf(buf + j, buflen - j, " %d", rates[i]);
3991
3992 buf[j] = '\0'; /* necessary when j == 0 */
3993}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003994EXPORT_SYMBOL_HDA(snd_print_pcm_rates);
Takashi Iwaib2022262008-11-21 21:24:03 +01003995
3996void snd_print_pcm_bits(int pcm, char *buf, int buflen)
3997{
3998 static unsigned int bits[] = { 8, 16, 20, 24, 32 };
3999 int i, j;
4000
4001 for (i = 0, j = 0; i < ARRAY_SIZE(bits); i++)
4002 if (pcm & (AC_SUPPCM_BITS_8 << i))
4003 j += snprintf(buf + j, buflen - j, " %d", bits[i]);
4004
4005 buf[j] = '\0'; /* necessary when j == 0 */
4006}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01004007EXPORT_SYMBOL_HDA(snd_print_pcm_bits);
Takashi Iwai1289e9e2008-11-27 15:47:11 +01004008
4009MODULE_DESCRIPTION("HDA codec core");
4010MODULE_LICENSE("GPL");