blob: 1ed1d88e18347cbe2d0e524cde52410a28f77ae7 [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));
Jaroslav Kysela3911a4c2009-11-11 13:43:01 +0100949 snd_array_init(&codec->mixers, sizeof(struct hda_nid_item), 60);
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 */
Jaroslav Kysela3911a4c2009-11-11 13:43:01 +01001520int snd_hda_ctl_add(struct hda_codec *codec, hda_nid_t nid,
1521 struct snd_kcontrol *kctl)
Takashi Iwaid13bd412008-07-30 15:01:45 +02001522{
1523 int err;
Jaroslav Kysela3911a4c2009-11-11 13:43:01 +01001524 struct hda_nid_item *item;
Takashi Iwaid13bd412008-07-30 15:01:45 +02001525
1526 err = snd_ctl_add(codec->bus->card, kctl);
1527 if (err < 0)
1528 return err;
Jaroslav Kysela3911a4c2009-11-11 13:43:01 +01001529 item = snd_array_new(&codec->mixers);
1530 if (!item)
Takashi Iwaid13bd412008-07-30 15:01:45 +02001531 return -ENOMEM;
Jaroslav Kysela3911a4c2009-11-11 13:43:01 +01001532 item->kctl = kctl;
1533 item->nid = nid;
Takashi Iwaid13bd412008-07-30 15:01:45 +02001534 return 0;
1535}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001536EXPORT_SYMBOL_HDA(snd_hda_ctl_add);
Takashi Iwaid13bd412008-07-30 15:01:45 +02001537
1538/* Clear all controls assigned to the given codec */
1539void snd_hda_ctls_clear(struct hda_codec *codec)
1540{
1541 int i;
Jaroslav Kysela3911a4c2009-11-11 13:43:01 +01001542 struct hda_nid_item *items = codec->mixers.list;
Takashi Iwaid13bd412008-07-30 15:01:45 +02001543 for (i = 0; i < codec->mixers.used; i++)
Jaroslav Kysela3911a4c2009-11-11 13:43:01 +01001544 snd_ctl_remove(codec->bus->card, items[i].kctl);
Takashi Iwaid13bd412008-07-30 15:01:45 +02001545 snd_array_free(&codec->mixers);
1546}
1547
Takashi Iwaia65d6292009-02-23 16:57:04 +01001548/* pseudo device locking
1549 * toggle card->shutdown to allow/disallow the device access (as a hack)
1550 */
1551static int hda_lock_devices(struct snd_card *card)
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001552{
Takashi Iwaia65d6292009-02-23 16:57:04 +01001553 spin_lock(&card->files_lock);
1554 if (card->shutdown) {
1555 spin_unlock(&card->files_lock);
1556 return -EINVAL;
1557 }
1558 card->shutdown = 1;
1559 spin_unlock(&card->files_lock);
1560 return 0;
1561}
1562
1563static void hda_unlock_devices(struct snd_card *card)
1564{
1565 spin_lock(&card->files_lock);
1566 card->shutdown = 0;
1567 spin_unlock(&card->files_lock);
1568}
1569
1570int snd_hda_codec_reset(struct hda_codec *codec)
1571{
1572 struct snd_card *card = codec->bus->card;
1573 int i, pcm;
1574
1575 if (hda_lock_devices(card) < 0)
1576 return -EBUSY;
1577 /* check whether the codec isn't used by any mixer or PCM streams */
1578 if (!list_empty(&card->ctl_files)) {
1579 hda_unlock_devices(card);
1580 return -EBUSY;
1581 }
1582 for (pcm = 0; pcm < codec->num_pcms; pcm++) {
1583 struct hda_pcm *cpcm = &codec->pcm_info[pcm];
1584 if (!cpcm->pcm)
1585 continue;
1586 if (cpcm->pcm->streams[0].substream_opened ||
1587 cpcm->pcm->streams[1].substream_opened) {
1588 hda_unlock_devices(card);
1589 return -EBUSY;
1590 }
1591 }
1592
1593 /* OK, let it free */
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001594
1595#ifdef CONFIG_SND_HDA_POWER_SAVE
1596 cancel_delayed_work(&codec->power_work);
Takashi Iwai6acaed32009-01-12 10:09:24 +01001597 flush_workqueue(codec->bus->workq);
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001598#endif
1599 snd_hda_ctls_clear(codec);
1600 /* relase PCMs */
1601 for (i = 0; i < codec->num_pcms; i++) {
Takashi Iwai529bd6c2008-11-27 14:17:01 +01001602 if (codec->pcm_info[i].pcm) {
Takashi Iwaia65d6292009-02-23 16:57:04 +01001603 snd_device_free(card, codec->pcm_info[i].pcm);
Takashi Iwai529bd6c2008-11-27 14:17:01 +01001604 clear_bit(codec->pcm_info[i].device,
1605 codec->bus->pcm_dev_bits);
1606 }
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001607 }
1608 if (codec->patch_ops.free)
1609 codec->patch_ops.free(codec);
Takashi Iwai56d17712008-11-28 14:36:23 +01001610 codec->proc_widget_hook = NULL;
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001611 codec->spec = NULL;
1612 free_hda_cache(&codec->amp_cache);
1613 free_hda_cache(&codec->cmd_cache);
Takashi Iwai827057f2008-12-19 10:12:02 +01001614 init_hda_cache(&codec->amp_cache, sizeof(struct hda_amp_info));
1615 init_hda_cache(&codec->cmd_cache, sizeof(struct hda_cache_head));
Takashi Iwai346ff702009-02-23 09:42:57 +01001616 /* free only driver_pins so that init_pins + user_pins are restored */
1617 snd_array_free(&codec->driver_pins);
Takashi Iwai3be14142009-02-20 14:11:16 +01001618 restore_pincfgs(codec);
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001619 codec->num_pcms = 0;
1620 codec->pcm_info = NULL;
1621 codec->preset = NULL;
Takashi Iwaid1f1af22009-03-02 10:35:29 +01001622 memset(&codec->patch_ops, 0, sizeof(codec->patch_ops));
1623 codec->slave_dig_outs = NULL;
1624 codec->spdif_status_reset = 0;
Takashi Iwai1289e9e2008-11-27 15:47:11 +01001625 module_put(codec->owner);
1626 codec->owner = NULL;
Takashi Iwaia65d6292009-02-23 16:57:04 +01001627
1628 /* allow device access again */
1629 hda_unlock_devices(card);
1630 return 0;
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001631}
1632
Takashi Iwai2134ea42008-01-10 16:53:55 +01001633/* create a virtual master control and add slaves */
1634int snd_hda_add_vmaster(struct hda_codec *codec, char *name,
1635 unsigned int *tlv, const char **slaves)
1636{
1637 struct snd_kcontrol *kctl;
1638 const char **s;
1639 int err;
1640
Takashi Iwai2f085542008-02-22 18:43:50 +01001641 for (s = slaves; *s && !snd_hda_find_mixer_ctl(codec, *s); s++)
1642 ;
1643 if (!*s) {
1644 snd_printdd("No slave found for %s\n", name);
1645 return 0;
1646 }
Takashi Iwai2134ea42008-01-10 16:53:55 +01001647 kctl = snd_ctl_make_virtual_master(name, tlv);
1648 if (!kctl)
1649 return -ENOMEM;
Jaroslav Kysela3911a4c2009-11-11 13:43:01 +01001650 err = snd_hda_ctl_add(codec, 0, kctl);
Takashi Iwai2134ea42008-01-10 16:53:55 +01001651 if (err < 0)
1652 return err;
1653
1654 for (s = slaves; *s; s++) {
1655 struct snd_kcontrol *sctl;
Takashi Iwai7a411ee2009-03-06 10:08:14 +01001656 int i = 0;
1657 for (;;) {
1658 sctl = _snd_hda_find_mixer_ctl(codec, *s, i);
1659 if (!sctl) {
1660 if (!i)
1661 snd_printdd("Cannot find slave %s, "
1662 "skipped\n", *s);
1663 break;
1664 }
1665 err = snd_ctl_add_slave(kctl, sctl);
1666 if (err < 0)
1667 return err;
1668 i++;
Takashi Iwai2134ea42008-01-10 16:53:55 +01001669 }
Takashi Iwai2134ea42008-01-10 16:53:55 +01001670 }
1671 return 0;
1672}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001673EXPORT_SYMBOL_HDA(snd_hda_add_vmaster);
Takashi Iwai2134ea42008-01-10 16:53:55 +01001674
Linus Torvalds1da177e2005-04-16 15:20:36 -07001675/* switch */
Takashi Iwai0ba21762007-04-16 11:29:14 +02001676int snd_hda_mixer_amp_switch_info(struct snd_kcontrol *kcontrol,
1677 struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001678{
1679 int chs = get_amp_channels(kcontrol);
1680
1681 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
1682 uinfo->count = chs == 3 ? 2 : 1;
1683 uinfo->value.integer.min = 0;
1684 uinfo->value.integer.max = 1;
1685 return 0;
1686}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001687EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_switch_info);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001688
Takashi Iwai0ba21762007-04-16 11:29:14 +02001689int snd_hda_mixer_amp_switch_get(struct snd_kcontrol *kcontrol,
1690 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001691{
1692 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1693 hda_nid_t nid = get_amp_nid(kcontrol);
1694 int chs = get_amp_channels(kcontrol);
1695 int dir = get_amp_direction(kcontrol);
1696 int idx = get_amp_index(kcontrol);
1697 long *valp = ucontrol->value.integer.value;
1698
1699 if (chs & 1)
Takashi Iwai0ba21762007-04-16 11:29:14 +02001700 *valp++ = (snd_hda_codec_amp_read(codec, nid, 0, dir, idx) &
Takashi Iwai47fd8302007-08-10 17:11:07 +02001701 HDA_AMP_MUTE) ? 0 : 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001702 if (chs & 2)
Takashi Iwai0ba21762007-04-16 11:29:14 +02001703 *valp = (snd_hda_codec_amp_read(codec, nid, 1, dir, idx) &
Takashi Iwai47fd8302007-08-10 17:11:07 +02001704 HDA_AMP_MUTE) ? 0 : 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001705 return 0;
1706}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001707EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_switch_get);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001708
Takashi Iwai0ba21762007-04-16 11:29:14 +02001709int snd_hda_mixer_amp_switch_put(struct snd_kcontrol *kcontrol,
1710 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001711{
1712 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1713 hda_nid_t nid = get_amp_nid(kcontrol);
1714 int chs = get_amp_channels(kcontrol);
1715 int dir = get_amp_direction(kcontrol);
1716 int idx = get_amp_index(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001717 long *valp = ucontrol->value.integer.value;
1718 int change = 0;
1719
Takashi Iwaicb53c622007-08-10 17:21:45 +02001720 snd_hda_power_up(codec);
Nicolas Grazianob9f5a892005-07-29 12:17:20 +02001721 if (chs & 1) {
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001722 change = snd_hda_codec_amp_update(codec, nid, 0, dir, idx,
Takashi Iwai47fd8302007-08-10 17:11:07 +02001723 HDA_AMP_MUTE,
1724 *valp ? 0 : HDA_AMP_MUTE);
Nicolas Grazianob9f5a892005-07-29 12:17:20 +02001725 valp++;
1726 }
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001727 if (chs & 2)
1728 change |= snd_hda_codec_amp_update(codec, nid, 1, dir, idx,
Takashi Iwai47fd8302007-08-10 17:11:07 +02001729 HDA_AMP_MUTE,
1730 *valp ? 0 : HDA_AMP_MUTE);
Takashi Iwaicb53c622007-08-10 17:21:45 +02001731#ifdef CONFIG_SND_HDA_POWER_SAVE
1732 if (codec->patch_ops.check_power_status)
1733 codec->patch_ops.check_power_status(codec, nid);
1734#endif
1735 snd_hda_power_down(codec);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001736 return change;
1737}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001738EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_switch_put);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001739
Jaroslav Kysela123c07a2009-10-21 14:48:23 +02001740int snd_hda_mixer_amp_switch_put_beep(struct snd_kcontrol *kcontrol,
1741 struct snd_ctl_elem_value *ucontrol)
1742{
1743 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1744 long *valp = ucontrol->value.integer.value;
1745
1746 snd_hda_enable_beep_device(codec, *valp);
1747 return snd_hda_mixer_amp_switch_put(kcontrol, ucontrol);
1748}
1749EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_switch_put_beep);
1750
Linus Torvalds1da177e2005-04-16 15:20:36 -07001751/*
Takashi Iwai985be542005-11-02 18:26:49 +01001752 * bound volume controls
1753 *
1754 * bind multiple volumes (# indices, from 0)
1755 */
1756
1757#define AMP_VAL_IDX_SHIFT 19
1758#define AMP_VAL_IDX_MASK (0x0f<<19)
1759
Takashi Iwai0ba21762007-04-16 11:29:14 +02001760int snd_hda_mixer_bind_switch_get(struct snd_kcontrol *kcontrol,
1761 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai985be542005-11-02 18:26:49 +01001762{
1763 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1764 unsigned long pval;
1765 int err;
1766
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001767 mutex_lock(&codec->control_mutex);
Takashi Iwai985be542005-11-02 18:26:49 +01001768 pval = kcontrol->private_value;
1769 kcontrol->private_value = pval & ~AMP_VAL_IDX_MASK; /* index 0 */
1770 err = snd_hda_mixer_amp_switch_get(kcontrol, ucontrol);
1771 kcontrol->private_value = pval;
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001772 mutex_unlock(&codec->control_mutex);
Takashi Iwai985be542005-11-02 18:26:49 +01001773 return err;
1774}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001775EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_switch_get);
Takashi Iwai985be542005-11-02 18:26:49 +01001776
Takashi Iwai0ba21762007-04-16 11:29:14 +02001777int snd_hda_mixer_bind_switch_put(struct snd_kcontrol *kcontrol,
1778 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai985be542005-11-02 18:26:49 +01001779{
1780 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1781 unsigned long pval;
1782 int i, indices, err = 0, change = 0;
1783
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001784 mutex_lock(&codec->control_mutex);
Takashi Iwai985be542005-11-02 18:26:49 +01001785 pval = kcontrol->private_value;
1786 indices = (pval & AMP_VAL_IDX_MASK) >> AMP_VAL_IDX_SHIFT;
1787 for (i = 0; i < indices; i++) {
Takashi Iwai0ba21762007-04-16 11:29:14 +02001788 kcontrol->private_value = (pval & ~AMP_VAL_IDX_MASK) |
1789 (i << AMP_VAL_IDX_SHIFT);
Takashi Iwai985be542005-11-02 18:26:49 +01001790 err = snd_hda_mixer_amp_switch_put(kcontrol, ucontrol);
1791 if (err < 0)
1792 break;
1793 change |= err;
1794 }
1795 kcontrol->private_value = pval;
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001796 mutex_unlock(&codec->control_mutex);
Takashi Iwai985be542005-11-02 18:26:49 +01001797 return err < 0 ? err : change;
1798}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001799EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_switch_put);
Takashi Iwai985be542005-11-02 18:26:49 +01001800
1801/*
Takashi Iwai532d5382007-07-27 19:02:40 +02001802 * generic bound volume/swtich controls
1803 */
1804int snd_hda_mixer_bind_ctls_info(struct snd_kcontrol *kcontrol,
1805 struct snd_ctl_elem_info *uinfo)
1806{
1807 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1808 struct hda_bind_ctls *c;
1809 int err;
1810
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001811 mutex_lock(&codec->control_mutex);
Serge A. Suchkov14c65f92008-02-22 18:43:16 +01001812 c = (struct hda_bind_ctls *)kcontrol->private_value;
Takashi Iwai532d5382007-07-27 19:02:40 +02001813 kcontrol->private_value = *c->values;
1814 err = c->ops->info(kcontrol, uinfo);
1815 kcontrol->private_value = (long)c;
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001816 mutex_unlock(&codec->control_mutex);
Takashi Iwai532d5382007-07-27 19:02:40 +02001817 return err;
1818}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001819EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_ctls_info);
Takashi Iwai532d5382007-07-27 19:02:40 +02001820
1821int snd_hda_mixer_bind_ctls_get(struct snd_kcontrol *kcontrol,
1822 struct snd_ctl_elem_value *ucontrol)
1823{
1824 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1825 struct hda_bind_ctls *c;
1826 int err;
1827
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001828 mutex_lock(&codec->control_mutex);
Serge A. Suchkov14c65f92008-02-22 18:43:16 +01001829 c = (struct hda_bind_ctls *)kcontrol->private_value;
Takashi Iwai532d5382007-07-27 19:02:40 +02001830 kcontrol->private_value = *c->values;
1831 err = c->ops->get(kcontrol, ucontrol);
1832 kcontrol->private_value = (long)c;
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001833 mutex_unlock(&codec->control_mutex);
Takashi Iwai532d5382007-07-27 19:02:40 +02001834 return err;
1835}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001836EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_ctls_get);
Takashi Iwai532d5382007-07-27 19:02:40 +02001837
1838int snd_hda_mixer_bind_ctls_put(struct snd_kcontrol *kcontrol,
1839 struct snd_ctl_elem_value *ucontrol)
1840{
1841 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1842 struct hda_bind_ctls *c;
1843 unsigned long *vals;
1844 int err = 0, change = 0;
1845
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001846 mutex_lock(&codec->control_mutex);
Serge A. Suchkov14c65f92008-02-22 18:43:16 +01001847 c = (struct hda_bind_ctls *)kcontrol->private_value;
Takashi Iwai532d5382007-07-27 19:02:40 +02001848 for (vals = c->values; *vals; vals++) {
1849 kcontrol->private_value = *vals;
1850 err = c->ops->put(kcontrol, ucontrol);
1851 if (err < 0)
1852 break;
1853 change |= err;
1854 }
1855 kcontrol->private_value = (long)c;
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001856 mutex_unlock(&codec->control_mutex);
Takashi Iwai532d5382007-07-27 19:02:40 +02001857 return err < 0 ? err : change;
1858}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001859EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_ctls_put);
Takashi Iwai532d5382007-07-27 19:02:40 +02001860
1861int snd_hda_mixer_bind_tlv(struct snd_kcontrol *kcontrol, int op_flag,
1862 unsigned int size, unsigned int __user *tlv)
1863{
1864 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1865 struct hda_bind_ctls *c;
1866 int err;
1867
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001868 mutex_lock(&codec->control_mutex);
Serge A. Suchkov14c65f92008-02-22 18:43:16 +01001869 c = (struct hda_bind_ctls *)kcontrol->private_value;
Takashi Iwai532d5382007-07-27 19:02:40 +02001870 kcontrol->private_value = *c->values;
1871 err = c->ops->tlv(kcontrol, op_flag, size, tlv);
1872 kcontrol->private_value = (long)c;
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001873 mutex_unlock(&codec->control_mutex);
Takashi Iwai532d5382007-07-27 19:02:40 +02001874 return err;
1875}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001876EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_tlv);
Takashi Iwai532d5382007-07-27 19:02:40 +02001877
1878struct hda_ctl_ops snd_hda_bind_vol = {
1879 .info = snd_hda_mixer_amp_volume_info,
1880 .get = snd_hda_mixer_amp_volume_get,
1881 .put = snd_hda_mixer_amp_volume_put,
1882 .tlv = snd_hda_mixer_amp_tlv
1883};
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001884EXPORT_SYMBOL_HDA(snd_hda_bind_vol);
Takashi Iwai532d5382007-07-27 19:02:40 +02001885
1886struct hda_ctl_ops snd_hda_bind_sw = {
1887 .info = snd_hda_mixer_amp_switch_info,
1888 .get = snd_hda_mixer_amp_switch_get,
1889 .put = snd_hda_mixer_amp_switch_put,
1890 .tlv = snd_hda_mixer_amp_tlv
1891};
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001892EXPORT_SYMBOL_HDA(snd_hda_bind_sw);
Takashi Iwai532d5382007-07-27 19:02:40 +02001893
1894/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07001895 * SPDIF out controls
1896 */
1897
Takashi Iwai0ba21762007-04-16 11:29:14 +02001898static int snd_hda_spdif_mask_info(struct snd_kcontrol *kcontrol,
1899 struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001900{
1901 uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
1902 uinfo->count = 1;
1903 return 0;
1904}
1905
Takashi Iwai0ba21762007-04-16 11:29:14 +02001906static int snd_hda_spdif_cmask_get(struct snd_kcontrol *kcontrol,
1907 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001908{
1909 ucontrol->value.iec958.status[0] = IEC958_AES0_PROFESSIONAL |
1910 IEC958_AES0_NONAUDIO |
1911 IEC958_AES0_CON_EMPHASIS_5015 |
1912 IEC958_AES0_CON_NOT_COPYRIGHT;
1913 ucontrol->value.iec958.status[1] = IEC958_AES1_CON_CATEGORY |
1914 IEC958_AES1_CON_ORIGINAL;
1915 return 0;
1916}
1917
Takashi Iwai0ba21762007-04-16 11:29:14 +02001918static int snd_hda_spdif_pmask_get(struct snd_kcontrol *kcontrol,
1919 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001920{
1921 ucontrol->value.iec958.status[0] = IEC958_AES0_PROFESSIONAL |
1922 IEC958_AES0_NONAUDIO |
1923 IEC958_AES0_PRO_EMPHASIS_5015;
1924 return 0;
1925}
1926
Takashi Iwai0ba21762007-04-16 11:29:14 +02001927static int snd_hda_spdif_default_get(struct snd_kcontrol *kcontrol,
1928 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001929{
1930 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1931
1932 ucontrol->value.iec958.status[0] = codec->spdif_status & 0xff;
1933 ucontrol->value.iec958.status[1] = (codec->spdif_status >> 8) & 0xff;
1934 ucontrol->value.iec958.status[2] = (codec->spdif_status >> 16) & 0xff;
1935 ucontrol->value.iec958.status[3] = (codec->spdif_status >> 24) & 0xff;
1936
1937 return 0;
1938}
1939
1940/* convert from SPDIF status bits to HDA SPDIF bits
1941 * bit 0 (DigEn) is always set zero (to be filled later)
1942 */
1943static unsigned short convert_from_spdif_status(unsigned int sbits)
1944{
1945 unsigned short val = 0;
1946
1947 if (sbits & IEC958_AES0_PROFESSIONAL)
Takashi Iwai0ba21762007-04-16 11:29:14 +02001948 val |= AC_DIG1_PROFESSIONAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001949 if (sbits & IEC958_AES0_NONAUDIO)
Takashi Iwai0ba21762007-04-16 11:29:14 +02001950 val |= AC_DIG1_NONAUDIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001951 if (sbits & IEC958_AES0_PROFESSIONAL) {
Takashi Iwai0ba21762007-04-16 11:29:14 +02001952 if ((sbits & IEC958_AES0_PRO_EMPHASIS) ==
1953 IEC958_AES0_PRO_EMPHASIS_5015)
1954 val |= AC_DIG1_EMPHASIS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001955 } else {
Takashi Iwai0ba21762007-04-16 11:29:14 +02001956 if ((sbits & IEC958_AES0_CON_EMPHASIS) ==
1957 IEC958_AES0_CON_EMPHASIS_5015)
1958 val |= AC_DIG1_EMPHASIS;
1959 if (!(sbits & IEC958_AES0_CON_NOT_COPYRIGHT))
1960 val |= AC_DIG1_COPYRIGHT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001961 if (sbits & (IEC958_AES1_CON_ORIGINAL << 8))
Takashi Iwai0ba21762007-04-16 11:29:14 +02001962 val |= AC_DIG1_LEVEL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001963 val |= sbits & (IEC958_AES1_CON_CATEGORY << 8);
1964 }
1965 return val;
1966}
1967
1968/* convert to SPDIF status bits from HDA SPDIF bits
1969 */
1970static unsigned int convert_to_spdif_status(unsigned short val)
1971{
1972 unsigned int sbits = 0;
1973
Takashi Iwai0ba21762007-04-16 11:29:14 +02001974 if (val & AC_DIG1_NONAUDIO)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001975 sbits |= IEC958_AES0_NONAUDIO;
Takashi Iwai0ba21762007-04-16 11:29:14 +02001976 if (val & AC_DIG1_PROFESSIONAL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001977 sbits |= IEC958_AES0_PROFESSIONAL;
1978 if (sbits & IEC958_AES0_PROFESSIONAL) {
Takashi Iwai0ba21762007-04-16 11:29:14 +02001979 if (sbits & AC_DIG1_EMPHASIS)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001980 sbits |= IEC958_AES0_PRO_EMPHASIS_5015;
1981 } else {
Takashi Iwai0ba21762007-04-16 11:29:14 +02001982 if (val & AC_DIG1_EMPHASIS)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001983 sbits |= IEC958_AES0_CON_EMPHASIS_5015;
Takashi Iwai0ba21762007-04-16 11:29:14 +02001984 if (!(val & AC_DIG1_COPYRIGHT))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001985 sbits |= IEC958_AES0_CON_NOT_COPYRIGHT;
Takashi Iwai0ba21762007-04-16 11:29:14 +02001986 if (val & AC_DIG1_LEVEL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001987 sbits |= (IEC958_AES1_CON_ORIGINAL << 8);
1988 sbits |= val & (0x7f << 8);
1989 }
1990 return sbits;
1991}
1992
Takashi Iwai2f728532008-09-25 16:32:41 +02001993/* set digital convert verbs both for the given NID and its slaves */
1994static void set_dig_out(struct hda_codec *codec, hda_nid_t nid,
1995 int verb, int val)
1996{
1997 hda_nid_t *d;
1998
Takashi Iwai9e976972008-11-25 08:17:20 +01001999 snd_hda_codec_write_cache(codec, nid, 0, verb, val);
Takashi Iwai2f728532008-09-25 16:32:41 +02002000 d = codec->slave_dig_outs;
2001 if (!d)
2002 return;
2003 for (; *d; d++)
Takashi Iwai9e976972008-11-25 08:17:20 +01002004 snd_hda_codec_write_cache(codec, *d, 0, verb, val);
Takashi Iwai2f728532008-09-25 16:32:41 +02002005}
2006
2007static inline void set_dig_out_convert(struct hda_codec *codec, hda_nid_t nid,
2008 int dig1, int dig2)
2009{
2010 if (dig1 != -1)
2011 set_dig_out(codec, nid, AC_VERB_SET_DIGI_CONVERT_1, dig1);
2012 if (dig2 != -1)
2013 set_dig_out(codec, nid, AC_VERB_SET_DIGI_CONVERT_2, dig2);
2014}
2015
Takashi Iwai0ba21762007-04-16 11:29:14 +02002016static int snd_hda_spdif_default_put(struct snd_kcontrol *kcontrol,
2017 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002018{
2019 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2020 hda_nid_t nid = kcontrol->private_value;
2021 unsigned short val;
2022 int change;
2023
Ingo Molnar62932df2006-01-16 16:34:20 +01002024 mutex_lock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002025 codec->spdif_status = ucontrol->value.iec958.status[0] |
2026 ((unsigned int)ucontrol->value.iec958.status[1] << 8) |
2027 ((unsigned int)ucontrol->value.iec958.status[2] << 16) |
2028 ((unsigned int)ucontrol->value.iec958.status[3] << 24);
2029 val = convert_from_spdif_status(codec->spdif_status);
2030 val |= codec->spdif_ctls & 1;
2031 change = codec->spdif_ctls != val;
2032 codec->spdif_ctls = val;
2033
Takashi Iwai2f728532008-09-25 16:32:41 +02002034 if (change)
2035 set_dig_out_convert(codec, nid, val & 0xff, (val >> 8) & 0xff);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002036
Ingo Molnar62932df2006-01-16 16:34:20 +01002037 mutex_unlock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002038 return change;
2039}
2040
Takashi Iwaia5ce8892007-07-23 15:42:26 +02002041#define snd_hda_spdif_out_switch_info snd_ctl_boolean_mono_info
Linus Torvalds1da177e2005-04-16 15:20:36 -07002042
Takashi Iwai0ba21762007-04-16 11:29:14 +02002043static int snd_hda_spdif_out_switch_get(struct snd_kcontrol *kcontrol,
2044 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002045{
2046 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2047
Takashi Iwai0ba21762007-04-16 11:29:14 +02002048 ucontrol->value.integer.value[0] = codec->spdif_ctls & AC_DIG1_ENABLE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002049 return 0;
2050}
2051
Takashi Iwai0ba21762007-04-16 11:29:14 +02002052static int snd_hda_spdif_out_switch_put(struct snd_kcontrol *kcontrol,
2053 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002054{
2055 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2056 hda_nid_t nid = kcontrol->private_value;
2057 unsigned short val;
2058 int change;
2059
Ingo Molnar62932df2006-01-16 16:34:20 +01002060 mutex_lock(&codec->spdif_mutex);
Takashi Iwai0ba21762007-04-16 11:29:14 +02002061 val = codec->spdif_ctls & ~AC_DIG1_ENABLE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002062 if (ucontrol->value.integer.value[0])
Takashi Iwai0ba21762007-04-16 11:29:14 +02002063 val |= AC_DIG1_ENABLE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002064 change = codec->spdif_ctls != val;
Takashi Iwai82beb8f2007-08-10 17:09:26 +02002065 if (change) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002066 codec->spdif_ctls = val;
Takashi Iwai2f728532008-09-25 16:32:41 +02002067 set_dig_out_convert(codec, nid, val & 0xff, -1);
Takashi Iwai0ba21762007-04-16 11:29:14 +02002068 /* unmute amp switch (if any) */
2069 if ((get_wcaps(codec, nid) & AC_WCAP_OUT_AMP) &&
Takashi Iwai47fd8302007-08-10 17:11:07 +02002070 (val & AC_DIG1_ENABLE))
2071 snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0,
2072 HDA_AMP_MUTE, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002073 }
Ingo Molnar62932df2006-01-16 16:34:20 +01002074 mutex_unlock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002075 return change;
2076}
2077
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01002078static struct snd_kcontrol_new dig_mixes[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002079 {
2080 .access = SNDRV_CTL_ELEM_ACCESS_READ,
2081 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2082 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,CON_MASK),
2083 .info = snd_hda_spdif_mask_info,
2084 .get = snd_hda_spdif_cmask_get,
2085 },
2086 {
2087 .access = SNDRV_CTL_ELEM_ACCESS_READ,
2088 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2089 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,PRO_MASK),
2090 .info = snd_hda_spdif_mask_info,
2091 .get = snd_hda_spdif_pmask_get,
2092 },
2093 {
2094 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2095 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT),
2096 .info = snd_hda_spdif_mask_info,
2097 .get = snd_hda_spdif_default_get,
2098 .put = snd_hda_spdif_default_put,
2099 },
2100 {
2101 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2102 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,SWITCH),
2103 .info = snd_hda_spdif_out_switch_info,
2104 .get = snd_hda_spdif_out_switch_get,
2105 .put = snd_hda_spdif_out_switch_put,
2106 },
2107 { } /* end */
2108};
2109
Takashi Iwai09f99702008-02-04 12:31:13 +01002110#define SPDIF_MAX_IDX 4 /* 4 instances should be enough to probe */
2111
Linus Torvalds1da177e2005-04-16 15:20:36 -07002112/**
2113 * snd_hda_create_spdif_out_ctls - create Output SPDIF-related controls
2114 * @codec: the HDA codec
2115 * @nid: audio out widget NID
2116 *
2117 * Creates controls related with the SPDIF output.
2118 * Called from each patch supporting the SPDIF out.
2119 *
2120 * Returns 0 if successful, or a negative error code.
2121 */
Takashi Iwai12f288b2007-08-02 15:51:59 +02002122int snd_hda_create_spdif_out_ctls(struct hda_codec *codec, hda_nid_t nid)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002123{
2124 int err;
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01002125 struct snd_kcontrol *kctl;
2126 struct snd_kcontrol_new *dig_mix;
Takashi Iwai09f99702008-02-04 12:31:13 +01002127 int idx;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002128
Takashi Iwai09f99702008-02-04 12:31:13 +01002129 for (idx = 0; idx < SPDIF_MAX_IDX; idx++) {
2130 if (!_snd_hda_find_mixer_ctl(codec, "IEC958 Playback Switch",
2131 idx))
2132 break;
2133 }
2134 if (idx >= SPDIF_MAX_IDX) {
2135 printk(KERN_ERR "hda_codec: too many IEC958 outputs\n");
2136 return -EBUSY;
2137 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002138 for (dig_mix = dig_mixes; dig_mix->name; dig_mix++) {
2139 kctl = snd_ctl_new1(dig_mix, codec);
Takashi Iwaib91f0802008-11-04 08:43:08 +01002140 if (!kctl)
2141 return -ENOMEM;
Takashi Iwai09f99702008-02-04 12:31:13 +01002142 kctl->id.index = idx;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002143 kctl->private_value = nid;
Jaroslav Kysela3911a4c2009-11-11 13:43:01 +01002144 err = snd_hda_ctl_add(codec, nid, kctl);
Takashi Iwai0ba21762007-04-16 11:29:14 +02002145 if (err < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002146 return err;
2147 }
Takashi Iwai0ba21762007-04-16 11:29:14 +02002148 codec->spdif_ctls =
Andrew Paprocki3982d172007-12-19 12:13:44 +01002149 snd_hda_codec_read(codec, nid, 0,
2150 AC_VERB_GET_DIGI_CONVERT_1, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002151 codec->spdif_status = convert_to_spdif_status(codec->spdif_ctls);
2152 return 0;
2153}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002154EXPORT_SYMBOL_HDA(snd_hda_create_spdif_out_ctls);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002155
2156/*
Takashi Iwai9a081602008-02-12 18:37:26 +01002157 * SPDIF sharing with analog output
2158 */
2159static int spdif_share_sw_get(struct snd_kcontrol *kcontrol,
2160 struct snd_ctl_elem_value *ucontrol)
2161{
2162 struct hda_multi_out *mout = snd_kcontrol_chip(kcontrol);
2163 ucontrol->value.integer.value[0] = mout->share_spdif;
2164 return 0;
2165}
2166
2167static int spdif_share_sw_put(struct snd_kcontrol *kcontrol,
2168 struct snd_ctl_elem_value *ucontrol)
2169{
2170 struct hda_multi_out *mout = snd_kcontrol_chip(kcontrol);
2171 mout->share_spdif = !!ucontrol->value.integer.value[0];
2172 return 0;
2173}
2174
2175static struct snd_kcontrol_new spdif_share_sw = {
2176 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2177 .name = "IEC958 Default PCM Playback Switch",
2178 .info = snd_ctl_boolean_mono_info,
2179 .get = spdif_share_sw_get,
2180 .put = spdif_share_sw_put,
2181};
2182
2183int snd_hda_create_spdif_share_sw(struct hda_codec *codec,
2184 struct hda_multi_out *mout)
2185{
2186 if (!mout->dig_out_nid)
2187 return 0;
2188 /* ATTENTION: here mout is passed as private_data, instead of codec */
Jaroslav Kysela3911a4c2009-11-11 13:43:01 +01002189 return snd_hda_ctl_add(codec, mout->dig_out_nid,
2190 snd_ctl_new1(&spdif_share_sw, mout));
Takashi Iwai9a081602008-02-12 18:37:26 +01002191}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002192EXPORT_SYMBOL_HDA(snd_hda_create_spdif_share_sw);
Takashi Iwai9a081602008-02-12 18:37:26 +01002193
2194/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002195 * SPDIF input
2196 */
2197
2198#define snd_hda_spdif_in_switch_info snd_hda_spdif_out_switch_info
2199
Takashi Iwai0ba21762007-04-16 11:29:14 +02002200static int snd_hda_spdif_in_switch_get(struct snd_kcontrol *kcontrol,
2201 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002202{
2203 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2204
2205 ucontrol->value.integer.value[0] = codec->spdif_in_enable;
2206 return 0;
2207}
2208
Takashi Iwai0ba21762007-04-16 11:29:14 +02002209static int snd_hda_spdif_in_switch_put(struct snd_kcontrol *kcontrol,
2210 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002211{
2212 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2213 hda_nid_t nid = kcontrol->private_value;
2214 unsigned int val = !!ucontrol->value.integer.value[0];
2215 int change;
2216
Ingo Molnar62932df2006-01-16 16:34:20 +01002217 mutex_lock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002218 change = codec->spdif_in_enable != val;
Takashi Iwai82beb8f2007-08-10 17:09:26 +02002219 if (change) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002220 codec->spdif_in_enable = val;
Takashi Iwai82beb8f2007-08-10 17:09:26 +02002221 snd_hda_codec_write_cache(codec, nid, 0,
2222 AC_VERB_SET_DIGI_CONVERT_1, val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002223 }
Ingo Molnar62932df2006-01-16 16:34:20 +01002224 mutex_unlock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002225 return change;
2226}
2227
Takashi Iwai0ba21762007-04-16 11:29:14 +02002228static int snd_hda_spdif_in_status_get(struct snd_kcontrol *kcontrol,
2229 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002230{
2231 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2232 hda_nid_t nid = kcontrol->private_value;
2233 unsigned short val;
2234 unsigned int sbits;
2235
Andrew Paprocki3982d172007-12-19 12:13:44 +01002236 val = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_DIGI_CONVERT_1, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002237 sbits = convert_to_spdif_status(val);
2238 ucontrol->value.iec958.status[0] = sbits;
2239 ucontrol->value.iec958.status[1] = sbits >> 8;
2240 ucontrol->value.iec958.status[2] = sbits >> 16;
2241 ucontrol->value.iec958.status[3] = sbits >> 24;
2242 return 0;
2243}
2244
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01002245static struct snd_kcontrol_new dig_in_ctls[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002246 {
2247 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2248 .name = SNDRV_CTL_NAME_IEC958("",CAPTURE,SWITCH),
2249 .info = snd_hda_spdif_in_switch_info,
2250 .get = snd_hda_spdif_in_switch_get,
2251 .put = snd_hda_spdif_in_switch_put,
2252 },
2253 {
2254 .access = SNDRV_CTL_ELEM_ACCESS_READ,
2255 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2256 .name = SNDRV_CTL_NAME_IEC958("",CAPTURE,DEFAULT),
2257 .info = snd_hda_spdif_mask_info,
2258 .get = snd_hda_spdif_in_status_get,
2259 },
2260 { } /* end */
2261};
2262
2263/**
2264 * snd_hda_create_spdif_in_ctls - create Input SPDIF-related controls
2265 * @codec: the HDA codec
2266 * @nid: audio in widget NID
2267 *
2268 * Creates controls related with the SPDIF input.
2269 * Called from each patch supporting the SPDIF in.
2270 *
2271 * Returns 0 if successful, or a negative error code.
2272 */
Takashi Iwai12f288b2007-08-02 15:51:59 +02002273int snd_hda_create_spdif_in_ctls(struct hda_codec *codec, hda_nid_t nid)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002274{
2275 int err;
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01002276 struct snd_kcontrol *kctl;
2277 struct snd_kcontrol_new *dig_mix;
Takashi Iwai09f99702008-02-04 12:31:13 +01002278 int idx;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002279
Takashi Iwai09f99702008-02-04 12:31:13 +01002280 for (idx = 0; idx < SPDIF_MAX_IDX; idx++) {
2281 if (!_snd_hda_find_mixer_ctl(codec, "IEC958 Capture Switch",
2282 idx))
2283 break;
2284 }
2285 if (idx >= SPDIF_MAX_IDX) {
2286 printk(KERN_ERR "hda_codec: too many IEC958 inputs\n");
2287 return -EBUSY;
2288 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002289 for (dig_mix = dig_in_ctls; dig_mix->name; dig_mix++) {
2290 kctl = snd_ctl_new1(dig_mix, codec);
Takashi Iwaic8dcdf82009-02-06 16:21:20 +01002291 if (!kctl)
2292 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002293 kctl->private_value = nid;
Jaroslav Kysela3911a4c2009-11-11 13:43:01 +01002294 err = snd_hda_ctl_add(codec, nid, kctl);
Takashi Iwai0ba21762007-04-16 11:29:14 +02002295 if (err < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002296 return err;
2297 }
Takashi Iwai0ba21762007-04-16 11:29:14 +02002298 codec->spdif_in_enable =
Andrew Paprocki3982d172007-12-19 12:13:44 +01002299 snd_hda_codec_read(codec, nid, 0,
2300 AC_VERB_GET_DIGI_CONVERT_1, 0) &
Takashi Iwai0ba21762007-04-16 11:29:14 +02002301 AC_DIG1_ENABLE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002302 return 0;
2303}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002304EXPORT_SYMBOL_HDA(snd_hda_create_spdif_in_ctls);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002305
Takashi Iwaicb53c622007-08-10 17:21:45 +02002306#ifdef SND_HDA_NEEDS_RESUME
Takashi Iwai82beb8f2007-08-10 17:09:26 +02002307/*
2308 * command cache
2309 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002310
Takashi Iwaib3ac5632007-08-10 17:03:40 +02002311/* build a 32bit cache key with the widget id and the command parameter */
2312#define build_cmd_cache_key(nid, verb) ((verb << 8) | nid)
2313#define get_cmd_cache_nid(key) ((key) & 0xff)
2314#define get_cmd_cache_cmd(key) (((key) >> 8) & 0xffff)
2315
2316/**
2317 * snd_hda_codec_write_cache - send a single command with caching
2318 * @codec: the HDA codec
2319 * @nid: NID to send the command
2320 * @direct: direct flag
2321 * @verb: the verb to send
2322 * @parm: the parameter for the verb
2323 *
2324 * Send a single command without waiting for response.
2325 *
2326 * Returns 0 if successful, or a negative error code.
2327 */
2328int snd_hda_codec_write_cache(struct hda_codec *codec, hda_nid_t nid,
2329 int direct, unsigned int verb, unsigned int parm)
2330{
Takashi Iwaiaa2936f2009-05-26 16:07:57 +02002331 int err = snd_hda_codec_write(codec, nid, direct, verb, parm);
2332 struct hda_cache_head *c;
2333 u32 key;
Takashi Iwai33fa35e2008-11-06 16:50:40 +01002334
Takashi Iwaiaa2936f2009-05-26 16:07:57 +02002335 if (err < 0)
2336 return err;
2337 /* parm may contain the verb stuff for get/set amp */
2338 verb = verb | (parm >> 8);
2339 parm &= 0xff;
2340 key = build_cmd_cache_key(nid, verb);
2341 mutex_lock(&codec->bus->cmd_mutex);
2342 c = get_alloc_hash(&codec->cmd_cache, key);
2343 if (c)
2344 c->val = parm;
2345 mutex_unlock(&codec->bus->cmd_mutex);
2346 return 0;
Takashi Iwaib3ac5632007-08-10 17:03:40 +02002347}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002348EXPORT_SYMBOL_HDA(snd_hda_codec_write_cache);
Takashi Iwaib3ac5632007-08-10 17:03:40 +02002349
2350/* resume the all commands from the cache */
2351void snd_hda_codec_resume_cache(struct hda_codec *codec)
2352{
Takashi Iwai603c4012008-07-30 15:01:44 +02002353 struct hda_cache_head *buffer = codec->cmd_cache.buf.list;
Takashi Iwaib3ac5632007-08-10 17:03:40 +02002354 int i;
2355
Takashi Iwai603c4012008-07-30 15:01:44 +02002356 for (i = 0; i < codec->cmd_cache.buf.used; i++, buffer++) {
Takashi Iwaib3ac5632007-08-10 17:03:40 +02002357 u32 key = buffer->key;
2358 if (!key)
2359 continue;
2360 snd_hda_codec_write(codec, get_cmd_cache_nid(key), 0,
2361 get_cmd_cache_cmd(key), buffer->val);
2362 }
2363}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002364EXPORT_SYMBOL_HDA(snd_hda_codec_resume_cache);
Takashi Iwaib3ac5632007-08-10 17:03:40 +02002365
2366/**
2367 * snd_hda_sequence_write_cache - sequence writes with caching
2368 * @codec: the HDA codec
2369 * @seq: VERB array to send
2370 *
2371 * Send the commands sequentially from the given array.
2372 * Thte commands are recorded on cache for power-save and resume.
2373 * The array must be terminated with NID=0.
2374 */
2375void snd_hda_sequence_write_cache(struct hda_codec *codec,
2376 const struct hda_verb *seq)
2377{
2378 for (; seq->nid; seq++)
2379 snd_hda_codec_write_cache(codec, seq->nid, 0, seq->verb,
2380 seq->param);
2381}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002382EXPORT_SYMBOL_HDA(snd_hda_sequence_write_cache);
Takashi Iwaicb53c622007-08-10 17:21:45 +02002383#endif /* SND_HDA_NEEDS_RESUME */
Takashi Iwaib3ac5632007-08-10 17:03:40 +02002384
Takashi Iwai54d17402005-11-21 16:33:22 +01002385/*
2386 * set power state of the codec
2387 */
2388static void hda_set_power_state(struct hda_codec *codec, hda_nid_t fg,
2389 unsigned int power_state)
2390{
Takashi Iwaicb53c622007-08-10 17:21:45 +02002391 hda_nid_t nid;
2392 int i;
Takashi Iwai54d17402005-11-21 16:33:22 +01002393
Takashi Iwai05ff7e12009-07-22 12:39:24 +02002394 /* this delay seems necessary to avoid click noise at power-down */
2395 if (power_state == AC_PWRST_D3)
2396 msleep(100);
2397 snd_hda_codec_read(codec, fg, 0, AC_VERB_SET_POWER_STATE,
Takashi Iwai54d17402005-11-21 16:33:22 +01002398 power_state);
Takashi Iwai05ff7e12009-07-22 12:39:24 +02002399 /* partial workaround for "azx_get_response timeout" */
2400 if (power_state == AC_PWRST_D0)
2401 msleep(10);
Takashi Iwai54d17402005-11-21 16:33:22 +01002402
Takashi Iwaicb53c622007-08-10 17:21:45 +02002403 nid = codec->start_nid;
2404 for (i = 0; i < codec->num_nodes; i++, nid++) {
Takashi Iwai7eba5c92007-11-14 14:53:42 +01002405 unsigned int wcaps = get_wcaps(codec, nid);
2406 if (wcaps & AC_WCAP_POWER) {
Takashi Iwaia22d5432009-07-27 12:54:26 +02002407 unsigned int wid_type = get_wcaps_type(wcaps);
Takashi Iwaia3b48c82009-04-21 13:37:29 +02002408 if (power_state == AC_PWRST_D3 &&
2409 wid_type == AC_WID_PIN) {
Takashi Iwai7eba5c92007-11-14 14:53:42 +01002410 unsigned int pincap;
2411 /*
2412 * don't power down the widget if it controls
2413 * eapd and EAPD_BTLENABLE is set.
2414 */
Takashi Iwai14bafe32009-03-23 16:35:39 +01002415 pincap = snd_hda_query_pin_caps(codec, nid);
Takashi Iwai7eba5c92007-11-14 14:53:42 +01002416 if (pincap & AC_PINCAP_EAPD) {
2417 int eapd = snd_hda_codec_read(codec,
2418 nid, 0,
2419 AC_VERB_GET_EAPD_BTLENABLE, 0);
2420 eapd &= 0x02;
Takashi Iwaia3b48c82009-04-21 13:37:29 +02002421 if (eapd)
Takashi Iwai7eba5c92007-11-14 14:53:42 +01002422 continue;
2423 }
Takashi Iwai1194b5b2007-10-10 10:04:26 +02002424 }
Takashi Iwai54d17402005-11-21 16:33:22 +01002425 snd_hda_codec_write(codec, nid, 0,
2426 AC_VERB_SET_POWER_STATE,
2427 power_state);
Takashi Iwai1194b5b2007-10-10 10:04:26 +02002428 }
Takashi Iwai54d17402005-11-21 16:33:22 +01002429 }
2430
Takashi Iwaicb53c622007-08-10 17:21:45 +02002431 if (power_state == AC_PWRST_D0) {
2432 unsigned long end_time;
2433 int state;
Takashi Iwai54d17402005-11-21 16:33:22 +01002434 msleep(10);
Takashi Iwaicb53c622007-08-10 17:21:45 +02002435 /* wait until the codec reachs to D0 */
2436 end_time = jiffies + msecs_to_jiffies(500);
2437 do {
2438 state = snd_hda_codec_read(codec, fg, 0,
2439 AC_VERB_GET_POWER_STATE, 0);
2440 if (state == power_state)
2441 break;
2442 msleep(1);
2443 } while (time_after_eq(end_time, jiffies));
2444 }
Takashi Iwai54d17402005-11-21 16:33:22 +01002445}
2446
Takashi Iwai11aeff02008-07-30 15:01:46 +02002447#ifdef CONFIG_SND_HDA_HWDEP
2448/* execute additional init verbs */
2449static void hda_exec_init_verbs(struct hda_codec *codec)
2450{
2451 if (codec->init_verbs.list)
2452 snd_hda_sequence_write(codec, codec->init_verbs.list);
2453}
2454#else
2455static inline void hda_exec_init_verbs(struct hda_codec *codec) {}
2456#endif
2457
Takashi Iwaicb53c622007-08-10 17:21:45 +02002458#ifdef SND_HDA_NEEDS_RESUME
2459/*
2460 * call suspend and power-down; used both from PM and power-save
2461 */
2462static void hda_call_codec_suspend(struct hda_codec *codec)
2463{
2464 if (codec->patch_ops.suspend)
2465 codec->patch_ops.suspend(codec, PMSG_SUSPEND);
2466 hda_set_power_state(codec,
2467 codec->afg ? codec->afg : codec->mfg,
2468 AC_PWRST_D3);
2469#ifdef CONFIG_SND_HDA_POWER_SAVE
Takashi Iwaia2f63092009-11-11 09:34:25 +01002470 snd_hda_update_power_acct(codec);
Takashi Iwaicb53c622007-08-10 17:21:45 +02002471 cancel_delayed_work(&codec->power_work);
Takashi Iwai95e99fd2007-08-13 15:29:04 +02002472 codec->power_on = 0;
Takashi Iwaia221e282007-08-16 16:35:33 +02002473 codec->power_transition = 0;
Takashi Iwaia2f63092009-11-11 09:34:25 +01002474 codec->power_jiffies = jiffies;
Takashi Iwaicb53c622007-08-10 17:21:45 +02002475#endif
2476}
2477
2478/*
2479 * kick up codec; used both from PM and power-save
2480 */
2481static void hda_call_codec_resume(struct hda_codec *codec)
2482{
2483 hda_set_power_state(codec,
2484 codec->afg ? codec->afg : codec->mfg,
2485 AC_PWRST_D0);
Takashi Iwai3be14142009-02-20 14:11:16 +01002486 restore_pincfgs(codec); /* restore all current pin configs */
Takashi Iwai11aeff02008-07-30 15:01:46 +02002487 hda_exec_init_verbs(codec);
Takashi Iwaicb53c622007-08-10 17:21:45 +02002488 if (codec->patch_ops.resume)
2489 codec->patch_ops.resume(codec);
2490 else {
Takashi Iwai9d99f312007-08-14 15:15:52 +02002491 if (codec->patch_ops.init)
2492 codec->patch_ops.init(codec);
Takashi Iwaicb53c622007-08-10 17:21:45 +02002493 snd_hda_codec_resume_amp(codec);
2494 snd_hda_codec_resume_cache(codec);
2495 }
2496}
2497#endif /* SND_HDA_NEEDS_RESUME */
2498
Takashi Iwai54d17402005-11-21 16:33:22 +01002499
Linus Torvalds1da177e2005-04-16 15:20:36 -07002500/**
2501 * snd_hda_build_controls - build mixer controls
2502 * @bus: the BUS
2503 *
2504 * Creates mixer controls for each codec included in the bus.
2505 *
2506 * Returns 0 if successful, otherwise a negative error code.
2507 */
Takashi Iwai1289e9e2008-11-27 15:47:11 +01002508int /*__devinit*/ snd_hda_build_controls(struct hda_bus *bus)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002509{
Takashi Iwai0ba21762007-04-16 11:29:14 +02002510 struct hda_codec *codec;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002511
Takashi Iwai0ba21762007-04-16 11:29:14 +02002512 list_for_each_entry(codec, &bus->codec_list, list) {
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02002513 int err = snd_hda_codec_build_controls(codec);
Takashi Iwaif93d4612009-03-02 10:44:15 +01002514 if (err < 0) {
2515 printk(KERN_ERR "hda_codec: cannot build controls"
2516 "for #%d (error %d)\n", codec->addr, err);
2517 err = snd_hda_codec_reset(codec);
2518 if (err < 0) {
2519 printk(KERN_ERR
2520 "hda_codec: cannot revert codec\n");
2521 return err;
2522 }
2523 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002524 }
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02002525 return 0;
2526}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002527EXPORT_SYMBOL_HDA(snd_hda_build_controls);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002528
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02002529int snd_hda_codec_build_controls(struct hda_codec *codec)
2530{
2531 int err = 0;
Takashi Iwai11aeff02008-07-30 15:01:46 +02002532 hda_exec_init_verbs(codec);
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02002533 /* continue to initialize... */
2534 if (codec->patch_ops.init)
2535 err = codec->patch_ops.init(codec);
2536 if (!err && codec->patch_ops.build_controls)
2537 err = codec->patch_ops.build_controls(codec);
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02002538 if (err < 0)
2539 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002540 return 0;
2541}
2542
Linus Torvalds1da177e2005-04-16 15:20:36 -07002543/*
2544 * stream formats
2545 */
Takashi Iwaibefdf312005-08-22 13:57:55 +02002546struct hda_rate_tbl {
2547 unsigned int hz;
2548 unsigned int alsa_bits;
2549 unsigned int hda_fmt;
2550};
2551
2552static struct hda_rate_tbl rate_bits[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002553 /* rate in Hz, ALSA rate bitmask, HDA format value */
Nicolas Graziano9d8f53f2005-08-22 13:47:16 +02002554
2555 /* autodetected value used in snd_hda_query_supported_pcm */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002556 { 8000, SNDRV_PCM_RATE_8000, 0x0500 }, /* 1/6 x 48 */
2557 { 11025, SNDRV_PCM_RATE_11025, 0x4300 }, /* 1/4 x 44 */
2558 { 16000, SNDRV_PCM_RATE_16000, 0x0200 }, /* 1/3 x 48 */
2559 { 22050, SNDRV_PCM_RATE_22050, 0x4100 }, /* 1/2 x 44 */
2560 { 32000, SNDRV_PCM_RATE_32000, 0x0a00 }, /* 2/3 x 48 */
2561 { 44100, SNDRV_PCM_RATE_44100, 0x4000 }, /* 44 */
2562 { 48000, SNDRV_PCM_RATE_48000, 0x0000 }, /* 48 */
2563 { 88200, SNDRV_PCM_RATE_88200, 0x4800 }, /* 2 x 44 */
2564 { 96000, SNDRV_PCM_RATE_96000, 0x0800 }, /* 2 x 48 */
2565 { 176400, SNDRV_PCM_RATE_176400, 0x5800 },/* 4 x 44 */
2566 { 192000, SNDRV_PCM_RATE_192000, 0x1800 }, /* 4 x 48 */
Takashi Iwaia961f9f2007-04-12 13:08:09 +02002567#define AC_PAR_PCM_RATE_BITS 11
2568 /* up to bits 10, 384kHZ isn't supported properly */
2569
2570 /* not autodetected value */
2571 { 9600, SNDRV_PCM_RATE_KNOT, 0x0400 }, /* 1/5 x 48 */
Nicolas Graziano9d8f53f2005-08-22 13:47:16 +02002572
Takashi Iwaibefdf312005-08-22 13:57:55 +02002573 { 0 } /* terminator */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002574};
2575
2576/**
2577 * snd_hda_calc_stream_format - calculate format bitset
2578 * @rate: the sample rate
2579 * @channels: the number of channels
2580 * @format: the PCM format (SNDRV_PCM_FORMAT_XXX)
2581 * @maxbps: the max. bps
2582 *
2583 * Calculate the format bitset from the given rate, channels and th PCM format.
2584 *
2585 * Return zero if invalid.
2586 */
2587unsigned int snd_hda_calc_stream_format(unsigned int rate,
2588 unsigned int channels,
2589 unsigned int format,
2590 unsigned int maxbps)
2591{
2592 int i;
2593 unsigned int val = 0;
2594
Takashi Iwaibefdf312005-08-22 13:57:55 +02002595 for (i = 0; rate_bits[i].hz; i++)
2596 if (rate_bits[i].hz == rate) {
2597 val = rate_bits[i].hda_fmt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002598 break;
2599 }
Takashi Iwai0ba21762007-04-16 11:29:14 +02002600 if (!rate_bits[i].hz) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002601 snd_printdd("invalid rate %d\n", rate);
2602 return 0;
2603 }
2604
2605 if (channels == 0 || channels > 8) {
2606 snd_printdd("invalid channels %d\n", channels);
2607 return 0;
2608 }
2609 val |= channels - 1;
2610
2611 switch (snd_pcm_format_width(format)) {
2612 case 8: val |= 0x00; break;
2613 case 16: val |= 0x10; break;
2614 case 20:
2615 case 24:
2616 case 32:
Takashi Iwaib0bb3aa2009-07-03 23:25:37 +02002617 if (maxbps >= 32 || format == SNDRV_PCM_FORMAT_FLOAT_LE)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002618 val |= 0x40;
2619 else if (maxbps >= 24)
2620 val |= 0x30;
2621 else
2622 val |= 0x20;
2623 break;
2624 default:
Takashi Iwai0ba21762007-04-16 11:29:14 +02002625 snd_printdd("invalid format width %d\n",
2626 snd_pcm_format_width(format));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002627 return 0;
2628 }
2629
2630 return val;
2631}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002632EXPORT_SYMBOL_HDA(snd_hda_calc_stream_format);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002633
Takashi Iwai92c7c8a2009-03-24 07:32:14 +01002634static unsigned int get_pcm_param(struct hda_codec *codec, hda_nid_t nid)
2635{
2636 unsigned int val = 0;
2637 if (nid != codec->afg &&
2638 (get_wcaps(codec, nid) & AC_WCAP_FORMAT_OVRD))
2639 val = snd_hda_param_read(codec, nid, AC_PAR_PCM);
2640 if (!val || val == -1)
2641 val = snd_hda_param_read(codec, codec->afg, AC_PAR_PCM);
2642 if (!val || val == -1)
2643 return 0;
2644 return val;
2645}
2646
2647static unsigned int query_pcm_param(struct hda_codec *codec, hda_nid_t nid)
2648{
2649 return query_caps_hash(codec, nid, HDA_HASH_PARPCM_KEY(nid),
2650 get_pcm_param);
2651}
2652
2653static unsigned int get_stream_param(struct hda_codec *codec, hda_nid_t nid)
2654{
2655 unsigned int streams = snd_hda_param_read(codec, nid, AC_PAR_STREAM);
2656 if (!streams || streams == -1)
2657 streams = snd_hda_param_read(codec, codec->afg, AC_PAR_STREAM);
2658 if (!streams || streams == -1)
2659 return 0;
2660 return streams;
2661}
2662
2663static unsigned int query_stream_param(struct hda_codec *codec, hda_nid_t nid)
2664{
2665 return query_caps_hash(codec, nid, HDA_HASH_PARSTR_KEY(nid),
2666 get_stream_param);
2667}
2668
Linus Torvalds1da177e2005-04-16 15:20:36 -07002669/**
2670 * snd_hda_query_supported_pcm - query the supported PCM rates and formats
2671 * @codec: the HDA codec
2672 * @nid: NID to query
2673 * @ratesp: the pointer to store the detected rate bitflags
2674 * @formatsp: the pointer to store the detected formats
2675 * @bpsp: the pointer to store the detected format widths
2676 *
2677 * Queries the supported PCM rates and formats. The NULL @ratesp, @formatsp
2678 * or @bsps argument is ignored.
2679 *
2680 * Returns 0 if successful, otherwise a negative error code.
2681 */
Takashi Iwai986862bd2008-11-27 12:40:13 +01002682static int snd_hda_query_supported_pcm(struct hda_codec *codec, hda_nid_t nid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002683 u32 *ratesp, u64 *formatsp, unsigned int *bpsp)
2684{
Jaroslav Kyselaee504712009-03-17 14:30:31 +01002685 unsigned int i, val, wcaps;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002686
Jaroslav Kyselaee504712009-03-17 14:30:31 +01002687 wcaps = get_wcaps(codec, nid);
Takashi Iwai92c7c8a2009-03-24 07:32:14 +01002688 val = query_pcm_param(codec, nid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002689
2690 if (ratesp) {
2691 u32 rates = 0;
Takashi Iwaia961f9f2007-04-12 13:08:09 +02002692 for (i = 0; i < AC_PAR_PCM_RATE_BITS; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002693 if (val & (1 << i))
Takashi Iwaibefdf312005-08-22 13:57:55 +02002694 rates |= rate_bits[i].alsa_bits;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002695 }
Jaroslav Kyselaee504712009-03-17 14:30:31 +01002696 if (rates == 0) {
2697 snd_printk(KERN_ERR "hda_codec: rates == 0 "
2698 "(nid=0x%x, val=0x%x, ovrd=%i)\n",
2699 nid, val,
2700 (wcaps & AC_WCAP_FORMAT_OVRD) ? 1 : 0);
2701 return -EIO;
2702 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002703 *ratesp = rates;
2704 }
2705
2706 if (formatsp || bpsp) {
2707 u64 formats = 0;
Jaroslav Kyselaee504712009-03-17 14:30:31 +01002708 unsigned int streams, bps;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002709
Takashi Iwai92c7c8a2009-03-24 07:32:14 +01002710 streams = query_stream_param(codec, nid);
2711 if (!streams)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002712 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002713
2714 bps = 0;
2715 if (streams & AC_SUPFMT_PCM) {
2716 if (val & AC_SUPPCM_BITS_8) {
2717 formats |= SNDRV_PCM_FMTBIT_U8;
2718 bps = 8;
2719 }
2720 if (val & AC_SUPPCM_BITS_16) {
2721 formats |= SNDRV_PCM_FMTBIT_S16_LE;
2722 bps = 16;
2723 }
2724 if (wcaps & AC_WCAP_DIGITAL) {
2725 if (val & AC_SUPPCM_BITS_32)
2726 formats |= SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_LE;
2727 if (val & (AC_SUPPCM_BITS_20|AC_SUPPCM_BITS_24))
2728 formats |= SNDRV_PCM_FMTBIT_S32_LE;
2729 if (val & AC_SUPPCM_BITS_24)
2730 bps = 24;
2731 else if (val & AC_SUPPCM_BITS_20)
2732 bps = 20;
Takashi Iwai0ba21762007-04-16 11:29:14 +02002733 } else if (val & (AC_SUPPCM_BITS_20|AC_SUPPCM_BITS_24|
2734 AC_SUPPCM_BITS_32)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002735 formats |= SNDRV_PCM_FMTBIT_S32_LE;
2736 if (val & AC_SUPPCM_BITS_32)
2737 bps = 32;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002738 else if (val & AC_SUPPCM_BITS_24)
2739 bps = 24;
Nicolas Graziano33ef76512006-09-19 14:23:14 +02002740 else if (val & AC_SUPPCM_BITS_20)
2741 bps = 20;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002742 }
2743 }
Takashi Iwaib5025c52009-07-01 18:05:27 +02002744 if (streams & AC_SUPFMT_FLOAT32) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002745 formats |= SNDRV_PCM_FMTBIT_FLOAT_LE;
Takashi Iwaib0bb3aa2009-07-03 23:25:37 +02002746 if (!bps)
2747 bps = 32;
Takashi Iwaib5025c52009-07-01 18:05:27 +02002748 }
2749 if (streams == AC_SUPFMT_AC3) {
Takashi Iwai0ba21762007-04-16 11:29:14 +02002750 /* should be exclusive */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002751 /* temporary hack: we have still no proper support
2752 * for the direct AC3 stream...
2753 */
2754 formats |= SNDRV_PCM_FMTBIT_U8;
2755 bps = 8;
2756 }
Jaroslav Kyselaee504712009-03-17 14:30:31 +01002757 if (formats == 0) {
2758 snd_printk(KERN_ERR "hda_codec: formats == 0 "
2759 "(nid=0x%x, val=0x%x, ovrd=%i, "
2760 "streams=0x%x)\n",
2761 nid, val,
2762 (wcaps & AC_WCAP_FORMAT_OVRD) ? 1 : 0,
2763 streams);
2764 return -EIO;
2765 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002766 if (formatsp)
2767 *formatsp = formats;
2768 if (bpsp)
2769 *bpsp = bps;
2770 }
2771
2772 return 0;
2773}
2774
2775/**
Takashi Iwai0ba21762007-04-16 11:29:14 +02002776 * snd_hda_is_supported_format - check whether the given node supports
2777 * the format val
Linus Torvalds1da177e2005-04-16 15:20:36 -07002778 *
2779 * Returns 1 if supported, 0 if not.
2780 */
2781int snd_hda_is_supported_format(struct hda_codec *codec, hda_nid_t nid,
2782 unsigned int format)
2783{
2784 int i;
2785 unsigned int val = 0, rate, stream;
2786
Takashi Iwai92c7c8a2009-03-24 07:32:14 +01002787 val = query_pcm_param(codec, nid);
2788 if (!val)
2789 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002790
2791 rate = format & 0xff00;
Takashi Iwaia961f9f2007-04-12 13:08:09 +02002792 for (i = 0; i < AC_PAR_PCM_RATE_BITS; i++)
Takashi Iwaibefdf312005-08-22 13:57:55 +02002793 if (rate_bits[i].hda_fmt == rate) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002794 if (val & (1 << i))
2795 break;
2796 return 0;
2797 }
Takashi Iwaia961f9f2007-04-12 13:08:09 +02002798 if (i >= AC_PAR_PCM_RATE_BITS)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002799 return 0;
2800
Takashi Iwai92c7c8a2009-03-24 07:32:14 +01002801 stream = query_stream_param(codec, nid);
2802 if (!stream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002803 return 0;
2804
2805 if (stream & AC_SUPFMT_PCM) {
2806 switch (format & 0xf0) {
2807 case 0x00:
Takashi Iwai0ba21762007-04-16 11:29:14 +02002808 if (!(val & AC_SUPPCM_BITS_8))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002809 return 0;
2810 break;
2811 case 0x10:
Takashi Iwai0ba21762007-04-16 11:29:14 +02002812 if (!(val & AC_SUPPCM_BITS_16))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002813 return 0;
2814 break;
2815 case 0x20:
Takashi Iwai0ba21762007-04-16 11:29:14 +02002816 if (!(val & AC_SUPPCM_BITS_20))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002817 return 0;
2818 break;
2819 case 0x30:
Takashi Iwai0ba21762007-04-16 11:29:14 +02002820 if (!(val & AC_SUPPCM_BITS_24))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002821 return 0;
2822 break;
2823 case 0x40:
Takashi Iwai0ba21762007-04-16 11:29:14 +02002824 if (!(val & AC_SUPPCM_BITS_32))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002825 return 0;
2826 break;
2827 default:
2828 return 0;
2829 }
2830 } else {
2831 /* FIXME: check for float32 and AC3? */
2832 }
2833
2834 return 1;
2835}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002836EXPORT_SYMBOL_HDA(snd_hda_is_supported_format);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002837
2838/*
2839 * PCM stuff
2840 */
2841static int hda_pcm_default_open_close(struct hda_pcm_stream *hinfo,
2842 struct hda_codec *codec,
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01002843 struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002844{
2845 return 0;
2846}
2847
2848static int hda_pcm_default_prepare(struct hda_pcm_stream *hinfo,
2849 struct hda_codec *codec,
2850 unsigned int stream_tag,
2851 unsigned int format,
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01002852 struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002853{
2854 snd_hda_codec_setup_stream(codec, hinfo->nid, stream_tag, 0, format);
2855 return 0;
2856}
2857
2858static int hda_pcm_default_cleanup(struct hda_pcm_stream *hinfo,
2859 struct hda_codec *codec,
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01002860 struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002861{
Takashi Iwai888afa12008-03-18 09:57:50 +01002862 snd_hda_codec_cleanup_stream(codec, hinfo->nid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002863 return 0;
2864}
2865
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02002866static int set_pcm_default_values(struct hda_codec *codec,
2867 struct hda_pcm_stream *info)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002868{
Jaroslav Kyselaee504712009-03-17 14:30:31 +01002869 int err;
2870
Takashi Iwai0ba21762007-04-16 11:29:14 +02002871 /* query support PCM information from the given NID */
2872 if (info->nid && (!info->rates || !info->formats)) {
Jaroslav Kyselaee504712009-03-17 14:30:31 +01002873 err = snd_hda_query_supported_pcm(codec, info->nid,
Takashi Iwai0ba21762007-04-16 11:29:14 +02002874 info->rates ? NULL : &info->rates,
2875 info->formats ? NULL : &info->formats,
2876 info->maxbps ? NULL : &info->maxbps);
Jaroslav Kyselaee504712009-03-17 14:30:31 +01002877 if (err < 0)
2878 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002879 }
2880 if (info->ops.open == NULL)
2881 info->ops.open = hda_pcm_default_open_close;
2882 if (info->ops.close == NULL)
2883 info->ops.close = hda_pcm_default_open_close;
2884 if (info->ops.prepare == NULL) {
Takashi Iwaida3cec32008-08-08 17:12:14 +02002885 if (snd_BUG_ON(!info->nid))
2886 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002887 info->ops.prepare = hda_pcm_default_prepare;
2888 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002889 if (info->ops.cleanup == NULL) {
Takashi Iwaida3cec32008-08-08 17:12:14 +02002890 if (snd_BUG_ON(!info->nid))
2891 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002892 info->ops.cleanup = hda_pcm_default_cleanup;
2893 }
2894 return 0;
2895}
2896
Jaroslav Kyselae3303232009-11-10 14:53:02 +01002897const char *snd_hda_pcm_type_name[HDA_PCM_NTYPES] = {
2898 "Audio", "SPDIF", "HDMI", "Modem"
2899};
2900
Takashi Iwai176d5332008-07-30 15:01:44 +02002901/*
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002902 * get the empty PCM device number to assign
2903 */
2904static int get_empty_pcm_device(struct hda_bus *bus, int type)
2905{
Wu Fengguangf5d6def2009-10-30 11:38:26 +01002906 /* audio device indices; not linear to keep compatibility */
2907 static int audio_idx[HDA_PCM_NTYPES][5] = {
2908 [HDA_PCM_TYPE_AUDIO] = { 0, 2, 4, 5, -1 },
2909 [HDA_PCM_TYPE_SPDIF] = { 1, -1 },
Wu Fengguang92608ba2009-10-30 11:40:03 +01002910 [HDA_PCM_TYPE_HDMI] = { 3, 7, 8, 9, -1 },
Wu Fengguangf5d6def2009-10-30 11:38:26 +01002911 [HDA_PCM_TYPE_MODEM] = { 6, -1 },
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002912 };
Wu Fengguangf5d6def2009-10-30 11:38:26 +01002913 int i;
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002914
Wu Fengguangf5d6def2009-10-30 11:38:26 +01002915 if (type >= HDA_PCM_NTYPES) {
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002916 snd_printk(KERN_WARNING "Invalid PCM type %d\n", type);
2917 return -EINVAL;
2918 }
Wu Fengguangf5d6def2009-10-30 11:38:26 +01002919
2920 for (i = 0; audio_idx[type][i] >= 0 ; i++)
2921 if (!test_and_set_bit(audio_idx[type][i], bus->pcm_dev_bits))
2922 return audio_idx[type][i];
2923
Jaroslav Kyselae3303232009-11-10 14:53:02 +01002924 snd_printk(KERN_WARNING "Too many %s devices\n", snd_hda_pcm_type_name[type]);
Wu Fengguangf5d6def2009-10-30 11:38:26 +01002925 return -EAGAIN;
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002926}
2927
2928/*
Takashi Iwai176d5332008-07-30 15:01:44 +02002929 * attach a new PCM stream
2930 */
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002931static int snd_hda_attach_pcm(struct hda_codec *codec, struct hda_pcm *pcm)
Takashi Iwai176d5332008-07-30 15:01:44 +02002932{
Takashi Iwai33fa35e2008-11-06 16:50:40 +01002933 struct hda_bus *bus = codec->bus;
Takashi Iwai176d5332008-07-30 15:01:44 +02002934 struct hda_pcm_stream *info;
2935 int stream, err;
2936
Takashi Iwaib91f0802008-11-04 08:43:08 +01002937 if (snd_BUG_ON(!pcm->name))
Takashi Iwai176d5332008-07-30 15:01:44 +02002938 return -EINVAL;
2939 for (stream = 0; stream < 2; stream++) {
2940 info = &pcm->stream[stream];
2941 if (info->substreams) {
2942 err = set_pcm_default_values(codec, info);
2943 if (err < 0)
2944 return err;
2945 }
2946 }
Takashi Iwai33fa35e2008-11-06 16:50:40 +01002947 return bus->ops.attach_pcm(bus, codec, pcm);
Takashi Iwai176d5332008-07-30 15:01:44 +02002948}
2949
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002950/* assign all PCMs of the given codec */
2951int snd_hda_codec_build_pcms(struct hda_codec *codec)
2952{
2953 unsigned int pcm;
2954 int err;
2955
2956 if (!codec->num_pcms) {
2957 if (!codec->patch_ops.build_pcms)
2958 return 0;
2959 err = codec->patch_ops.build_pcms(codec);
Takashi Iwai6e655bf2009-03-02 10:46:03 +01002960 if (err < 0) {
2961 printk(KERN_ERR "hda_codec: cannot build PCMs"
2962 "for #%d (error %d)\n", codec->addr, err);
2963 err = snd_hda_codec_reset(codec);
2964 if (err < 0) {
2965 printk(KERN_ERR
2966 "hda_codec: cannot revert codec\n");
2967 return err;
2968 }
2969 }
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002970 }
2971 for (pcm = 0; pcm < codec->num_pcms; pcm++) {
2972 struct hda_pcm *cpcm = &codec->pcm_info[pcm];
2973 int dev;
2974
2975 if (!cpcm->stream[0].substreams && !cpcm->stream[1].substreams)
Takashi Iwai41b5b012009-01-20 18:21:23 +01002976 continue; /* no substreams assigned */
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002977
2978 if (!cpcm->pcm) {
2979 dev = get_empty_pcm_device(codec->bus, cpcm->pcm_type);
2980 if (dev < 0)
Takashi Iwai6e655bf2009-03-02 10:46:03 +01002981 continue; /* no fatal error */
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002982 cpcm->device = dev;
2983 err = snd_hda_attach_pcm(codec, cpcm);
Takashi Iwai6e655bf2009-03-02 10:46:03 +01002984 if (err < 0) {
2985 printk(KERN_ERR "hda_codec: cannot attach "
2986 "PCM stream %d for codec #%d\n",
2987 dev, codec->addr);
2988 continue; /* no fatal error */
2989 }
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002990 }
2991 }
2992 return 0;
2993}
2994
Linus Torvalds1da177e2005-04-16 15:20:36 -07002995/**
2996 * snd_hda_build_pcms - build PCM information
2997 * @bus: the BUS
2998 *
2999 * Create PCM information for each codec included in the bus.
3000 *
3001 * The build_pcms codec patch is requested to set up codec->num_pcms and
3002 * codec->pcm_info properly. The array is referred by the top-level driver
3003 * to create its PCM instances.
3004 * The allocated codec->pcm_info should be released in codec->patch_ops.free
3005 * callback.
3006 *
3007 * At least, substreams, channels_min and channels_max must be filled for
3008 * each stream. substreams = 0 indicates that the stream doesn't exist.
3009 * When rates and/or formats are zero, the supported values are queried
3010 * from the given nid. The nid is used also by the default ops.prepare
3011 * and ops.cleanup callbacks.
3012 *
3013 * The driver needs to call ops.open in its open callback. Similarly,
3014 * ops.close is supposed to be called in the close callback.
3015 * ops.prepare should be called in the prepare or hw_params callback
3016 * with the proper parameters for set up.
3017 * ops.cleanup should be called in hw_free for clean up of streams.
3018 *
3019 * This function returns 0 if successfull, or a negative error code.
3020 */
Takashi Iwai529bd6c2008-11-27 14:17:01 +01003021int __devinit snd_hda_build_pcms(struct hda_bus *bus)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003022{
Takashi Iwai0ba21762007-04-16 11:29:14 +02003023 struct hda_codec *codec;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003024
Takashi Iwai0ba21762007-04-16 11:29:14 +02003025 list_for_each_entry(codec, &bus->codec_list, list) {
Takashi Iwai529bd6c2008-11-27 14:17:01 +01003026 int err = snd_hda_codec_build_pcms(codec);
3027 if (err < 0)
3028 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003029 }
3030 return 0;
3031}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003032EXPORT_SYMBOL_HDA(snd_hda_build_pcms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003033
Linus Torvalds1da177e2005-04-16 15:20:36 -07003034/**
3035 * snd_hda_check_board_config - compare the current codec with the config table
3036 * @codec: the HDA codec
Takashi Iwaif5fcc132006-11-24 17:07:44 +01003037 * @num_configs: number of config enums
3038 * @models: array of model name strings
Linus Torvalds1da177e2005-04-16 15:20:36 -07003039 * @tbl: configuration table, terminated by null entries
3040 *
3041 * Compares the modelname or PCI subsystem id of the current codec with the
3042 * given configuration table. If a matching entry is found, returns its
3043 * config value (supposed to be 0 or positive).
3044 *
3045 * If no entries are matching, the function returns a negative value.
3046 */
Takashi Iwai12f288b2007-08-02 15:51:59 +02003047int snd_hda_check_board_config(struct hda_codec *codec,
3048 int num_configs, const char **models,
3049 const struct snd_pci_quirk *tbl)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003050{
Takashi Iwaif44ac832008-07-30 15:01:45 +02003051 if (codec->modelname && models) {
Takashi Iwaif5fcc132006-11-24 17:07:44 +01003052 int i;
3053 for (i = 0; i < num_configs; i++) {
3054 if (models[i] &&
Takashi Iwaif44ac832008-07-30 15:01:45 +02003055 !strcmp(codec->modelname, models[i])) {
Takashi Iwaif5fcc132006-11-24 17:07:44 +01003056 snd_printd(KERN_INFO "hda_codec: model '%s' is "
3057 "selected\n", models[i]);
3058 return i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003059 }
3060 }
3061 }
3062
Takashi Iwaif5fcc132006-11-24 17:07:44 +01003063 if (!codec->bus->pci || !tbl)
3064 return -1;
3065
3066 tbl = snd_pci_quirk_lookup(codec->bus->pci, tbl);
3067 if (!tbl)
3068 return -1;
3069 if (tbl->value >= 0 && tbl->value < num_configs) {
Takashi Iwai62cf8722008-05-20 12:15:15 +02003070#ifdef CONFIG_SND_DEBUG_VERBOSE
Takashi Iwaif5fcc132006-11-24 17:07:44 +01003071 char tmp[10];
3072 const char *model = NULL;
3073 if (models)
3074 model = models[tbl->value];
3075 if (!model) {
3076 sprintf(tmp, "#%d", tbl->value);
3077 model = tmp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003078 }
Takashi Iwaif5fcc132006-11-24 17:07:44 +01003079 snd_printdd(KERN_INFO "hda_codec: model '%s' is selected "
3080 "for config %x:%x (%s)\n",
3081 model, tbl->subvendor, tbl->subdevice,
3082 (tbl->name ? tbl->name : "Unknown device"));
3083#endif
3084 return tbl->value;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003085 }
3086 return -1;
3087}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003088EXPORT_SYMBOL_HDA(snd_hda_check_board_config);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003089
3090/**
Mauro Carvalho Chehab2eda3442008-08-11 10:18:39 +02003091 * snd_hda_check_board_codec_sid_config - compare the current codec
3092 subsystem ID with the
3093 config table
3094
3095 This is important for Gateway notebooks with SB450 HDA Audio
3096 where the vendor ID of the PCI device is:
3097 ATI Technologies Inc SB450 HDA Audio [1002:437b]
3098 and the vendor/subvendor are found only at the codec.
3099
3100 * @codec: the HDA codec
3101 * @num_configs: number of config enums
3102 * @models: array of model name strings
3103 * @tbl: configuration table, terminated by null entries
3104 *
3105 * Compares the modelname or PCI subsystem id of the current codec with the
3106 * given configuration table. If a matching entry is found, returns its
3107 * config value (supposed to be 0 or positive).
3108 *
3109 * If no entries are matching, the function returns a negative value.
3110 */
3111int snd_hda_check_board_codec_sid_config(struct hda_codec *codec,
3112 int num_configs, const char **models,
3113 const struct snd_pci_quirk *tbl)
3114{
3115 const struct snd_pci_quirk *q;
3116
3117 /* Search for codec ID */
3118 for (q = tbl; q->subvendor; q++) {
3119 unsigned long vendorid = (q->subdevice) | (q->subvendor << 16);
3120
3121 if (vendorid == codec->subsystem_id)
3122 break;
3123 }
3124
3125 if (!q->subvendor)
3126 return -1;
3127
3128 tbl = q;
3129
3130 if (tbl->value >= 0 && tbl->value < num_configs) {
Takashi Iwaid94ff6b2009-09-02 00:20:21 +02003131#ifdef CONFIG_SND_DEBUG_VERBOSE
Mauro Carvalho Chehab2eda3442008-08-11 10:18:39 +02003132 char tmp[10];
3133 const char *model = NULL;
3134 if (models)
3135 model = models[tbl->value];
3136 if (!model) {
3137 sprintf(tmp, "#%d", tbl->value);
3138 model = tmp;
3139 }
3140 snd_printdd(KERN_INFO "hda_codec: model '%s' is selected "
3141 "for config %x:%x (%s)\n",
3142 model, tbl->subvendor, tbl->subdevice,
3143 (tbl->name ? tbl->name : "Unknown device"));
3144#endif
3145 return tbl->value;
3146 }
3147 return -1;
3148}
3149EXPORT_SYMBOL_HDA(snd_hda_check_board_codec_sid_config);
3150
3151/**
Linus Torvalds1da177e2005-04-16 15:20:36 -07003152 * snd_hda_add_new_ctls - create controls from the array
3153 * @codec: the HDA codec
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01003154 * @knew: the array of struct snd_kcontrol_new
Linus Torvalds1da177e2005-04-16 15:20:36 -07003155 *
3156 * This helper function creates and add new controls in the given array.
3157 * The array must be terminated with an empty entry as terminator.
3158 *
3159 * Returns 0 if successful, or a negative error code.
3160 */
Takashi Iwai12f288b2007-08-02 15:51:59 +02003161int snd_hda_add_new_ctls(struct hda_codec *codec, struct snd_kcontrol_new *knew)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003162{
Takashi Iwaicb53c622007-08-10 17:21:45 +02003163 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003164
3165 for (; knew->name; knew++) {
Takashi Iwai54d17402005-11-21 16:33:22 +01003166 struct snd_kcontrol *kctl;
3167 kctl = snd_ctl_new1(knew, codec);
Takashi Iwai0ba21762007-04-16 11:29:14 +02003168 if (!kctl)
Takashi Iwai54d17402005-11-21 16:33:22 +01003169 return -ENOMEM;
Jaroslav Kysela3911a4c2009-11-11 13:43:01 +01003170 err = snd_hda_ctl_add(codec, 0, kctl);
Takashi Iwai54d17402005-11-21 16:33:22 +01003171 if (err < 0) {
Takashi Iwai0ba21762007-04-16 11:29:14 +02003172 if (!codec->addr)
Takashi Iwai54d17402005-11-21 16:33:22 +01003173 return err;
3174 kctl = snd_ctl_new1(knew, codec);
Takashi Iwai0ba21762007-04-16 11:29:14 +02003175 if (!kctl)
Takashi Iwai54d17402005-11-21 16:33:22 +01003176 return -ENOMEM;
3177 kctl->id.device = codec->addr;
Jaroslav Kysela3911a4c2009-11-11 13:43:01 +01003178 err = snd_hda_ctl_add(codec, 0, kctl);
Takashi Iwai0ba21762007-04-16 11:29:14 +02003179 if (err < 0)
Takashi Iwai54d17402005-11-21 16:33:22 +01003180 return err;
3181 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003182 }
3183 return 0;
3184}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003185EXPORT_SYMBOL_HDA(snd_hda_add_new_ctls);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003186
Takashi Iwaicb53c622007-08-10 17:21:45 +02003187#ifdef CONFIG_SND_HDA_POWER_SAVE
3188static void hda_set_power_state(struct hda_codec *codec, hda_nid_t fg,
3189 unsigned int power_state);
3190
3191static void hda_power_work(struct work_struct *work)
3192{
3193 struct hda_codec *codec =
3194 container_of(work, struct hda_codec, power_work.work);
Takashi Iwai33fa35e2008-11-06 16:50:40 +01003195 struct hda_bus *bus = codec->bus;
Takashi Iwaicb53c622007-08-10 17:21:45 +02003196
Maxim Levitsky2e492462007-09-03 15:26:57 +02003197 if (!codec->power_on || codec->power_count) {
3198 codec->power_transition = 0;
Takashi Iwaicb53c622007-08-10 17:21:45 +02003199 return;
Maxim Levitsky2e492462007-09-03 15:26:57 +02003200 }
Takashi Iwaicb53c622007-08-10 17:21:45 +02003201
3202 hda_call_codec_suspend(codec);
Takashi Iwai33fa35e2008-11-06 16:50:40 +01003203 if (bus->ops.pm_notify)
3204 bus->ops.pm_notify(bus);
Takashi Iwaicb53c622007-08-10 17:21:45 +02003205}
3206
3207static void hda_keep_power_on(struct hda_codec *codec)
3208{
3209 codec->power_count++;
3210 codec->power_on = 1;
Takashi Iwaia2f63092009-11-11 09:34:25 +01003211 codec->power_jiffies = jiffies;
3212}
3213
3214void snd_hda_update_power_acct(struct hda_codec *codec)
3215{
3216 unsigned long delta = jiffies - codec->power_jiffies;
3217 if (codec->power_on)
3218 codec->power_on_acct += delta;
3219 else
3220 codec->power_off_acct += delta;
3221 codec->power_jiffies += delta;
Takashi Iwaicb53c622007-08-10 17:21:45 +02003222}
3223
3224void snd_hda_power_up(struct hda_codec *codec)
3225{
Takashi Iwai33fa35e2008-11-06 16:50:40 +01003226 struct hda_bus *bus = codec->bus;
3227
Takashi Iwaicb53c622007-08-10 17:21:45 +02003228 codec->power_count++;
Takashi Iwaia221e282007-08-16 16:35:33 +02003229 if (codec->power_on || codec->power_transition)
Takashi Iwaicb53c622007-08-10 17:21:45 +02003230 return;
3231
Takashi Iwaia2f63092009-11-11 09:34:25 +01003232 snd_hda_update_power_acct(codec);
Takashi Iwaicb53c622007-08-10 17:21:45 +02003233 codec->power_on = 1;
Takashi Iwaia2f63092009-11-11 09:34:25 +01003234 codec->power_jiffies = jiffies;
Takashi Iwai33fa35e2008-11-06 16:50:40 +01003235 if (bus->ops.pm_notify)
3236 bus->ops.pm_notify(bus);
Takashi Iwaicb53c622007-08-10 17:21:45 +02003237 hda_call_codec_resume(codec);
3238 cancel_delayed_work(&codec->power_work);
Takashi Iwaia221e282007-08-16 16:35:33 +02003239 codec->power_transition = 0;
Takashi Iwaicb53c622007-08-10 17:21:45 +02003240}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003241EXPORT_SYMBOL_HDA(snd_hda_power_up);
Takashi Iwai1289e9e2008-11-27 15:47:11 +01003242
3243#define power_save(codec) \
3244 ((codec)->bus->power_save ? *(codec)->bus->power_save : 0)
Takashi Iwaicb53c622007-08-10 17:21:45 +02003245
Takashi Iwaifee2fba2008-11-27 12:43:28 +01003246#define power_save(codec) \
3247 ((codec)->bus->power_save ? *(codec)->bus->power_save : 0)
3248
Takashi Iwaicb53c622007-08-10 17:21:45 +02003249void snd_hda_power_down(struct hda_codec *codec)
3250{
3251 --codec->power_count;
Takashi Iwaia221e282007-08-16 16:35:33 +02003252 if (!codec->power_on || codec->power_count || codec->power_transition)
Takashi Iwaicb53c622007-08-10 17:21:45 +02003253 return;
Takashi Iwaifee2fba2008-11-27 12:43:28 +01003254 if (power_save(codec)) {
Takashi Iwaia221e282007-08-16 16:35:33 +02003255 codec->power_transition = 1; /* avoid reentrance */
Takashi Iwaic107b412009-01-13 17:46:37 +01003256 queue_delayed_work(codec->bus->workq, &codec->power_work,
Takashi Iwaifee2fba2008-11-27 12:43:28 +01003257 msecs_to_jiffies(power_save(codec) * 1000));
Takashi Iwaia221e282007-08-16 16:35:33 +02003258 }
Takashi Iwaicb53c622007-08-10 17:21:45 +02003259}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003260EXPORT_SYMBOL_HDA(snd_hda_power_down);
Takashi Iwaicb53c622007-08-10 17:21:45 +02003261
3262int snd_hda_check_amp_list_power(struct hda_codec *codec,
3263 struct hda_loopback_check *check,
3264 hda_nid_t nid)
3265{
3266 struct hda_amp_list *p;
3267 int ch, v;
3268
3269 if (!check->amplist)
3270 return 0;
3271 for (p = check->amplist; p->nid; p++) {
3272 if (p->nid == nid)
3273 break;
3274 }
3275 if (!p->nid)
3276 return 0; /* nothing changed */
3277
3278 for (p = check->amplist; p->nid; p++) {
3279 for (ch = 0; ch < 2; ch++) {
3280 v = snd_hda_codec_amp_read(codec, p->nid, ch, p->dir,
3281 p->idx);
3282 if (!(v & HDA_AMP_MUTE) && v > 0) {
3283 if (!check->power_on) {
3284 check->power_on = 1;
3285 snd_hda_power_up(codec);
3286 }
3287 return 1;
3288 }
3289 }
3290 }
3291 if (check->power_on) {
3292 check->power_on = 0;
3293 snd_hda_power_down(codec);
3294 }
3295 return 0;
3296}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003297EXPORT_SYMBOL_HDA(snd_hda_check_amp_list_power);
Takashi Iwaicb53c622007-08-10 17:21:45 +02003298#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07003299
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01003300/*
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01003301 * Channel mode helper
3302 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003303int snd_hda_ch_mode_info(struct hda_codec *codec,
3304 struct snd_ctl_elem_info *uinfo,
3305 const struct hda_channel_mode *chmode,
3306 int num_chmodes)
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01003307{
3308 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
3309 uinfo->count = 1;
3310 uinfo->value.enumerated.items = num_chmodes;
3311 if (uinfo->value.enumerated.item >= num_chmodes)
3312 uinfo->value.enumerated.item = num_chmodes - 1;
3313 sprintf(uinfo->value.enumerated.name, "%dch",
3314 chmode[uinfo->value.enumerated.item].channels);
3315 return 0;
3316}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003317EXPORT_SYMBOL_HDA(snd_hda_ch_mode_info);
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01003318
Takashi Iwai0ba21762007-04-16 11:29:14 +02003319int snd_hda_ch_mode_get(struct hda_codec *codec,
3320 struct snd_ctl_elem_value *ucontrol,
3321 const struct hda_channel_mode *chmode,
3322 int num_chmodes,
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01003323 int max_channels)
3324{
3325 int i;
3326
3327 for (i = 0; i < num_chmodes; i++) {
3328 if (max_channels == chmode[i].channels) {
3329 ucontrol->value.enumerated.item[0] = i;
3330 break;
3331 }
3332 }
3333 return 0;
3334}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003335EXPORT_SYMBOL_HDA(snd_hda_ch_mode_get);
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01003336
Takashi Iwai0ba21762007-04-16 11:29:14 +02003337int snd_hda_ch_mode_put(struct hda_codec *codec,
3338 struct snd_ctl_elem_value *ucontrol,
3339 const struct hda_channel_mode *chmode,
3340 int num_chmodes,
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01003341 int *max_channelsp)
3342{
3343 unsigned int mode;
3344
3345 mode = ucontrol->value.enumerated.item[0];
Takashi Iwai68ea7b22007-11-15 15:54:38 +01003346 if (mode >= num_chmodes)
3347 return -EINVAL;
Takashi Iwai82beb8f2007-08-10 17:09:26 +02003348 if (*max_channelsp == chmode[mode].channels)
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01003349 return 0;
3350 /* change the current channel setting */
3351 *max_channelsp = chmode[mode].channels;
3352 if (chmode[mode].sequence)
Takashi Iwai82beb8f2007-08-10 17:09:26 +02003353 snd_hda_sequence_write_cache(codec, chmode[mode].sequence);
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01003354 return 1;
3355}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003356EXPORT_SYMBOL_HDA(snd_hda_ch_mode_put);
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01003357
Linus Torvalds1da177e2005-04-16 15:20:36 -07003358/*
3359 * input MUX helper
3360 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003361int snd_hda_input_mux_info(const struct hda_input_mux *imux,
3362 struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003363{
3364 unsigned int index;
3365
3366 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
3367 uinfo->count = 1;
3368 uinfo->value.enumerated.items = imux->num_items;
Takashi Iwai5513b0c2007-10-09 11:58:41 +02003369 if (!imux->num_items)
3370 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003371 index = uinfo->value.enumerated.item;
3372 if (index >= imux->num_items)
3373 index = imux->num_items - 1;
3374 strcpy(uinfo->value.enumerated.name, imux->items[index].label);
3375 return 0;
3376}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003377EXPORT_SYMBOL_HDA(snd_hda_input_mux_info);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003378
Takashi Iwai0ba21762007-04-16 11:29:14 +02003379int snd_hda_input_mux_put(struct hda_codec *codec,
3380 const struct hda_input_mux *imux,
3381 struct snd_ctl_elem_value *ucontrol,
3382 hda_nid_t nid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003383 unsigned int *cur_val)
3384{
3385 unsigned int idx;
3386
Takashi Iwai5513b0c2007-10-09 11:58:41 +02003387 if (!imux->num_items)
3388 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003389 idx = ucontrol->value.enumerated.item[0];
3390 if (idx >= imux->num_items)
3391 idx = imux->num_items - 1;
Takashi Iwai82beb8f2007-08-10 17:09:26 +02003392 if (*cur_val == idx)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003393 return 0;
Takashi Iwai82beb8f2007-08-10 17:09:26 +02003394 snd_hda_codec_write_cache(codec, nid, 0, AC_VERB_SET_CONNECT_SEL,
3395 imux->items[idx].index);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003396 *cur_val = idx;
3397 return 1;
3398}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003399EXPORT_SYMBOL_HDA(snd_hda_input_mux_put);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003400
3401
3402/*
3403 * Multi-channel / digital-out PCM helper functions
3404 */
3405
Takashi Iwai6b97eb42007-04-05 14:51:48 +02003406/* setup SPDIF output stream */
3407static void setup_dig_out_stream(struct hda_codec *codec, hda_nid_t nid,
3408 unsigned int stream_tag, unsigned int format)
3409{
3410 /* turn off SPDIF once; otherwise the IEC958 bits won't be updated */
Takashi Iwai2f728532008-09-25 16:32:41 +02003411 if (codec->spdif_status_reset && (codec->spdif_ctls & AC_DIG1_ENABLE))
3412 set_dig_out_convert(codec, nid,
3413 codec->spdif_ctls & ~AC_DIG1_ENABLE & 0xff,
3414 -1);
Takashi Iwai6b97eb42007-04-05 14:51:48 +02003415 snd_hda_codec_setup_stream(codec, nid, stream_tag, 0, format);
Takashi Iwai2f728532008-09-25 16:32:41 +02003416 if (codec->slave_dig_outs) {
3417 hda_nid_t *d;
3418 for (d = codec->slave_dig_outs; *d; d++)
3419 snd_hda_codec_setup_stream(codec, *d, stream_tag, 0,
3420 format);
Matthew Ranostayde51ca12008-09-07 14:31:40 -04003421 }
Takashi Iwai2f728532008-09-25 16:32:41 +02003422 /* turn on again (if needed) */
3423 if (codec->spdif_status_reset && (codec->spdif_ctls & AC_DIG1_ENABLE))
3424 set_dig_out_convert(codec, nid,
3425 codec->spdif_ctls & 0xff, -1);
3426}
Matthew Ranostayde51ca12008-09-07 14:31:40 -04003427
Takashi Iwai2f728532008-09-25 16:32:41 +02003428static void cleanup_dig_out_stream(struct hda_codec *codec, hda_nid_t nid)
3429{
3430 snd_hda_codec_cleanup_stream(codec, nid);
3431 if (codec->slave_dig_outs) {
3432 hda_nid_t *d;
3433 for (d = codec->slave_dig_outs; *d; d++)
3434 snd_hda_codec_cleanup_stream(codec, *d);
3435 }
Takashi Iwai6b97eb42007-04-05 14:51:48 +02003436}
3437
Takashi Iwaifb8d1a32009-11-10 16:02:29 +01003438/* call each reboot notifier */
3439void snd_hda_bus_reboot_notify(struct hda_bus *bus)
3440{
3441 struct hda_codec *codec;
3442
3443 if (!bus)
3444 return;
3445 list_for_each_entry(codec, &bus->codec_list, list) {
3446#ifdef CONFIG_SND_HDA_POWER_SAVE
3447 if (!codec->power_on)
3448 continue;
3449#endif
3450 if (codec->patch_ops.reboot_notify)
3451 codec->patch_ops.reboot_notify(codec);
3452 }
3453}
Takashi Iwai8f217a22009-11-10 18:26:12 +01003454EXPORT_SYMBOL_HDA(snd_hda_bus_reboot_notify);
Takashi Iwaifb8d1a32009-11-10 16:02:29 +01003455
Linus Torvalds1da177e2005-04-16 15:20:36 -07003456/*
3457 * open the digital out in the exclusive mode
3458 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003459int snd_hda_multi_out_dig_open(struct hda_codec *codec,
3460 struct hda_multi_out *mout)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003461{
Ingo Molnar62932df2006-01-16 16:34:20 +01003462 mutex_lock(&codec->spdif_mutex);
Takashi Iwai5930ca42007-04-16 11:23:56 +02003463 if (mout->dig_out_used == HDA_DIG_ANALOG_DUP)
3464 /* already opened as analog dup; reset it once */
Takashi Iwai2f728532008-09-25 16:32:41 +02003465 cleanup_dig_out_stream(codec, mout->dig_out_nid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003466 mout->dig_out_used = HDA_DIG_EXCLUSIVE;
Ingo Molnar62932df2006-01-16 16:34:20 +01003467 mutex_unlock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003468 return 0;
3469}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003470EXPORT_SYMBOL_HDA(snd_hda_multi_out_dig_open);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003471
Takashi Iwai6b97eb42007-04-05 14:51:48 +02003472int snd_hda_multi_out_dig_prepare(struct hda_codec *codec,
3473 struct hda_multi_out *mout,
3474 unsigned int stream_tag,
3475 unsigned int format,
3476 struct snd_pcm_substream *substream)
3477{
3478 mutex_lock(&codec->spdif_mutex);
3479 setup_dig_out_stream(codec, mout->dig_out_nid, stream_tag, format);
3480 mutex_unlock(&codec->spdif_mutex);
3481 return 0;
3482}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003483EXPORT_SYMBOL_HDA(snd_hda_multi_out_dig_prepare);
Takashi Iwai6b97eb42007-04-05 14:51:48 +02003484
Takashi Iwai9411e212009-02-13 11:32:28 +01003485int snd_hda_multi_out_dig_cleanup(struct hda_codec *codec,
3486 struct hda_multi_out *mout)
3487{
3488 mutex_lock(&codec->spdif_mutex);
3489 cleanup_dig_out_stream(codec, mout->dig_out_nid);
3490 mutex_unlock(&codec->spdif_mutex);
3491 return 0;
3492}
3493EXPORT_SYMBOL_HDA(snd_hda_multi_out_dig_cleanup);
3494
Linus Torvalds1da177e2005-04-16 15:20:36 -07003495/*
3496 * release the digital out
3497 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003498int snd_hda_multi_out_dig_close(struct hda_codec *codec,
3499 struct hda_multi_out *mout)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003500{
Ingo Molnar62932df2006-01-16 16:34:20 +01003501 mutex_lock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003502 mout->dig_out_used = 0;
Ingo Molnar62932df2006-01-16 16:34:20 +01003503 mutex_unlock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003504 return 0;
3505}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003506EXPORT_SYMBOL_HDA(snd_hda_multi_out_dig_close);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003507
3508/*
3509 * set up more restrictions for analog out
3510 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003511int snd_hda_multi_out_analog_open(struct hda_codec *codec,
3512 struct hda_multi_out *mout,
Takashi Iwai9a081602008-02-12 18:37:26 +01003513 struct snd_pcm_substream *substream,
3514 struct hda_pcm_stream *hinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003515{
Takashi Iwai9a081602008-02-12 18:37:26 +01003516 struct snd_pcm_runtime *runtime = substream->runtime;
3517 runtime->hw.channels_max = mout->max_channels;
3518 if (mout->dig_out_nid) {
3519 if (!mout->analog_rates) {
3520 mout->analog_rates = hinfo->rates;
3521 mout->analog_formats = hinfo->formats;
3522 mout->analog_maxbps = hinfo->maxbps;
3523 } else {
3524 runtime->hw.rates = mout->analog_rates;
3525 runtime->hw.formats = mout->analog_formats;
3526 hinfo->maxbps = mout->analog_maxbps;
3527 }
3528 if (!mout->spdif_rates) {
3529 snd_hda_query_supported_pcm(codec, mout->dig_out_nid,
3530 &mout->spdif_rates,
3531 &mout->spdif_formats,
3532 &mout->spdif_maxbps);
3533 }
3534 mutex_lock(&codec->spdif_mutex);
3535 if (mout->share_spdif) {
Takashi Iwai022b4662009-07-03 23:03:30 +02003536 if ((runtime->hw.rates & mout->spdif_rates) &&
3537 (runtime->hw.formats & mout->spdif_formats)) {
3538 runtime->hw.rates &= mout->spdif_rates;
3539 runtime->hw.formats &= mout->spdif_formats;
3540 if (mout->spdif_maxbps < hinfo->maxbps)
3541 hinfo->maxbps = mout->spdif_maxbps;
3542 } else {
3543 mout->share_spdif = 0;
3544 /* FIXME: need notify? */
3545 }
Takashi Iwai9a081602008-02-12 18:37:26 +01003546 }
Frederik Deweerdteaa99852008-04-14 13:11:44 +02003547 mutex_unlock(&codec->spdif_mutex);
Takashi Iwai9a081602008-02-12 18:37:26 +01003548 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003549 return snd_pcm_hw_constraint_step(substream->runtime, 0,
3550 SNDRV_PCM_HW_PARAM_CHANNELS, 2);
3551}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003552EXPORT_SYMBOL_HDA(snd_hda_multi_out_analog_open);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003553
3554/*
3555 * set up the i/o for analog out
3556 * when the digital out is available, copy the front out to digital out, too.
3557 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003558int snd_hda_multi_out_analog_prepare(struct hda_codec *codec,
3559 struct hda_multi_out *mout,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003560 unsigned int stream_tag,
3561 unsigned int format,
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01003562 struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003563{
3564 hda_nid_t *nids = mout->dac_nids;
3565 int chs = substream->runtime->channels;
3566 int i;
3567
Ingo Molnar62932df2006-01-16 16:34:20 +01003568 mutex_lock(&codec->spdif_mutex);
Takashi Iwai9a081602008-02-12 18:37:26 +01003569 if (mout->dig_out_nid && mout->share_spdif &&
3570 mout->dig_out_used != HDA_DIG_EXCLUSIVE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003571 if (chs == 2 &&
Takashi Iwai0ba21762007-04-16 11:29:14 +02003572 snd_hda_is_supported_format(codec, mout->dig_out_nid,
3573 format) &&
3574 !(codec->spdif_status & IEC958_AES0_NONAUDIO)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003575 mout->dig_out_used = HDA_DIG_ANALOG_DUP;
Takashi Iwai6b97eb42007-04-05 14:51:48 +02003576 setup_dig_out_stream(codec, mout->dig_out_nid,
3577 stream_tag, format);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003578 } else {
3579 mout->dig_out_used = 0;
Takashi Iwai2f728532008-09-25 16:32:41 +02003580 cleanup_dig_out_stream(codec, mout->dig_out_nid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003581 }
3582 }
Ingo Molnar62932df2006-01-16 16:34:20 +01003583 mutex_unlock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003584
3585 /* front */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003586 snd_hda_codec_setup_stream(codec, nids[HDA_FRONT], stream_tag,
3587 0, format);
Takashi Iwaid29240c2007-10-26 12:35:56 +02003588 if (!mout->no_share_stream &&
3589 mout->hp_nid && mout->hp_nid != nids[HDA_FRONT])
Linus Torvalds1da177e2005-04-16 15:20:36 -07003590 /* headphone out will just decode front left/right (stereo) */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003591 snd_hda_codec_setup_stream(codec, mout->hp_nid, stream_tag,
3592 0, format);
Takashi Iwai82bc9552006-03-21 11:24:42 +01003593 /* extra outputs copied from front */
3594 for (i = 0; i < ARRAY_SIZE(mout->extra_out_nid); i++)
Takashi Iwaid29240c2007-10-26 12:35:56 +02003595 if (!mout->no_share_stream && mout->extra_out_nid[i])
Takashi Iwai82bc9552006-03-21 11:24:42 +01003596 snd_hda_codec_setup_stream(codec,
3597 mout->extra_out_nid[i],
3598 stream_tag, 0, format);
3599
Linus Torvalds1da177e2005-04-16 15:20:36 -07003600 /* surrounds */
3601 for (i = 1; i < mout->num_dacs; i++) {
Takashi Iwai4b3acaf2005-06-10 19:48:10 +02003602 if (chs >= (i + 1) * 2) /* independent out */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003603 snd_hda_codec_setup_stream(codec, nids[i], stream_tag,
3604 i * 2, format);
Takashi Iwaid29240c2007-10-26 12:35:56 +02003605 else if (!mout->no_share_stream) /* copy front */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003606 snd_hda_codec_setup_stream(codec, nids[i], stream_tag,
3607 0, format);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003608 }
3609 return 0;
3610}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003611EXPORT_SYMBOL_HDA(snd_hda_multi_out_analog_prepare);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003612
3613/*
3614 * clean up the setting for analog out
3615 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003616int snd_hda_multi_out_analog_cleanup(struct hda_codec *codec,
3617 struct hda_multi_out *mout)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003618{
3619 hda_nid_t *nids = mout->dac_nids;
3620 int i;
3621
3622 for (i = 0; i < mout->num_dacs; i++)
Takashi Iwai888afa12008-03-18 09:57:50 +01003623 snd_hda_codec_cleanup_stream(codec, nids[i]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003624 if (mout->hp_nid)
Takashi Iwai888afa12008-03-18 09:57:50 +01003625 snd_hda_codec_cleanup_stream(codec, mout->hp_nid);
Takashi Iwai82bc9552006-03-21 11:24:42 +01003626 for (i = 0; i < ARRAY_SIZE(mout->extra_out_nid); i++)
3627 if (mout->extra_out_nid[i])
Takashi Iwai888afa12008-03-18 09:57:50 +01003628 snd_hda_codec_cleanup_stream(codec,
3629 mout->extra_out_nid[i]);
Ingo Molnar62932df2006-01-16 16:34:20 +01003630 mutex_lock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003631 if (mout->dig_out_nid && mout->dig_out_used == HDA_DIG_ANALOG_DUP) {
Takashi Iwai2f728532008-09-25 16:32:41 +02003632 cleanup_dig_out_stream(codec, mout->dig_out_nid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003633 mout->dig_out_used = 0;
3634 }
Ingo Molnar62932df2006-01-16 16:34:20 +01003635 mutex_unlock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003636 return 0;
3637}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003638EXPORT_SYMBOL_HDA(snd_hda_multi_out_analog_cleanup);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003639
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003640/*
Wu Fengguang6b345002008-10-07 14:21:41 +08003641 * Helper for automatic pin configuration
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003642 */
Kailang Yangdf694da2005-12-05 19:42:22 +01003643
Takashi Iwai12f288b2007-08-02 15:51:59 +02003644static int is_in_nid_list(hda_nid_t nid, hda_nid_t *list)
Kailang Yangdf694da2005-12-05 19:42:22 +01003645{
3646 for (; *list; list++)
3647 if (*list == nid)
3648 return 1;
3649 return 0;
3650}
3651
Steve Longerbeam81937d32007-05-08 15:33:03 +02003652
3653/*
3654 * Sort an associated group of pins according to their sequence numbers.
3655 */
3656static void sort_pins_by_sequence(hda_nid_t * pins, short * sequences,
3657 int num_pins)
3658{
3659 int i, j;
3660 short seq;
3661 hda_nid_t nid;
3662
3663 for (i = 0; i < num_pins; i++) {
3664 for (j = i + 1; j < num_pins; j++) {
3665 if (sequences[i] > sequences[j]) {
3666 seq = sequences[i];
3667 sequences[i] = sequences[j];
3668 sequences[j] = seq;
3669 nid = pins[i];
3670 pins[i] = pins[j];
3671 pins[j] = nid;
3672 }
3673 }
3674 }
3675}
3676
3677
Takashi Iwai82bc9552006-03-21 11:24:42 +01003678/*
3679 * Parse all pin widgets and store the useful pin nids to cfg
3680 *
3681 * The number of line-outs or any primary output is stored in line_outs,
3682 * and the corresponding output pins are assigned to line_out_pins[],
3683 * in the order of front, rear, CLFE, side, ...
3684 *
3685 * If more extra outputs (speaker and headphone) are found, the pins are
Takashi Iwaieb06ed82006-09-20 17:10:27 +02003686 * assisnged to hp_pins[] and speaker_pins[], respectively. If no line-out jack
Takashi Iwai82bc9552006-03-21 11:24:42 +01003687 * is detected, one of speaker of HP pins is assigned as the primary
3688 * output, i.e. to line_out_pins[0]. So, line_outs is always positive
3689 * if any analog output exists.
3690 *
3691 * The analog input pins are assigned to input_pins array.
3692 * The digital input/output pins are assigned to dig_in_pin and dig_out_pin,
3693 * respectively.
3694 */
Takashi Iwai12f288b2007-08-02 15:51:59 +02003695int snd_hda_parse_pin_def_config(struct hda_codec *codec,
3696 struct auto_pin_cfg *cfg,
3697 hda_nid_t *ignore_nids)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003698{
Takashi Iwai0ef6ce72008-01-22 15:35:37 +01003699 hda_nid_t nid, end_nid;
Steve Longerbeam81937d32007-05-08 15:33:03 +02003700 short seq, assoc_line_out, assoc_speaker;
3701 short sequences_line_out[ARRAY_SIZE(cfg->line_out_pins)];
3702 short sequences_speaker[ARRAY_SIZE(cfg->speaker_pins)];
Takashi Iwaif889fa92007-10-31 15:49:32 +01003703 short sequences_hp[ARRAY_SIZE(cfg->hp_pins)];
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003704
3705 memset(cfg, 0, sizeof(*cfg));
3706
Steve Longerbeam81937d32007-05-08 15:33:03 +02003707 memset(sequences_line_out, 0, sizeof(sequences_line_out));
3708 memset(sequences_speaker, 0, sizeof(sequences_speaker));
Takashi Iwaif889fa92007-10-31 15:49:32 +01003709 memset(sequences_hp, 0, sizeof(sequences_hp));
Steve Longerbeam81937d32007-05-08 15:33:03 +02003710 assoc_line_out = assoc_speaker = 0;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003711
Takashi Iwai0ef6ce72008-01-22 15:35:37 +01003712 end_nid = codec->start_nid + codec->num_nodes;
3713 for (nid = codec->start_nid; nid < end_nid; nid++) {
Takashi Iwai54d17402005-11-21 16:33:22 +01003714 unsigned int wid_caps = get_wcaps(codec, nid);
Takashi Iwaia22d5432009-07-27 12:54:26 +02003715 unsigned int wid_type = get_wcaps_type(wid_caps);
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003716 unsigned int def_conf;
3717 short assoc, loc;
3718
3719 /* read all default configuration for pin complex */
3720 if (wid_type != AC_WID_PIN)
3721 continue;
Kailang Yangdf694da2005-12-05 19:42:22 +01003722 /* ignore the given nids (e.g. pc-beep returns error) */
3723 if (ignore_nids && is_in_nid_list(nid, ignore_nids))
3724 continue;
3725
Takashi Iwaic17a1ab2009-02-23 09:28:12 +01003726 def_conf = snd_hda_codec_get_pincfg(codec, nid);
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003727 if (get_defcfg_connect(def_conf) == AC_JACK_PORT_NONE)
3728 continue;
3729 loc = get_defcfg_location(def_conf);
3730 switch (get_defcfg_device(def_conf)) {
3731 case AC_JACK_LINE_OUT:
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003732 seq = get_defcfg_sequence(def_conf);
3733 assoc = get_defcfg_association(def_conf);
Matthew Ranostay90da78b2008-01-24 11:48:01 +01003734
3735 if (!(wid_caps & AC_WCAP_STEREO))
3736 if (!cfg->mono_out_pin)
3737 cfg->mono_out_pin = nid;
Takashi Iwai0ba21762007-04-16 11:29:14 +02003738 if (!assoc)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003739 continue;
Takashi Iwai0ba21762007-04-16 11:29:14 +02003740 if (!assoc_line_out)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003741 assoc_line_out = assoc;
3742 else if (assoc_line_out != assoc)
3743 continue;
3744 if (cfg->line_outs >= ARRAY_SIZE(cfg->line_out_pins))
3745 continue;
3746 cfg->line_out_pins[cfg->line_outs] = nid;
Steve Longerbeam81937d32007-05-08 15:33:03 +02003747 sequences_line_out[cfg->line_outs] = seq;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003748 cfg->line_outs++;
3749 break;
Takashi Iwai8d88bc32005-11-17 11:09:23 +01003750 case AC_JACK_SPEAKER:
Steve Longerbeam81937d32007-05-08 15:33:03 +02003751 seq = get_defcfg_sequence(def_conf);
3752 assoc = get_defcfg_association(def_conf);
3753 if (! assoc)
3754 continue;
3755 if (! assoc_speaker)
3756 assoc_speaker = assoc;
3757 else if (assoc_speaker != assoc)
3758 continue;
Takashi Iwai82bc9552006-03-21 11:24:42 +01003759 if (cfg->speaker_outs >= ARRAY_SIZE(cfg->speaker_pins))
3760 continue;
3761 cfg->speaker_pins[cfg->speaker_outs] = nid;
Steve Longerbeam81937d32007-05-08 15:33:03 +02003762 sequences_speaker[cfg->speaker_outs] = seq;
Takashi Iwai82bc9552006-03-21 11:24:42 +01003763 cfg->speaker_outs++;
Takashi Iwai8d88bc32005-11-17 11:09:23 +01003764 break;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003765 case AC_JACK_HP_OUT:
Takashi Iwaif889fa92007-10-31 15:49:32 +01003766 seq = get_defcfg_sequence(def_conf);
3767 assoc = get_defcfg_association(def_conf);
Takashi Iwaieb06ed82006-09-20 17:10:27 +02003768 if (cfg->hp_outs >= ARRAY_SIZE(cfg->hp_pins))
3769 continue;
3770 cfg->hp_pins[cfg->hp_outs] = nid;
Takashi Iwaif889fa92007-10-31 15:49:32 +01003771 sequences_hp[cfg->hp_outs] = (assoc << 4) | seq;
Takashi Iwaieb06ed82006-09-20 17:10:27 +02003772 cfg->hp_outs++;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003773 break;
Takashi Iwai314634b2006-09-21 11:56:18 +02003774 case AC_JACK_MIC_IN: {
3775 int preferred, alt;
3776 if (loc == AC_JACK_LOC_FRONT) {
3777 preferred = AUTO_PIN_FRONT_MIC;
3778 alt = AUTO_PIN_MIC;
3779 } else {
3780 preferred = AUTO_PIN_MIC;
3781 alt = AUTO_PIN_FRONT_MIC;
3782 }
3783 if (!cfg->input_pins[preferred])
3784 cfg->input_pins[preferred] = nid;
3785 else if (!cfg->input_pins[alt])
3786 cfg->input_pins[alt] = nid;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003787 break;
Takashi Iwai314634b2006-09-21 11:56:18 +02003788 }
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003789 case AC_JACK_LINE_IN:
3790 if (loc == AC_JACK_LOC_FRONT)
3791 cfg->input_pins[AUTO_PIN_FRONT_LINE] = nid;
3792 else
3793 cfg->input_pins[AUTO_PIN_LINE] = nid;
3794 break;
3795 case AC_JACK_CD:
3796 cfg->input_pins[AUTO_PIN_CD] = nid;
3797 break;
3798 case AC_JACK_AUX:
3799 cfg->input_pins[AUTO_PIN_AUX] = nid;
3800 break;
3801 case AC_JACK_SPDIF_OUT:
Takashi Iwai1b52ae72009-01-20 17:17:29 +01003802 case AC_JACK_DIG_OTHER_OUT:
Takashi Iwai0852d7a2009-02-11 11:35:15 +01003803 if (cfg->dig_outs >= ARRAY_SIZE(cfg->dig_out_pins))
3804 continue;
3805 cfg->dig_out_pins[cfg->dig_outs] = nid;
3806 cfg->dig_out_type[cfg->dig_outs] =
3807 (loc == AC_JACK_LOC_HDMI) ?
3808 HDA_PCM_TYPE_HDMI : HDA_PCM_TYPE_SPDIF;
3809 cfg->dig_outs++;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003810 break;
3811 case AC_JACK_SPDIF_IN:
Takashi Iwai1b52ae72009-01-20 17:17:29 +01003812 case AC_JACK_DIG_OTHER_IN:
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003813 cfg->dig_in_pin = nid;
Takashi Iwai2297bd62009-01-20 18:24:13 +01003814 if (loc == AC_JACK_LOC_HDMI)
3815 cfg->dig_in_type = HDA_PCM_TYPE_HDMI;
3816 else
3817 cfg->dig_in_type = HDA_PCM_TYPE_SPDIF;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003818 break;
3819 }
3820 }
3821
Takashi Iwai5832fcf2008-02-12 18:30:12 +01003822 /* FIX-UP:
3823 * If no line-out is defined but multiple HPs are found,
3824 * some of them might be the real line-outs.
3825 */
3826 if (!cfg->line_outs && cfg->hp_outs > 1) {
3827 int i = 0;
3828 while (i < cfg->hp_outs) {
3829 /* The real HPs should have the sequence 0x0f */
3830 if ((sequences_hp[i] & 0x0f) == 0x0f) {
3831 i++;
3832 continue;
3833 }
3834 /* Move it to the line-out table */
3835 cfg->line_out_pins[cfg->line_outs] = cfg->hp_pins[i];
3836 sequences_line_out[cfg->line_outs] = sequences_hp[i];
3837 cfg->line_outs++;
3838 cfg->hp_outs--;
3839 memmove(cfg->hp_pins + i, cfg->hp_pins + i + 1,
3840 sizeof(cfg->hp_pins[0]) * (cfg->hp_outs - i));
3841 memmove(sequences_hp + i - 1, sequences_hp + i,
3842 sizeof(sequences_hp[0]) * (cfg->hp_outs - i));
3843 }
3844 }
3845
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003846 /* sort by sequence */
Steve Longerbeam81937d32007-05-08 15:33:03 +02003847 sort_pins_by_sequence(cfg->line_out_pins, sequences_line_out,
3848 cfg->line_outs);
3849 sort_pins_by_sequence(cfg->speaker_pins, sequences_speaker,
3850 cfg->speaker_outs);
Takashi Iwaif889fa92007-10-31 15:49:32 +01003851 sort_pins_by_sequence(cfg->hp_pins, sequences_hp,
3852 cfg->hp_outs);
Steve Longerbeam81937d32007-05-08 15:33:03 +02003853
Takashi Iwaif889fa92007-10-31 15:49:32 +01003854 /* if we have only one mic, make it AUTO_PIN_MIC */
3855 if (!cfg->input_pins[AUTO_PIN_MIC] &&
3856 cfg->input_pins[AUTO_PIN_FRONT_MIC]) {
3857 cfg->input_pins[AUTO_PIN_MIC] =
3858 cfg->input_pins[AUTO_PIN_FRONT_MIC];
3859 cfg->input_pins[AUTO_PIN_FRONT_MIC] = 0;
3860 }
3861 /* ditto for line-in */
3862 if (!cfg->input_pins[AUTO_PIN_LINE] &&
3863 cfg->input_pins[AUTO_PIN_FRONT_LINE]) {
3864 cfg->input_pins[AUTO_PIN_LINE] =
3865 cfg->input_pins[AUTO_PIN_FRONT_LINE];
3866 cfg->input_pins[AUTO_PIN_FRONT_LINE] = 0;
3867 }
3868
Steve Longerbeam81937d32007-05-08 15:33:03 +02003869 /*
3870 * FIX-UP: if no line-outs are detected, try to use speaker or HP pin
3871 * as a primary output
3872 */
3873 if (!cfg->line_outs) {
3874 if (cfg->speaker_outs) {
3875 cfg->line_outs = cfg->speaker_outs;
3876 memcpy(cfg->line_out_pins, cfg->speaker_pins,
3877 sizeof(cfg->speaker_pins));
3878 cfg->speaker_outs = 0;
3879 memset(cfg->speaker_pins, 0, sizeof(cfg->speaker_pins));
3880 cfg->line_out_type = AUTO_PIN_SPEAKER_OUT;
3881 } else if (cfg->hp_outs) {
3882 cfg->line_outs = cfg->hp_outs;
3883 memcpy(cfg->line_out_pins, cfg->hp_pins,
3884 sizeof(cfg->hp_pins));
3885 cfg->hp_outs = 0;
3886 memset(cfg->hp_pins, 0, sizeof(cfg->hp_pins));
3887 cfg->line_out_type = AUTO_PIN_HP_OUT;
3888 }
3889 }
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003890
Takashi Iwaicb8e2f82005-07-29 11:54:32 +02003891 /* Reorder the surround channels
3892 * ALSA sequence is front/surr/clfe/side
3893 * HDA sequence is:
3894 * 4-ch: front/surr => OK as it is
3895 * 6-ch: front/clfe/surr
Takashi Iwai9422db42007-04-20 16:11:43 +02003896 * 8-ch: front/clfe/rear/side|fc
Takashi Iwaicb8e2f82005-07-29 11:54:32 +02003897 */
3898 switch (cfg->line_outs) {
3899 case 3:
Takashi Iwaicb8e2f82005-07-29 11:54:32 +02003900 case 4:
3901 nid = cfg->line_out_pins[1];
Takashi Iwai9422db42007-04-20 16:11:43 +02003902 cfg->line_out_pins[1] = cfg->line_out_pins[2];
Takashi Iwaicb8e2f82005-07-29 11:54:32 +02003903 cfg->line_out_pins[2] = nid;
3904 break;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003905 }
3906
Takashi Iwai82bc9552006-03-21 11:24:42 +01003907 /*
3908 * debug prints of the parsed results
3909 */
3910 snd_printd("autoconfig: line_outs=%d (0x%x/0x%x/0x%x/0x%x/0x%x)\n",
3911 cfg->line_outs, cfg->line_out_pins[0], cfg->line_out_pins[1],
3912 cfg->line_out_pins[2], cfg->line_out_pins[3],
3913 cfg->line_out_pins[4]);
3914 snd_printd(" speaker_outs=%d (0x%x/0x%x/0x%x/0x%x/0x%x)\n",
3915 cfg->speaker_outs, cfg->speaker_pins[0],
3916 cfg->speaker_pins[1], cfg->speaker_pins[2],
3917 cfg->speaker_pins[3], cfg->speaker_pins[4]);
Takashi Iwaieb06ed82006-09-20 17:10:27 +02003918 snd_printd(" hp_outs=%d (0x%x/0x%x/0x%x/0x%x/0x%x)\n",
3919 cfg->hp_outs, cfg->hp_pins[0],
3920 cfg->hp_pins[1], cfg->hp_pins[2],
3921 cfg->hp_pins[3], cfg->hp_pins[4]);
Matthew Ranostay90da78b2008-01-24 11:48:01 +01003922 snd_printd(" mono: mono_out=0x%x\n", cfg->mono_out_pin);
Takashi Iwai0852d7a2009-02-11 11:35:15 +01003923 if (cfg->dig_outs)
3924 snd_printd(" dig-out=0x%x/0x%x\n",
3925 cfg->dig_out_pins[0], cfg->dig_out_pins[1]);
Takashi Iwai82bc9552006-03-21 11:24:42 +01003926 snd_printd(" inputs: mic=0x%x, fmic=0x%x, line=0x%x, fline=0x%x,"
3927 " cd=0x%x, aux=0x%x\n",
3928 cfg->input_pins[AUTO_PIN_MIC],
3929 cfg->input_pins[AUTO_PIN_FRONT_MIC],
3930 cfg->input_pins[AUTO_PIN_LINE],
3931 cfg->input_pins[AUTO_PIN_FRONT_LINE],
3932 cfg->input_pins[AUTO_PIN_CD],
3933 cfg->input_pins[AUTO_PIN_AUX]);
Takashi Iwai32d2c7f2009-02-11 11:33:13 +01003934 if (cfg->dig_in_pin)
Takashi Iwai89ce9e82009-01-20 17:15:57 +01003935 snd_printd(" dig-in=0x%x\n", cfg->dig_in_pin);
Takashi Iwai82bc9552006-03-21 11:24:42 +01003936
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003937 return 0;
3938}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003939EXPORT_SYMBOL_HDA(snd_hda_parse_pin_def_config);
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003940
Takashi Iwai4a471b72005-12-07 13:56:29 +01003941/* labels for input pins */
3942const char *auto_pin_cfg_labels[AUTO_PIN_LAST] = {
3943 "Mic", "Front Mic", "Line", "Front Line", "CD", "Aux"
3944};
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003945EXPORT_SYMBOL_HDA(auto_pin_cfg_labels);
Takashi Iwai4a471b72005-12-07 13:56:29 +01003946
3947
Linus Torvalds1da177e2005-04-16 15:20:36 -07003948#ifdef CONFIG_PM
3949/*
3950 * power management
3951 */
3952
3953/**
3954 * snd_hda_suspend - suspend the codecs
3955 * @bus: the HDA bus
Linus Torvalds1da177e2005-04-16 15:20:36 -07003956 *
3957 * Returns 0 if successful.
3958 */
Takashi Iwai8dd78332009-06-02 01:16:07 +02003959int snd_hda_suspend(struct hda_bus *bus)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003960{
Takashi Iwai0ba21762007-04-16 11:29:14 +02003961 struct hda_codec *codec;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003962
Takashi Iwai0ba21762007-04-16 11:29:14 +02003963 list_for_each_entry(codec, &bus->codec_list, list) {
Takashi Iwai0b7a2e92007-08-14 15:18:26 +02003964#ifdef CONFIG_SND_HDA_POWER_SAVE
3965 if (!codec->power_on)
3966 continue;
3967#endif
Takashi Iwaicb53c622007-08-10 17:21:45 +02003968 hda_call_codec_suspend(codec);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003969 }
3970 return 0;
3971}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003972EXPORT_SYMBOL_HDA(snd_hda_suspend);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003973
3974/**
3975 * snd_hda_resume - resume the codecs
3976 * @bus: the HDA bus
Linus Torvalds1da177e2005-04-16 15:20:36 -07003977 *
3978 * Returns 0 if successful.
Takashi Iwaicb53c622007-08-10 17:21:45 +02003979 *
3980 * This fucntion is defined only when POWER_SAVE isn't set.
3981 * In the power-save mode, the codec is resumed dynamically.
Linus Torvalds1da177e2005-04-16 15:20:36 -07003982 */
3983int snd_hda_resume(struct hda_bus *bus)
3984{
Takashi Iwai0ba21762007-04-16 11:29:14 +02003985 struct hda_codec *codec;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003986
Takashi Iwai0ba21762007-04-16 11:29:14 +02003987 list_for_each_entry(codec, &bus->codec_list, list) {
Maxim Levitskyd804ad92007-09-03 15:28:04 +02003988 if (snd_hda_codec_needs_resume(codec))
3989 hda_call_codec_resume(codec);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003990 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003991 return 0;
3992}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003993EXPORT_SYMBOL_HDA(snd_hda_resume);
Takashi Iwai1289e9e2008-11-27 15:47:11 +01003994#endif /* CONFIG_PM */
Takashi Iwaib2e18592008-07-30 15:01:44 +02003995
3996/*
3997 * generic arrays
3998 */
3999
4000/* get a new element from the given array
4001 * if it exceeds the pre-allocated array size, re-allocate the array
4002 */
4003void *snd_array_new(struct snd_array *array)
4004{
4005 if (array->used >= array->alloced) {
4006 int num = array->alloced + array->alloc_align;
Takashi Iwaib910d9a2008-11-07 00:26:52 +01004007 void *nlist;
4008 if (snd_BUG_ON(num >= 4096))
4009 return NULL;
4010 nlist = kcalloc(num + 1, array->elem_size, GFP_KERNEL);
Takashi Iwaib2e18592008-07-30 15:01:44 +02004011 if (!nlist)
4012 return NULL;
4013 if (array->list) {
4014 memcpy(nlist, array->list,
4015 array->elem_size * array->alloced);
4016 kfree(array->list);
4017 }
4018 array->list = nlist;
4019 array->alloced = num;
4020 }
Takashi Iwaif43aa022008-11-10 16:24:26 +01004021 return snd_array_elem(array, array->used++);
Takashi Iwaib2e18592008-07-30 15:01:44 +02004022}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01004023EXPORT_SYMBOL_HDA(snd_array_new);
Takashi Iwaib2e18592008-07-30 15:01:44 +02004024
4025/* free the given array elements */
4026void snd_array_free(struct snd_array *array)
4027{
4028 kfree(array->list);
4029 array->used = 0;
4030 array->alloced = 0;
4031 array->list = NULL;
4032}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01004033EXPORT_SYMBOL_HDA(snd_array_free);
Takashi Iwaib2022262008-11-21 21:24:03 +01004034
4035/*
4036 * used by hda_proc.c and hda_eld.c
4037 */
4038void snd_print_pcm_rates(int pcm, char *buf, int buflen)
4039{
4040 static unsigned int rates[] = {
4041 8000, 11025, 16000, 22050, 32000, 44100, 48000, 88200,
4042 96000, 176400, 192000, 384000
4043 };
4044 int i, j;
4045
4046 for (i = 0, j = 0; i < ARRAY_SIZE(rates); i++)
4047 if (pcm & (1 << i))
4048 j += snprintf(buf + j, buflen - j, " %d", rates[i]);
4049
4050 buf[j] = '\0'; /* necessary when j == 0 */
4051}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01004052EXPORT_SYMBOL_HDA(snd_print_pcm_rates);
Takashi Iwaib2022262008-11-21 21:24:03 +01004053
4054void snd_print_pcm_bits(int pcm, char *buf, int buflen)
4055{
4056 static unsigned int bits[] = { 8, 16, 20, 24, 32 };
4057 int i, j;
4058
4059 for (i = 0, j = 0; i < ARRAY_SIZE(bits); i++)
4060 if (pcm & (AC_SUPPCM_BITS_8 << i))
4061 j += snprintf(buf + j, buflen - j, " %d", bits[i]);
4062
4063 buf[j] = '\0'; /* necessary when j == 0 */
4064}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01004065EXPORT_SYMBOL_HDA(snd_print_pcm_bits);
Takashi Iwai1289e9e2008-11-27 15:47:11 +01004066
4067MODULE_DESCRIPTION("HDA codec core");
4068MODULE_LICENSE("GPL");