blob: 7fd2abe1129d4a08388a426f980c07a18220715c [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"
Jaroslav Kysela123c07a2009-10-21 14:48:23 +020033#include "hda_beep.h"
Takashi Iwai28073142007-07-27 18:58:06 +020034#include <sound/hda_hwdep.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070035
Linus Torvalds1da177e2005-04-16 15:20:36 -070036/*
37 * vendor / preset table
38 */
39
40struct hda_vendor_id {
41 unsigned int id;
42 const char *name;
43};
44
45/* codec vendor labels */
46static struct hda_vendor_id hda_vendor_ids[] = {
Takashi Iwaic8cd1282008-02-13 16:59:29 +010047 { 0x1002, "ATI" },
Takashi Iwaie5f14242009-07-01 18:11:44 +020048 { 0x1013, "Cirrus Logic" },
Takashi Iwaia9226252006-09-17 22:05:54 +020049 { 0x1057, "Motorola" },
Takashi Iwaic8cd1282008-02-13 16:59:29 +010050 { 0x1095, "Silicon Image" },
Takashi Iwai31117b72008-12-16 14:43:21 +010051 { 0x10de, "Nvidia" },
Takashi Iwaic8cd1282008-02-13 16:59:29 +010052 { 0x10ec, "Realtek" },
Takashi Iwai4e01f542009-04-16 08:53:34 +020053 { 0x1102, "Creative" },
Joseph Chanc577b8a2006-11-29 15:29:40 +010054 { 0x1106, "VIA" },
Matthew Ranostay7f168592007-10-18 17:38:17 +020055 { 0x111d, "IDT" },
Takashi Iwaic8cd1282008-02-13 16:59:29 +010056 { 0x11c1, "LSI" },
Takashi Iwai54b903e2005-05-15 14:30:10 +020057 { 0x11d4, "Analog Devices" },
Linus Torvalds1da177e2005-04-16 15:20:36 -070058 { 0x13f6, "C-Media" },
Takashi Iwaia9226252006-09-17 22:05:54 +020059 { 0x14f1, "Conexant" },
Takashi Iwaic8cd1282008-02-13 16:59:29 +010060 { 0x17e8, "Chrontel" },
61 { 0x1854, "LG" },
Mark Brown8199de32008-10-28 14:50:13 +000062 { 0x1aec, "Wolfson Microelectronics" },
Linus Torvalds1da177e2005-04-16 15:20:36 -070063 { 0x434d, "C-Media" },
Takashi Iwai74c61132008-12-18 09:11:33 +010064 { 0x8086, "Intel" },
Matt2f2f4252005-04-13 14:45:30 +020065 { 0x8384, "SigmaTel" },
Linus Torvalds1da177e2005-04-16 15:20:36 -070066 {} /* terminator */
67};
68
Takashi Iwai1289e9e2008-11-27 15:47:11 +010069static DEFINE_MUTEX(preset_mutex);
70static LIST_HEAD(hda_preset_tables);
71
72int snd_hda_add_codec_preset(struct hda_codec_preset_list *preset)
73{
74 mutex_lock(&preset_mutex);
75 list_add_tail(&preset->list, &hda_preset_tables);
76 mutex_unlock(&preset_mutex);
77 return 0;
78}
Takashi Iwaiff7a3262008-11-28 15:17:06 +010079EXPORT_SYMBOL_HDA(snd_hda_add_codec_preset);
Takashi Iwai1289e9e2008-11-27 15:47:11 +010080
81int snd_hda_delete_codec_preset(struct hda_codec_preset_list *preset)
82{
83 mutex_lock(&preset_mutex);
84 list_del(&preset->list);
85 mutex_unlock(&preset_mutex);
86 return 0;
87}
Takashi Iwaiff7a3262008-11-28 15:17:06 +010088EXPORT_SYMBOL_HDA(snd_hda_delete_codec_preset);
Linus Torvalds1da177e2005-04-16 15:20:36 -070089
Takashi Iwaicb53c622007-08-10 17:21:45 +020090#ifdef CONFIG_SND_HDA_POWER_SAVE
91static void hda_power_work(struct work_struct *work);
92static void hda_keep_power_on(struct hda_codec *codec);
93#else
94static inline void hda_keep_power_on(struct hda_codec *codec) {}
95#endif
96
Matthew Ranostay50a9f792008-10-25 01:05:45 -040097const char *snd_hda_get_jack_location(u32 cfg)
98{
99 static char *bases[7] = {
100 "N/A", "Rear", "Front", "Left", "Right", "Top", "Bottom",
101 };
102 static unsigned char specials_idx[] = {
103 0x07, 0x08,
104 0x17, 0x18, 0x19,
105 0x37, 0x38
106 };
107 static char *specials[] = {
108 "Rear Panel", "Drive Bar",
109 "Riser", "HDMI", "ATAPI",
110 "Mobile-In", "Mobile-Out"
111 };
112 int i;
113 cfg = (cfg & AC_DEFCFG_LOCATION) >> AC_DEFCFG_LOCATION_SHIFT;
114 if ((cfg & 0x0f) < 7)
115 return bases[cfg & 0x0f];
116 for (i = 0; i < ARRAY_SIZE(specials_idx); i++) {
117 if (cfg == specials_idx[i])
118 return specials[i];
119 }
120 return "UNKNOWN";
121}
Takashi Iwaiff7a3262008-11-28 15:17:06 +0100122EXPORT_SYMBOL_HDA(snd_hda_get_jack_location);
Matthew Ranostay50a9f792008-10-25 01:05:45 -0400123
124const char *snd_hda_get_jack_connectivity(u32 cfg)
125{
126 static char *jack_locations[4] = { "Ext", "Int", "Sep", "Oth" };
127
128 return jack_locations[(cfg >> (AC_DEFCFG_LOCATION_SHIFT + 4)) & 3];
129}
Takashi Iwaiff7a3262008-11-28 15:17:06 +0100130EXPORT_SYMBOL_HDA(snd_hda_get_jack_connectivity);
Matthew Ranostay50a9f792008-10-25 01:05:45 -0400131
132const char *snd_hda_get_jack_type(u32 cfg)
133{
134 static char *jack_types[16] = {
135 "Line Out", "Speaker", "HP Out", "CD",
136 "SPDIF Out", "Digital Out", "Modem Line", "Modem Hand",
137 "Line In", "Aux", "Mic", "Telephony",
138 "SPDIF In", "Digitial In", "Reserved", "Other"
139 };
140
141 return jack_types[(cfg & AC_DEFCFG_DEVICE)
142 >> AC_DEFCFG_DEVICE_SHIFT];
143}
Takashi Iwaiff7a3262008-11-28 15:17:06 +0100144EXPORT_SYMBOL_HDA(snd_hda_get_jack_type);
Matthew Ranostay50a9f792008-10-25 01:05:45 -0400145
Takashi Iwai33fa35e2008-11-06 16:50:40 +0100146/*
147 * Compose a 32bit command word to be sent to the HD-audio controller
148 */
149static inline unsigned int
150make_codec_cmd(struct hda_codec *codec, hda_nid_t nid, int direct,
151 unsigned int verb, unsigned int parm)
152{
153 u32 val;
154
Takashi Iwai82e1b802009-07-17 12:47:34 +0200155 if ((codec->addr & ~0xf) || (direct & ~1) || (nid & ~0x7f) ||
156 (verb & ~0xfff) || (parm & ~0xffff)) {
Wu Fengguang6430aee2009-07-17 16:49:19 +0800157 printk(KERN_ERR "hda-codec: out of range cmd %x:%x:%x:%x:%x\n",
158 codec->addr, direct, nid, verb, parm);
159 return ~0;
160 }
161
162 val = (u32)codec->addr << 28;
Takashi Iwai33fa35e2008-11-06 16:50:40 +0100163 val |= (u32)direct << 27;
164 val |= (u32)nid << 20;
165 val |= verb << 8;
166 val |= parm;
167 return val;
168}
169
Takashi Iwaiaa2936f2009-05-26 16:07:57 +0200170/*
171 * Send and receive a verb
172 */
173static int codec_exec_verb(struct hda_codec *codec, unsigned int cmd,
174 unsigned int *res)
175{
176 struct hda_bus *bus = codec->bus;
Takashi Iwai8dd78332009-06-02 01:16:07 +0200177 int err;
Takashi Iwaiaa2936f2009-05-26 16:07:57 +0200178
Wu Fengguang6430aee2009-07-17 16:49:19 +0800179 if (cmd == ~0)
180 return -1;
181
Takashi Iwaiaa2936f2009-05-26 16:07:57 +0200182 if (res)
183 *res = -1;
Takashi Iwai8dd78332009-06-02 01:16:07 +0200184 again:
Takashi Iwaiaa2936f2009-05-26 16:07:57 +0200185 snd_hda_power_up(codec);
186 mutex_lock(&bus->cmd_mutex);
Takashi Iwaiaa2936f2009-05-26 16:07:57 +0200187 err = bus->ops.command(bus, cmd);
Takashi Iwai8dd78332009-06-02 01:16:07 +0200188 if (!err && res)
Wu Fengguangdeadff12009-08-01 18:45:16 +0800189 *res = bus->ops.get_response(bus, codec->addr);
Takashi Iwaiaa2936f2009-05-26 16:07:57 +0200190 mutex_unlock(&bus->cmd_mutex);
191 snd_hda_power_down(codec);
Takashi Iwai8dd78332009-06-02 01:16:07 +0200192 if (res && *res == -1 && bus->rirb_error) {
193 if (bus->response_reset) {
194 snd_printd("hda_codec: resetting BUS due to "
195 "fatal communication error\n");
196 bus->ops.bus_reset(bus);
197 }
198 goto again;
199 }
200 /* clear reset-flag when the communication gets recovered */
201 if (!err)
202 bus->response_reset = 0;
Takashi Iwaiaa2936f2009-05-26 16:07:57 +0200203 return err;
204}
205
Linus Torvalds1da177e2005-04-16 15:20:36 -0700206/**
207 * snd_hda_codec_read - send a command and get the response
208 * @codec: the HDA codec
209 * @nid: NID to send the command
210 * @direct: direct flag
211 * @verb: the verb to send
212 * @parm: the parameter for the verb
213 *
214 * Send a single command and read the corresponding response.
215 *
216 * Returns the obtained response value, or -1 for an error.
217 */
Takashi Iwai0ba21762007-04-16 11:29:14 +0200218unsigned int snd_hda_codec_read(struct hda_codec *codec, hda_nid_t nid,
219 int direct,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700220 unsigned int verb, unsigned int parm)
221{
Takashi Iwaiaa2936f2009-05-26 16:07:57 +0200222 unsigned cmd = make_codec_cmd(codec, nid, direct, verb, parm);
223 unsigned int res;
224 codec_exec_verb(codec, cmd, &res);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700225 return res;
226}
Takashi Iwaiff7a3262008-11-28 15:17:06 +0100227EXPORT_SYMBOL_HDA(snd_hda_codec_read);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700228
229/**
230 * snd_hda_codec_write - send a single command without waiting for response
231 * @codec: the HDA codec
232 * @nid: NID to send the command
233 * @direct: direct flag
234 * @verb: the verb to send
235 * @parm: the parameter for the verb
236 *
237 * Send a single command without waiting for response.
238 *
239 * Returns 0 if successful, or a negative error code.
240 */
241int snd_hda_codec_write(struct hda_codec *codec, hda_nid_t nid, int direct,
242 unsigned int verb, unsigned int parm)
243{
Takashi Iwaiaa2936f2009-05-26 16:07:57 +0200244 unsigned int cmd = make_codec_cmd(codec, nid, direct, verb, parm);
Takashi Iwai33fa35e2008-11-06 16:50:40 +0100245 unsigned int res;
Takashi Iwaib20f3b82009-06-02 01:20:22 +0200246 return codec_exec_verb(codec, cmd,
247 codec->bus->sync_write ? &res : NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700248}
Takashi Iwaiff7a3262008-11-28 15:17:06 +0100249EXPORT_SYMBOL_HDA(snd_hda_codec_write);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700250
251/**
252 * snd_hda_sequence_write - sequence writes
253 * @codec: the HDA codec
254 * @seq: VERB array to send
255 *
256 * Send the commands sequentially from the given array.
257 * The array must be terminated with NID=0.
258 */
259void snd_hda_sequence_write(struct hda_codec *codec, const struct hda_verb *seq)
260{
261 for (; seq->nid; seq++)
262 snd_hda_codec_write(codec, seq->nid, 0, seq->verb, seq->param);
263}
Takashi Iwaiff7a3262008-11-28 15:17:06 +0100264EXPORT_SYMBOL_HDA(snd_hda_sequence_write);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700265
266/**
267 * snd_hda_get_sub_nodes - get the range of sub nodes
268 * @codec: the HDA codec
269 * @nid: NID to parse
270 * @start_id: the pointer to store the start NID
271 *
272 * Parse the NID and store the start NID of its sub-nodes.
273 * Returns the number of sub-nodes.
274 */
Takashi Iwai0ba21762007-04-16 11:29:14 +0200275int snd_hda_get_sub_nodes(struct hda_codec *codec, hda_nid_t nid,
276 hda_nid_t *start_id)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700277{
278 unsigned int parm;
279
280 parm = snd_hda_param_read(codec, nid, AC_PAR_NODE_COUNT);
Danny Tholene8a7f132007-09-11 21:41:56 +0200281 if (parm == -1)
282 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700283 *start_id = (parm >> 16) & 0x7fff;
284 return (int)(parm & 0x7fff);
285}
Takashi Iwaiff7a3262008-11-28 15:17:06 +0100286EXPORT_SYMBOL_HDA(snd_hda_get_sub_nodes);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700287
288/**
289 * snd_hda_get_connections - get connection list
290 * @codec: the HDA codec
291 * @nid: NID to parse
292 * @conn_list: connection list array
293 * @max_conns: max. number of connections to store
294 *
295 * Parses the connection list of the given widget and stores the list
296 * of NIDs.
297 *
298 * Returns the number of connections, or a negative error code.
299 */
300int snd_hda_get_connections(struct hda_codec *codec, hda_nid_t nid,
301 hda_nid_t *conn_list, int max_conns)
302{
303 unsigned int parm;
Takashi Iwai54d17402005-11-21 16:33:22 +0100304 int i, conn_len, conns;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700305 unsigned int shift, num_elems, mask;
Takashi Iwai1ba7a7c2009-07-27 12:56:26 +0200306 unsigned int wcaps;
Takashi Iwai54d17402005-11-21 16:33:22 +0100307 hda_nid_t prev_nid;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700308
Takashi Iwaida3cec32008-08-08 17:12:14 +0200309 if (snd_BUG_ON(!conn_list || max_conns <= 0))
310 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700311
Takashi Iwai1ba7a7c2009-07-27 12:56:26 +0200312 wcaps = get_wcaps(codec, nid);
313 if (!(wcaps & AC_WCAP_CONN_LIST) &&
314 get_wcaps_type(wcaps) != AC_WID_VOL_KNB) {
Jaroslav Kysela16a433d2009-07-22 16:20:40 +0200315 snd_printk(KERN_WARNING "hda_codec: "
316 "connection list not available for 0x%x\n", nid);
317 return -EINVAL;
318 }
319
Linus Torvalds1da177e2005-04-16 15:20:36 -0700320 parm = snd_hda_param_read(codec, nid, AC_PAR_CONNLIST_LEN);
321 if (parm & AC_CLIST_LONG) {
322 /* long form */
323 shift = 16;
324 num_elems = 2;
325 } else {
326 /* short form */
327 shift = 8;
328 num_elems = 4;
329 }
330 conn_len = parm & AC_CLIST_LENGTH;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700331 mask = (1 << (shift-1)) - 1;
332
Takashi Iwai0ba21762007-04-16 11:29:14 +0200333 if (!conn_len)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700334 return 0; /* no connection */
335
336 if (conn_len == 1) {
337 /* single connection */
Takashi Iwai0ba21762007-04-16 11:29:14 +0200338 parm = snd_hda_codec_read(codec, nid, 0,
339 AC_VERB_GET_CONNECT_LIST, 0);
Takashi Iwai3c6aae42009-07-10 12:52:27 +0200340 if (parm == -1 && codec->bus->rirb_error)
341 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700342 conn_list[0] = parm & mask;
343 return 1;
344 }
345
346 /* multi connection */
347 conns = 0;
Takashi Iwai54d17402005-11-21 16:33:22 +0100348 prev_nid = 0;
349 for (i = 0; i < conn_len; i++) {
350 int range_val;
351 hda_nid_t val, n;
352
Takashi Iwai3c6aae42009-07-10 12:52:27 +0200353 if (i % num_elems == 0) {
Takashi Iwai54d17402005-11-21 16:33:22 +0100354 parm = snd_hda_codec_read(codec, nid, 0,
355 AC_VERB_GET_CONNECT_LIST, i);
Takashi Iwai3c6aae42009-07-10 12:52:27 +0200356 if (parm == -1 && codec->bus->rirb_error)
357 return -EIO;
358 }
Takashi Iwai0ba21762007-04-16 11:29:14 +0200359 range_val = !!(parm & (1 << (shift-1))); /* ranges */
Takashi Iwai54d17402005-11-21 16:33:22 +0100360 val = parm & mask;
Jaroslav Kysela2e9bf242009-07-18 11:48:19 +0200361 if (val == 0) {
362 snd_printk(KERN_WARNING "hda_codec: "
363 "invalid CONNECT_LIST verb %x[%i]:%x\n",
364 nid, i, parm);
365 return 0;
366 }
Takashi Iwai54d17402005-11-21 16:33:22 +0100367 parm >>= shift;
368 if (range_val) {
369 /* ranges between the previous and this one */
Takashi Iwai0ba21762007-04-16 11:29:14 +0200370 if (!prev_nid || prev_nid >= val) {
371 snd_printk(KERN_WARNING "hda_codec: "
372 "invalid dep_range_val %x:%x\n",
373 prev_nid, val);
Takashi Iwai54d17402005-11-21 16:33:22 +0100374 continue;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700375 }
Takashi Iwai54d17402005-11-21 16:33:22 +0100376 for (n = prev_nid + 1; n <= val; n++) {
377 if (conns >= max_conns) {
Takashi Iwai0ba21762007-04-16 11:29:14 +0200378 snd_printk(KERN_ERR
379 "Too many connections\n");
Takashi Iwai54d17402005-11-21 16:33:22 +0100380 return -EINVAL;
381 }
382 conn_list[conns++] = n;
383 }
384 } else {
385 if (conns >= max_conns) {
386 snd_printk(KERN_ERR "Too many connections\n");
387 return -EINVAL;
388 }
389 conn_list[conns++] = val;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700390 }
Takashi Iwai54d17402005-11-21 16:33:22 +0100391 prev_nid = val;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700392 }
393 return conns;
394}
Takashi Iwaiff7a3262008-11-28 15:17:06 +0100395EXPORT_SYMBOL_HDA(snd_hda_get_connections);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700396
397
398/**
399 * snd_hda_queue_unsol_event - add an unsolicited event to queue
400 * @bus: the BUS
401 * @res: unsolicited event (lower 32bit of RIRB entry)
402 * @res_ex: codec addr and flags (upper 32bit or RIRB entry)
403 *
404 * Adds the given event to the queue. The events are processed in
405 * the workqueue asynchronously. Call this function in the interrupt
406 * hanlder when RIRB receives an unsolicited event.
407 *
408 * Returns 0 if successful, or a negative error code.
409 */
410int snd_hda_queue_unsol_event(struct hda_bus *bus, u32 res, u32 res_ex)
411{
412 struct hda_bus_unsolicited *unsol;
413 unsigned int wp;
414
Takashi Iwai0ba21762007-04-16 11:29:14 +0200415 unsol = bus->unsol;
416 if (!unsol)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700417 return 0;
418
419 wp = (unsol->wp + 1) % HDA_UNSOL_QUEUE_SIZE;
420 unsol->wp = wp;
421
422 wp <<= 1;
423 unsol->queue[wp] = res;
424 unsol->queue[wp + 1] = res_ex;
425
Takashi Iwai6acaed32009-01-12 10:09:24 +0100426 queue_work(bus->workq, &unsol->work);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700427
428 return 0;
429}
Takashi Iwaiff7a3262008-11-28 15:17:06 +0100430EXPORT_SYMBOL_HDA(snd_hda_queue_unsol_event);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700431
432/*
Wu Fengguang5c1d1a92008-10-07 14:17:53 +0800433 * process queued unsolicited events
Linus Torvalds1da177e2005-04-16 15:20:36 -0700434 */
David Howellsc4028952006-11-22 14:57:56 +0000435static void process_unsol_events(struct work_struct *work)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700436{
David Howellsc4028952006-11-22 14:57:56 +0000437 struct hda_bus_unsolicited *unsol =
438 container_of(work, struct hda_bus_unsolicited, work);
439 struct hda_bus *bus = unsol->bus;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700440 struct hda_codec *codec;
441 unsigned int rp, caddr, res;
442
443 while (unsol->rp != unsol->wp) {
444 rp = (unsol->rp + 1) % HDA_UNSOL_QUEUE_SIZE;
445 unsol->rp = rp;
446 rp <<= 1;
447 res = unsol->queue[rp];
448 caddr = unsol->queue[rp + 1];
Takashi Iwai0ba21762007-04-16 11:29:14 +0200449 if (!(caddr & (1 << 4))) /* no unsolicited event? */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700450 continue;
451 codec = bus->caddr_tbl[caddr & 0x0f];
452 if (codec && codec->patch_ops.unsol_event)
453 codec->patch_ops.unsol_event(codec, res);
454 }
455}
456
457/*
458 * initialize unsolicited queue
459 */
Takashi Iwai6c1f45e2008-07-30 15:01:45 +0200460static int init_unsol_queue(struct hda_bus *bus)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700461{
462 struct hda_bus_unsolicited *unsol;
463
Takashi Iwai9f146bb2005-11-17 11:07:49 +0100464 if (bus->unsol) /* already initialized */
465 return 0;
466
Takashi Iwaie560d8d2005-09-09 14:21:46 +0200467 unsol = kzalloc(sizeof(*unsol), GFP_KERNEL);
Takashi Iwai0ba21762007-04-16 11:29:14 +0200468 if (!unsol) {
469 snd_printk(KERN_ERR "hda_codec: "
470 "can't allocate unsolicited queue\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700471 return -ENOMEM;
472 }
David Howellsc4028952006-11-22 14:57:56 +0000473 INIT_WORK(&unsol->work, process_unsol_events);
474 unsol->bus = bus;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700475 bus->unsol = unsol;
476 return 0;
477}
478
479/*
480 * destructor
481 */
482static void snd_hda_codec_free(struct hda_codec *codec);
483
484static int snd_hda_bus_free(struct hda_bus *bus)
485{
Takashi Iwai0ba21762007-04-16 11:29:14 +0200486 struct hda_codec *codec, *n;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700487
Takashi Iwai0ba21762007-04-16 11:29:14 +0200488 if (!bus)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700489 return 0;
Takashi Iwai6acaed32009-01-12 10:09:24 +0100490 if (bus->workq)
491 flush_workqueue(bus->workq);
492 if (bus->unsol)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700493 kfree(bus->unsol);
Takashi Iwai0ba21762007-04-16 11:29:14 +0200494 list_for_each_entry_safe(codec, n, &bus->codec_list, list) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700495 snd_hda_codec_free(codec);
496 }
497 if (bus->ops.private_free)
498 bus->ops.private_free(bus);
Takashi Iwai6acaed32009-01-12 10:09:24 +0100499 if (bus->workq)
500 destroy_workqueue(bus->workq);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700501 kfree(bus);
502 return 0;
503}
504
Takashi Iwaic8b6bf92005-11-17 14:57:47 +0100505static int snd_hda_bus_dev_free(struct snd_device *device)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700506{
507 struct hda_bus *bus = device->device_data;
Takashi Iwaib94d35392008-11-21 09:08:06 +0100508 bus->shutdown = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700509 return snd_hda_bus_free(bus);
510}
511
Takashi Iwaid7ffba12008-07-30 15:01:46 +0200512#ifdef CONFIG_SND_HDA_HWDEP
513static int snd_hda_bus_dev_register(struct snd_device *device)
514{
515 struct hda_bus *bus = device->device_data;
516 struct hda_codec *codec;
517 list_for_each_entry(codec, &bus->codec_list, list) {
518 snd_hda_hwdep_add_sysfs(codec);
Takashi Iwaia2f63092009-11-11 09:34:25 +0100519 snd_hda_hwdep_add_power_sysfs(codec);
Takashi Iwaid7ffba12008-07-30 15:01:46 +0200520 }
521 return 0;
522}
523#else
524#define snd_hda_bus_dev_register NULL
525#endif
526
Linus Torvalds1da177e2005-04-16 15:20:36 -0700527/**
528 * snd_hda_bus_new - create a HDA bus
529 * @card: the card entry
530 * @temp: the template for hda_bus information
531 * @busp: the pointer to store the created bus instance
532 *
533 * Returns 0 if successful, or a negative error code.
534 */
Takashi Iwai1289e9e2008-11-27 15:47:11 +0100535int /*__devinit*/ snd_hda_bus_new(struct snd_card *card,
Takashi Iwai756e2b02007-04-16 11:27:07 +0200536 const struct hda_bus_template *temp,
537 struct hda_bus **busp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700538{
539 struct hda_bus *bus;
540 int err;
Takashi Iwaic8b6bf92005-11-17 14:57:47 +0100541 static struct snd_device_ops dev_ops = {
Takashi Iwaid7ffba12008-07-30 15:01:46 +0200542 .dev_register = snd_hda_bus_dev_register,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700543 .dev_free = snd_hda_bus_dev_free,
544 };
545
Takashi Iwaida3cec32008-08-08 17:12:14 +0200546 if (snd_BUG_ON(!temp))
547 return -EINVAL;
548 if (snd_BUG_ON(!temp->ops.command || !temp->ops.get_response))
549 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700550
551 if (busp)
552 *busp = NULL;
553
Takashi Iwaie560d8d2005-09-09 14:21:46 +0200554 bus = kzalloc(sizeof(*bus), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700555 if (bus == NULL) {
556 snd_printk(KERN_ERR "can't allocate struct hda_bus\n");
557 return -ENOMEM;
558 }
559
560 bus->card = card;
561 bus->private_data = temp->private_data;
562 bus->pci = temp->pci;
563 bus->modelname = temp->modelname;
Takashi Iwaifee2fba2008-11-27 12:43:28 +0100564 bus->power_save = temp->power_save;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700565 bus->ops = temp->ops;
566
Ingo Molnar62932df2006-01-16 16:34:20 +0100567 mutex_init(&bus->cmd_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700568 INIT_LIST_HEAD(&bus->codec_list);
569
Takashi Iwaie8c0ee52009-02-05 07:34:28 +0100570 snprintf(bus->workq_name, sizeof(bus->workq_name),
571 "hd-audio%d", card->number);
572 bus->workq = create_singlethread_workqueue(bus->workq_name);
Takashi Iwai6acaed32009-01-12 10:09:24 +0100573 if (!bus->workq) {
Takashi Iwaie8c0ee52009-02-05 07:34:28 +0100574 snd_printk(KERN_ERR "cannot create workqueue %s\n",
575 bus->workq_name);
Takashi Iwai6acaed32009-01-12 10:09:24 +0100576 kfree(bus);
577 return -ENOMEM;
578 }
579
Takashi Iwai0ba21762007-04-16 11:29:14 +0200580 err = snd_device_new(card, SNDRV_DEV_BUS, bus, &dev_ops);
581 if (err < 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700582 snd_hda_bus_free(bus);
583 return err;
584 }
585 if (busp)
586 *busp = bus;
587 return 0;
588}
Takashi Iwaiff7a3262008-11-28 15:17:06 +0100589EXPORT_SYMBOL_HDA(snd_hda_bus_new);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700590
Takashi Iwai82467612007-07-27 19:15:54 +0200591#ifdef CONFIG_SND_HDA_GENERIC
592#define is_generic_config(codec) \
Takashi Iwaif44ac832008-07-30 15:01:45 +0200593 (codec->modelname && !strcmp(codec->modelname, "generic"))
Takashi Iwai82467612007-07-27 19:15:54 +0200594#else
595#define is_generic_config(codec) 0
596#endif
597
Takashi Iwai645f10c2008-11-28 15:07:37 +0100598#ifdef MODULE
Takashi Iwai1289e9e2008-11-27 15:47:11 +0100599#define HDA_MODREQ_MAX_COUNT 2 /* two request_modules()'s */
600#else
Takashi Iwai645f10c2008-11-28 15:07:37 +0100601#define HDA_MODREQ_MAX_COUNT 0 /* all presets are statically linked */
Takashi Iwai1289e9e2008-11-27 15:47:11 +0100602#endif
603
Linus Torvalds1da177e2005-04-16 15:20:36 -0700604/*
605 * find a matching codec preset
606 */
Takashi Iwai6c1f45e2008-07-30 15:01:45 +0200607static const struct hda_codec_preset *
Takashi Iwai756e2b02007-04-16 11:27:07 +0200608find_codec_preset(struct hda_codec *codec)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700609{
Takashi Iwai1289e9e2008-11-27 15:47:11 +0100610 struct hda_codec_preset_list *tbl;
611 const struct hda_codec_preset *preset;
612 int mod_requested = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700613
Takashi Iwai82467612007-07-27 19:15:54 +0200614 if (is_generic_config(codec))
Takashi Iwaid5ad6302007-03-07 15:55:59 +0100615 return NULL; /* use the generic parser */
616
Takashi Iwai1289e9e2008-11-27 15:47:11 +0100617 again:
618 mutex_lock(&preset_mutex);
619 list_for_each_entry(tbl, &hda_preset_tables, list) {
620 if (!try_module_get(tbl->owner)) {
621 snd_printk(KERN_ERR "hda_codec: cannot module_get\n");
622 continue;
623 }
624 for (preset = tbl->preset; preset->id; preset++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700625 u32 mask = preset->mask;
Marc Boucherca7cfae2008-01-22 15:32:25 +0100626 if (preset->afg && preset->afg != codec->afg)
627 continue;
628 if (preset->mfg && preset->mfg != codec->mfg)
629 continue;
Takashi Iwai0ba21762007-04-16 11:29:14 +0200630 if (!mask)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700631 mask = ~0;
Takashi Iwai9c7f8522006-06-28 15:08:22 +0200632 if (preset->id == (codec->vendor_id & mask) &&
Takashi Iwai0ba21762007-04-16 11:29:14 +0200633 (!preset->rev ||
Takashi Iwai1289e9e2008-11-27 15:47:11 +0100634 preset->rev == codec->revision_id)) {
635 mutex_unlock(&preset_mutex);
636 codec->owner = tbl->owner;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700637 return preset;
Takashi Iwai1289e9e2008-11-27 15:47:11 +0100638 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700639 }
Takashi Iwai1289e9e2008-11-27 15:47:11 +0100640 module_put(tbl->owner);
641 }
642 mutex_unlock(&preset_mutex);
643
644 if (mod_requested < HDA_MODREQ_MAX_COUNT) {
645 char name[32];
646 if (!mod_requested)
647 snprintf(name, sizeof(name), "snd-hda-codec-id:%08x",
648 codec->vendor_id);
649 else
650 snprintf(name, sizeof(name), "snd-hda-codec-id:%04x*",
651 (codec->vendor_id >> 16) & 0xffff);
652 request_module(name);
653 mod_requested++;
654 goto again;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700655 }
656 return NULL;
657}
658
659/*
Takashi Iwaif44ac832008-07-30 15:01:45 +0200660 * get_codec_name - store the codec name
Linus Torvalds1da177e2005-04-16 15:20:36 -0700661 */
Takashi Iwaif44ac832008-07-30 15:01:45 +0200662static int get_codec_name(struct hda_codec *codec)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700663{
664 const struct hda_vendor_id *c;
665 const char *vendor = NULL;
666 u16 vendor_id = codec->vendor_id >> 16;
Takashi Iwai812a2cc2009-05-16 10:00:49 +0200667 char tmp[16];
668
669 if (codec->vendor_name)
670 goto get_chip_name;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700671
672 for (c = hda_vendor_ids; c->id; c++) {
673 if (c->id == vendor_id) {
674 vendor = c->name;
675 break;
676 }
677 }
Takashi Iwai0ba21762007-04-16 11:29:14 +0200678 if (!vendor) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700679 sprintf(tmp, "Generic %04x", vendor_id);
680 vendor = tmp;
681 }
Takashi Iwai812a2cc2009-05-16 10:00:49 +0200682 codec->vendor_name = kstrdup(vendor, GFP_KERNEL);
683 if (!codec->vendor_name)
684 return -ENOMEM;
685
686 get_chip_name:
687 if (codec->chip_name)
688 return 0;
689
Linus Torvalds1da177e2005-04-16 15:20:36 -0700690 if (codec->preset && codec->preset->name)
Takashi Iwai812a2cc2009-05-16 10:00:49 +0200691 codec->chip_name = kstrdup(codec->preset->name, GFP_KERNEL);
692 else {
693 sprintf(tmp, "ID %x", codec->vendor_id & 0xffff);
694 codec->chip_name = kstrdup(tmp, GFP_KERNEL);
695 }
696 if (!codec->chip_name)
Takashi Iwaif44ac832008-07-30 15:01:45 +0200697 return -ENOMEM;
698 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700699}
700
701/*
Sasha Khapyorsky673b6832005-08-11 11:00:16 +0200702 * look for an AFG and MFG nodes
Linus Torvalds1da177e2005-04-16 15:20:36 -0700703 */
Takashi Iwai1289e9e2008-11-27 15:47:11 +0100704static void /*__devinit*/ setup_fg_nodes(struct hda_codec *codec)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700705{
Takashi Iwai93e82ae2009-04-17 18:04:41 +0200706 int i, total_nodes, function_id;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700707 hda_nid_t nid;
708
709 total_nodes = snd_hda_get_sub_nodes(codec, AC_NODE_ROOT, &nid);
710 for (i = 0; i < total_nodes; i++, nid++) {
Takashi Iwai93e82ae2009-04-17 18:04:41 +0200711 function_id = snd_hda_param_read(codec, nid,
Pascal de Bruijn234b4342009-03-23 11:15:59 +0100712 AC_PAR_FUNCTION_TYPE) & 0xff;
Takashi Iwai93e82ae2009-04-17 18:04:41 +0200713 switch (function_id) {
Sasha Khapyorsky673b6832005-08-11 11:00:16 +0200714 case AC_GRP_AUDIO_FUNCTION:
715 codec->afg = nid;
Takashi Iwai93e82ae2009-04-17 18:04:41 +0200716 codec->function_id = function_id;
Sasha Khapyorsky673b6832005-08-11 11:00:16 +0200717 break;
718 case AC_GRP_MODEM_FUNCTION:
719 codec->mfg = nid;
Takashi Iwai93e82ae2009-04-17 18:04:41 +0200720 codec->function_id = function_id;
Sasha Khapyorsky673b6832005-08-11 11:00:16 +0200721 break;
722 default:
723 break;
724 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700725 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700726}
727
728/*
Takashi Iwai54d17402005-11-21 16:33:22 +0100729 * read widget caps for each widget and store in cache
730 */
731static int read_widget_caps(struct hda_codec *codec, hda_nid_t fg_node)
732{
733 int i;
734 hda_nid_t nid;
735
736 codec->num_nodes = snd_hda_get_sub_nodes(codec, fg_node,
737 &codec->start_nid);
738 codec->wcaps = kmalloc(codec->num_nodes * 4, GFP_KERNEL);
Takashi Iwai0ba21762007-04-16 11:29:14 +0200739 if (!codec->wcaps)
Takashi Iwai54d17402005-11-21 16:33:22 +0100740 return -ENOMEM;
741 nid = codec->start_nid;
742 for (i = 0; i < codec->num_nodes; i++, nid++)
743 codec->wcaps[i] = snd_hda_param_read(codec, nid,
744 AC_PAR_AUDIO_WIDGET_CAP);
745 return 0;
746}
747
Takashi Iwai3be14142009-02-20 14:11:16 +0100748/* read all pin default configurations and save codec->init_pins */
749static int read_pin_defaults(struct hda_codec *codec)
750{
751 int i;
752 hda_nid_t nid = codec->start_nid;
753
754 for (i = 0; i < codec->num_nodes; i++, nid++) {
755 struct hda_pincfg *pin;
756 unsigned int wcaps = get_wcaps(codec, nid);
Takashi Iwaia22d5432009-07-27 12:54:26 +0200757 unsigned int wid_type = get_wcaps_type(wcaps);
Takashi Iwai3be14142009-02-20 14:11:16 +0100758 if (wid_type != AC_WID_PIN)
759 continue;
760 pin = snd_array_new(&codec->init_pins);
761 if (!pin)
762 return -ENOMEM;
763 pin->nid = nid;
764 pin->cfg = snd_hda_codec_read(codec, nid, 0,
765 AC_VERB_GET_CONFIG_DEFAULT, 0);
766 }
767 return 0;
768}
769
770/* look up the given pin config list and return the item matching with NID */
771static struct hda_pincfg *look_up_pincfg(struct hda_codec *codec,
772 struct snd_array *array,
773 hda_nid_t nid)
774{
775 int i;
776 for (i = 0; i < array->used; i++) {
777 struct hda_pincfg *pin = snd_array_elem(array, i);
778 if (pin->nid == nid)
779 return pin;
780 }
781 return NULL;
782}
783
784/* write a config value for the given NID */
785static void set_pincfg(struct hda_codec *codec, hda_nid_t nid,
786 unsigned int cfg)
787{
788 int i;
789 for (i = 0; i < 4; i++) {
790 snd_hda_codec_write(codec, nid, 0,
791 AC_VERB_SET_CONFIG_DEFAULT_BYTES_0 + i,
792 cfg & 0xff);
793 cfg >>= 8;
794 }
795}
796
797/* set the current pin config value for the given NID.
798 * the value is cached, and read via snd_hda_codec_get_pincfg()
799 */
800int snd_hda_add_pincfg(struct hda_codec *codec, struct snd_array *list,
801 hda_nid_t nid, unsigned int cfg)
802{
803 struct hda_pincfg *pin;
Takashi Iwai5e7b8e02009-02-23 09:45:59 +0100804 unsigned int oldcfg;
Takashi Iwai3be14142009-02-20 14:11:16 +0100805
Takashi Iwai5e7b8e02009-02-23 09:45:59 +0100806 oldcfg = snd_hda_codec_get_pincfg(codec, nid);
Takashi Iwai3be14142009-02-20 14:11:16 +0100807 pin = look_up_pincfg(codec, list, nid);
808 if (!pin) {
809 pin = snd_array_new(list);
810 if (!pin)
811 return -ENOMEM;
812 pin->nid = nid;
813 }
814 pin->cfg = cfg;
Takashi Iwai5e7b8e02009-02-23 09:45:59 +0100815
816 /* change only when needed; e.g. if the pincfg is already present
817 * in user_pins[], don't write it
818 */
819 cfg = snd_hda_codec_get_pincfg(codec, nid);
820 if (oldcfg != cfg)
821 set_pincfg(codec, nid, cfg);
Takashi Iwai3be14142009-02-20 14:11:16 +0100822 return 0;
823}
824
825int snd_hda_codec_set_pincfg(struct hda_codec *codec,
826 hda_nid_t nid, unsigned int cfg)
827{
Takashi Iwai346ff702009-02-23 09:42:57 +0100828 return snd_hda_add_pincfg(codec, &codec->driver_pins, nid, cfg);
Takashi Iwai3be14142009-02-20 14:11:16 +0100829}
830EXPORT_SYMBOL_HDA(snd_hda_codec_set_pincfg);
831
832/* get the current pin config value of the given pin NID */
833unsigned int snd_hda_codec_get_pincfg(struct hda_codec *codec, hda_nid_t nid)
834{
835 struct hda_pincfg *pin;
836
Takashi Iwai3be14142009-02-20 14:11:16 +0100837#ifdef CONFIG_SND_HDA_HWDEP
Takashi Iwai346ff702009-02-23 09:42:57 +0100838 pin = look_up_pincfg(codec, &codec->user_pins, nid);
Takashi Iwai3be14142009-02-20 14:11:16 +0100839 if (pin)
840 return pin->cfg;
841#endif
Takashi Iwai5e7b8e02009-02-23 09:45:59 +0100842 pin = look_up_pincfg(codec, &codec->driver_pins, nid);
843 if (pin)
844 return pin->cfg;
Takashi Iwai3be14142009-02-20 14:11:16 +0100845 pin = look_up_pincfg(codec, &codec->init_pins, nid);
846 if (pin)
847 return pin->cfg;
848 return 0;
849}
850EXPORT_SYMBOL_HDA(snd_hda_codec_get_pincfg);
851
852/* restore all current pin configs */
853static void restore_pincfgs(struct hda_codec *codec)
854{
855 int i;
856 for (i = 0; i < codec->init_pins.used; i++) {
857 struct hda_pincfg *pin = snd_array_elem(&codec->init_pins, i);
858 set_pincfg(codec, pin->nid,
859 snd_hda_codec_get_pincfg(codec, pin->nid));
860 }
861}
Takashi Iwai54d17402005-11-21 16:33:22 +0100862
Takashi Iwai01751f52007-08-10 16:59:39 +0200863static void init_hda_cache(struct hda_cache_rec *cache,
864 unsigned int record_size);
Takashi Iwai1fcaee62007-08-23 00:01:09 +0200865static void free_hda_cache(struct hda_cache_rec *cache);
Takashi Iwai01751f52007-08-10 16:59:39 +0200866
Takashi Iwai3be14142009-02-20 14:11:16 +0100867/* restore the initial pin cfgs and release all pincfg lists */
868static void restore_init_pincfgs(struct hda_codec *codec)
869{
Takashi Iwai346ff702009-02-23 09:42:57 +0100870 /* first free driver_pins and user_pins, then call restore_pincfg
Takashi Iwai3be14142009-02-20 14:11:16 +0100871 * so that only the values in init_pins are restored
872 */
Takashi Iwai346ff702009-02-23 09:42:57 +0100873 snd_array_free(&codec->driver_pins);
Takashi Iwai3be14142009-02-20 14:11:16 +0100874#ifdef CONFIG_SND_HDA_HWDEP
Takashi Iwai346ff702009-02-23 09:42:57 +0100875 snd_array_free(&codec->user_pins);
Takashi Iwai3be14142009-02-20 14:11:16 +0100876#endif
877 restore_pincfgs(codec);
878 snd_array_free(&codec->init_pins);
879}
880
Takashi Iwai54d17402005-11-21 16:33:22 +0100881/*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700882 * codec destructor
883 */
884static void snd_hda_codec_free(struct hda_codec *codec)
885{
Takashi Iwai0ba21762007-04-16 11:29:14 +0200886 if (!codec)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700887 return;
Takashi Iwai3be14142009-02-20 14:11:16 +0100888 restore_init_pincfgs(codec);
Takashi Iwaicb53c622007-08-10 17:21:45 +0200889#ifdef CONFIG_SND_HDA_POWER_SAVE
890 cancel_delayed_work(&codec->power_work);
Takashi Iwai6acaed32009-01-12 10:09:24 +0100891 flush_workqueue(codec->bus->workq);
Takashi Iwaicb53c622007-08-10 17:21:45 +0200892#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700893 list_del(&codec->list);
Takashi Iwaid13bd412008-07-30 15:01:45 +0200894 snd_array_free(&codec->mixers);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700895 codec->bus->caddr_tbl[codec->addr] = NULL;
896 if (codec->patch_ops.free)
897 codec->patch_ops.free(codec);
Takashi Iwai1289e9e2008-11-27 15:47:11 +0100898 module_put(codec->owner);
Takashi Iwai01751f52007-08-10 16:59:39 +0200899 free_hda_cache(&codec->amp_cache);
Takashi Iwaib3ac5632007-08-10 17:03:40 +0200900 free_hda_cache(&codec->cmd_cache);
Takashi Iwai812a2cc2009-05-16 10:00:49 +0200901 kfree(codec->vendor_name);
902 kfree(codec->chip_name);
Takashi Iwaif44ac832008-07-30 15:01:45 +0200903 kfree(codec->modelname);
Takashi Iwai54d17402005-11-21 16:33:22 +0100904 kfree(codec->wcaps);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700905 kfree(codec);
906}
907
Takashi Iwaibb6ac722009-03-13 09:02:42 +0100908static void hda_set_power_state(struct hda_codec *codec, hda_nid_t fg,
909 unsigned int power_state);
910
Linus Torvalds1da177e2005-04-16 15:20:36 -0700911/**
912 * snd_hda_codec_new - create a HDA codec
913 * @bus: the bus to assign
914 * @codec_addr: the codec address
915 * @codecp: the pointer to store the generated codec
916 *
917 * Returns 0 if successful, or a negative error code.
918 */
Takashi Iwai1289e9e2008-11-27 15:47:11 +0100919int /*__devinit*/ snd_hda_codec_new(struct hda_bus *bus, unsigned int codec_addr,
Takashi Iwaia1e21c92009-06-17 09:33:52 +0200920 struct hda_codec **codecp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700921{
922 struct hda_codec *codec;
Jaroslav Kyselaba443682008-08-13 20:55:32 +0200923 char component[31];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700924 int err;
925
Takashi Iwaida3cec32008-08-08 17:12:14 +0200926 if (snd_BUG_ON(!bus))
927 return -EINVAL;
928 if (snd_BUG_ON(codec_addr > HDA_MAX_CODEC_ADDRESS))
929 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700930
931 if (bus->caddr_tbl[codec_addr]) {
Takashi Iwai0ba21762007-04-16 11:29:14 +0200932 snd_printk(KERN_ERR "hda_codec: "
933 "address 0x%x is already occupied\n", codec_addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700934 return -EBUSY;
935 }
936
Takashi Iwaie560d8d2005-09-09 14:21:46 +0200937 codec = kzalloc(sizeof(*codec), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700938 if (codec == NULL) {
939 snd_printk(KERN_ERR "can't allocate struct hda_codec\n");
940 return -ENOMEM;
941 }
942
943 codec->bus = bus;
944 codec->addr = codec_addr;
Ingo Molnar62932df2006-01-16 16:34:20 +0100945 mutex_init(&codec->spdif_mutex);
Wu Fengguang5a9e02e2009-01-09 16:45:24 +0800946 mutex_init(&codec->control_mutex);
Takashi Iwai01751f52007-08-10 16:59:39 +0200947 init_hda_cache(&codec->amp_cache, sizeof(struct hda_amp_info));
Takashi Iwaib3ac5632007-08-10 17:03:40 +0200948 init_hda_cache(&codec->cmd_cache, sizeof(struct hda_cache_head));
Takashi Iwaid13bd412008-07-30 15:01:45 +0200949 snd_array_init(&codec->mixers, sizeof(struct snd_kcontrol *), 32);
Takashi Iwai3be14142009-02-20 14:11:16 +0100950 snd_array_init(&codec->init_pins, sizeof(struct hda_pincfg), 16);
Takashi Iwai346ff702009-02-23 09:42:57 +0100951 snd_array_init(&codec->driver_pins, sizeof(struct hda_pincfg), 16);
Takashi Iwai6c1f45e2008-07-30 15:01:45 +0200952 if (codec->bus->modelname) {
953 codec->modelname = kstrdup(codec->bus->modelname, GFP_KERNEL);
954 if (!codec->modelname) {
955 snd_hda_codec_free(codec);
956 return -ENODEV;
957 }
958 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700959
Takashi Iwaicb53c622007-08-10 17:21:45 +0200960#ifdef CONFIG_SND_HDA_POWER_SAVE
961 INIT_DELAYED_WORK(&codec->power_work, hda_power_work);
962 /* snd_hda_codec_new() marks the codec as power-up, and leave it as is.
963 * the caller has to power down appropriatley after initialization
964 * phase.
965 */
966 hda_keep_power_on(codec);
967#endif
968
Linus Torvalds1da177e2005-04-16 15:20:36 -0700969 list_add_tail(&codec->list, &bus->codec_list);
970 bus->caddr_tbl[codec_addr] = codec;
971
Takashi Iwai0ba21762007-04-16 11:29:14 +0200972 codec->vendor_id = snd_hda_param_read(codec, AC_NODE_ROOT,
973 AC_PAR_VENDOR_ID);
Takashi Iwai111d3af2006-02-16 18:17:58 +0100974 if (codec->vendor_id == -1)
975 /* read again, hopefully the access method was corrected
976 * in the last read...
977 */
978 codec->vendor_id = snd_hda_param_read(codec, AC_NODE_ROOT,
979 AC_PAR_VENDOR_ID);
Takashi Iwai0ba21762007-04-16 11:29:14 +0200980 codec->subsystem_id = snd_hda_param_read(codec, AC_NODE_ROOT,
981 AC_PAR_SUBSYSTEM_ID);
982 codec->revision_id = snd_hda_param_read(codec, AC_NODE_ROOT,
983 AC_PAR_REV_ID);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700984
Sasha Khapyorsky673b6832005-08-11 11:00:16 +0200985 setup_fg_nodes(codec);
Takashi Iwai0ba21762007-04-16 11:29:14 +0200986 if (!codec->afg && !codec->mfg) {
Sasha Khapyorsky673b6832005-08-11 11:00:16 +0200987 snd_printdd("hda_codec: no AFG or MFG node found\n");
Takashi Iwai3be14142009-02-20 14:11:16 +0100988 err = -ENODEV;
989 goto error;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700990 }
991
Takashi Iwai3be14142009-02-20 14:11:16 +0100992 err = read_widget_caps(codec, codec->afg ? codec->afg : codec->mfg);
993 if (err < 0) {
Takashi Iwai54d17402005-11-21 16:33:22 +0100994 snd_printk(KERN_ERR "hda_codec: cannot malloc\n");
Takashi Iwai3be14142009-02-20 14:11:16 +0100995 goto error;
Takashi Iwai54d17402005-11-21 16:33:22 +0100996 }
Takashi Iwai3be14142009-02-20 14:11:16 +0100997 err = read_pin_defaults(codec);
998 if (err < 0)
999 goto error;
Takashi Iwai54d17402005-11-21 16:33:22 +01001000
Takashi Iwai0ba21762007-04-16 11:29:14 +02001001 if (!codec->subsystem_id) {
Takashi Iwai86284e42005-10-11 15:05:54 +02001002 hda_nid_t nid = codec->afg ? codec->afg : codec->mfg;
Takashi Iwai0ba21762007-04-16 11:29:14 +02001003 codec->subsystem_id =
1004 snd_hda_codec_read(codec, nid, 0,
1005 AC_VERB_GET_SUBSYSTEM_ID, 0);
Takashi Iwai86284e42005-10-11 15:05:54 +02001006 }
1007
Takashi Iwaibb6ac722009-03-13 09:02:42 +01001008 /* power-up all before initialization */
1009 hda_set_power_state(codec,
1010 codec->afg ? codec->afg : codec->mfg,
1011 AC_PWRST_D0);
1012
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001013 snd_hda_codec_proc_new(codec);
1014
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001015 snd_hda_create_hwdep(codec);
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001016
1017 sprintf(component, "HDA:%08x,%08x,%08x", codec->vendor_id,
1018 codec->subsystem_id, codec->revision_id);
1019 snd_component_add(codec->bus->card, component);
1020
1021 if (codecp)
1022 *codecp = codec;
1023 return 0;
Takashi Iwai3be14142009-02-20 14:11:16 +01001024
1025 error:
1026 snd_hda_codec_free(codec);
1027 return err;
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001028}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001029EXPORT_SYMBOL_HDA(snd_hda_codec_new);
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001030
1031int snd_hda_codec_configure(struct hda_codec *codec)
1032{
1033 int err;
1034
Takashi Iwaid5ad6302007-03-07 15:55:59 +01001035 codec->preset = find_codec_preset(codec);
Takashi Iwai812a2cc2009-05-16 10:00:49 +02001036 if (!codec->vendor_name || !codec->chip_name) {
Takashi Iwaif44ac832008-07-30 15:01:45 +02001037 err = get_codec_name(codec);
1038 if (err < 0)
1039 return err;
1040 }
Takashi Iwai43ea1d42007-04-26 19:12:08 +02001041 /* audio codec should override the mixer name */
Takashi Iwaif44ac832008-07-30 15:01:45 +02001042 if (codec->afg || !*codec->bus->card->mixername)
Takashi Iwai812a2cc2009-05-16 10:00:49 +02001043 snprintf(codec->bus->card->mixername,
1044 sizeof(codec->bus->card->mixername),
1045 "%s %s", codec->vendor_name, codec->chip_name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001046
Takashi Iwai82467612007-07-27 19:15:54 +02001047 if (is_generic_config(codec)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001048 err = snd_hda_parse_generic_codec(codec);
Takashi Iwai82467612007-07-27 19:15:54 +02001049 goto patched;
1050 }
Takashi Iwai82467612007-07-27 19:15:54 +02001051 if (codec->preset && codec->preset->patch) {
1052 err = codec->preset->patch(codec);
1053 goto patched;
1054 }
1055
1056 /* call the default parser */
Takashi Iwai82467612007-07-27 19:15:54 +02001057 err = snd_hda_parse_generic_codec(codec);
Takashi Iwai35a1e0c2007-10-19 08:13:40 +02001058 if (err < 0)
1059 printk(KERN_ERR "hda-codec: No codec parser is available\n");
Takashi Iwai82467612007-07-27 19:15:54 +02001060
1061 patched:
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001062 if (!err && codec->patch_ops.unsol_event)
1063 err = init_unsol_queue(codec->bus);
1064 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001065}
Takashi Iwaia1e21c92009-06-17 09:33:52 +02001066EXPORT_SYMBOL_HDA(snd_hda_codec_configure);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001067
1068/**
1069 * snd_hda_codec_setup_stream - set up the codec for streaming
1070 * @codec: the CODEC to set up
1071 * @nid: the NID to set up
1072 * @stream_tag: stream tag to pass, it's between 0x1 and 0xf.
1073 * @channel_id: channel id to pass, zero based.
1074 * @format: stream format.
1075 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02001076void snd_hda_codec_setup_stream(struct hda_codec *codec, hda_nid_t nid,
1077 u32 stream_tag,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001078 int channel_id, int format)
1079{
Takashi Iwai0ba21762007-04-16 11:29:14 +02001080 if (!nid)
Takashi Iwaid21b37e2005-04-20 13:45:55 +02001081 return;
1082
Takashi Iwai0ba21762007-04-16 11:29:14 +02001083 snd_printdd("hda_codec_setup_stream: "
1084 "NID=0x%x, stream=0x%x, channel=%d, format=0x%x\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07001085 nid, stream_tag, channel_id, format);
1086 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CHANNEL_STREAMID,
1087 (stream_tag << 4) | channel_id);
1088 msleep(1);
1089 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_STREAM_FORMAT, format);
1090}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001091EXPORT_SYMBOL_HDA(snd_hda_codec_setup_stream);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001092
Takashi Iwai888afa12008-03-18 09:57:50 +01001093void snd_hda_codec_cleanup_stream(struct hda_codec *codec, hda_nid_t nid)
1094{
1095 if (!nid)
1096 return;
1097
1098 snd_printdd("hda_codec_cleanup_stream: NID=0x%x\n", nid);
1099 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CHANNEL_STREAMID, 0);
1100#if 0 /* keep the format */
1101 msleep(1);
1102 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_STREAM_FORMAT, 0);
1103#endif
1104}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001105EXPORT_SYMBOL_HDA(snd_hda_codec_cleanup_stream);
Takashi Iwai888afa12008-03-18 09:57:50 +01001106
Linus Torvalds1da177e2005-04-16 15:20:36 -07001107/*
1108 * amp access functions
1109 */
1110
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001111/* FIXME: more better hash key? */
1112#define HDA_HASH_KEY(nid,dir,idx) (u32)((nid) + ((idx) << 16) + ((dir) << 24))
Takashi Iwai1327a322009-03-23 13:07:47 +01001113#define HDA_HASH_PINCAP_KEY(nid) (u32)((nid) + (0x02 << 24))
Takashi Iwai92c7c8a2009-03-24 07:32:14 +01001114#define HDA_HASH_PARPCM_KEY(nid) (u32)((nid) + (0x03 << 24))
1115#define HDA_HASH_PARSTR_KEY(nid) (u32)((nid) + (0x04 << 24))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001116#define INFO_AMP_CAPS (1<<0)
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001117#define INFO_AMP_VOL(ch) (1 << (1 + (ch)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001118
1119/* initialize the hash table */
Takashi Iwai1289e9e2008-11-27 15:47:11 +01001120static void /*__devinit*/ init_hda_cache(struct hda_cache_rec *cache,
Takashi Iwai01751f52007-08-10 16:59:39 +02001121 unsigned int record_size)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001122{
Takashi Iwai01751f52007-08-10 16:59:39 +02001123 memset(cache, 0, sizeof(*cache));
1124 memset(cache->hash, 0xff, sizeof(cache->hash));
Takashi Iwai603c4012008-07-30 15:01:44 +02001125 snd_array_init(&cache->buf, record_size, 64);
Takashi Iwai01751f52007-08-10 16:59:39 +02001126}
1127
Takashi Iwai1fcaee62007-08-23 00:01:09 +02001128static void free_hda_cache(struct hda_cache_rec *cache)
Takashi Iwai01751f52007-08-10 16:59:39 +02001129{
Takashi Iwai603c4012008-07-30 15:01:44 +02001130 snd_array_free(&cache->buf);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001131}
1132
1133/* query the hash. allocate an entry if not found. */
Takashi Iwai01751f52007-08-10 16:59:39 +02001134static struct hda_cache_head *get_alloc_hash(struct hda_cache_rec *cache,
1135 u32 key)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001136{
Takashi Iwai01751f52007-08-10 16:59:39 +02001137 u16 idx = key % (u16)ARRAY_SIZE(cache->hash);
1138 u16 cur = cache->hash[idx];
1139 struct hda_cache_head *info;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001140
1141 while (cur != 0xffff) {
Takashi Iwaif43aa022008-11-10 16:24:26 +01001142 info = snd_array_elem(&cache->buf, cur);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001143 if (info->key == key)
1144 return info;
1145 cur = info->next;
1146 }
1147
1148 /* add a new hash entry */
Takashi Iwai603c4012008-07-30 15:01:44 +02001149 info = snd_array_new(&cache->buf);
Takashi Iwaic2174292008-11-07 00:23:30 +01001150 if (!info)
1151 return NULL;
Takashi Iwaif43aa022008-11-10 16:24:26 +01001152 cur = snd_array_index(&cache->buf, info);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001153 info->key = key;
Takashi Iwai01751f52007-08-10 16:59:39 +02001154 info->val = 0;
1155 info->next = cache->hash[idx];
1156 cache->hash[idx] = cur;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001157
1158 return info;
1159}
1160
Takashi Iwai01751f52007-08-10 16:59:39 +02001161/* query and allocate an amp hash entry */
1162static inline struct hda_amp_info *
1163get_alloc_amp_hash(struct hda_codec *codec, u32 key)
1164{
1165 return (struct hda_amp_info *)get_alloc_hash(&codec->amp_cache, key);
1166}
1167
Linus Torvalds1da177e2005-04-16 15:20:36 -07001168/*
1169 * query AMP capabilities for the given widget and direction
1170 */
Matthew Ranostay09a99952008-01-24 11:49:21 +01001171u32 query_amp_caps(struct hda_codec *codec, hda_nid_t nid, int direction)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001172{
Takashi Iwai0ba21762007-04-16 11:29:14 +02001173 struct hda_amp_info *info;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001174
Takashi Iwai0ba21762007-04-16 11:29:14 +02001175 info = get_alloc_amp_hash(codec, HDA_HASH_KEY(nid, direction, 0));
1176 if (!info)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001177 return 0;
Takashi Iwai01751f52007-08-10 16:59:39 +02001178 if (!(info->head.val & INFO_AMP_CAPS)) {
Takashi Iwai0ba21762007-04-16 11:29:14 +02001179 if (!(get_wcaps(codec, nid) & AC_WCAP_AMP_OVRD))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001180 nid = codec->afg;
Takashi Iwai0ba21762007-04-16 11:29:14 +02001181 info->amp_caps = snd_hda_param_read(codec, nid,
1182 direction == HDA_OUTPUT ?
1183 AC_PAR_AMP_OUT_CAP :
1184 AC_PAR_AMP_IN_CAP);
Takashi Iwaib75e53f2007-05-10 16:56:09 +02001185 if (info->amp_caps)
Takashi Iwai01751f52007-08-10 16:59:39 +02001186 info->head.val |= INFO_AMP_CAPS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001187 }
1188 return info->amp_caps;
1189}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001190EXPORT_SYMBOL_HDA(query_amp_caps);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001191
Takashi Iwai897cc182007-05-29 19:01:37 +02001192int snd_hda_override_amp_caps(struct hda_codec *codec, hda_nid_t nid, int dir,
1193 unsigned int caps)
1194{
1195 struct hda_amp_info *info;
1196
1197 info = get_alloc_amp_hash(codec, HDA_HASH_KEY(nid, dir, 0));
1198 if (!info)
1199 return -EINVAL;
1200 info->amp_caps = caps;
Takashi Iwai01751f52007-08-10 16:59:39 +02001201 info->head.val |= INFO_AMP_CAPS;
Takashi Iwai897cc182007-05-29 19:01:37 +02001202 return 0;
1203}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001204EXPORT_SYMBOL_HDA(snd_hda_override_amp_caps);
Takashi Iwai897cc182007-05-29 19:01:37 +02001205
Takashi Iwai92c7c8a2009-03-24 07:32:14 +01001206static unsigned int
1207query_caps_hash(struct hda_codec *codec, hda_nid_t nid, u32 key,
1208 unsigned int (*func)(struct hda_codec *, hda_nid_t))
Takashi Iwai1327a322009-03-23 13:07:47 +01001209{
1210 struct hda_amp_info *info;
1211
Takashi Iwai92c7c8a2009-03-24 07:32:14 +01001212 info = get_alloc_amp_hash(codec, key);
Takashi Iwai1327a322009-03-23 13:07:47 +01001213 if (!info)
1214 return 0;
1215 if (!info->head.val) {
Takashi Iwai1327a322009-03-23 13:07:47 +01001216 info->head.val |= INFO_AMP_CAPS;
Takashi Iwai92c7c8a2009-03-24 07:32:14 +01001217 info->amp_caps = func(codec, nid);
Takashi Iwai1327a322009-03-23 13:07:47 +01001218 }
1219 return info->amp_caps;
1220}
Takashi Iwai92c7c8a2009-03-24 07:32:14 +01001221
1222static unsigned int read_pin_cap(struct hda_codec *codec, hda_nid_t nid)
1223{
1224 return snd_hda_param_read(codec, nid, AC_PAR_PIN_CAP);
1225}
1226
1227u32 snd_hda_query_pin_caps(struct hda_codec *codec, hda_nid_t nid)
1228{
1229 return query_caps_hash(codec, nid, HDA_HASH_PINCAP_KEY(nid),
1230 read_pin_cap);
1231}
Takashi Iwai1327a322009-03-23 13:07:47 +01001232EXPORT_SYMBOL_HDA(snd_hda_query_pin_caps);
1233
Linus Torvalds1da177e2005-04-16 15:20:36 -07001234/*
1235 * read the current volume to info
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001236 * if the cache exists, read the cache value.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001237 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02001238static unsigned int get_vol_mute(struct hda_codec *codec,
1239 struct hda_amp_info *info, hda_nid_t nid,
1240 int ch, int direction, int index)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001241{
1242 u32 val, parm;
1243
Takashi Iwai01751f52007-08-10 16:59:39 +02001244 if (info->head.val & INFO_AMP_VOL(ch))
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001245 return info->vol[ch];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001246
1247 parm = ch ? AC_AMP_GET_RIGHT : AC_AMP_GET_LEFT;
1248 parm |= direction == HDA_OUTPUT ? AC_AMP_GET_OUTPUT : AC_AMP_GET_INPUT;
1249 parm |= index;
Takashi Iwai0ba21762007-04-16 11:29:14 +02001250 val = snd_hda_codec_read(codec, nid, 0,
1251 AC_VERB_GET_AMP_GAIN_MUTE, parm);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001252 info->vol[ch] = val & 0xff;
Takashi Iwai01751f52007-08-10 16:59:39 +02001253 info->head.val |= INFO_AMP_VOL(ch);
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001254 return info->vol[ch];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001255}
1256
1257/*
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001258 * write the current volume in info to the h/w and update the cache
Linus Torvalds1da177e2005-04-16 15:20:36 -07001259 */
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001260static void put_vol_mute(struct hda_codec *codec, struct hda_amp_info *info,
Takashi Iwai0ba21762007-04-16 11:29:14 +02001261 hda_nid_t nid, int ch, int direction, int index,
1262 int val)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001263{
1264 u32 parm;
1265
1266 parm = ch ? AC_AMP_SET_RIGHT : AC_AMP_SET_LEFT;
1267 parm |= direction == HDA_OUTPUT ? AC_AMP_SET_OUTPUT : AC_AMP_SET_INPUT;
1268 parm |= index << AC_AMP_SET_INDEX_SHIFT;
1269 parm |= val;
1270 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, parm);
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001271 info->vol[ch] = val;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001272}
1273
1274/*
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001275 * read AMP value. The volume is between 0 to 0x7f, 0x80 = mute bit.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001276 */
Takashi Iwai834be882006-03-01 14:16:17 +01001277int snd_hda_codec_amp_read(struct hda_codec *codec, hda_nid_t nid, int ch,
1278 int direction, int index)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001279{
Takashi Iwai0ba21762007-04-16 11:29:14 +02001280 struct hda_amp_info *info;
1281 info = get_alloc_amp_hash(codec, HDA_HASH_KEY(nid, direction, index));
1282 if (!info)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001283 return 0;
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001284 return get_vol_mute(codec, info, nid, ch, direction, index);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001285}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001286EXPORT_SYMBOL_HDA(snd_hda_codec_amp_read);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001287
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001288/*
1289 * update the AMP value, mask = bit mask to set, val = the value
1290 */
Takashi Iwai834be882006-03-01 14:16:17 +01001291int snd_hda_codec_amp_update(struct hda_codec *codec, hda_nid_t nid, int ch,
1292 int direction, int idx, int mask, int val)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001293{
Takashi Iwai0ba21762007-04-16 11:29:14 +02001294 struct hda_amp_info *info;
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001295
Takashi Iwai0ba21762007-04-16 11:29:14 +02001296 info = get_alloc_amp_hash(codec, HDA_HASH_KEY(nid, direction, idx));
1297 if (!info)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001298 return 0;
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001299 val &= mask;
1300 val |= get_vol_mute(codec, info, nid, ch, direction, idx) & ~mask;
Takashi Iwai82beb8f2007-08-10 17:09:26 +02001301 if (info->vol[ch] == val)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001302 return 0;
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001303 put_vol_mute(codec, info, nid, ch, direction, idx, val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001304 return 1;
1305}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001306EXPORT_SYMBOL_HDA(snd_hda_codec_amp_update);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001307
Takashi Iwai47fd8302007-08-10 17:11:07 +02001308/*
1309 * update the AMP stereo with the same mask and value
1310 */
1311int snd_hda_codec_amp_stereo(struct hda_codec *codec, hda_nid_t nid,
1312 int direction, int idx, int mask, int val)
1313{
1314 int ch, ret = 0;
1315 for (ch = 0; ch < 2; ch++)
1316 ret |= snd_hda_codec_amp_update(codec, nid, ch, direction,
1317 idx, mask, val);
1318 return ret;
1319}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001320EXPORT_SYMBOL_HDA(snd_hda_codec_amp_stereo);
Takashi Iwai47fd8302007-08-10 17:11:07 +02001321
Takashi Iwaicb53c622007-08-10 17:21:45 +02001322#ifdef SND_HDA_NEEDS_RESUME
Takashi Iwaib3ac5632007-08-10 17:03:40 +02001323/* resume the all amp commands from the cache */
1324void snd_hda_codec_resume_amp(struct hda_codec *codec)
1325{
Takashi Iwai603c4012008-07-30 15:01:44 +02001326 struct hda_amp_info *buffer = codec->amp_cache.buf.list;
Takashi Iwaib3ac5632007-08-10 17:03:40 +02001327 int i;
1328
Takashi Iwai603c4012008-07-30 15:01:44 +02001329 for (i = 0; i < codec->amp_cache.buf.used; i++, buffer++) {
Takashi Iwaib3ac5632007-08-10 17:03:40 +02001330 u32 key = buffer->head.key;
1331 hda_nid_t nid;
1332 unsigned int idx, dir, ch;
1333 if (!key)
1334 continue;
1335 nid = key & 0xff;
1336 idx = (key >> 16) & 0xff;
1337 dir = (key >> 24) & 0xff;
1338 for (ch = 0; ch < 2; ch++) {
1339 if (!(buffer->head.val & INFO_AMP_VOL(ch)))
1340 continue;
1341 put_vol_mute(codec, buffer, nid, ch, dir, idx,
1342 buffer->vol[ch]);
1343 }
1344 }
1345}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001346EXPORT_SYMBOL_HDA(snd_hda_codec_resume_amp);
Takashi Iwaicb53c622007-08-10 17:21:45 +02001347#endif /* SND_HDA_NEEDS_RESUME */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001348
Linus Torvalds1da177e2005-04-16 15:20:36 -07001349/* volume */
Takashi Iwai0ba21762007-04-16 11:29:14 +02001350int snd_hda_mixer_amp_volume_info(struct snd_kcontrol *kcontrol,
1351 struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001352{
1353 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1354 u16 nid = get_amp_nid(kcontrol);
1355 u8 chs = get_amp_channels(kcontrol);
1356 int dir = get_amp_direction(kcontrol);
Takashi Iwai29fdbec2009-01-20 13:07:55 +01001357 unsigned int ofs = get_amp_offset(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001358 u32 caps;
1359
1360 caps = query_amp_caps(codec, nid, dir);
Takashi Iwai0ba21762007-04-16 11:29:14 +02001361 /* num steps */
1362 caps = (caps & AC_AMPCAP_NUM_STEPS) >> AC_AMPCAP_NUM_STEPS_SHIFT;
1363 if (!caps) {
1364 printk(KERN_WARNING "hda_codec: "
Takashi Iwai9c8f2ab2008-01-11 16:12:23 +01001365 "num_steps = 0 for NID=0x%x (ctl = %s)\n", nid,
1366 kcontrol->id.name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001367 return -EINVAL;
1368 }
Takashi Iwai29fdbec2009-01-20 13:07:55 +01001369 if (ofs < caps)
1370 caps -= ofs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001371 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
1372 uinfo->count = chs == 3 ? 2 : 1;
1373 uinfo->value.integer.min = 0;
1374 uinfo->value.integer.max = caps;
1375 return 0;
1376}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001377EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_volume_info);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001378
Takashi Iwai29fdbec2009-01-20 13:07:55 +01001379
1380static inline unsigned int
1381read_amp_value(struct hda_codec *codec, hda_nid_t nid,
1382 int ch, int dir, int idx, unsigned int ofs)
1383{
1384 unsigned int val;
1385 val = snd_hda_codec_amp_read(codec, nid, ch, dir, idx);
1386 val &= HDA_AMP_VOLMASK;
1387 if (val >= ofs)
1388 val -= ofs;
1389 else
1390 val = 0;
1391 return val;
1392}
1393
1394static inline int
1395update_amp_value(struct hda_codec *codec, hda_nid_t nid,
1396 int ch, int dir, int idx, unsigned int ofs,
1397 unsigned int val)
1398{
1399 if (val > 0)
1400 val += ofs;
1401 return snd_hda_codec_amp_update(codec, nid, ch, dir, idx,
1402 HDA_AMP_VOLMASK, val);
1403}
1404
Takashi Iwai0ba21762007-04-16 11:29:14 +02001405int snd_hda_mixer_amp_volume_get(struct snd_kcontrol *kcontrol,
1406 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001407{
1408 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1409 hda_nid_t nid = get_amp_nid(kcontrol);
1410 int chs = get_amp_channels(kcontrol);
1411 int dir = get_amp_direction(kcontrol);
1412 int idx = get_amp_index(kcontrol);
Takashi Iwai29fdbec2009-01-20 13:07:55 +01001413 unsigned int ofs = get_amp_offset(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001414 long *valp = ucontrol->value.integer.value;
1415
1416 if (chs & 1)
Takashi Iwai29fdbec2009-01-20 13:07:55 +01001417 *valp++ = read_amp_value(codec, nid, 0, dir, idx, ofs);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001418 if (chs & 2)
Takashi Iwai29fdbec2009-01-20 13:07:55 +01001419 *valp = read_amp_value(codec, nid, 1, dir, idx, ofs);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001420 return 0;
1421}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001422EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_volume_get);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001423
Takashi Iwai0ba21762007-04-16 11:29:14 +02001424int snd_hda_mixer_amp_volume_put(struct snd_kcontrol *kcontrol,
1425 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001426{
1427 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1428 hda_nid_t nid = get_amp_nid(kcontrol);
1429 int chs = get_amp_channels(kcontrol);
1430 int dir = get_amp_direction(kcontrol);
1431 int idx = get_amp_index(kcontrol);
Takashi Iwai29fdbec2009-01-20 13:07:55 +01001432 unsigned int ofs = get_amp_offset(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001433 long *valp = ucontrol->value.integer.value;
1434 int change = 0;
1435
Takashi Iwaicb53c622007-08-10 17:21:45 +02001436 snd_hda_power_up(codec);
Nicolas Grazianob9f5a892005-07-29 12:17:20 +02001437 if (chs & 1) {
Takashi Iwai29fdbec2009-01-20 13:07:55 +01001438 change = update_amp_value(codec, nid, 0, dir, idx, ofs, *valp);
Nicolas Grazianob9f5a892005-07-29 12:17:20 +02001439 valp++;
1440 }
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001441 if (chs & 2)
Takashi Iwai29fdbec2009-01-20 13:07:55 +01001442 change |= update_amp_value(codec, nid, 1, dir, idx, ofs, *valp);
Takashi Iwaicb53c622007-08-10 17:21:45 +02001443 snd_hda_power_down(codec);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001444 return change;
1445}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001446EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_volume_put);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001447
Jaroslav Kysela302e9c52006-07-05 17:39:49 +02001448int snd_hda_mixer_amp_tlv(struct snd_kcontrol *kcontrol, int op_flag,
1449 unsigned int size, unsigned int __user *_tlv)
1450{
1451 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1452 hda_nid_t nid = get_amp_nid(kcontrol);
1453 int dir = get_amp_direction(kcontrol);
Takashi Iwai29fdbec2009-01-20 13:07:55 +01001454 unsigned int ofs = get_amp_offset(kcontrol);
Jaroslav Kysela302e9c52006-07-05 17:39:49 +02001455 u32 caps, val1, val2;
1456
1457 if (size < 4 * sizeof(unsigned int))
1458 return -ENOMEM;
1459 caps = query_amp_caps(codec, nid, dir);
Takashi Iwai0ba21762007-04-16 11:29:14 +02001460 val2 = (caps & AC_AMPCAP_STEP_SIZE) >> AC_AMPCAP_STEP_SIZE_SHIFT;
1461 val2 = (val2 + 1) * 25;
Jaroslav Kysela302e9c52006-07-05 17:39:49 +02001462 val1 = -((caps & AC_AMPCAP_OFFSET) >> AC_AMPCAP_OFFSET_SHIFT);
Takashi Iwai29fdbec2009-01-20 13:07:55 +01001463 val1 += ofs;
Jaroslav Kysela302e9c52006-07-05 17:39:49 +02001464 val1 = ((int)val1) * ((int)val2);
Jaroslav Kysela302e9c52006-07-05 17:39:49 +02001465 if (put_user(SNDRV_CTL_TLVT_DB_SCALE, _tlv))
1466 return -EFAULT;
1467 if (put_user(2 * sizeof(unsigned int), _tlv + 1))
1468 return -EFAULT;
1469 if (put_user(val1, _tlv + 2))
1470 return -EFAULT;
1471 if (put_user(val2, _tlv + 3))
1472 return -EFAULT;
1473 return 0;
1474}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001475EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_tlv);
Jaroslav Kysela302e9c52006-07-05 17:39:49 +02001476
Takashi Iwai2134ea42008-01-10 16:53:55 +01001477/*
1478 * set (static) TLV for virtual master volume; recalculated as max 0dB
1479 */
1480void snd_hda_set_vmaster_tlv(struct hda_codec *codec, hda_nid_t nid, int dir,
1481 unsigned int *tlv)
1482{
1483 u32 caps;
1484 int nums, step;
1485
1486 caps = query_amp_caps(codec, nid, dir);
1487 nums = (caps & AC_AMPCAP_NUM_STEPS) >> AC_AMPCAP_NUM_STEPS_SHIFT;
1488 step = (caps & AC_AMPCAP_STEP_SIZE) >> AC_AMPCAP_STEP_SIZE_SHIFT;
1489 step = (step + 1) * 25;
1490 tlv[0] = SNDRV_CTL_TLVT_DB_SCALE;
1491 tlv[1] = 2 * sizeof(unsigned int);
1492 tlv[2] = -nums * step;
1493 tlv[3] = step;
1494}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001495EXPORT_SYMBOL_HDA(snd_hda_set_vmaster_tlv);
Takashi Iwai2134ea42008-01-10 16:53:55 +01001496
1497/* find a mixer control element with the given name */
Takashi Iwai09f99702008-02-04 12:31:13 +01001498static struct snd_kcontrol *
1499_snd_hda_find_mixer_ctl(struct hda_codec *codec,
1500 const char *name, int idx)
Takashi Iwai2134ea42008-01-10 16:53:55 +01001501{
1502 struct snd_ctl_elem_id id;
1503 memset(&id, 0, sizeof(id));
1504 id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
Takashi Iwai09f99702008-02-04 12:31:13 +01001505 id.index = idx;
Takashi Iwai18cb7102009-04-16 10:22:24 +02001506 if (snd_BUG_ON(strlen(name) >= sizeof(id.name)))
1507 return NULL;
Takashi Iwai2134ea42008-01-10 16:53:55 +01001508 strcpy(id.name, name);
1509 return snd_ctl_find_id(codec->bus->card, &id);
1510}
1511
Takashi Iwai09f99702008-02-04 12:31:13 +01001512struct snd_kcontrol *snd_hda_find_mixer_ctl(struct hda_codec *codec,
1513 const char *name)
1514{
1515 return _snd_hda_find_mixer_ctl(codec, name, 0);
1516}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001517EXPORT_SYMBOL_HDA(snd_hda_find_mixer_ctl);
Takashi Iwai09f99702008-02-04 12:31:13 +01001518
Takashi Iwaid13bd412008-07-30 15:01:45 +02001519/* Add a control element and assign to the codec */
1520int snd_hda_ctl_add(struct hda_codec *codec, struct snd_kcontrol *kctl)
1521{
1522 int err;
1523 struct snd_kcontrol **knewp;
1524
1525 err = snd_ctl_add(codec->bus->card, kctl);
1526 if (err < 0)
1527 return err;
1528 knewp = snd_array_new(&codec->mixers);
1529 if (!knewp)
1530 return -ENOMEM;
1531 *knewp = kctl;
1532 return 0;
1533}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001534EXPORT_SYMBOL_HDA(snd_hda_ctl_add);
Takashi Iwaid13bd412008-07-30 15:01:45 +02001535
1536/* Clear all controls assigned to the given codec */
1537void snd_hda_ctls_clear(struct hda_codec *codec)
1538{
1539 int i;
1540 struct snd_kcontrol **kctls = codec->mixers.list;
1541 for (i = 0; i < codec->mixers.used; i++)
1542 snd_ctl_remove(codec->bus->card, kctls[i]);
1543 snd_array_free(&codec->mixers);
1544}
1545
Takashi Iwaia65d6292009-02-23 16:57:04 +01001546/* pseudo device locking
1547 * toggle card->shutdown to allow/disallow the device access (as a hack)
1548 */
1549static int hda_lock_devices(struct snd_card *card)
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001550{
Takashi Iwaia65d6292009-02-23 16:57:04 +01001551 spin_lock(&card->files_lock);
1552 if (card->shutdown) {
1553 spin_unlock(&card->files_lock);
1554 return -EINVAL;
1555 }
1556 card->shutdown = 1;
1557 spin_unlock(&card->files_lock);
1558 return 0;
1559}
1560
1561static void hda_unlock_devices(struct snd_card *card)
1562{
1563 spin_lock(&card->files_lock);
1564 card->shutdown = 0;
1565 spin_unlock(&card->files_lock);
1566}
1567
1568int snd_hda_codec_reset(struct hda_codec *codec)
1569{
1570 struct snd_card *card = codec->bus->card;
1571 int i, pcm;
1572
1573 if (hda_lock_devices(card) < 0)
1574 return -EBUSY;
1575 /* check whether the codec isn't used by any mixer or PCM streams */
1576 if (!list_empty(&card->ctl_files)) {
1577 hda_unlock_devices(card);
1578 return -EBUSY;
1579 }
1580 for (pcm = 0; pcm < codec->num_pcms; pcm++) {
1581 struct hda_pcm *cpcm = &codec->pcm_info[pcm];
1582 if (!cpcm->pcm)
1583 continue;
1584 if (cpcm->pcm->streams[0].substream_opened ||
1585 cpcm->pcm->streams[1].substream_opened) {
1586 hda_unlock_devices(card);
1587 return -EBUSY;
1588 }
1589 }
1590
1591 /* OK, let it free */
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001592
1593#ifdef CONFIG_SND_HDA_POWER_SAVE
1594 cancel_delayed_work(&codec->power_work);
Takashi Iwai6acaed32009-01-12 10:09:24 +01001595 flush_workqueue(codec->bus->workq);
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001596#endif
1597 snd_hda_ctls_clear(codec);
1598 /* relase PCMs */
1599 for (i = 0; i < codec->num_pcms; i++) {
Takashi Iwai529bd6c2008-11-27 14:17:01 +01001600 if (codec->pcm_info[i].pcm) {
Takashi Iwaia65d6292009-02-23 16:57:04 +01001601 snd_device_free(card, codec->pcm_info[i].pcm);
Takashi Iwai529bd6c2008-11-27 14:17:01 +01001602 clear_bit(codec->pcm_info[i].device,
1603 codec->bus->pcm_dev_bits);
1604 }
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001605 }
1606 if (codec->patch_ops.free)
1607 codec->patch_ops.free(codec);
Takashi Iwai56d17712008-11-28 14:36:23 +01001608 codec->proc_widget_hook = NULL;
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001609 codec->spec = NULL;
1610 free_hda_cache(&codec->amp_cache);
1611 free_hda_cache(&codec->cmd_cache);
Takashi Iwai827057f2008-12-19 10:12:02 +01001612 init_hda_cache(&codec->amp_cache, sizeof(struct hda_amp_info));
1613 init_hda_cache(&codec->cmd_cache, sizeof(struct hda_cache_head));
Takashi Iwai346ff702009-02-23 09:42:57 +01001614 /* free only driver_pins so that init_pins + user_pins are restored */
1615 snd_array_free(&codec->driver_pins);
Takashi Iwai3be14142009-02-20 14:11:16 +01001616 restore_pincfgs(codec);
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001617 codec->num_pcms = 0;
1618 codec->pcm_info = NULL;
1619 codec->preset = NULL;
Takashi Iwaid1f1af22009-03-02 10:35:29 +01001620 memset(&codec->patch_ops, 0, sizeof(codec->patch_ops));
1621 codec->slave_dig_outs = NULL;
1622 codec->spdif_status_reset = 0;
Takashi Iwai1289e9e2008-11-27 15:47:11 +01001623 module_put(codec->owner);
1624 codec->owner = NULL;
Takashi Iwaia65d6292009-02-23 16:57:04 +01001625
1626 /* allow device access again */
1627 hda_unlock_devices(card);
1628 return 0;
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001629}
1630
Takashi Iwai2134ea42008-01-10 16:53:55 +01001631/* create a virtual master control and add slaves */
1632int snd_hda_add_vmaster(struct hda_codec *codec, char *name,
1633 unsigned int *tlv, const char **slaves)
1634{
1635 struct snd_kcontrol *kctl;
1636 const char **s;
1637 int err;
1638
Takashi Iwai2f085542008-02-22 18:43:50 +01001639 for (s = slaves; *s && !snd_hda_find_mixer_ctl(codec, *s); s++)
1640 ;
1641 if (!*s) {
1642 snd_printdd("No slave found for %s\n", name);
1643 return 0;
1644 }
Takashi Iwai2134ea42008-01-10 16:53:55 +01001645 kctl = snd_ctl_make_virtual_master(name, tlv);
1646 if (!kctl)
1647 return -ENOMEM;
Takashi Iwaid13bd412008-07-30 15:01:45 +02001648 err = snd_hda_ctl_add(codec, kctl);
Takashi Iwai2134ea42008-01-10 16:53:55 +01001649 if (err < 0)
1650 return err;
1651
1652 for (s = slaves; *s; s++) {
1653 struct snd_kcontrol *sctl;
Takashi Iwai7a411ee2009-03-06 10:08:14 +01001654 int i = 0;
1655 for (;;) {
1656 sctl = _snd_hda_find_mixer_ctl(codec, *s, i);
1657 if (!sctl) {
1658 if (!i)
1659 snd_printdd("Cannot find slave %s, "
1660 "skipped\n", *s);
1661 break;
1662 }
1663 err = snd_ctl_add_slave(kctl, sctl);
1664 if (err < 0)
1665 return err;
1666 i++;
Takashi Iwai2134ea42008-01-10 16:53:55 +01001667 }
Takashi Iwai2134ea42008-01-10 16:53:55 +01001668 }
1669 return 0;
1670}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001671EXPORT_SYMBOL_HDA(snd_hda_add_vmaster);
Takashi Iwai2134ea42008-01-10 16:53:55 +01001672
Linus Torvalds1da177e2005-04-16 15:20:36 -07001673/* switch */
Takashi Iwai0ba21762007-04-16 11:29:14 +02001674int snd_hda_mixer_amp_switch_info(struct snd_kcontrol *kcontrol,
1675 struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001676{
1677 int chs = get_amp_channels(kcontrol);
1678
1679 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
1680 uinfo->count = chs == 3 ? 2 : 1;
1681 uinfo->value.integer.min = 0;
1682 uinfo->value.integer.max = 1;
1683 return 0;
1684}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001685EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_switch_info);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001686
Takashi Iwai0ba21762007-04-16 11:29:14 +02001687int snd_hda_mixer_amp_switch_get(struct snd_kcontrol *kcontrol,
1688 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001689{
1690 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1691 hda_nid_t nid = get_amp_nid(kcontrol);
1692 int chs = get_amp_channels(kcontrol);
1693 int dir = get_amp_direction(kcontrol);
1694 int idx = get_amp_index(kcontrol);
1695 long *valp = ucontrol->value.integer.value;
1696
1697 if (chs & 1)
Takashi Iwai0ba21762007-04-16 11:29:14 +02001698 *valp++ = (snd_hda_codec_amp_read(codec, nid, 0, dir, idx) &
Takashi Iwai47fd8302007-08-10 17:11:07 +02001699 HDA_AMP_MUTE) ? 0 : 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001700 if (chs & 2)
Takashi Iwai0ba21762007-04-16 11:29:14 +02001701 *valp = (snd_hda_codec_amp_read(codec, nid, 1, dir, idx) &
Takashi Iwai47fd8302007-08-10 17:11:07 +02001702 HDA_AMP_MUTE) ? 0 : 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001703 return 0;
1704}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001705EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_switch_get);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001706
Takashi Iwai0ba21762007-04-16 11:29:14 +02001707int snd_hda_mixer_amp_switch_put(struct snd_kcontrol *kcontrol,
1708 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001709{
1710 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1711 hda_nid_t nid = get_amp_nid(kcontrol);
1712 int chs = get_amp_channels(kcontrol);
1713 int dir = get_amp_direction(kcontrol);
1714 int idx = get_amp_index(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001715 long *valp = ucontrol->value.integer.value;
1716 int change = 0;
1717
Takashi Iwaicb53c622007-08-10 17:21:45 +02001718 snd_hda_power_up(codec);
Nicolas Grazianob9f5a892005-07-29 12:17:20 +02001719 if (chs & 1) {
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001720 change = snd_hda_codec_amp_update(codec, nid, 0, dir, idx,
Takashi Iwai47fd8302007-08-10 17:11:07 +02001721 HDA_AMP_MUTE,
1722 *valp ? 0 : HDA_AMP_MUTE);
Nicolas Grazianob9f5a892005-07-29 12:17:20 +02001723 valp++;
1724 }
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001725 if (chs & 2)
1726 change |= snd_hda_codec_amp_update(codec, nid, 1, dir, idx,
Takashi Iwai47fd8302007-08-10 17:11:07 +02001727 HDA_AMP_MUTE,
1728 *valp ? 0 : HDA_AMP_MUTE);
Takashi Iwaicb53c622007-08-10 17:21:45 +02001729#ifdef CONFIG_SND_HDA_POWER_SAVE
1730 if (codec->patch_ops.check_power_status)
1731 codec->patch_ops.check_power_status(codec, nid);
1732#endif
1733 snd_hda_power_down(codec);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001734 return change;
1735}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001736EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_switch_put);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001737
Jaroslav Kysela123c07a2009-10-21 14:48:23 +02001738int snd_hda_mixer_amp_switch_put_beep(struct snd_kcontrol *kcontrol,
1739 struct snd_ctl_elem_value *ucontrol)
1740{
1741 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1742 long *valp = ucontrol->value.integer.value;
1743
1744 snd_hda_enable_beep_device(codec, *valp);
1745 return snd_hda_mixer_amp_switch_put(kcontrol, ucontrol);
1746}
1747EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_switch_put_beep);
1748
Linus Torvalds1da177e2005-04-16 15:20:36 -07001749/*
Takashi Iwai985be542005-11-02 18:26:49 +01001750 * bound volume controls
1751 *
1752 * bind multiple volumes (# indices, from 0)
1753 */
1754
1755#define AMP_VAL_IDX_SHIFT 19
1756#define AMP_VAL_IDX_MASK (0x0f<<19)
1757
Takashi Iwai0ba21762007-04-16 11:29:14 +02001758int snd_hda_mixer_bind_switch_get(struct snd_kcontrol *kcontrol,
1759 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai985be542005-11-02 18:26:49 +01001760{
1761 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1762 unsigned long pval;
1763 int err;
1764
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001765 mutex_lock(&codec->control_mutex);
Takashi Iwai985be542005-11-02 18:26:49 +01001766 pval = kcontrol->private_value;
1767 kcontrol->private_value = pval & ~AMP_VAL_IDX_MASK; /* index 0 */
1768 err = snd_hda_mixer_amp_switch_get(kcontrol, ucontrol);
1769 kcontrol->private_value = pval;
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001770 mutex_unlock(&codec->control_mutex);
Takashi Iwai985be542005-11-02 18:26:49 +01001771 return err;
1772}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001773EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_switch_get);
Takashi Iwai985be542005-11-02 18:26:49 +01001774
Takashi Iwai0ba21762007-04-16 11:29:14 +02001775int snd_hda_mixer_bind_switch_put(struct snd_kcontrol *kcontrol,
1776 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai985be542005-11-02 18:26:49 +01001777{
1778 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1779 unsigned long pval;
1780 int i, indices, err = 0, change = 0;
1781
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001782 mutex_lock(&codec->control_mutex);
Takashi Iwai985be542005-11-02 18:26:49 +01001783 pval = kcontrol->private_value;
1784 indices = (pval & AMP_VAL_IDX_MASK) >> AMP_VAL_IDX_SHIFT;
1785 for (i = 0; i < indices; i++) {
Takashi Iwai0ba21762007-04-16 11:29:14 +02001786 kcontrol->private_value = (pval & ~AMP_VAL_IDX_MASK) |
1787 (i << AMP_VAL_IDX_SHIFT);
Takashi Iwai985be542005-11-02 18:26:49 +01001788 err = snd_hda_mixer_amp_switch_put(kcontrol, ucontrol);
1789 if (err < 0)
1790 break;
1791 change |= err;
1792 }
1793 kcontrol->private_value = pval;
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001794 mutex_unlock(&codec->control_mutex);
Takashi Iwai985be542005-11-02 18:26:49 +01001795 return err < 0 ? err : change;
1796}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001797EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_switch_put);
Takashi Iwai985be542005-11-02 18:26:49 +01001798
1799/*
Takashi Iwai532d5382007-07-27 19:02:40 +02001800 * generic bound volume/swtich controls
1801 */
1802int snd_hda_mixer_bind_ctls_info(struct snd_kcontrol *kcontrol,
1803 struct snd_ctl_elem_info *uinfo)
1804{
1805 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1806 struct hda_bind_ctls *c;
1807 int err;
1808
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001809 mutex_lock(&codec->control_mutex);
Serge A. Suchkov14c65f92008-02-22 18:43:16 +01001810 c = (struct hda_bind_ctls *)kcontrol->private_value;
Takashi Iwai532d5382007-07-27 19:02:40 +02001811 kcontrol->private_value = *c->values;
1812 err = c->ops->info(kcontrol, uinfo);
1813 kcontrol->private_value = (long)c;
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001814 mutex_unlock(&codec->control_mutex);
Takashi Iwai532d5382007-07-27 19:02:40 +02001815 return err;
1816}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001817EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_ctls_info);
Takashi Iwai532d5382007-07-27 19:02:40 +02001818
1819int snd_hda_mixer_bind_ctls_get(struct snd_kcontrol *kcontrol,
1820 struct snd_ctl_elem_value *ucontrol)
1821{
1822 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1823 struct hda_bind_ctls *c;
1824 int err;
1825
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001826 mutex_lock(&codec->control_mutex);
Serge A. Suchkov14c65f92008-02-22 18:43:16 +01001827 c = (struct hda_bind_ctls *)kcontrol->private_value;
Takashi Iwai532d5382007-07-27 19:02:40 +02001828 kcontrol->private_value = *c->values;
1829 err = c->ops->get(kcontrol, ucontrol);
1830 kcontrol->private_value = (long)c;
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001831 mutex_unlock(&codec->control_mutex);
Takashi Iwai532d5382007-07-27 19:02:40 +02001832 return err;
1833}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001834EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_ctls_get);
Takashi Iwai532d5382007-07-27 19:02:40 +02001835
1836int snd_hda_mixer_bind_ctls_put(struct snd_kcontrol *kcontrol,
1837 struct snd_ctl_elem_value *ucontrol)
1838{
1839 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1840 struct hda_bind_ctls *c;
1841 unsigned long *vals;
1842 int err = 0, change = 0;
1843
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001844 mutex_lock(&codec->control_mutex);
Serge A. Suchkov14c65f92008-02-22 18:43:16 +01001845 c = (struct hda_bind_ctls *)kcontrol->private_value;
Takashi Iwai532d5382007-07-27 19:02:40 +02001846 for (vals = c->values; *vals; vals++) {
1847 kcontrol->private_value = *vals;
1848 err = c->ops->put(kcontrol, ucontrol);
1849 if (err < 0)
1850 break;
1851 change |= err;
1852 }
1853 kcontrol->private_value = (long)c;
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001854 mutex_unlock(&codec->control_mutex);
Takashi Iwai532d5382007-07-27 19:02:40 +02001855 return err < 0 ? err : change;
1856}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001857EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_ctls_put);
Takashi Iwai532d5382007-07-27 19:02:40 +02001858
1859int snd_hda_mixer_bind_tlv(struct snd_kcontrol *kcontrol, int op_flag,
1860 unsigned int size, unsigned int __user *tlv)
1861{
1862 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1863 struct hda_bind_ctls *c;
1864 int err;
1865
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001866 mutex_lock(&codec->control_mutex);
Serge A. Suchkov14c65f92008-02-22 18:43:16 +01001867 c = (struct hda_bind_ctls *)kcontrol->private_value;
Takashi Iwai532d5382007-07-27 19:02:40 +02001868 kcontrol->private_value = *c->values;
1869 err = c->ops->tlv(kcontrol, op_flag, size, tlv);
1870 kcontrol->private_value = (long)c;
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001871 mutex_unlock(&codec->control_mutex);
Takashi Iwai532d5382007-07-27 19:02:40 +02001872 return err;
1873}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001874EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_tlv);
Takashi Iwai532d5382007-07-27 19:02:40 +02001875
1876struct hda_ctl_ops snd_hda_bind_vol = {
1877 .info = snd_hda_mixer_amp_volume_info,
1878 .get = snd_hda_mixer_amp_volume_get,
1879 .put = snd_hda_mixer_amp_volume_put,
1880 .tlv = snd_hda_mixer_amp_tlv
1881};
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001882EXPORT_SYMBOL_HDA(snd_hda_bind_vol);
Takashi Iwai532d5382007-07-27 19:02:40 +02001883
1884struct hda_ctl_ops snd_hda_bind_sw = {
1885 .info = snd_hda_mixer_amp_switch_info,
1886 .get = snd_hda_mixer_amp_switch_get,
1887 .put = snd_hda_mixer_amp_switch_put,
1888 .tlv = snd_hda_mixer_amp_tlv
1889};
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001890EXPORT_SYMBOL_HDA(snd_hda_bind_sw);
Takashi Iwai532d5382007-07-27 19:02:40 +02001891
1892/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07001893 * SPDIF out controls
1894 */
1895
Takashi Iwai0ba21762007-04-16 11:29:14 +02001896static int snd_hda_spdif_mask_info(struct snd_kcontrol *kcontrol,
1897 struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001898{
1899 uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
1900 uinfo->count = 1;
1901 return 0;
1902}
1903
Takashi Iwai0ba21762007-04-16 11:29:14 +02001904static int snd_hda_spdif_cmask_get(struct snd_kcontrol *kcontrol,
1905 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001906{
1907 ucontrol->value.iec958.status[0] = IEC958_AES0_PROFESSIONAL |
1908 IEC958_AES0_NONAUDIO |
1909 IEC958_AES0_CON_EMPHASIS_5015 |
1910 IEC958_AES0_CON_NOT_COPYRIGHT;
1911 ucontrol->value.iec958.status[1] = IEC958_AES1_CON_CATEGORY |
1912 IEC958_AES1_CON_ORIGINAL;
1913 return 0;
1914}
1915
Takashi Iwai0ba21762007-04-16 11:29:14 +02001916static int snd_hda_spdif_pmask_get(struct snd_kcontrol *kcontrol,
1917 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001918{
1919 ucontrol->value.iec958.status[0] = IEC958_AES0_PROFESSIONAL |
1920 IEC958_AES0_NONAUDIO |
1921 IEC958_AES0_PRO_EMPHASIS_5015;
1922 return 0;
1923}
1924
Takashi Iwai0ba21762007-04-16 11:29:14 +02001925static int snd_hda_spdif_default_get(struct snd_kcontrol *kcontrol,
1926 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001927{
1928 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1929
1930 ucontrol->value.iec958.status[0] = codec->spdif_status & 0xff;
1931 ucontrol->value.iec958.status[1] = (codec->spdif_status >> 8) & 0xff;
1932 ucontrol->value.iec958.status[2] = (codec->spdif_status >> 16) & 0xff;
1933 ucontrol->value.iec958.status[3] = (codec->spdif_status >> 24) & 0xff;
1934
1935 return 0;
1936}
1937
1938/* convert from SPDIF status bits to HDA SPDIF bits
1939 * bit 0 (DigEn) is always set zero (to be filled later)
1940 */
1941static unsigned short convert_from_spdif_status(unsigned int sbits)
1942{
1943 unsigned short val = 0;
1944
1945 if (sbits & IEC958_AES0_PROFESSIONAL)
Takashi Iwai0ba21762007-04-16 11:29:14 +02001946 val |= AC_DIG1_PROFESSIONAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001947 if (sbits & IEC958_AES0_NONAUDIO)
Takashi Iwai0ba21762007-04-16 11:29:14 +02001948 val |= AC_DIG1_NONAUDIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001949 if (sbits & IEC958_AES0_PROFESSIONAL) {
Takashi Iwai0ba21762007-04-16 11:29:14 +02001950 if ((sbits & IEC958_AES0_PRO_EMPHASIS) ==
1951 IEC958_AES0_PRO_EMPHASIS_5015)
1952 val |= AC_DIG1_EMPHASIS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001953 } else {
Takashi Iwai0ba21762007-04-16 11:29:14 +02001954 if ((sbits & IEC958_AES0_CON_EMPHASIS) ==
1955 IEC958_AES0_CON_EMPHASIS_5015)
1956 val |= AC_DIG1_EMPHASIS;
1957 if (!(sbits & IEC958_AES0_CON_NOT_COPYRIGHT))
1958 val |= AC_DIG1_COPYRIGHT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001959 if (sbits & (IEC958_AES1_CON_ORIGINAL << 8))
Takashi Iwai0ba21762007-04-16 11:29:14 +02001960 val |= AC_DIG1_LEVEL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001961 val |= sbits & (IEC958_AES1_CON_CATEGORY << 8);
1962 }
1963 return val;
1964}
1965
1966/* convert to SPDIF status bits from HDA SPDIF bits
1967 */
1968static unsigned int convert_to_spdif_status(unsigned short val)
1969{
1970 unsigned int sbits = 0;
1971
Takashi Iwai0ba21762007-04-16 11:29:14 +02001972 if (val & AC_DIG1_NONAUDIO)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001973 sbits |= IEC958_AES0_NONAUDIO;
Takashi Iwai0ba21762007-04-16 11:29:14 +02001974 if (val & AC_DIG1_PROFESSIONAL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001975 sbits |= IEC958_AES0_PROFESSIONAL;
1976 if (sbits & IEC958_AES0_PROFESSIONAL) {
Takashi Iwai0ba21762007-04-16 11:29:14 +02001977 if (sbits & AC_DIG1_EMPHASIS)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001978 sbits |= IEC958_AES0_PRO_EMPHASIS_5015;
1979 } else {
Takashi Iwai0ba21762007-04-16 11:29:14 +02001980 if (val & AC_DIG1_EMPHASIS)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001981 sbits |= IEC958_AES0_CON_EMPHASIS_5015;
Takashi Iwai0ba21762007-04-16 11:29:14 +02001982 if (!(val & AC_DIG1_COPYRIGHT))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001983 sbits |= IEC958_AES0_CON_NOT_COPYRIGHT;
Takashi Iwai0ba21762007-04-16 11:29:14 +02001984 if (val & AC_DIG1_LEVEL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001985 sbits |= (IEC958_AES1_CON_ORIGINAL << 8);
1986 sbits |= val & (0x7f << 8);
1987 }
1988 return sbits;
1989}
1990
Takashi Iwai2f728532008-09-25 16:32:41 +02001991/* set digital convert verbs both for the given NID and its slaves */
1992static void set_dig_out(struct hda_codec *codec, hda_nid_t nid,
1993 int verb, int val)
1994{
1995 hda_nid_t *d;
1996
Takashi Iwai9e976972008-11-25 08:17:20 +01001997 snd_hda_codec_write_cache(codec, nid, 0, verb, val);
Takashi Iwai2f728532008-09-25 16:32:41 +02001998 d = codec->slave_dig_outs;
1999 if (!d)
2000 return;
2001 for (; *d; d++)
Takashi Iwai9e976972008-11-25 08:17:20 +01002002 snd_hda_codec_write_cache(codec, *d, 0, verb, val);
Takashi Iwai2f728532008-09-25 16:32:41 +02002003}
2004
2005static inline void set_dig_out_convert(struct hda_codec *codec, hda_nid_t nid,
2006 int dig1, int dig2)
2007{
2008 if (dig1 != -1)
2009 set_dig_out(codec, nid, AC_VERB_SET_DIGI_CONVERT_1, dig1);
2010 if (dig2 != -1)
2011 set_dig_out(codec, nid, AC_VERB_SET_DIGI_CONVERT_2, dig2);
2012}
2013
Takashi Iwai0ba21762007-04-16 11:29:14 +02002014static int snd_hda_spdif_default_put(struct snd_kcontrol *kcontrol,
2015 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002016{
2017 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2018 hda_nid_t nid = kcontrol->private_value;
2019 unsigned short val;
2020 int change;
2021
Ingo Molnar62932df2006-01-16 16:34:20 +01002022 mutex_lock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002023 codec->spdif_status = ucontrol->value.iec958.status[0] |
2024 ((unsigned int)ucontrol->value.iec958.status[1] << 8) |
2025 ((unsigned int)ucontrol->value.iec958.status[2] << 16) |
2026 ((unsigned int)ucontrol->value.iec958.status[3] << 24);
2027 val = convert_from_spdif_status(codec->spdif_status);
2028 val |= codec->spdif_ctls & 1;
2029 change = codec->spdif_ctls != val;
2030 codec->spdif_ctls = val;
2031
Takashi Iwai2f728532008-09-25 16:32:41 +02002032 if (change)
2033 set_dig_out_convert(codec, nid, val & 0xff, (val >> 8) & 0xff);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002034
Ingo Molnar62932df2006-01-16 16:34:20 +01002035 mutex_unlock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002036 return change;
2037}
2038
Takashi Iwaia5ce8892007-07-23 15:42:26 +02002039#define snd_hda_spdif_out_switch_info snd_ctl_boolean_mono_info
Linus Torvalds1da177e2005-04-16 15:20:36 -07002040
Takashi Iwai0ba21762007-04-16 11:29:14 +02002041static int snd_hda_spdif_out_switch_get(struct snd_kcontrol *kcontrol,
2042 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002043{
2044 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2045
Takashi Iwai0ba21762007-04-16 11:29:14 +02002046 ucontrol->value.integer.value[0] = codec->spdif_ctls & AC_DIG1_ENABLE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002047 return 0;
2048}
2049
Takashi Iwai0ba21762007-04-16 11:29:14 +02002050static int snd_hda_spdif_out_switch_put(struct snd_kcontrol *kcontrol,
2051 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002052{
2053 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2054 hda_nid_t nid = kcontrol->private_value;
2055 unsigned short val;
2056 int change;
2057
Ingo Molnar62932df2006-01-16 16:34:20 +01002058 mutex_lock(&codec->spdif_mutex);
Takashi Iwai0ba21762007-04-16 11:29:14 +02002059 val = codec->spdif_ctls & ~AC_DIG1_ENABLE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002060 if (ucontrol->value.integer.value[0])
Takashi Iwai0ba21762007-04-16 11:29:14 +02002061 val |= AC_DIG1_ENABLE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002062 change = codec->spdif_ctls != val;
Takashi Iwai82beb8f2007-08-10 17:09:26 +02002063 if (change) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002064 codec->spdif_ctls = val;
Takashi Iwai2f728532008-09-25 16:32:41 +02002065 set_dig_out_convert(codec, nid, val & 0xff, -1);
Takashi Iwai0ba21762007-04-16 11:29:14 +02002066 /* unmute amp switch (if any) */
2067 if ((get_wcaps(codec, nid) & AC_WCAP_OUT_AMP) &&
Takashi Iwai47fd8302007-08-10 17:11:07 +02002068 (val & AC_DIG1_ENABLE))
2069 snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0,
2070 HDA_AMP_MUTE, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002071 }
Ingo Molnar62932df2006-01-16 16:34:20 +01002072 mutex_unlock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002073 return change;
2074}
2075
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01002076static struct snd_kcontrol_new dig_mixes[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002077 {
2078 .access = SNDRV_CTL_ELEM_ACCESS_READ,
2079 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2080 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,CON_MASK),
2081 .info = snd_hda_spdif_mask_info,
2082 .get = snd_hda_spdif_cmask_get,
2083 },
2084 {
2085 .access = SNDRV_CTL_ELEM_ACCESS_READ,
2086 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2087 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,PRO_MASK),
2088 .info = snd_hda_spdif_mask_info,
2089 .get = snd_hda_spdif_pmask_get,
2090 },
2091 {
2092 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2093 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT),
2094 .info = snd_hda_spdif_mask_info,
2095 .get = snd_hda_spdif_default_get,
2096 .put = snd_hda_spdif_default_put,
2097 },
2098 {
2099 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2100 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,SWITCH),
2101 .info = snd_hda_spdif_out_switch_info,
2102 .get = snd_hda_spdif_out_switch_get,
2103 .put = snd_hda_spdif_out_switch_put,
2104 },
2105 { } /* end */
2106};
2107
Takashi Iwai09f99702008-02-04 12:31:13 +01002108#define SPDIF_MAX_IDX 4 /* 4 instances should be enough to probe */
2109
Linus Torvalds1da177e2005-04-16 15:20:36 -07002110/**
2111 * snd_hda_create_spdif_out_ctls - create Output SPDIF-related controls
2112 * @codec: the HDA codec
2113 * @nid: audio out widget NID
2114 *
2115 * Creates controls related with the SPDIF output.
2116 * Called from each patch supporting the SPDIF out.
2117 *
2118 * Returns 0 if successful, or a negative error code.
2119 */
Takashi Iwai12f288b2007-08-02 15:51:59 +02002120int snd_hda_create_spdif_out_ctls(struct hda_codec *codec, hda_nid_t nid)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002121{
2122 int err;
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01002123 struct snd_kcontrol *kctl;
2124 struct snd_kcontrol_new *dig_mix;
Takashi Iwai09f99702008-02-04 12:31:13 +01002125 int idx;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002126
Takashi Iwai09f99702008-02-04 12:31:13 +01002127 for (idx = 0; idx < SPDIF_MAX_IDX; idx++) {
2128 if (!_snd_hda_find_mixer_ctl(codec, "IEC958 Playback Switch",
2129 idx))
2130 break;
2131 }
2132 if (idx >= SPDIF_MAX_IDX) {
2133 printk(KERN_ERR "hda_codec: too many IEC958 outputs\n");
2134 return -EBUSY;
2135 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002136 for (dig_mix = dig_mixes; dig_mix->name; dig_mix++) {
2137 kctl = snd_ctl_new1(dig_mix, codec);
Takashi Iwaib91f0802008-11-04 08:43:08 +01002138 if (!kctl)
2139 return -ENOMEM;
Takashi Iwai09f99702008-02-04 12:31:13 +01002140 kctl->id.index = idx;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002141 kctl->private_value = nid;
Takashi Iwaid13bd412008-07-30 15:01:45 +02002142 err = snd_hda_ctl_add(codec, kctl);
Takashi Iwai0ba21762007-04-16 11:29:14 +02002143 if (err < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002144 return err;
2145 }
Takashi Iwai0ba21762007-04-16 11:29:14 +02002146 codec->spdif_ctls =
Andrew Paprocki3982d172007-12-19 12:13:44 +01002147 snd_hda_codec_read(codec, nid, 0,
2148 AC_VERB_GET_DIGI_CONVERT_1, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002149 codec->spdif_status = convert_to_spdif_status(codec->spdif_ctls);
2150 return 0;
2151}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002152EXPORT_SYMBOL_HDA(snd_hda_create_spdif_out_ctls);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002153
2154/*
Takashi Iwai9a081602008-02-12 18:37:26 +01002155 * SPDIF sharing with analog output
2156 */
2157static int spdif_share_sw_get(struct snd_kcontrol *kcontrol,
2158 struct snd_ctl_elem_value *ucontrol)
2159{
2160 struct hda_multi_out *mout = snd_kcontrol_chip(kcontrol);
2161 ucontrol->value.integer.value[0] = mout->share_spdif;
2162 return 0;
2163}
2164
2165static int spdif_share_sw_put(struct snd_kcontrol *kcontrol,
2166 struct snd_ctl_elem_value *ucontrol)
2167{
2168 struct hda_multi_out *mout = snd_kcontrol_chip(kcontrol);
2169 mout->share_spdif = !!ucontrol->value.integer.value[0];
2170 return 0;
2171}
2172
2173static struct snd_kcontrol_new spdif_share_sw = {
2174 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2175 .name = "IEC958 Default PCM Playback Switch",
2176 .info = snd_ctl_boolean_mono_info,
2177 .get = spdif_share_sw_get,
2178 .put = spdif_share_sw_put,
2179};
2180
2181int snd_hda_create_spdif_share_sw(struct hda_codec *codec,
2182 struct hda_multi_out *mout)
2183{
2184 if (!mout->dig_out_nid)
2185 return 0;
2186 /* ATTENTION: here mout is passed as private_data, instead of codec */
Takashi Iwaid13bd412008-07-30 15:01:45 +02002187 return snd_hda_ctl_add(codec,
Takashi Iwai9a081602008-02-12 18:37:26 +01002188 snd_ctl_new1(&spdif_share_sw, mout));
2189}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002190EXPORT_SYMBOL_HDA(snd_hda_create_spdif_share_sw);
Takashi Iwai9a081602008-02-12 18:37:26 +01002191
2192/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002193 * SPDIF input
2194 */
2195
2196#define snd_hda_spdif_in_switch_info snd_hda_spdif_out_switch_info
2197
Takashi Iwai0ba21762007-04-16 11:29:14 +02002198static int snd_hda_spdif_in_switch_get(struct snd_kcontrol *kcontrol,
2199 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002200{
2201 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2202
2203 ucontrol->value.integer.value[0] = codec->spdif_in_enable;
2204 return 0;
2205}
2206
Takashi Iwai0ba21762007-04-16 11:29:14 +02002207static int snd_hda_spdif_in_switch_put(struct snd_kcontrol *kcontrol,
2208 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002209{
2210 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2211 hda_nid_t nid = kcontrol->private_value;
2212 unsigned int val = !!ucontrol->value.integer.value[0];
2213 int change;
2214
Ingo Molnar62932df2006-01-16 16:34:20 +01002215 mutex_lock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002216 change = codec->spdif_in_enable != val;
Takashi Iwai82beb8f2007-08-10 17:09:26 +02002217 if (change) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002218 codec->spdif_in_enable = val;
Takashi Iwai82beb8f2007-08-10 17:09:26 +02002219 snd_hda_codec_write_cache(codec, nid, 0,
2220 AC_VERB_SET_DIGI_CONVERT_1, val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002221 }
Ingo Molnar62932df2006-01-16 16:34:20 +01002222 mutex_unlock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002223 return change;
2224}
2225
Takashi Iwai0ba21762007-04-16 11:29:14 +02002226static int snd_hda_spdif_in_status_get(struct snd_kcontrol *kcontrol,
2227 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002228{
2229 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2230 hda_nid_t nid = kcontrol->private_value;
2231 unsigned short val;
2232 unsigned int sbits;
2233
Andrew Paprocki3982d172007-12-19 12:13:44 +01002234 val = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_DIGI_CONVERT_1, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002235 sbits = convert_to_spdif_status(val);
2236 ucontrol->value.iec958.status[0] = sbits;
2237 ucontrol->value.iec958.status[1] = sbits >> 8;
2238 ucontrol->value.iec958.status[2] = sbits >> 16;
2239 ucontrol->value.iec958.status[3] = sbits >> 24;
2240 return 0;
2241}
2242
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01002243static struct snd_kcontrol_new dig_in_ctls[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002244 {
2245 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2246 .name = SNDRV_CTL_NAME_IEC958("",CAPTURE,SWITCH),
2247 .info = snd_hda_spdif_in_switch_info,
2248 .get = snd_hda_spdif_in_switch_get,
2249 .put = snd_hda_spdif_in_switch_put,
2250 },
2251 {
2252 .access = SNDRV_CTL_ELEM_ACCESS_READ,
2253 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2254 .name = SNDRV_CTL_NAME_IEC958("",CAPTURE,DEFAULT),
2255 .info = snd_hda_spdif_mask_info,
2256 .get = snd_hda_spdif_in_status_get,
2257 },
2258 { } /* end */
2259};
2260
2261/**
2262 * snd_hda_create_spdif_in_ctls - create Input SPDIF-related controls
2263 * @codec: the HDA codec
2264 * @nid: audio in widget NID
2265 *
2266 * Creates controls related with the SPDIF input.
2267 * Called from each patch supporting the SPDIF in.
2268 *
2269 * Returns 0 if successful, or a negative error code.
2270 */
Takashi Iwai12f288b2007-08-02 15:51:59 +02002271int snd_hda_create_spdif_in_ctls(struct hda_codec *codec, hda_nid_t nid)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002272{
2273 int err;
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01002274 struct snd_kcontrol *kctl;
2275 struct snd_kcontrol_new *dig_mix;
Takashi Iwai09f99702008-02-04 12:31:13 +01002276 int idx;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002277
Takashi Iwai09f99702008-02-04 12:31:13 +01002278 for (idx = 0; idx < SPDIF_MAX_IDX; idx++) {
2279 if (!_snd_hda_find_mixer_ctl(codec, "IEC958 Capture Switch",
2280 idx))
2281 break;
2282 }
2283 if (idx >= SPDIF_MAX_IDX) {
2284 printk(KERN_ERR "hda_codec: too many IEC958 inputs\n");
2285 return -EBUSY;
2286 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002287 for (dig_mix = dig_in_ctls; dig_mix->name; dig_mix++) {
2288 kctl = snd_ctl_new1(dig_mix, codec);
Takashi Iwaic8dcdf82009-02-06 16:21:20 +01002289 if (!kctl)
2290 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002291 kctl->private_value = nid;
Takashi Iwaid13bd412008-07-30 15:01:45 +02002292 err = snd_hda_ctl_add(codec, kctl);
Takashi Iwai0ba21762007-04-16 11:29:14 +02002293 if (err < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002294 return err;
2295 }
Takashi Iwai0ba21762007-04-16 11:29:14 +02002296 codec->spdif_in_enable =
Andrew Paprocki3982d172007-12-19 12:13:44 +01002297 snd_hda_codec_read(codec, nid, 0,
2298 AC_VERB_GET_DIGI_CONVERT_1, 0) &
Takashi Iwai0ba21762007-04-16 11:29:14 +02002299 AC_DIG1_ENABLE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002300 return 0;
2301}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002302EXPORT_SYMBOL_HDA(snd_hda_create_spdif_in_ctls);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002303
Takashi Iwaicb53c622007-08-10 17:21:45 +02002304#ifdef SND_HDA_NEEDS_RESUME
Takashi Iwai82beb8f2007-08-10 17:09:26 +02002305/*
2306 * command cache
2307 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002308
Takashi Iwaib3ac5632007-08-10 17:03:40 +02002309/* build a 32bit cache key with the widget id and the command parameter */
2310#define build_cmd_cache_key(nid, verb) ((verb << 8) | nid)
2311#define get_cmd_cache_nid(key) ((key) & 0xff)
2312#define get_cmd_cache_cmd(key) (((key) >> 8) & 0xffff)
2313
2314/**
2315 * snd_hda_codec_write_cache - send a single command with caching
2316 * @codec: the HDA codec
2317 * @nid: NID to send the command
2318 * @direct: direct flag
2319 * @verb: the verb to send
2320 * @parm: the parameter for the verb
2321 *
2322 * Send a single command without waiting for response.
2323 *
2324 * Returns 0 if successful, or a negative error code.
2325 */
2326int snd_hda_codec_write_cache(struct hda_codec *codec, hda_nid_t nid,
2327 int direct, unsigned int verb, unsigned int parm)
2328{
Takashi Iwaiaa2936f2009-05-26 16:07:57 +02002329 int err = snd_hda_codec_write(codec, nid, direct, verb, parm);
2330 struct hda_cache_head *c;
2331 u32 key;
Takashi Iwai33fa35e2008-11-06 16:50:40 +01002332
Takashi Iwaiaa2936f2009-05-26 16:07:57 +02002333 if (err < 0)
2334 return err;
2335 /* parm may contain the verb stuff for get/set amp */
2336 verb = verb | (parm >> 8);
2337 parm &= 0xff;
2338 key = build_cmd_cache_key(nid, verb);
2339 mutex_lock(&codec->bus->cmd_mutex);
2340 c = get_alloc_hash(&codec->cmd_cache, key);
2341 if (c)
2342 c->val = parm;
2343 mutex_unlock(&codec->bus->cmd_mutex);
2344 return 0;
Takashi Iwaib3ac5632007-08-10 17:03:40 +02002345}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002346EXPORT_SYMBOL_HDA(snd_hda_codec_write_cache);
Takashi Iwaib3ac5632007-08-10 17:03:40 +02002347
2348/* resume the all commands from the cache */
2349void snd_hda_codec_resume_cache(struct hda_codec *codec)
2350{
Takashi Iwai603c4012008-07-30 15:01:44 +02002351 struct hda_cache_head *buffer = codec->cmd_cache.buf.list;
Takashi Iwaib3ac5632007-08-10 17:03:40 +02002352 int i;
2353
Takashi Iwai603c4012008-07-30 15:01:44 +02002354 for (i = 0; i < codec->cmd_cache.buf.used; i++, buffer++) {
Takashi Iwaib3ac5632007-08-10 17:03:40 +02002355 u32 key = buffer->key;
2356 if (!key)
2357 continue;
2358 snd_hda_codec_write(codec, get_cmd_cache_nid(key), 0,
2359 get_cmd_cache_cmd(key), buffer->val);
2360 }
2361}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002362EXPORT_SYMBOL_HDA(snd_hda_codec_resume_cache);
Takashi Iwaib3ac5632007-08-10 17:03:40 +02002363
2364/**
2365 * snd_hda_sequence_write_cache - sequence writes with caching
2366 * @codec: the HDA codec
2367 * @seq: VERB array to send
2368 *
2369 * Send the commands sequentially from the given array.
2370 * Thte commands are recorded on cache for power-save and resume.
2371 * The array must be terminated with NID=0.
2372 */
2373void snd_hda_sequence_write_cache(struct hda_codec *codec,
2374 const struct hda_verb *seq)
2375{
2376 for (; seq->nid; seq++)
2377 snd_hda_codec_write_cache(codec, seq->nid, 0, seq->verb,
2378 seq->param);
2379}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002380EXPORT_SYMBOL_HDA(snd_hda_sequence_write_cache);
Takashi Iwaicb53c622007-08-10 17:21:45 +02002381#endif /* SND_HDA_NEEDS_RESUME */
Takashi Iwaib3ac5632007-08-10 17:03:40 +02002382
Takashi Iwai54d17402005-11-21 16:33:22 +01002383/*
2384 * set power state of the codec
2385 */
2386static void hda_set_power_state(struct hda_codec *codec, hda_nid_t fg,
2387 unsigned int power_state)
2388{
Takashi Iwaicb53c622007-08-10 17:21:45 +02002389 hda_nid_t nid;
2390 int i;
Takashi Iwai54d17402005-11-21 16:33:22 +01002391
Takashi Iwai05ff7e12009-07-22 12:39:24 +02002392 /* this delay seems necessary to avoid click noise at power-down */
2393 if (power_state == AC_PWRST_D3)
2394 msleep(100);
2395 snd_hda_codec_read(codec, fg, 0, AC_VERB_SET_POWER_STATE,
Takashi Iwai54d17402005-11-21 16:33:22 +01002396 power_state);
Takashi Iwai05ff7e12009-07-22 12:39:24 +02002397 /* partial workaround for "azx_get_response timeout" */
2398 if (power_state == AC_PWRST_D0)
2399 msleep(10);
Takashi Iwai54d17402005-11-21 16:33:22 +01002400
Takashi Iwaicb53c622007-08-10 17:21:45 +02002401 nid = codec->start_nid;
2402 for (i = 0; i < codec->num_nodes; i++, nid++) {
Takashi Iwai7eba5c92007-11-14 14:53:42 +01002403 unsigned int wcaps = get_wcaps(codec, nid);
2404 if (wcaps & AC_WCAP_POWER) {
Takashi Iwaia22d5432009-07-27 12:54:26 +02002405 unsigned int wid_type = get_wcaps_type(wcaps);
Takashi Iwaia3b48c82009-04-21 13:37:29 +02002406 if (power_state == AC_PWRST_D3 &&
2407 wid_type == AC_WID_PIN) {
Takashi Iwai7eba5c92007-11-14 14:53:42 +01002408 unsigned int pincap;
2409 /*
2410 * don't power down the widget if it controls
2411 * eapd and EAPD_BTLENABLE is set.
2412 */
Takashi Iwai14bafe32009-03-23 16:35:39 +01002413 pincap = snd_hda_query_pin_caps(codec, nid);
Takashi Iwai7eba5c92007-11-14 14:53:42 +01002414 if (pincap & AC_PINCAP_EAPD) {
2415 int eapd = snd_hda_codec_read(codec,
2416 nid, 0,
2417 AC_VERB_GET_EAPD_BTLENABLE, 0);
2418 eapd &= 0x02;
Takashi Iwaia3b48c82009-04-21 13:37:29 +02002419 if (eapd)
Takashi Iwai7eba5c92007-11-14 14:53:42 +01002420 continue;
2421 }
Takashi Iwai1194b5b2007-10-10 10:04:26 +02002422 }
Takashi Iwai54d17402005-11-21 16:33:22 +01002423 snd_hda_codec_write(codec, nid, 0,
2424 AC_VERB_SET_POWER_STATE,
2425 power_state);
Takashi Iwai1194b5b2007-10-10 10:04:26 +02002426 }
Takashi Iwai54d17402005-11-21 16:33:22 +01002427 }
2428
Takashi Iwaicb53c622007-08-10 17:21:45 +02002429 if (power_state == AC_PWRST_D0) {
2430 unsigned long end_time;
2431 int state;
Takashi Iwai54d17402005-11-21 16:33:22 +01002432 msleep(10);
Takashi Iwaicb53c622007-08-10 17:21:45 +02002433 /* wait until the codec reachs to D0 */
2434 end_time = jiffies + msecs_to_jiffies(500);
2435 do {
2436 state = snd_hda_codec_read(codec, fg, 0,
2437 AC_VERB_GET_POWER_STATE, 0);
2438 if (state == power_state)
2439 break;
2440 msleep(1);
2441 } while (time_after_eq(end_time, jiffies));
2442 }
Takashi Iwai54d17402005-11-21 16:33:22 +01002443}
2444
Takashi Iwai11aeff02008-07-30 15:01:46 +02002445#ifdef CONFIG_SND_HDA_HWDEP
2446/* execute additional init verbs */
2447static void hda_exec_init_verbs(struct hda_codec *codec)
2448{
2449 if (codec->init_verbs.list)
2450 snd_hda_sequence_write(codec, codec->init_verbs.list);
2451}
2452#else
2453static inline void hda_exec_init_verbs(struct hda_codec *codec) {}
2454#endif
2455
Takashi Iwaicb53c622007-08-10 17:21:45 +02002456#ifdef SND_HDA_NEEDS_RESUME
2457/*
2458 * call suspend and power-down; used both from PM and power-save
2459 */
2460static void hda_call_codec_suspend(struct hda_codec *codec)
2461{
2462 if (codec->patch_ops.suspend)
2463 codec->patch_ops.suspend(codec, PMSG_SUSPEND);
2464 hda_set_power_state(codec,
2465 codec->afg ? codec->afg : codec->mfg,
2466 AC_PWRST_D3);
2467#ifdef CONFIG_SND_HDA_POWER_SAVE
Takashi Iwaia2f63092009-11-11 09:34:25 +01002468 snd_hda_update_power_acct(codec);
Takashi Iwaicb53c622007-08-10 17:21:45 +02002469 cancel_delayed_work(&codec->power_work);
Takashi Iwai95e99fd2007-08-13 15:29:04 +02002470 codec->power_on = 0;
Takashi Iwaia221e282007-08-16 16:35:33 +02002471 codec->power_transition = 0;
Takashi Iwaia2f63092009-11-11 09:34:25 +01002472 codec->power_jiffies = jiffies;
Takashi Iwaicb53c622007-08-10 17:21:45 +02002473#endif
2474}
2475
2476/*
2477 * kick up codec; used both from PM and power-save
2478 */
2479static void hda_call_codec_resume(struct hda_codec *codec)
2480{
2481 hda_set_power_state(codec,
2482 codec->afg ? codec->afg : codec->mfg,
2483 AC_PWRST_D0);
Takashi Iwai3be14142009-02-20 14:11:16 +01002484 restore_pincfgs(codec); /* restore all current pin configs */
Takashi Iwai11aeff02008-07-30 15:01:46 +02002485 hda_exec_init_verbs(codec);
Takashi Iwaicb53c622007-08-10 17:21:45 +02002486 if (codec->patch_ops.resume)
2487 codec->patch_ops.resume(codec);
2488 else {
Takashi Iwai9d99f312007-08-14 15:15:52 +02002489 if (codec->patch_ops.init)
2490 codec->patch_ops.init(codec);
Takashi Iwaicb53c622007-08-10 17:21:45 +02002491 snd_hda_codec_resume_amp(codec);
2492 snd_hda_codec_resume_cache(codec);
2493 }
2494}
2495#endif /* SND_HDA_NEEDS_RESUME */
2496
Takashi Iwai54d17402005-11-21 16:33:22 +01002497
Linus Torvalds1da177e2005-04-16 15:20:36 -07002498/**
2499 * snd_hda_build_controls - build mixer controls
2500 * @bus: the BUS
2501 *
2502 * Creates mixer controls for each codec included in the bus.
2503 *
2504 * Returns 0 if successful, otherwise a negative error code.
2505 */
Takashi Iwai1289e9e2008-11-27 15:47:11 +01002506int /*__devinit*/ snd_hda_build_controls(struct hda_bus *bus)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002507{
Takashi Iwai0ba21762007-04-16 11:29:14 +02002508 struct hda_codec *codec;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002509
Takashi Iwai0ba21762007-04-16 11:29:14 +02002510 list_for_each_entry(codec, &bus->codec_list, list) {
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02002511 int err = snd_hda_codec_build_controls(codec);
Takashi Iwaif93d4612009-03-02 10:44:15 +01002512 if (err < 0) {
2513 printk(KERN_ERR "hda_codec: cannot build controls"
2514 "for #%d (error %d)\n", codec->addr, err);
2515 err = snd_hda_codec_reset(codec);
2516 if (err < 0) {
2517 printk(KERN_ERR
2518 "hda_codec: cannot revert codec\n");
2519 return err;
2520 }
2521 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002522 }
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02002523 return 0;
2524}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002525EXPORT_SYMBOL_HDA(snd_hda_build_controls);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002526
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02002527int snd_hda_codec_build_controls(struct hda_codec *codec)
2528{
2529 int err = 0;
Takashi Iwai11aeff02008-07-30 15:01:46 +02002530 hda_exec_init_verbs(codec);
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02002531 /* continue to initialize... */
2532 if (codec->patch_ops.init)
2533 err = codec->patch_ops.init(codec);
2534 if (!err && codec->patch_ops.build_controls)
2535 err = codec->patch_ops.build_controls(codec);
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02002536 if (err < 0)
2537 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002538 return 0;
2539}
2540
Linus Torvalds1da177e2005-04-16 15:20:36 -07002541/*
2542 * stream formats
2543 */
Takashi Iwaibefdf312005-08-22 13:57:55 +02002544struct hda_rate_tbl {
2545 unsigned int hz;
2546 unsigned int alsa_bits;
2547 unsigned int hda_fmt;
2548};
2549
2550static struct hda_rate_tbl rate_bits[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002551 /* rate in Hz, ALSA rate bitmask, HDA format value */
Nicolas Graziano9d8f53f2005-08-22 13:47:16 +02002552
2553 /* autodetected value used in snd_hda_query_supported_pcm */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002554 { 8000, SNDRV_PCM_RATE_8000, 0x0500 }, /* 1/6 x 48 */
2555 { 11025, SNDRV_PCM_RATE_11025, 0x4300 }, /* 1/4 x 44 */
2556 { 16000, SNDRV_PCM_RATE_16000, 0x0200 }, /* 1/3 x 48 */
2557 { 22050, SNDRV_PCM_RATE_22050, 0x4100 }, /* 1/2 x 44 */
2558 { 32000, SNDRV_PCM_RATE_32000, 0x0a00 }, /* 2/3 x 48 */
2559 { 44100, SNDRV_PCM_RATE_44100, 0x4000 }, /* 44 */
2560 { 48000, SNDRV_PCM_RATE_48000, 0x0000 }, /* 48 */
2561 { 88200, SNDRV_PCM_RATE_88200, 0x4800 }, /* 2 x 44 */
2562 { 96000, SNDRV_PCM_RATE_96000, 0x0800 }, /* 2 x 48 */
2563 { 176400, SNDRV_PCM_RATE_176400, 0x5800 },/* 4 x 44 */
2564 { 192000, SNDRV_PCM_RATE_192000, 0x1800 }, /* 4 x 48 */
Takashi Iwaia961f9f2007-04-12 13:08:09 +02002565#define AC_PAR_PCM_RATE_BITS 11
2566 /* up to bits 10, 384kHZ isn't supported properly */
2567
2568 /* not autodetected value */
2569 { 9600, SNDRV_PCM_RATE_KNOT, 0x0400 }, /* 1/5 x 48 */
Nicolas Graziano9d8f53f2005-08-22 13:47:16 +02002570
Takashi Iwaibefdf312005-08-22 13:57:55 +02002571 { 0 } /* terminator */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002572};
2573
2574/**
2575 * snd_hda_calc_stream_format - calculate format bitset
2576 * @rate: the sample rate
2577 * @channels: the number of channels
2578 * @format: the PCM format (SNDRV_PCM_FORMAT_XXX)
2579 * @maxbps: the max. bps
2580 *
2581 * Calculate the format bitset from the given rate, channels and th PCM format.
2582 *
2583 * Return zero if invalid.
2584 */
2585unsigned int snd_hda_calc_stream_format(unsigned int rate,
2586 unsigned int channels,
2587 unsigned int format,
2588 unsigned int maxbps)
2589{
2590 int i;
2591 unsigned int val = 0;
2592
Takashi Iwaibefdf312005-08-22 13:57:55 +02002593 for (i = 0; rate_bits[i].hz; i++)
2594 if (rate_bits[i].hz == rate) {
2595 val = rate_bits[i].hda_fmt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002596 break;
2597 }
Takashi Iwai0ba21762007-04-16 11:29:14 +02002598 if (!rate_bits[i].hz) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002599 snd_printdd("invalid rate %d\n", rate);
2600 return 0;
2601 }
2602
2603 if (channels == 0 || channels > 8) {
2604 snd_printdd("invalid channels %d\n", channels);
2605 return 0;
2606 }
2607 val |= channels - 1;
2608
2609 switch (snd_pcm_format_width(format)) {
2610 case 8: val |= 0x00; break;
2611 case 16: val |= 0x10; break;
2612 case 20:
2613 case 24:
2614 case 32:
Takashi Iwaib0bb3aa2009-07-03 23:25:37 +02002615 if (maxbps >= 32 || format == SNDRV_PCM_FORMAT_FLOAT_LE)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002616 val |= 0x40;
2617 else if (maxbps >= 24)
2618 val |= 0x30;
2619 else
2620 val |= 0x20;
2621 break;
2622 default:
Takashi Iwai0ba21762007-04-16 11:29:14 +02002623 snd_printdd("invalid format width %d\n",
2624 snd_pcm_format_width(format));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002625 return 0;
2626 }
2627
2628 return val;
2629}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002630EXPORT_SYMBOL_HDA(snd_hda_calc_stream_format);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002631
Takashi Iwai92c7c8a2009-03-24 07:32:14 +01002632static unsigned int get_pcm_param(struct hda_codec *codec, hda_nid_t nid)
2633{
2634 unsigned int val = 0;
2635 if (nid != codec->afg &&
2636 (get_wcaps(codec, nid) & AC_WCAP_FORMAT_OVRD))
2637 val = snd_hda_param_read(codec, nid, AC_PAR_PCM);
2638 if (!val || val == -1)
2639 val = snd_hda_param_read(codec, codec->afg, AC_PAR_PCM);
2640 if (!val || val == -1)
2641 return 0;
2642 return val;
2643}
2644
2645static unsigned int query_pcm_param(struct hda_codec *codec, hda_nid_t nid)
2646{
2647 return query_caps_hash(codec, nid, HDA_HASH_PARPCM_KEY(nid),
2648 get_pcm_param);
2649}
2650
2651static unsigned int get_stream_param(struct hda_codec *codec, hda_nid_t nid)
2652{
2653 unsigned int streams = snd_hda_param_read(codec, nid, AC_PAR_STREAM);
2654 if (!streams || streams == -1)
2655 streams = snd_hda_param_read(codec, codec->afg, AC_PAR_STREAM);
2656 if (!streams || streams == -1)
2657 return 0;
2658 return streams;
2659}
2660
2661static unsigned int query_stream_param(struct hda_codec *codec, hda_nid_t nid)
2662{
2663 return query_caps_hash(codec, nid, HDA_HASH_PARSTR_KEY(nid),
2664 get_stream_param);
2665}
2666
Linus Torvalds1da177e2005-04-16 15:20:36 -07002667/**
2668 * snd_hda_query_supported_pcm - query the supported PCM rates and formats
2669 * @codec: the HDA codec
2670 * @nid: NID to query
2671 * @ratesp: the pointer to store the detected rate bitflags
2672 * @formatsp: the pointer to store the detected formats
2673 * @bpsp: the pointer to store the detected format widths
2674 *
2675 * Queries the supported PCM rates and formats. The NULL @ratesp, @formatsp
2676 * or @bsps argument is ignored.
2677 *
2678 * Returns 0 if successful, otherwise a negative error code.
2679 */
Takashi Iwai986862bd2008-11-27 12:40:13 +01002680static int snd_hda_query_supported_pcm(struct hda_codec *codec, hda_nid_t nid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002681 u32 *ratesp, u64 *formatsp, unsigned int *bpsp)
2682{
Jaroslav Kyselaee504712009-03-17 14:30:31 +01002683 unsigned int i, val, wcaps;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002684
Jaroslav Kyselaee504712009-03-17 14:30:31 +01002685 wcaps = get_wcaps(codec, nid);
Takashi Iwai92c7c8a2009-03-24 07:32:14 +01002686 val = query_pcm_param(codec, nid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002687
2688 if (ratesp) {
2689 u32 rates = 0;
Takashi Iwaia961f9f2007-04-12 13:08:09 +02002690 for (i = 0; i < AC_PAR_PCM_RATE_BITS; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002691 if (val & (1 << i))
Takashi Iwaibefdf312005-08-22 13:57:55 +02002692 rates |= rate_bits[i].alsa_bits;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002693 }
Jaroslav Kyselaee504712009-03-17 14:30:31 +01002694 if (rates == 0) {
2695 snd_printk(KERN_ERR "hda_codec: rates == 0 "
2696 "(nid=0x%x, val=0x%x, ovrd=%i)\n",
2697 nid, val,
2698 (wcaps & AC_WCAP_FORMAT_OVRD) ? 1 : 0);
2699 return -EIO;
2700 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002701 *ratesp = rates;
2702 }
2703
2704 if (formatsp || bpsp) {
2705 u64 formats = 0;
Jaroslav Kyselaee504712009-03-17 14:30:31 +01002706 unsigned int streams, bps;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002707
Takashi Iwai92c7c8a2009-03-24 07:32:14 +01002708 streams = query_stream_param(codec, nid);
2709 if (!streams)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002710 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002711
2712 bps = 0;
2713 if (streams & AC_SUPFMT_PCM) {
2714 if (val & AC_SUPPCM_BITS_8) {
2715 formats |= SNDRV_PCM_FMTBIT_U8;
2716 bps = 8;
2717 }
2718 if (val & AC_SUPPCM_BITS_16) {
2719 formats |= SNDRV_PCM_FMTBIT_S16_LE;
2720 bps = 16;
2721 }
2722 if (wcaps & AC_WCAP_DIGITAL) {
2723 if (val & AC_SUPPCM_BITS_32)
2724 formats |= SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_LE;
2725 if (val & (AC_SUPPCM_BITS_20|AC_SUPPCM_BITS_24))
2726 formats |= SNDRV_PCM_FMTBIT_S32_LE;
2727 if (val & AC_SUPPCM_BITS_24)
2728 bps = 24;
2729 else if (val & AC_SUPPCM_BITS_20)
2730 bps = 20;
Takashi Iwai0ba21762007-04-16 11:29:14 +02002731 } else if (val & (AC_SUPPCM_BITS_20|AC_SUPPCM_BITS_24|
2732 AC_SUPPCM_BITS_32)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002733 formats |= SNDRV_PCM_FMTBIT_S32_LE;
2734 if (val & AC_SUPPCM_BITS_32)
2735 bps = 32;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002736 else if (val & AC_SUPPCM_BITS_24)
2737 bps = 24;
Nicolas Graziano33ef76512006-09-19 14:23:14 +02002738 else if (val & AC_SUPPCM_BITS_20)
2739 bps = 20;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002740 }
2741 }
Takashi Iwaib5025c52009-07-01 18:05:27 +02002742 if (streams & AC_SUPFMT_FLOAT32) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002743 formats |= SNDRV_PCM_FMTBIT_FLOAT_LE;
Takashi Iwaib0bb3aa2009-07-03 23:25:37 +02002744 if (!bps)
2745 bps = 32;
Takashi Iwaib5025c52009-07-01 18:05:27 +02002746 }
2747 if (streams == AC_SUPFMT_AC3) {
Takashi Iwai0ba21762007-04-16 11:29:14 +02002748 /* should be exclusive */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002749 /* temporary hack: we have still no proper support
2750 * for the direct AC3 stream...
2751 */
2752 formats |= SNDRV_PCM_FMTBIT_U8;
2753 bps = 8;
2754 }
Jaroslav Kyselaee504712009-03-17 14:30:31 +01002755 if (formats == 0) {
2756 snd_printk(KERN_ERR "hda_codec: formats == 0 "
2757 "(nid=0x%x, val=0x%x, ovrd=%i, "
2758 "streams=0x%x)\n",
2759 nid, val,
2760 (wcaps & AC_WCAP_FORMAT_OVRD) ? 1 : 0,
2761 streams);
2762 return -EIO;
2763 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002764 if (formatsp)
2765 *formatsp = formats;
2766 if (bpsp)
2767 *bpsp = bps;
2768 }
2769
2770 return 0;
2771}
2772
2773/**
Takashi Iwai0ba21762007-04-16 11:29:14 +02002774 * snd_hda_is_supported_format - check whether the given node supports
2775 * the format val
Linus Torvalds1da177e2005-04-16 15:20:36 -07002776 *
2777 * Returns 1 if supported, 0 if not.
2778 */
2779int snd_hda_is_supported_format(struct hda_codec *codec, hda_nid_t nid,
2780 unsigned int format)
2781{
2782 int i;
2783 unsigned int val = 0, rate, stream;
2784
Takashi Iwai92c7c8a2009-03-24 07:32:14 +01002785 val = query_pcm_param(codec, nid);
2786 if (!val)
2787 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002788
2789 rate = format & 0xff00;
Takashi Iwaia961f9f2007-04-12 13:08:09 +02002790 for (i = 0; i < AC_PAR_PCM_RATE_BITS; i++)
Takashi Iwaibefdf312005-08-22 13:57:55 +02002791 if (rate_bits[i].hda_fmt == rate) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002792 if (val & (1 << i))
2793 break;
2794 return 0;
2795 }
Takashi Iwaia961f9f2007-04-12 13:08:09 +02002796 if (i >= AC_PAR_PCM_RATE_BITS)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002797 return 0;
2798
Takashi Iwai92c7c8a2009-03-24 07:32:14 +01002799 stream = query_stream_param(codec, nid);
2800 if (!stream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002801 return 0;
2802
2803 if (stream & AC_SUPFMT_PCM) {
2804 switch (format & 0xf0) {
2805 case 0x00:
Takashi Iwai0ba21762007-04-16 11:29:14 +02002806 if (!(val & AC_SUPPCM_BITS_8))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002807 return 0;
2808 break;
2809 case 0x10:
Takashi Iwai0ba21762007-04-16 11:29:14 +02002810 if (!(val & AC_SUPPCM_BITS_16))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002811 return 0;
2812 break;
2813 case 0x20:
Takashi Iwai0ba21762007-04-16 11:29:14 +02002814 if (!(val & AC_SUPPCM_BITS_20))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002815 return 0;
2816 break;
2817 case 0x30:
Takashi Iwai0ba21762007-04-16 11:29:14 +02002818 if (!(val & AC_SUPPCM_BITS_24))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002819 return 0;
2820 break;
2821 case 0x40:
Takashi Iwai0ba21762007-04-16 11:29:14 +02002822 if (!(val & AC_SUPPCM_BITS_32))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002823 return 0;
2824 break;
2825 default:
2826 return 0;
2827 }
2828 } else {
2829 /* FIXME: check for float32 and AC3? */
2830 }
2831
2832 return 1;
2833}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002834EXPORT_SYMBOL_HDA(snd_hda_is_supported_format);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002835
2836/*
2837 * PCM stuff
2838 */
2839static int hda_pcm_default_open_close(struct hda_pcm_stream *hinfo,
2840 struct hda_codec *codec,
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01002841 struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002842{
2843 return 0;
2844}
2845
2846static int hda_pcm_default_prepare(struct hda_pcm_stream *hinfo,
2847 struct hda_codec *codec,
2848 unsigned int stream_tag,
2849 unsigned int format,
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01002850 struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002851{
2852 snd_hda_codec_setup_stream(codec, hinfo->nid, stream_tag, 0, format);
2853 return 0;
2854}
2855
2856static int hda_pcm_default_cleanup(struct hda_pcm_stream *hinfo,
2857 struct hda_codec *codec,
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01002858 struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002859{
Takashi Iwai888afa12008-03-18 09:57:50 +01002860 snd_hda_codec_cleanup_stream(codec, hinfo->nid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002861 return 0;
2862}
2863
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02002864static int set_pcm_default_values(struct hda_codec *codec,
2865 struct hda_pcm_stream *info)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002866{
Jaroslav Kyselaee504712009-03-17 14:30:31 +01002867 int err;
2868
Takashi Iwai0ba21762007-04-16 11:29:14 +02002869 /* query support PCM information from the given NID */
2870 if (info->nid && (!info->rates || !info->formats)) {
Jaroslav Kyselaee504712009-03-17 14:30:31 +01002871 err = snd_hda_query_supported_pcm(codec, info->nid,
Takashi Iwai0ba21762007-04-16 11:29:14 +02002872 info->rates ? NULL : &info->rates,
2873 info->formats ? NULL : &info->formats,
2874 info->maxbps ? NULL : &info->maxbps);
Jaroslav Kyselaee504712009-03-17 14:30:31 +01002875 if (err < 0)
2876 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002877 }
2878 if (info->ops.open == NULL)
2879 info->ops.open = hda_pcm_default_open_close;
2880 if (info->ops.close == NULL)
2881 info->ops.close = hda_pcm_default_open_close;
2882 if (info->ops.prepare == NULL) {
Takashi Iwaida3cec32008-08-08 17:12:14 +02002883 if (snd_BUG_ON(!info->nid))
2884 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002885 info->ops.prepare = hda_pcm_default_prepare;
2886 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002887 if (info->ops.cleanup == NULL) {
Takashi Iwaida3cec32008-08-08 17:12:14 +02002888 if (snd_BUG_ON(!info->nid))
2889 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002890 info->ops.cleanup = hda_pcm_default_cleanup;
2891 }
2892 return 0;
2893}
2894
Jaroslav Kyselae3303232009-11-10 14:53:02 +01002895const char *snd_hda_pcm_type_name[HDA_PCM_NTYPES] = {
2896 "Audio", "SPDIF", "HDMI", "Modem"
2897};
2898
Takashi Iwai176d5332008-07-30 15:01:44 +02002899/*
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002900 * get the empty PCM device number to assign
2901 */
2902static int get_empty_pcm_device(struct hda_bus *bus, int type)
2903{
Wu Fengguangf5d6def2009-10-30 11:38:26 +01002904 /* audio device indices; not linear to keep compatibility */
2905 static int audio_idx[HDA_PCM_NTYPES][5] = {
2906 [HDA_PCM_TYPE_AUDIO] = { 0, 2, 4, 5, -1 },
2907 [HDA_PCM_TYPE_SPDIF] = { 1, -1 },
Wu Fengguang92608ba2009-10-30 11:40:03 +01002908 [HDA_PCM_TYPE_HDMI] = { 3, 7, 8, 9, -1 },
Wu Fengguangf5d6def2009-10-30 11:38:26 +01002909 [HDA_PCM_TYPE_MODEM] = { 6, -1 },
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002910 };
Wu Fengguangf5d6def2009-10-30 11:38:26 +01002911 int i;
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002912
Wu Fengguangf5d6def2009-10-30 11:38:26 +01002913 if (type >= HDA_PCM_NTYPES) {
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002914 snd_printk(KERN_WARNING "Invalid PCM type %d\n", type);
2915 return -EINVAL;
2916 }
Wu Fengguangf5d6def2009-10-30 11:38:26 +01002917
2918 for (i = 0; audio_idx[type][i] >= 0 ; i++)
2919 if (!test_and_set_bit(audio_idx[type][i], bus->pcm_dev_bits))
2920 return audio_idx[type][i];
2921
Jaroslav Kyselae3303232009-11-10 14:53:02 +01002922 snd_printk(KERN_WARNING "Too many %s devices\n", snd_hda_pcm_type_name[type]);
Wu Fengguangf5d6def2009-10-30 11:38:26 +01002923 return -EAGAIN;
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002924}
2925
2926/*
Takashi Iwai176d5332008-07-30 15:01:44 +02002927 * attach a new PCM stream
2928 */
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002929static int snd_hda_attach_pcm(struct hda_codec *codec, struct hda_pcm *pcm)
Takashi Iwai176d5332008-07-30 15:01:44 +02002930{
Takashi Iwai33fa35e2008-11-06 16:50:40 +01002931 struct hda_bus *bus = codec->bus;
Takashi Iwai176d5332008-07-30 15:01:44 +02002932 struct hda_pcm_stream *info;
2933 int stream, err;
2934
Takashi Iwaib91f0802008-11-04 08:43:08 +01002935 if (snd_BUG_ON(!pcm->name))
Takashi Iwai176d5332008-07-30 15:01:44 +02002936 return -EINVAL;
2937 for (stream = 0; stream < 2; stream++) {
2938 info = &pcm->stream[stream];
2939 if (info->substreams) {
2940 err = set_pcm_default_values(codec, info);
2941 if (err < 0)
2942 return err;
2943 }
2944 }
Takashi Iwai33fa35e2008-11-06 16:50:40 +01002945 return bus->ops.attach_pcm(bus, codec, pcm);
Takashi Iwai176d5332008-07-30 15:01:44 +02002946}
2947
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002948/* assign all PCMs of the given codec */
2949int snd_hda_codec_build_pcms(struct hda_codec *codec)
2950{
2951 unsigned int pcm;
2952 int err;
2953
2954 if (!codec->num_pcms) {
2955 if (!codec->patch_ops.build_pcms)
2956 return 0;
2957 err = codec->patch_ops.build_pcms(codec);
Takashi Iwai6e655bf2009-03-02 10:46:03 +01002958 if (err < 0) {
2959 printk(KERN_ERR "hda_codec: cannot build PCMs"
2960 "for #%d (error %d)\n", codec->addr, err);
2961 err = snd_hda_codec_reset(codec);
2962 if (err < 0) {
2963 printk(KERN_ERR
2964 "hda_codec: cannot revert codec\n");
2965 return err;
2966 }
2967 }
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002968 }
2969 for (pcm = 0; pcm < codec->num_pcms; pcm++) {
2970 struct hda_pcm *cpcm = &codec->pcm_info[pcm];
2971 int dev;
2972
2973 if (!cpcm->stream[0].substreams && !cpcm->stream[1].substreams)
Takashi Iwai41b5b012009-01-20 18:21:23 +01002974 continue; /* no substreams assigned */
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002975
2976 if (!cpcm->pcm) {
2977 dev = get_empty_pcm_device(codec->bus, cpcm->pcm_type);
2978 if (dev < 0)
Takashi Iwai6e655bf2009-03-02 10:46:03 +01002979 continue; /* no fatal error */
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002980 cpcm->device = dev;
2981 err = snd_hda_attach_pcm(codec, cpcm);
Takashi Iwai6e655bf2009-03-02 10:46:03 +01002982 if (err < 0) {
2983 printk(KERN_ERR "hda_codec: cannot attach "
2984 "PCM stream %d for codec #%d\n",
2985 dev, codec->addr);
2986 continue; /* no fatal error */
2987 }
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002988 }
2989 }
2990 return 0;
2991}
2992
Linus Torvalds1da177e2005-04-16 15:20:36 -07002993/**
2994 * snd_hda_build_pcms - build PCM information
2995 * @bus: the BUS
2996 *
2997 * Create PCM information for each codec included in the bus.
2998 *
2999 * The build_pcms codec patch is requested to set up codec->num_pcms and
3000 * codec->pcm_info properly. The array is referred by the top-level driver
3001 * to create its PCM instances.
3002 * The allocated codec->pcm_info should be released in codec->patch_ops.free
3003 * callback.
3004 *
3005 * At least, substreams, channels_min and channels_max must be filled for
3006 * each stream. substreams = 0 indicates that the stream doesn't exist.
3007 * When rates and/or formats are zero, the supported values are queried
3008 * from the given nid. The nid is used also by the default ops.prepare
3009 * and ops.cleanup callbacks.
3010 *
3011 * The driver needs to call ops.open in its open callback. Similarly,
3012 * ops.close is supposed to be called in the close callback.
3013 * ops.prepare should be called in the prepare or hw_params callback
3014 * with the proper parameters for set up.
3015 * ops.cleanup should be called in hw_free for clean up of streams.
3016 *
3017 * This function returns 0 if successfull, or a negative error code.
3018 */
Takashi Iwai529bd6c2008-11-27 14:17:01 +01003019int __devinit snd_hda_build_pcms(struct hda_bus *bus)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003020{
Takashi Iwai0ba21762007-04-16 11:29:14 +02003021 struct hda_codec *codec;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003022
Takashi Iwai0ba21762007-04-16 11:29:14 +02003023 list_for_each_entry(codec, &bus->codec_list, list) {
Takashi Iwai529bd6c2008-11-27 14:17:01 +01003024 int err = snd_hda_codec_build_pcms(codec);
3025 if (err < 0)
3026 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003027 }
3028 return 0;
3029}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003030EXPORT_SYMBOL_HDA(snd_hda_build_pcms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003031
Linus Torvalds1da177e2005-04-16 15:20:36 -07003032/**
3033 * snd_hda_check_board_config - compare the current codec with the config table
3034 * @codec: the HDA codec
Takashi Iwaif5fcc132006-11-24 17:07:44 +01003035 * @num_configs: number of config enums
3036 * @models: array of model name strings
Linus Torvalds1da177e2005-04-16 15:20:36 -07003037 * @tbl: configuration table, terminated by null entries
3038 *
3039 * Compares the modelname or PCI subsystem id of the current codec with the
3040 * given configuration table. If a matching entry is found, returns its
3041 * config value (supposed to be 0 or positive).
3042 *
3043 * If no entries are matching, the function returns a negative value.
3044 */
Takashi Iwai12f288b2007-08-02 15:51:59 +02003045int snd_hda_check_board_config(struct hda_codec *codec,
3046 int num_configs, const char **models,
3047 const struct snd_pci_quirk *tbl)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003048{
Takashi Iwaif44ac832008-07-30 15:01:45 +02003049 if (codec->modelname && models) {
Takashi Iwaif5fcc132006-11-24 17:07:44 +01003050 int i;
3051 for (i = 0; i < num_configs; i++) {
3052 if (models[i] &&
Takashi Iwaif44ac832008-07-30 15:01:45 +02003053 !strcmp(codec->modelname, models[i])) {
Takashi Iwaif5fcc132006-11-24 17:07:44 +01003054 snd_printd(KERN_INFO "hda_codec: model '%s' is "
3055 "selected\n", models[i]);
3056 return i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003057 }
3058 }
3059 }
3060
Takashi Iwaif5fcc132006-11-24 17:07:44 +01003061 if (!codec->bus->pci || !tbl)
3062 return -1;
3063
3064 tbl = snd_pci_quirk_lookup(codec->bus->pci, tbl);
3065 if (!tbl)
3066 return -1;
3067 if (tbl->value >= 0 && tbl->value < num_configs) {
Takashi Iwai62cf8722008-05-20 12:15:15 +02003068#ifdef CONFIG_SND_DEBUG_VERBOSE
Takashi Iwaif5fcc132006-11-24 17:07:44 +01003069 char tmp[10];
3070 const char *model = NULL;
3071 if (models)
3072 model = models[tbl->value];
3073 if (!model) {
3074 sprintf(tmp, "#%d", tbl->value);
3075 model = tmp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003076 }
Takashi Iwaif5fcc132006-11-24 17:07:44 +01003077 snd_printdd(KERN_INFO "hda_codec: model '%s' is selected "
3078 "for config %x:%x (%s)\n",
3079 model, tbl->subvendor, tbl->subdevice,
3080 (tbl->name ? tbl->name : "Unknown device"));
3081#endif
3082 return tbl->value;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003083 }
3084 return -1;
3085}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003086EXPORT_SYMBOL_HDA(snd_hda_check_board_config);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003087
3088/**
Mauro Carvalho Chehab2eda3442008-08-11 10:18:39 +02003089 * snd_hda_check_board_codec_sid_config - compare the current codec
3090 subsystem ID with the
3091 config table
3092
3093 This is important for Gateway notebooks with SB450 HDA Audio
3094 where the vendor ID of the PCI device is:
3095 ATI Technologies Inc SB450 HDA Audio [1002:437b]
3096 and the vendor/subvendor are found only at the codec.
3097
3098 * @codec: the HDA codec
3099 * @num_configs: number of config enums
3100 * @models: array of model name strings
3101 * @tbl: configuration table, terminated by null entries
3102 *
3103 * Compares the modelname or PCI subsystem id of the current codec with the
3104 * given configuration table. If a matching entry is found, returns its
3105 * config value (supposed to be 0 or positive).
3106 *
3107 * If no entries are matching, the function returns a negative value.
3108 */
3109int snd_hda_check_board_codec_sid_config(struct hda_codec *codec,
3110 int num_configs, const char **models,
3111 const struct snd_pci_quirk *tbl)
3112{
3113 const struct snd_pci_quirk *q;
3114
3115 /* Search for codec ID */
3116 for (q = tbl; q->subvendor; q++) {
3117 unsigned long vendorid = (q->subdevice) | (q->subvendor << 16);
3118
3119 if (vendorid == codec->subsystem_id)
3120 break;
3121 }
3122
3123 if (!q->subvendor)
3124 return -1;
3125
3126 tbl = q;
3127
3128 if (tbl->value >= 0 && tbl->value < num_configs) {
Takashi Iwaid94ff6b2009-09-02 00:20:21 +02003129#ifdef CONFIG_SND_DEBUG_VERBOSE
Mauro Carvalho Chehab2eda3442008-08-11 10:18:39 +02003130 char tmp[10];
3131 const char *model = NULL;
3132 if (models)
3133 model = models[tbl->value];
3134 if (!model) {
3135 sprintf(tmp, "#%d", tbl->value);
3136 model = tmp;
3137 }
3138 snd_printdd(KERN_INFO "hda_codec: model '%s' is selected "
3139 "for config %x:%x (%s)\n",
3140 model, tbl->subvendor, tbl->subdevice,
3141 (tbl->name ? tbl->name : "Unknown device"));
3142#endif
3143 return tbl->value;
3144 }
3145 return -1;
3146}
3147EXPORT_SYMBOL_HDA(snd_hda_check_board_codec_sid_config);
3148
3149/**
Linus Torvalds1da177e2005-04-16 15:20:36 -07003150 * snd_hda_add_new_ctls - create controls from the array
3151 * @codec: the HDA codec
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01003152 * @knew: the array of struct snd_kcontrol_new
Linus Torvalds1da177e2005-04-16 15:20:36 -07003153 *
3154 * This helper function creates and add new controls in the given array.
3155 * The array must be terminated with an empty entry as terminator.
3156 *
3157 * Returns 0 if successful, or a negative error code.
3158 */
Takashi Iwai12f288b2007-08-02 15:51:59 +02003159int snd_hda_add_new_ctls(struct hda_codec *codec, struct snd_kcontrol_new *knew)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003160{
Takashi Iwaicb53c622007-08-10 17:21:45 +02003161 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003162
3163 for (; knew->name; knew++) {
Takashi Iwai54d17402005-11-21 16:33:22 +01003164 struct snd_kcontrol *kctl;
3165 kctl = snd_ctl_new1(knew, codec);
Takashi Iwai0ba21762007-04-16 11:29:14 +02003166 if (!kctl)
Takashi Iwai54d17402005-11-21 16:33:22 +01003167 return -ENOMEM;
Takashi Iwaid13bd412008-07-30 15:01:45 +02003168 err = snd_hda_ctl_add(codec, kctl);
Takashi Iwai54d17402005-11-21 16:33:22 +01003169 if (err < 0) {
Takashi Iwai0ba21762007-04-16 11:29:14 +02003170 if (!codec->addr)
Takashi Iwai54d17402005-11-21 16:33:22 +01003171 return err;
3172 kctl = snd_ctl_new1(knew, codec);
Takashi Iwai0ba21762007-04-16 11:29:14 +02003173 if (!kctl)
Takashi Iwai54d17402005-11-21 16:33:22 +01003174 return -ENOMEM;
3175 kctl->id.device = codec->addr;
Takashi Iwaid13bd412008-07-30 15:01:45 +02003176 err = snd_hda_ctl_add(codec, kctl);
Takashi Iwai0ba21762007-04-16 11:29:14 +02003177 if (err < 0)
Takashi Iwai54d17402005-11-21 16:33:22 +01003178 return err;
3179 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003180 }
3181 return 0;
3182}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003183EXPORT_SYMBOL_HDA(snd_hda_add_new_ctls);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003184
Takashi Iwaicb53c622007-08-10 17:21:45 +02003185#ifdef CONFIG_SND_HDA_POWER_SAVE
3186static void hda_set_power_state(struct hda_codec *codec, hda_nid_t fg,
3187 unsigned int power_state);
3188
3189static void hda_power_work(struct work_struct *work)
3190{
3191 struct hda_codec *codec =
3192 container_of(work, struct hda_codec, power_work.work);
Takashi Iwai33fa35e2008-11-06 16:50:40 +01003193 struct hda_bus *bus = codec->bus;
Takashi Iwaicb53c622007-08-10 17:21:45 +02003194
Maxim Levitsky2e492462007-09-03 15:26:57 +02003195 if (!codec->power_on || codec->power_count) {
3196 codec->power_transition = 0;
Takashi Iwaicb53c622007-08-10 17:21:45 +02003197 return;
Maxim Levitsky2e492462007-09-03 15:26:57 +02003198 }
Takashi Iwaicb53c622007-08-10 17:21:45 +02003199
3200 hda_call_codec_suspend(codec);
Takashi Iwai33fa35e2008-11-06 16:50:40 +01003201 if (bus->ops.pm_notify)
3202 bus->ops.pm_notify(bus);
Takashi Iwaicb53c622007-08-10 17:21:45 +02003203}
3204
3205static void hda_keep_power_on(struct hda_codec *codec)
3206{
3207 codec->power_count++;
3208 codec->power_on = 1;
Takashi Iwaia2f63092009-11-11 09:34:25 +01003209 codec->power_jiffies = jiffies;
3210}
3211
3212void snd_hda_update_power_acct(struct hda_codec *codec)
3213{
3214 unsigned long delta = jiffies - codec->power_jiffies;
3215 if (codec->power_on)
3216 codec->power_on_acct += delta;
3217 else
3218 codec->power_off_acct += delta;
3219 codec->power_jiffies += delta;
Takashi Iwaicb53c622007-08-10 17:21:45 +02003220}
3221
3222void snd_hda_power_up(struct hda_codec *codec)
3223{
Takashi Iwai33fa35e2008-11-06 16:50:40 +01003224 struct hda_bus *bus = codec->bus;
3225
Takashi Iwaicb53c622007-08-10 17:21:45 +02003226 codec->power_count++;
Takashi Iwaia221e282007-08-16 16:35:33 +02003227 if (codec->power_on || codec->power_transition)
Takashi Iwaicb53c622007-08-10 17:21:45 +02003228 return;
3229
Takashi Iwaia2f63092009-11-11 09:34:25 +01003230 snd_hda_update_power_acct(codec);
Takashi Iwaicb53c622007-08-10 17:21:45 +02003231 codec->power_on = 1;
Takashi Iwaia2f63092009-11-11 09:34:25 +01003232 codec->power_jiffies = jiffies;
Takashi Iwai33fa35e2008-11-06 16:50:40 +01003233 if (bus->ops.pm_notify)
3234 bus->ops.pm_notify(bus);
Takashi Iwaicb53c622007-08-10 17:21:45 +02003235 hda_call_codec_resume(codec);
3236 cancel_delayed_work(&codec->power_work);
Takashi Iwaia221e282007-08-16 16:35:33 +02003237 codec->power_transition = 0;
Takashi Iwaicb53c622007-08-10 17:21:45 +02003238}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003239EXPORT_SYMBOL_HDA(snd_hda_power_up);
Takashi Iwai1289e9e2008-11-27 15:47:11 +01003240
3241#define power_save(codec) \
3242 ((codec)->bus->power_save ? *(codec)->bus->power_save : 0)
Takashi Iwaicb53c622007-08-10 17:21:45 +02003243
Takashi Iwaifee2fba2008-11-27 12:43:28 +01003244#define power_save(codec) \
3245 ((codec)->bus->power_save ? *(codec)->bus->power_save : 0)
3246
Takashi Iwaicb53c622007-08-10 17:21:45 +02003247void snd_hda_power_down(struct hda_codec *codec)
3248{
3249 --codec->power_count;
Takashi Iwaia221e282007-08-16 16:35:33 +02003250 if (!codec->power_on || codec->power_count || codec->power_transition)
Takashi Iwaicb53c622007-08-10 17:21:45 +02003251 return;
Takashi Iwaifee2fba2008-11-27 12:43:28 +01003252 if (power_save(codec)) {
Takashi Iwaia221e282007-08-16 16:35:33 +02003253 codec->power_transition = 1; /* avoid reentrance */
Takashi Iwaic107b412009-01-13 17:46:37 +01003254 queue_delayed_work(codec->bus->workq, &codec->power_work,
Takashi Iwaifee2fba2008-11-27 12:43:28 +01003255 msecs_to_jiffies(power_save(codec) * 1000));
Takashi Iwaia221e282007-08-16 16:35:33 +02003256 }
Takashi Iwaicb53c622007-08-10 17:21:45 +02003257}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003258EXPORT_SYMBOL_HDA(snd_hda_power_down);
Takashi Iwaicb53c622007-08-10 17:21:45 +02003259
3260int snd_hda_check_amp_list_power(struct hda_codec *codec,
3261 struct hda_loopback_check *check,
3262 hda_nid_t nid)
3263{
3264 struct hda_amp_list *p;
3265 int ch, v;
3266
3267 if (!check->amplist)
3268 return 0;
3269 for (p = check->amplist; p->nid; p++) {
3270 if (p->nid == nid)
3271 break;
3272 }
3273 if (!p->nid)
3274 return 0; /* nothing changed */
3275
3276 for (p = check->amplist; p->nid; p++) {
3277 for (ch = 0; ch < 2; ch++) {
3278 v = snd_hda_codec_amp_read(codec, p->nid, ch, p->dir,
3279 p->idx);
3280 if (!(v & HDA_AMP_MUTE) && v > 0) {
3281 if (!check->power_on) {
3282 check->power_on = 1;
3283 snd_hda_power_up(codec);
3284 }
3285 return 1;
3286 }
3287 }
3288 }
3289 if (check->power_on) {
3290 check->power_on = 0;
3291 snd_hda_power_down(codec);
3292 }
3293 return 0;
3294}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003295EXPORT_SYMBOL_HDA(snd_hda_check_amp_list_power);
Takashi Iwaicb53c622007-08-10 17:21:45 +02003296#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07003297
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01003298/*
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01003299 * Channel mode helper
3300 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003301int snd_hda_ch_mode_info(struct hda_codec *codec,
3302 struct snd_ctl_elem_info *uinfo,
3303 const struct hda_channel_mode *chmode,
3304 int num_chmodes)
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01003305{
3306 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
3307 uinfo->count = 1;
3308 uinfo->value.enumerated.items = num_chmodes;
3309 if (uinfo->value.enumerated.item >= num_chmodes)
3310 uinfo->value.enumerated.item = num_chmodes - 1;
3311 sprintf(uinfo->value.enumerated.name, "%dch",
3312 chmode[uinfo->value.enumerated.item].channels);
3313 return 0;
3314}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003315EXPORT_SYMBOL_HDA(snd_hda_ch_mode_info);
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01003316
Takashi Iwai0ba21762007-04-16 11:29:14 +02003317int snd_hda_ch_mode_get(struct hda_codec *codec,
3318 struct snd_ctl_elem_value *ucontrol,
3319 const struct hda_channel_mode *chmode,
3320 int num_chmodes,
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01003321 int max_channels)
3322{
3323 int i;
3324
3325 for (i = 0; i < num_chmodes; i++) {
3326 if (max_channels == chmode[i].channels) {
3327 ucontrol->value.enumerated.item[0] = i;
3328 break;
3329 }
3330 }
3331 return 0;
3332}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003333EXPORT_SYMBOL_HDA(snd_hda_ch_mode_get);
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01003334
Takashi Iwai0ba21762007-04-16 11:29:14 +02003335int snd_hda_ch_mode_put(struct hda_codec *codec,
3336 struct snd_ctl_elem_value *ucontrol,
3337 const struct hda_channel_mode *chmode,
3338 int num_chmodes,
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01003339 int *max_channelsp)
3340{
3341 unsigned int mode;
3342
3343 mode = ucontrol->value.enumerated.item[0];
Takashi Iwai68ea7b22007-11-15 15:54:38 +01003344 if (mode >= num_chmodes)
3345 return -EINVAL;
Takashi Iwai82beb8f2007-08-10 17:09:26 +02003346 if (*max_channelsp == chmode[mode].channels)
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01003347 return 0;
3348 /* change the current channel setting */
3349 *max_channelsp = chmode[mode].channels;
3350 if (chmode[mode].sequence)
Takashi Iwai82beb8f2007-08-10 17:09:26 +02003351 snd_hda_sequence_write_cache(codec, chmode[mode].sequence);
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01003352 return 1;
3353}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003354EXPORT_SYMBOL_HDA(snd_hda_ch_mode_put);
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01003355
Linus Torvalds1da177e2005-04-16 15:20:36 -07003356/*
3357 * input MUX helper
3358 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003359int snd_hda_input_mux_info(const struct hda_input_mux *imux,
3360 struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003361{
3362 unsigned int index;
3363
3364 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
3365 uinfo->count = 1;
3366 uinfo->value.enumerated.items = imux->num_items;
Takashi Iwai5513b0c2007-10-09 11:58:41 +02003367 if (!imux->num_items)
3368 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003369 index = uinfo->value.enumerated.item;
3370 if (index >= imux->num_items)
3371 index = imux->num_items - 1;
3372 strcpy(uinfo->value.enumerated.name, imux->items[index].label);
3373 return 0;
3374}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003375EXPORT_SYMBOL_HDA(snd_hda_input_mux_info);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003376
Takashi Iwai0ba21762007-04-16 11:29:14 +02003377int snd_hda_input_mux_put(struct hda_codec *codec,
3378 const struct hda_input_mux *imux,
3379 struct snd_ctl_elem_value *ucontrol,
3380 hda_nid_t nid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003381 unsigned int *cur_val)
3382{
3383 unsigned int idx;
3384
Takashi Iwai5513b0c2007-10-09 11:58:41 +02003385 if (!imux->num_items)
3386 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003387 idx = ucontrol->value.enumerated.item[0];
3388 if (idx >= imux->num_items)
3389 idx = imux->num_items - 1;
Takashi Iwai82beb8f2007-08-10 17:09:26 +02003390 if (*cur_val == idx)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003391 return 0;
Takashi Iwai82beb8f2007-08-10 17:09:26 +02003392 snd_hda_codec_write_cache(codec, nid, 0, AC_VERB_SET_CONNECT_SEL,
3393 imux->items[idx].index);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003394 *cur_val = idx;
3395 return 1;
3396}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003397EXPORT_SYMBOL_HDA(snd_hda_input_mux_put);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003398
3399
3400/*
3401 * Multi-channel / digital-out PCM helper functions
3402 */
3403
Takashi Iwai6b97eb42007-04-05 14:51:48 +02003404/* setup SPDIF output stream */
3405static void setup_dig_out_stream(struct hda_codec *codec, hda_nid_t nid,
3406 unsigned int stream_tag, unsigned int format)
3407{
3408 /* turn off SPDIF once; otherwise the IEC958 bits won't be updated */
Takashi Iwai2f728532008-09-25 16:32:41 +02003409 if (codec->spdif_status_reset && (codec->spdif_ctls & AC_DIG1_ENABLE))
3410 set_dig_out_convert(codec, nid,
3411 codec->spdif_ctls & ~AC_DIG1_ENABLE & 0xff,
3412 -1);
Takashi Iwai6b97eb42007-04-05 14:51:48 +02003413 snd_hda_codec_setup_stream(codec, nid, stream_tag, 0, format);
Takashi Iwai2f728532008-09-25 16:32:41 +02003414 if (codec->slave_dig_outs) {
3415 hda_nid_t *d;
3416 for (d = codec->slave_dig_outs; *d; d++)
3417 snd_hda_codec_setup_stream(codec, *d, stream_tag, 0,
3418 format);
Matthew Ranostayde51ca12008-09-07 14:31:40 -04003419 }
Takashi Iwai2f728532008-09-25 16:32:41 +02003420 /* turn on again (if needed) */
3421 if (codec->spdif_status_reset && (codec->spdif_ctls & AC_DIG1_ENABLE))
3422 set_dig_out_convert(codec, nid,
3423 codec->spdif_ctls & 0xff, -1);
3424}
Matthew Ranostayde51ca12008-09-07 14:31:40 -04003425
Takashi Iwai2f728532008-09-25 16:32:41 +02003426static void cleanup_dig_out_stream(struct hda_codec *codec, hda_nid_t nid)
3427{
3428 snd_hda_codec_cleanup_stream(codec, nid);
3429 if (codec->slave_dig_outs) {
3430 hda_nid_t *d;
3431 for (d = codec->slave_dig_outs; *d; d++)
3432 snd_hda_codec_cleanup_stream(codec, *d);
3433 }
Takashi Iwai6b97eb42007-04-05 14:51:48 +02003434}
3435
Takashi Iwaifb8d1a32009-11-10 16:02:29 +01003436/* call each reboot notifier */
3437void snd_hda_bus_reboot_notify(struct hda_bus *bus)
3438{
3439 struct hda_codec *codec;
3440
3441 if (!bus)
3442 return;
3443 list_for_each_entry(codec, &bus->codec_list, list) {
3444#ifdef CONFIG_SND_HDA_POWER_SAVE
3445 if (!codec->power_on)
3446 continue;
3447#endif
3448 if (codec->patch_ops.reboot_notify)
3449 codec->patch_ops.reboot_notify(codec);
3450 }
3451}
Takashi Iwai8f217a22009-11-10 18:26:12 +01003452EXPORT_SYMBOL_HDA(snd_hda_bus_reboot_notify);
Takashi Iwaifb8d1a32009-11-10 16:02:29 +01003453
Linus Torvalds1da177e2005-04-16 15:20:36 -07003454/*
3455 * open the digital out in the exclusive mode
3456 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003457int snd_hda_multi_out_dig_open(struct hda_codec *codec,
3458 struct hda_multi_out *mout)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003459{
Ingo Molnar62932df2006-01-16 16:34:20 +01003460 mutex_lock(&codec->spdif_mutex);
Takashi Iwai5930ca42007-04-16 11:23:56 +02003461 if (mout->dig_out_used == HDA_DIG_ANALOG_DUP)
3462 /* already opened as analog dup; reset it once */
Takashi Iwai2f728532008-09-25 16:32:41 +02003463 cleanup_dig_out_stream(codec, mout->dig_out_nid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003464 mout->dig_out_used = HDA_DIG_EXCLUSIVE;
Ingo Molnar62932df2006-01-16 16:34:20 +01003465 mutex_unlock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003466 return 0;
3467}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003468EXPORT_SYMBOL_HDA(snd_hda_multi_out_dig_open);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003469
Takashi Iwai6b97eb42007-04-05 14:51:48 +02003470int snd_hda_multi_out_dig_prepare(struct hda_codec *codec,
3471 struct hda_multi_out *mout,
3472 unsigned int stream_tag,
3473 unsigned int format,
3474 struct snd_pcm_substream *substream)
3475{
3476 mutex_lock(&codec->spdif_mutex);
3477 setup_dig_out_stream(codec, mout->dig_out_nid, stream_tag, format);
3478 mutex_unlock(&codec->spdif_mutex);
3479 return 0;
3480}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003481EXPORT_SYMBOL_HDA(snd_hda_multi_out_dig_prepare);
Takashi Iwai6b97eb42007-04-05 14:51:48 +02003482
Takashi Iwai9411e212009-02-13 11:32:28 +01003483int snd_hda_multi_out_dig_cleanup(struct hda_codec *codec,
3484 struct hda_multi_out *mout)
3485{
3486 mutex_lock(&codec->spdif_mutex);
3487 cleanup_dig_out_stream(codec, mout->dig_out_nid);
3488 mutex_unlock(&codec->spdif_mutex);
3489 return 0;
3490}
3491EXPORT_SYMBOL_HDA(snd_hda_multi_out_dig_cleanup);
3492
Linus Torvalds1da177e2005-04-16 15:20:36 -07003493/*
3494 * release the digital out
3495 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003496int snd_hda_multi_out_dig_close(struct hda_codec *codec,
3497 struct hda_multi_out *mout)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003498{
Ingo Molnar62932df2006-01-16 16:34:20 +01003499 mutex_lock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003500 mout->dig_out_used = 0;
Ingo Molnar62932df2006-01-16 16:34:20 +01003501 mutex_unlock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003502 return 0;
3503}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003504EXPORT_SYMBOL_HDA(snd_hda_multi_out_dig_close);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003505
3506/*
3507 * set up more restrictions for analog out
3508 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003509int snd_hda_multi_out_analog_open(struct hda_codec *codec,
3510 struct hda_multi_out *mout,
Takashi Iwai9a081602008-02-12 18:37:26 +01003511 struct snd_pcm_substream *substream,
3512 struct hda_pcm_stream *hinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003513{
Takashi Iwai9a081602008-02-12 18:37:26 +01003514 struct snd_pcm_runtime *runtime = substream->runtime;
3515 runtime->hw.channels_max = mout->max_channels;
3516 if (mout->dig_out_nid) {
3517 if (!mout->analog_rates) {
3518 mout->analog_rates = hinfo->rates;
3519 mout->analog_formats = hinfo->formats;
3520 mout->analog_maxbps = hinfo->maxbps;
3521 } else {
3522 runtime->hw.rates = mout->analog_rates;
3523 runtime->hw.formats = mout->analog_formats;
3524 hinfo->maxbps = mout->analog_maxbps;
3525 }
3526 if (!mout->spdif_rates) {
3527 snd_hda_query_supported_pcm(codec, mout->dig_out_nid,
3528 &mout->spdif_rates,
3529 &mout->spdif_formats,
3530 &mout->spdif_maxbps);
3531 }
3532 mutex_lock(&codec->spdif_mutex);
3533 if (mout->share_spdif) {
Takashi Iwai022b4662009-07-03 23:03:30 +02003534 if ((runtime->hw.rates & mout->spdif_rates) &&
3535 (runtime->hw.formats & mout->spdif_formats)) {
3536 runtime->hw.rates &= mout->spdif_rates;
3537 runtime->hw.formats &= mout->spdif_formats;
3538 if (mout->spdif_maxbps < hinfo->maxbps)
3539 hinfo->maxbps = mout->spdif_maxbps;
3540 } else {
3541 mout->share_spdif = 0;
3542 /* FIXME: need notify? */
3543 }
Takashi Iwai9a081602008-02-12 18:37:26 +01003544 }
Frederik Deweerdteaa99852008-04-14 13:11:44 +02003545 mutex_unlock(&codec->spdif_mutex);
Takashi Iwai9a081602008-02-12 18:37:26 +01003546 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003547 return snd_pcm_hw_constraint_step(substream->runtime, 0,
3548 SNDRV_PCM_HW_PARAM_CHANNELS, 2);
3549}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003550EXPORT_SYMBOL_HDA(snd_hda_multi_out_analog_open);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003551
3552/*
3553 * set up the i/o for analog out
3554 * when the digital out is available, copy the front out to digital out, too.
3555 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003556int snd_hda_multi_out_analog_prepare(struct hda_codec *codec,
3557 struct hda_multi_out *mout,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003558 unsigned int stream_tag,
3559 unsigned int format,
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01003560 struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003561{
3562 hda_nid_t *nids = mout->dac_nids;
3563 int chs = substream->runtime->channels;
3564 int i;
3565
Ingo Molnar62932df2006-01-16 16:34:20 +01003566 mutex_lock(&codec->spdif_mutex);
Takashi Iwai9a081602008-02-12 18:37:26 +01003567 if (mout->dig_out_nid && mout->share_spdif &&
3568 mout->dig_out_used != HDA_DIG_EXCLUSIVE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003569 if (chs == 2 &&
Takashi Iwai0ba21762007-04-16 11:29:14 +02003570 snd_hda_is_supported_format(codec, mout->dig_out_nid,
3571 format) &&
3572 !(codec->spdif_status & IEC958_AES0_NONAUDIO)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003573 mout->dig_out_used = HDA_DIG_ANALOG_DUP;
Takashi Iwai6b97eb42007-04-05 14:51:48 +02003574 setup_dig_out_stream(codec, mout->dig_out_nid,
3575 stream_tag, format);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003576 } else {
3577 mout->dig_out_used = 0;
Takashi Iwai2f728532008-09-25 16:32:41 +02003578 cleanup_dig_out_stream(codec, mout->dig_out_nid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003579 }
3580 }
Ingo Molnar62932df2006-01-16 16:34:20 +01003581 mutex_unlock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003582
3583 /* front */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003584 snd_hda_codec_setup_stream(codec, nids[HDA_FRONT], stream_tag,
3585 0, format);
Takashi Iwaid29240c2007-10-26 12:35:56 +02003586 if (!mout->no_share_stream &&
3587 mout->hp_nid && mout->hp_nid != nids[HDA_FRONT])
Linus Torvalds1da177e2005-04-16 15:20:36 -07003588 /* headphone out will just decode front left/right (stereo) */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003589 snd_hda_codec_setup_stream(codec, mout->hp_nid, stream_tag,
3590 0, format);
Takashi Iwai82bc9552006-03-21 11:24:42 +01003591 /* extra outputs copied from front */
3592 for (i = 0; i < ARRAY_SIZE(mout->extra_out_nid); i++)
Takashi Iwaid29240c2007-10-26 12:35:56 +02003593 if (!mout->no_share_stream && mout->extra_out_nid[i])
Takashi Iwai82bc9552006-03-21 11:24:42 +01003594 snd_hda_codec_setup_stream(codec,
3595 mout->extra_out_nid[i],
3596 stream_tag, 0, format);
3597
Linus Torvalds1da177e2005-04-16 15:20:36 -07003598 /* surrounds */
3599 for (i = 1; i < mout->num_dacs; i++) {
Takashi Iwai4b3acaf2005-06-10 19:48:10 +02003600 if (chs >= (i + 1) * 2) /* independent out */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003601 snd_hda_codec_setup_stream(codec, nids[i], stream_tag,
3602 i * 2, format);
Takashi Iwaid29240c2007-10-26 12:35:56 +02003603 else if (!mout->no_share_stream) /* copy front */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003604 snd_hda_codec_setup_stream(codec, nids[i], stream_tag,
3605 0, format);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003606 }
3607 return 0;
3608}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003609EXPORT_SYMBOL_HDA(snd_hda_multi_out_analog_prepare);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003610
3611/*
3612 * clean up the setting for analog out
3613 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003614int snd_hda_multi_out_analog_cleanup(struct hda_codec *codec,
3615 struct hda_multi_out *mout)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003616{
3617 hda_nid_t *nids = mout->dac_nids;
3618 int i;
3619
3620 for (i = 0; i < mout->num_dacs; i++)
Takashi Iwai888afa12008-03-18 09:57:50 +01003621 snd_hda_codec_cleanup_stream(codec, nids[i]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003622 if (mout->hp_nid)
Takashi Iwai888afa12008-03-18 09:57:50 +01003623 snd_hda_codec_cleanup_stream(codec, mout->hp_nid);
Takashi Iwai82bc9552006-03-21 11:24:42 +01003624 for (i = 0; i < ARRAY_SIZE(mout->extra_out_nid); i++)
3625 if (mout->extra_out_nid[i])
Takashi Iwai888afa12008-03-18 09:57:50 +01003626 snd_hda_codec_cleanup_stream(codec,
3627 mout->extra_out_nid[i]);
Ingo Molnar62932df2006-01-16 16:34:20 +01003628 mutex_lock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003629 if (mout->dig_out_nid && mout->dig_out_used == HDA_DIG_ANALOG_DUP) {
Takashi Iwai2f728532008-09-25 16:32:41 +02003630 cleanup_dig_out_stream(codec, mout->dig_out_nid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003631 mout->dig_out_used = 0;
3632 }
Ingo Molnar62932df2006-01-16 16:34:20 +01003633 mutex_unlock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003634 return 0;
3635}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003636EXPORT_SYMBOL_HDA(snd_hda_multi_out_analog_cleanup);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003637
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003638/*
Wu Fengguang6b345002008-10-07 14:21:41 +08003639 * Helper for automatic pin configuration
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003640 */
Kailang Yangdf694da2005-12-05 19:42:22 +01003641
Takashi Iwai12f288b2007-08-02 15:51:59 +02003642static int is_in_nid_list(hda_nid_t nid, hda_nid_t *list)
Kailang Yangdf694da2005-12-05 19:42:22 +01003643{
3644 for (; *list; list++)
3645 if (*list == nid)
3646 return 1;
3647 return 0;
3648}
3649
Steve Longerbeam81937d32007-05-08 15:33:03 +02003650
3651/*
3652 * Sort an associated group of pins according to their sequence numbers.
3653 */
3654static void sort_pins_by_sequence(hda_nid_t * pins, short * sequences,
3655 int num_pins)
3656{
3657 int i, j;
3658 short seq;
3659 hda_nid_t nid;
3660
3661 for (i = 0; i < num_pins; i++) {
3662 for (j = i + 1; j < num_pins; j++) {
3663 if (sequences[i] > sequences[j]) {
3664 seq = sequences[i];
3665 sequences[i] = sequences[j];
3666 sequences[j] = seq;
3667 nid = pins[i];
3668 pins[i] = pins[j];
3669 pins[j] = nid;
3670 }
3671 }
3672 }
3673}
3674
3675
Takashi Iwai82bc9552006-03-21 11:24:42 +01003676/*
3677 * Parse all pin widgets and store the useful pin nids to cfg
3678 *
3679 * The number of line-outs or any primary output is stored in line_outs,
3680 * and the corresponding output pins are assigned to line_out_pins[],
3681 * in the order of front, rear, CLFE, side, ...
3682 *
3683 * If more extra outputs (speaker and headphone) are found, the pins are
Takashi Iwaieb06ed82006-09-20 17:10:27 +02003684 * assisnged to hp_pins[] and speaker_pins[], respectively. If no line-out jack
Takashi Iwai82bc9552006-03-21 11:24:42 +01003685 * is detected, one of speaker of HP pins is assigned as the primary
3686 * output, i.e. to line_out_pins[0]. So, line_outs is always positive
3687 * if any analog output exists.
3688 *
3689 * The analog input pins are assigned to input_pins array.
3690 * The digital input/output pins are assigned to dig_in_pin and dig_out_pin,
3691 * respectively.
3692 */
Takashi Iwai12f288b2007-08-02 15:51:59 +02003693int snd_hda_parse_pin_def_config(struct hda_codec *codec,
3694 struct auto_pin_cfg *cfg,
3695 hda_nid_t *ignore_nids)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003696{
Takashi Iwai0ef6ce72008-01-22 15:35:37 +01003697 hda_nid_t nid, end_nid;
Steve Longerbeam81937d32007-05-08 15:33:03 +02003698 short seq, assoc_line_out, assoc_speaker;
3699 short sequences_line_out[ARRAY_SIZE(cfg->line_out_pins)];
3700 short sequences_speaker[ARRAY_SIZE(cfg->speaker_pins)];
Takashi Iwaif889fa92007-10-31 15:49:32 +01003701 short sequences_hp[ARRAY_SIZE(cfg->hp_pins)];
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003702
3703 memset(cfg, 0, sizeof(*cfg));
3704
Steve Longerbeam81937d32007-05-08 15:33:03 +02003705 memset(sequences_line_out, 0, sizeof(sequences_line_out));
3706 memset(sequences_speaker, 0, sizeof(sequences_speaker));
Takashi Iwaif889fa92007-10-31 15:49:32 +01003707 memset(sequences_hp, 0, sizeof(sequences_hp));
Steve Longerbeam81937d32007-05-08 15:33:03 +02003708 assoc_line_out = assoc_speaker = 0;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003709
Takashi Iwai0ef6ce72008-01-22 15:35:37 +01003710 end_nid = codec->start_nid + codec->num_nodes;
3711 for (nid = codec->start_nid; nid < end_nid; nid++) {
Takashi Iwai54d17402005-11-21 16:33:22 +01003712 unsigned int wid_caps = get_wcaps(codec, nid);
Takashi Iwaia22d5432009-07-27 12:54:26 +02003713 unsigned int wid_type = get_wcaps_type(wid_caps);
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003714 unsigned int def_conf;
3715 short assoc, loc;
3716
3717 /* read all default configuration for pin complex */
3718 if (wid_type != AC_WID_PIN)
3719 continue;
Kailang Yangdf694da2005-12-05 19:42:22 +01003720 /* ignore the given nids (e.g. pc-beep returns error) */
3721 if (ignore_nids && is_in_nid_list(nid, ignore_nids))
3722 continue;
3723
Takashi Iwaic17a1ab2009-02-23 09:28:12 +01003724 def_conf = snd_hda_codec_get_pincfg(codec, nid);
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003725 if (get_defcfg_connect(def_conf) == AC_JACK_PORT_NONE)
3726 continue;
3727 loc = get_defcfg_location(def_conf);
3728 switch (get_defcfg_device(def_conf)) {
3729 case AC_JACK_LINE_OUT:
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003730 seq = get_defcfg_sequence(def_conf);
3731 assoc = get_defcfg_association(def_conf);
Matthew Ranostay90da78b2008-01-24 11:48:01 +01003732
3733 if (!(wid_caps & AC_WCAP_STEREO))
3734 if (!cfg->mono_out_pin)
3735 cfg->mono_out_pin = nid;
Takashi Iwai0ba21762007-04-16 11:29:14 +02003736 if (!assoc)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003737 continue;
Takashi Iwai0ba21762007-04-16 11:29:14 +02003738 if (!assoc_line_out)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003739 assoc_line_out = assoc;
3740 else if (assoc_line_out != assoc)
3741 continue;
3742 if (cfg->line_outs >= ARRAY_SIZE(cfg->line_out_pins))
3743 continue;
3744 cfg->line_out_pins[cfg->line_outs] = nid;
Steve Longerbeam81937d32007-05-08 15:33:03 +02003745 sequences_line_out[cfg->line_outs] = seq;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003746 cfg->line_outs++;
3747 break;
Takashi Iwai8d88bc32005-11-17 11:09:23 +01003748 case AC_JACK_SPEAKER:
Steve Longerbeam81937d32007-05-08 15:33:03 +02003749 seq = get_defcfg_sequence(def_conf);
3750 assoc = get_defcfg_association(def_conf);
3751 if (! assoc)
3752 continue;
3753 if (! assoc_speaker)
3754 assoc_speaker = assoc;
3755 else if (assoc_speaker != assoc)
3756 continue;
Takashi Iwai82bc9552006-03-21 11:24:42 +01003757 if (cfg->speaker_outs >= ARRAY_SIZE(cfg->speaker_pins))
3758 continue;
3759 cfg->speaker_pins[cfg->speaker_outs] = nid;
Steve Longerbeam81937d32007-05-08 15:33:03 +02003760 sequences_speaker[cfg->speaker_outs] = seq;
Takashi Iwai82bc9552006-03-21 11:24:42 +01003761 cfg->speaker_outs++;
Takashi Iwai8d88bc32005-11-17 11:09:23 +01003762 break;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003763 case AC_JACK_HP_OUT:
Takashi Iwaif889fa92007-10-31 15:49:32 +01003764 seq = get_defcfg_sequence(def_conf);
3765 assoc = get_defcfg_association(def_conf);
Takashi Iwaieb06ed82006-09-20 17:10:27 +02003766 if (cfg->hp_outs >= ARRAY_SIZE(cfg->hp_pins))
3767 continue;
3768 cfg->hp_pins[cfg->hp_outs] = nid;
Takashi Iwaif889fa92007-10-31 15:49:32 +01003769 sequences_hp[cfg->hp_outs] = (assoc << 4) | seq;
Takashi Iwaieb06ed82006-09-20 17:10:27 +02003770 cfg->hp_outs++;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003771 break;
Takashi Iwai314634b2006-09-21 11:56:18 +02003772 case AC_JACK_MIC_IN: {
3773 int preferred, alt;
3774 if (loc == AC_JACK_LOC_FRONT) {
3775 preferred = AUTO_PIN_FRONT_MIC;
3776 alt = AUTO_PIN_MIC;
3777 } else {
3778 preferred = AUTO_PIN_MIC;
3779 alt = AUTO_PIN_FRONT_MIC;
3780 }
3781 if (!cfg->input_pins[preferred])
3782 cfg->input_pins[preferred] = nid;
3783 else if (!cfg->input_pins[alt])
3784 cfg->input_pins[alt] = nid;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003785 break;
Takashi Iwai314634b2006-09-21 11:56:18 +02003786 }
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003787 case AC_JACK_LINE_IN:
3788 if (loc == AC_JACK_LOC_FRONT)
3789 cfg->input_pins[AUTO_PIN_FRONT_LINE] = nid;
3790 else
3791 cfg->input_pins[AUTO_PIN_LINE] = nid;
3792 break;
3793 case AC_JACK_CD:
3794 cfg->input_pins[AUTO_PIN_CD] = nid;
3795 break;
3796 case AC_JACK_AUX:
3797 cfg->input_pins[AUTO_PIN_AUX] = nid;
3798 break;
3799 case AC_JACK_SPDIF_OUT:
Takashi Iwai1b52ae72009-01-20 17:17:29 +01003800 case AC_JACK_DIG_OTHER_OUT:
Takashi Iwai0852d7a2009-02-11 11:35:15 +01003801 if (cfg->dig_outs >= ARRAY_SIZE(cfg->dig_out_pins))
3802 continue;
3803 cfg->dig_out_pins[cfg->dig_outs] = nid;
3804 cfg->dig_out_type[cfg->dig_outs] =
3805 (loc == AC_JACK_LOC_HDMI) ?
3806 HDA_PCM_TYPE_HDMI : HDA_PCM_TYPE_SPDIF;
3807 cfg->dig_outs++;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003808 break;
3809 case AC_JACK_SPDIF_IN:
Takashi Iwai1b52ae72009-01-20 17:17:29 +01003810 case AC_JACK_DIG_OTHER_IN:
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003811 cfg->dig_in_pin = nid;
Takashi Iwai2297bd62009-01-20 18:24:13 +01003812 if (loc == AC_JACK_LOC_HDMI)
3813 cfg->dig_in_type = HDA_PCM_TYPE_HDMI;
3814 else
3815 cfg->dig_in_type = HDA_PCM_TYPE_SPDIF;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003816 break;
3817 }
3818 }
3819
Takashi Iwai5832fcf2008-02-12 18:30:12 +01003820 /* FIX-UP:
3821 * If no line-out is defined but multiple HPs are found,
3822 * some of them might be the real line-outs.
3823 */
3824 if (!cfg->line_outs && cfg->hp_outs > 1) {
3825 int i = 0;
3826 while (i < cfg->hp_outs) {
3827 /* The real HPs should have the sequence 0x0f */
3828 if ((sequences_hp[i] & 0x0f) == 0x0f) {
3829 i++;
3830 continue;
3831 }
3832 /* Move it to the line-out table */
3833 cfg->line_out_pins[cfg->line_outs] = cfg->hp_pins[i];
3834 sequences_line_out[cfg->line_outs] = sequences_hp[i];
3835 cfg->line_outs++;
3836 cfg->hp_outs--;
3837 memmove(cfg->hp_pins + i, cfg->hp_pins + i + 1,
3838 sizeof(cfg->hp_pins[0]) * (cfg->hp_outs - i));
3839 memmove(sequences_hp + i - 1, sequences_hp + i,
3840 sizeof(sequences_hp[0]) * (cfg->hp_outs - i));
3841 }
3842 }
3843
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003844 /* sort by sequence */
Steve Longerbeam81937d32007-05-08 15:33:03 +02003845 sort_pins_by_sequence(cfg->line_out_pins, sequences_line_out,
3846 cfg->line_outs);
3847 sort_pins_by_sequence(cfg->speaker_pins, sequences_speaker,
3848 cfg->speaker_outs);
Takashi Iwaif889fa92007-10-31 15:49:32 +01003849 sort_pins_by_sequence(cfg->hp_pins, sequences_hp,
3850 cfg->hp_outs);
Steve Longerbeam81937d32007-05-08 15:33:03 +02003851
Takashi Iwaif889fa92007-10-31 15:49:32 +01003852 /* if we have only one mic, make it AUTO_PIN_MIC */
3853 if (!cfg->input_pins[AUTO_PIN_MIC] &&
3854 cfg->input_pins[AUTO_PIN_FRONT_MIC]) {
3855 cfg->input_pins[AUTO_PIN_MIC] =
3856 cfg->input_pins[AUTO_PIN_FRONT_MIC];
3857 cfg->input_pins[AUTO_PIN_FRONT_MIC] = 0;
3858 }
3859 /* ditto for line-in */
3860 if (!cfg->input_pins[AUTO_PIN_LINE] &&
3861 cfg->input_pins[AUTO_PIN_FRONT_LINE]) {
3862 cfg->input_pins[AUTO_PIN_LINE] =
3863 cfg->input_pins[AUTO_PIN_FRONT_LINE];
3864 cfg->input_pins[AUTO_PIN_FRONT_LINE] = 0;
3865 }
3866
Steve Longerbeam81937d32007-05-08 15:33:03 +02003867 /*
3868 * FIX-UP: if no line-outs are detected, try to use speaker or HP pin
3869 * as a primary output
3870 */
3871 if (!cfg->line_outs) {
3872 if (cfg->speaker_outs) {
3873 cfg->line_outs = cfg->speaker_outs;
3874 memcpy(cfg->line_out_pins, cfg->speaker_pins,
3875 sizeof(cfg->speaker_pins));
3876 cfg->speaker_outs = 0;
3877 memset(cfg->speaker_pins, 0, sizeof(cfg->speaker_pins));
3878 cfg->line_out_type = AUTO_PIN_SPEAKER_OUT;
3879 } else if (cfg->hp_outs) {
3880 cfg->line_outs = cfg->hp_outs;
3881 memcpy(cfg->line_out_pins, cfg->hp_pins,
3882 sizeof(cfg->hp_pins));
3883 cfg->hp_outs = 0;
3884 memset(cfg->hp_pins, 0, sizeof(cfg->hp_pins));
3885 cfg->line_out_type = AUTO_PIN_HP_OUT;
3886 }
3887 }
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003888
Takashi Iwaicb8e2f82005-07-29 11:54:32 +02003889 /* Reorder the surround channels
3890 * ALSA sequence is front/surr/clfe/side
3891 * HDA sequence is:
3892 * 4-ch: front/surr => OK as it is
3893 * 6-ch: front/clfe/surr
Takashi Iwai9422db42007-04-20 16:11:43 +02003894 * 8-ch: front/clfe/rear/side|fc
Takashi Iwaicb8e2f82005-07-29 11:54:32 +02003895 */
3896 switch (cfg->line_outs) {
3897 case 3:
Takashi Iwaicb8e2f82005-07-29 11:54:32 +02003898 case 4:
3899 nid = cfg->line_out_pins[1];
Takashi Iwai9422db42007-04-20 16:11:43 +02003900 cfg->line_out_pins[1] = cfg->line_out_pins[2];
Takashi Iwaicb8e2f82005-07-29 11:54:32 +02003901 cfg->line_out_pins[2] = nid;
3902 break;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003903 }
3904
Takashi Iwai82bc9552006-03-21 11:24:42 +01003905 /*
3906 * debug prints of the parsed results
3907 */
3908 snd_printd("autoconfig: line_outs=%d (0x%x/0x%x/0x%x/0x%x/0x%x)\n",
3909 cfg->line_outs, cfg->line_out_pins[0], cfg->line_out_pins[1],
3910 cfg->line_out_pins[2], cfg->line_out_pins[3],
3911 cfg->line_out_pins[4]);
3912 snd_printd(" speaker_outs=%d (0x%x/0x%x/0x%x/0x%x/0x%x)\n",
3913 cfg->speaker_outs, cfg->speaker_pins[0],
3914 cfg->speaker_pins[1], cfg->speaker_pins[2],
3915 cfg->speaker_pins[3], cfg->speaker_pins[4]);
Takashi Iwaieb06ed82006-09-20 17:10:27 +02003916 snd_printd(" hp_outs=%d (0x%x/0x%x/0x%x/0x%x/0x%x)\n",
3917 cfg->hp_outs, cfg->hp_pins[0],
3918 cfg->hp_pins[1], cfg->hp_pins[2],
3919 cfg->hp_pins[3], cfg->hp_pins[4]);
Matthew Ranostay90da78b2008-01-24 11:48:01 +01003920 snd_printd(" mono: mono_out=0x%x\n", cfg->mono_out_pin);
Takashi Iwai0852d7a2009-02-11 11:35:15 +01003921 if (cfg->dig_outs)
3922 snd_printd(" dig-out=0x%x/0x%x\n",
3923 cfg->dig_out_pins[0], cfg->dig_out_pins[1]);
Takashi Iwai82bc9552006-03-21 11:24:42 +01003924 snd_printd(" inputs: mic=0x%x, fmic=0x%x, line=0x%x, fline=0x%x,"
3925 " cd=0x%x, aux=0x%x\n",
3926 cfg->input_pins[AUTO_PIN_MIC],
3927 cfg->input_pins[AUTO_PIN_FRONT_MIC],
3928 cfg->input_pins[AUTO_PIN_LINE],
3929 cfg->input_pins[AUTO_PIN_FRONT_LINE],
3930 cfg->input_pins[AUTO_PIN_CD],
3931 cfg->input_pins[AUTO_PIN_AUX]);
Takashi Iwai32d2c7f2009-02-11 11:33:13 +01003932 if (cfg->dig_in_pin)
Takashi Iwai89ce9e82009-01-20 17:15:57 +01003933 snd_printd(" dig-in=0x%x\n", cfg->dig_in_pin);
Takashi Iwai82bc9552006-03-21 11:24:42 +01003934
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003935 return 0;
3936}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003937EXPORT_SYMBOL_HDA(snd_hda_parse_pin_def_config);
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003938
Takashi Iwai4a471b72005-12-07 13:56:29 +01003939/* labels for input pins */
3940const char *auto_pin_cfg_labels[AUTO_PIN_LAST] = {
3941 "Mic", "Front Mic", "Line", "Front Line", "CD", "Aux"
3942};
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003943EXPORT_SYMBOL_HDA(auto_pin_cfg_labels);
Takashi Iwai4a471b72005-12-07 13:56:29 +01003944
3945
Linus Torvalds1da177e2005-04-16 15:20:36 -07003946#ifdef CONFIG_PM
3947/*
3948 * power management
3949 */
3950
3951/**
3952 * snd_hda_suspend - suspend the codecs
3953 * @bus: the HDA bus
Linus Torvalds1da177e2005-04-16 15:20:36 -07003954 *
3955 * Returns 0 if successful.
3956 */
Takashi Iwai8dd78332009-06-02 01:16:07 +02003957int snd_hda_suspend(struct hda_bus *bus)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003958{
Takashi Iwai0ba21762007-04-16 11:29:14 +02003959 struct hda_codec *codec;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003960
Takashi Iwai0ba21762007-04-16 11:29:14 +02003961 list_for_each_entry(codec, &bus->codec_list, list) {
Takashi Iwai0b7a2e92007-08-14 15:18:26 +02003962#ifdef CONFIG_SND_HDA_POWER_SAVE
3963 if (!codec->power_on)
3964 continue;
3965#endif
Takashi Iwaicb53c622007-08-10 17:21:45 +02003966 hda_call_codec_suspend(codec);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003967 }
3968 return 0;
3969}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003970EXPORT_SYMBOL_HDA(snd_hda_suspend);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003971
3972/**
3973 * snd_hda_resume - resume the codecs
3974 * @bus: the HDA bus
Linus Torvalds1da177e2005-04-16 15:20:36 -07003975 *
3976 * Returns 0 if successful.
Takashi Iwaicb53c622007-08-10 17:21:45 +02003977 *
3978 * This fucntion is defined only when POWER_SAVE isn't set.
3979 * In the power-save mode, the codec is resumed dynamically.
Linus Torvalds1da177e2005-04-16 15:20:36 -07003980 */
3981int snd_hda_resume(struct hda_bus *bus)
3982{
Takashi Iwai0ba21762007-04-16 11:29:14 +02003983 struct hda_codec *codec;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003984
Takashi Iwai0ba21762007-04-16 11:29:14 +02003985 list_for_each_entry(codec, &bus->codec_list, list) {
Maxim Levitskyd804ad92007-09-03 15:28:04 +02003986 if (snd_hda_codec_needs_resume(codec))
3987 hda_call_codec_resume(codec);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003988 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003989 return 0;
3990}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003991EXPORT_SYMBOL_HDA(snd_hda_resume);
Takashi Iwai1289e9e2008-11-27 15:47:11 +01003992#endif /* CONFIG_PM */
Takashi Iwaib2e18592008-07-30 15:01:44 +02003993
3994/*
3995 * generic arrays
3996 */
3997
3998/* get a new element from the given array
3999 * if it exceeds the pre-allocated array size, re-allocate the array
4000 */
4001void *snd_array_new(struct snd_array *array)
4002{
4003 if (array->used >= array->alloced) {
4004 int num = array->alloced + array->alloc_align;
Takashi Iwaib910d9a2008-11-07 00:26:52 +01004005 void *nlist;
4006 if (snd_BUG_ON(num >= 4096))
4007 return NULL;
4008 nlist = kcalloc(num + 1, array->elem_size, GFP_KERNEL);
Takashi Iwaib2e18592008-07-30 15:01:44 +02004009 if (!nlist)
4010 return NULL;
4011 if (array->list) {
4012 memcpy(nlist, array->list,
4013 array->elem_size * array->alloced);
4014 kfree(array->list);
4015 }
4016 array->list = nlist;
4017 array->alloced = num;
4018 }
Takashi Iwaif43aa022008-11-10 16:24:26 +01004019 return snd_array_elem(array, array->used++);
Takashi Iwaib2e18592008-07-30 15:01:44 +02004020}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01004021EXPORT_SYMBOL_HDA(snd_array_new);
Takashi Iwaib2e18592008-07-30 15:01:44 +02004022
4023/* free the given array elements */
4024void snd_array_free(struct snd_array *array)
4025{
4026 kfree(array->list);
4027 array->used = 0;
4028 array->alloced = 0;
4029 array->list = NULL;
4030}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01004031EXPORT_SYMBOL_HDA(snd_array_free);
Takashi Iwaib2022262008-11-21 21:24:03 +01004032
4033/*
4034 * used by hda_proc.c and hda_eld.c
4035 */
4036void snd_print_pcm_rates(int pcm, char *buf, int buflen)
4037{
4038 static unsigned int rates[] = {
4039 8000, 11025, 16000, 22050, 32000, 44100, 48000, 88200,
4040 96000, 176400, 192000, 384000
4041 };
4042 int i, j;
4043
4044 for (i = 0, j = 0; i < ARRAY_SIZE(rates); i++)
4045 if (pcm & (1 << i))
4046 j += snprintf(buf + j, buflen - j, " %d", rates[i]);
4047
4048 buf[j] = '\0'; /* necessary when j == 0 */
4049}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01004050EXPORT_SYMBOL_HDA(snd_print_pcm_rates);
Takashi Iwaib2022262008-11-21 21:24:03 +01004051
4052void snd_print_pcm_bits(int pcm, char *buf, int buflen)
4053{
4054 static unsigned int bits[] = { 8, 16, 20, 24, 32 };
4055 int i, j;
4056
4057 for (i = 0, j = 0; i < ARRAY_SIZE(bits); i++)
4058 if (pcm & (AC_SUPPCM_BITS_8 << i))
4059 j += snprintf(buf + j, buflen - j, " %d", bits[i]);
4060
4061 buf[j] = '\0'; /* necessary when j == 0 */
4062}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01004063EXPORT_SYMBOL_HDA(snd_print_pcm_bits);
Takashi Iwai1289e9e2008-11-27 15:47:11 +01004064
4065MODULE_DESCRIPTION("HDA codec core");
4066MODULE_LICENSE("GPL");