blob: d71e651046eb34c04ff74f12e889c7cacc2578b0 [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
Jaroslav Kysela4d02d1b2009-11-12 10:15:48 +01001526 if (kctl->id.subdevice & (1<<31)) {
1527 if (nid == 0)
1528 nid = kctl->id.subdevice & 0xffff;
1529 kctl->id.subdevice = 0;
1530 }
Takashi Iwaid13bd412008-07-30 15:01:45 +02001531 err = snd_ctl_add(codec->bus->card, kctl);
1532 if (err < 0)
1533 return err;
Jaroslav Kysela3911a4c2009-11-11 13:43:01 +01001534 item = snd_array_new(&codec->mixers);
1535 if (!item)
Takashi Iwaid13bd412008-07-30 15:01:45 +02001536 return -ENOMEM;
Jaroslav Kysela3911a4c2009-11-11 13:43:01 +01001537 item->kctl = kctl;
1538 item->nid = nid;
Takashi Iwaid13bd412008-07-30 15:01:45 +02001539 return 0;
1540}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001541EXPORT_SYMBOL_HDA(snd_hda_ctl_add);
Takashi Iwaid13bd412008-07-30 15:01:45 +02001542
1543/* Clear all controls assigned to the given codec */
1544void snd_hda_ctls_clear(struct hda_codec *codec)
1545{
1546 int i;
Jaroslav Kysela3911a4c2009-11-11 13:43:01 +01001547 struct hda_nid_item *items = codec->mixers.list;
Takashi Iwaid13bd412008-07-30 15:01:45 +02001548 for (i = 0; i < codec->mixers.used; i++)
Jaroslav Kysela3911a4c2009-11-11 13:43:01 +01001549 snd_ctl_remove(codec->bus->card, items[i].kctl);
Takashi Iwaid13bd412008-07-30 15:01:45 +02001550 snd_array_free(&codec->mixers);
1551}
1552
Takashi Iwaia65d6292009-02-23 16:57:04 +01001553/* pseudo device locking
1554 * toggle card->shutdown to allow/disallow the device access (as a hack)
1555 */
1556static int hda_lock_devices(struct snd_card *card)
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001557{
Takashi Iwaia65d6292009-02-23 16:57:04 +01001558 spin_lock(&card->files_lock);
1559 if (card->shutdown) {
1560 spin_unlock(&card->files_lock);
1561 return -EINVAL;
1562 }
1563 card->shutdown = 1;
1564 spin_unlock(&card->files_lock);
1565 return 0;
1566}
1567
1568static void hda_unlock_devices(struct snd_card *card)
1569{
1570 spin_lock(&card->files_lock);
1571 card->shutdown = 0;
1572 spin_unlock(&card->files_lock);
1573}
1574
1575int snd_hda_codec_reset(struct hda_codec *codec)
1576{
1577 struct snd_card *card = codec->bus->card;
1578 int i, pcm;
1579
1580 if (hda_lock_devices(card) < 0)
1581 return -EBUSY;
1582 /* check whether the codec isn't used by any mixer or PCM streams */
1583 if (!list_empty(&card->ctl_files)) {
1584 hda_unlock_devices(card);
1585 return -EBUSY;
1586 }
1587 for (pcm = 0; pcm < codec->num_pcms; pcm++) {
1588 struct hda_pcm *cpcm = &codec->pcm_info[pcm];
1589 if (!cpcm->pcm)
1590 continue;
1591 if (cpcm->pcm->streams[0].substream_opened ||
1592 cpcm->pcm->streams[1].substream_opened) {
1593 hda_unlock_devices(card);
1594 return -EBUSY;
1595 }
1596 }
1597
1598 /* OK, let it free */
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001599
1600#ifdef CONFIG_SND_HDA_POWER_SAVE
1601 cancel_delayed_work(&codec->power_work);
Takashi Iwai6acaed32009-01-12 10:09:24 +01001602 flush_workqueue(codec->bus->workq);
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001603#endif
1604 snd_hda_ctls_clear(codec);
1605 /* relase PCMs */
1606 for (i = 0; i < codec->num_pcms; i++) {
Takashi Iwai529bd6c2008-11-27 14:17:01 +01001607 if (codec->pcm_info[i].pcm) {
Takashi Iwaia65d6292009-02-23 16:57:04 +01001608 snd_device_free(card, codec->pcm_info[i].pcm);
Takashi Iwai529bd6c2008-11-27 14:17:01 +01001609 clear_bit(codec->pcm_info[i].device,
1610 codec->bus->pcm_dev_bits);
1611 }
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001612 }
1613 if (codec->patch_ops.free)
1614 codec->patch_ops.free(codec);
Takashi Iwai56d17712008-11-28 14:36:23 +01001615 codec->proc_widget_hook = NULL;
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001616 codec->spec = NULL;
1617 free_hda_cache(&codec->amp_cache);
1618 free_hda_cache(&codec->cmd_cache);
Takashi Iwai827057f2008-12-19 10:12:02 +01001619 init_hda_cache(&codec->amp_cache, sizeof(struct hda_amp_info));
1620 init_hda_cache(&codec->cmd_cache, sizeof(struct hda_cache_head));
Takashi Iwai346ff702009-02-23 09:42:57 +01001621 /* free only driver_pins so that init_pins + user_pins are restored */
1622 snd_array_free(&codec->driver_pins);
Takashi Iwai3be14142009-02-20 14:11:16 +01001623 restore_pincfgs(codec);
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001624 codec->num_pcms = 0;
1625 codec->pcm_info = NULL;
1626 codec->preset = NULL;
Takashi Iwaid1f1af22009-03-02 10:35:29 +01001627 memset(&codec->patch_ops, 0, sizeof(codec->patch_ops));
1628 codec->slave_dig_outs = NULL;
1629 codec->spdif_status_reset = 0;
Takashi Iwai1289e9e2008-11-27 15:47:11 +01001630 module_put(codec->owner);
1631 codec->owner = NULL;
Takashi Iwaia65d6292009-02-23 16:57:04 +01001632
1633 /* allow device access again */
1634 hda_unlock_devices(card);
1635 return 0;
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001636}
1637
Takashi Iwai2134ea42008-01-10 16:53:55 +01001638/* create a virtual master control and add slaves */
1639int snd_hda_add_vmaster(struct hda_codec *codec, char *name,
1640 unsigned int *tlv, const char **slaves)
1641{
1642 struct snd_kcontrol *kctl;
1643 const char **s;
1644 int err;
1645
Takashi Iwai2f085542008-02-22 18:43:50 +01001646 for (s = slaves; *s && !snd_hda_find_mixer_ctl(codec, *s); s++)
1647 ;
1648 if (!*s) {
1649 snd_printdd("No slave found for %s\n", name);
1650 return 0;
1651 }
Takashi Iwai2134ea42008-01-10 16:53:55 +01001652 kctl = snd_ctl_make_virtual_master(name, tlv);
1653 if (!kctl)
1654 return -ENOMEM;
Jaroslav Kysela3911a4c2009-11-11 13:43:01 +01001655 err = snd_hda_ctl_add(codec, 0, kctl);
Takashi Iwai2134ea42008-01-10 16:53:55 +01001656 if (err < 0)
1657 return err;
1658
1659 for (s = slaves; *s; s++) {
1660 struct snd_kcontrol *sctl;
Takashi Iwai7a411ee2009-03-06 10:08:14 +01001661 int i = 0;
1662 for (;;) {
1663 sctl = _snd_hda_find_mixer_ctl(codec, *s, i);
1664 if (!sctl) {
1665 if (!i)
1666 snd_printdd("Cannot find slave %s, "
1667 "skipped\n", *s);
1668 break;
1669 }
1670 err = snd_ctl_add_slave(kctl, sctl);
1671 if (err < 0)
1672 return err;
1673 i++;
Takashi Iwai2134ea42008-01-10 16:53:55 +01001674 }
Takashi Iwai2134ea42008-01-10 16:53:55 +01001675 }
1676 return 0;
1677}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001678EXPORT_SYMBOL_HDA(snd_hda_add_vmaster);
Takashi Iwai2134ea42008-01-10 16:53:55 +01001679
Linus Torvalds1da177e2005-04-16 15:20:36 -07001680/* switch */
Takashi Iwai0ba21762007-04-16 11:29:14 +02001681int snd_hda_mixer_amp_switch_info(struct snd_kcontrol *kcontrol,
1682 struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001683{
1684 int chs = get_amp_channels(kcontrol);
1685
1686 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
1687 uinfo->count = chs == 3 ? 2 : 1;
1688 uinfo->value.integer.min = 0;
1689 uinfo->value.integer.max = 1;
1690 return 0;
1691}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001692EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_switch_info);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001693
Takashi Iwai0ba21762007-04-16 11:29:14 +02001694int snd_hda_mixer_amp_switch_get(struct snd_kcontrol *kcontrol,
1695 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001696{
1697 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1698 hda_nid_t nid = get_amp_nid(kcontrol);
1699 int chs = get_amp_channels(kcontrol);
1700 int dir = get_amp_direction(kcontrol);
1701 int idx = get_amp_index(kcontrol);
1702 long *valp = ucontrol->value.integer.value;
1703
1704 if (chs & 1)
Takashi Iwai0ba21762007-04-16 11:29:14 +02001705 *valp++ = (snd_hda_codec_amp_read(codec, nid, 0, dir, idx) &
Takashi Iwai47fd8302007-08-10 17:11:07 +02001706 HDA_AMP_MUTE) ? 0 : 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001707 if (chs & 2)
Takashi Iwai0ba21762007-04-16 11:29:14 +02001708 *valp = (snd_hda_codec_amp_read(codec, nid, 1, dir, idx) &
Takashi Iwai47fd8302007-08-10 17:11:07 +02001709 HDA_AMP_MUTE) ? 0 : 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001710 return 0;
1711}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001712EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_switch_get);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001713
Takashi Iwai0ba21762007-04-16 11:29:14 +02001714int snd_hda_mixer_amp_switch_put(struct snd_kcontrol *kcontrol,
1715 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001716{
1717 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1718 hda_nid_t nid = get_amp_nid(kcontrol);
1719 int chs = get_amp_channels(kcontrol);
1720 int dir = get_amp_direction(kcontrol);
1721 int idx = get_amp_index(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001722 long *valp = ucontrol->value.integer.value;
1723 int change = 0;
1724
Takashi Iwaicb53c622007-08-10 17:21:45 +02001725 snd_hda_power_up(codec);
Nicolas Grazianob9f5a892005-07-29 12:17:20 +02001726 if (chs & 1) {
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001727 change = snd_hda_codec_amp_update(codec, nid, 0, dir, idx,
Takashi Iwai47fd8302007-08-10 17:11:07 +02001728 HDA_AMP_MUTE,
1729 *valp ? 0 : HDA_AMP_MUTE);
Nicolas Grazianob9f5a892005-07-29 12:17:20 +02001730 valp++;
1731 }
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001732 if (chs & 2)
1733 change |= snd_hda_codec_amp_update(codec, nid, 1, dir, idx,
Takashi Iwai47fd8302007-08-10 17:11:07 +02001734 HDA_AMP_MUTE,
1735 *valp ? 0 : HDA_AMP_MUTE);
Takashi Iwaicb53c622007-08-10 17:21:45 +02001736#ifdef CONFIG_SND_HDA_POWER_SAVE
1737 if (codec->patch_ops.check_power_status)
1738 codec->patch_ops.check_power_status(codec, nid);
1739#endif
1740 snd_hda_power_down(codec);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001741 return change;
1742}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001743EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_switch_put);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001744
Jaroslav Kysela123c07a2009-10-21 14:48:23 +02001745int snd_hda_mixer_amp_switch_put_beep(struct snd_kcontrol *kcontrol,
1746 struct snd_ctl_elem_value *ucontrol)
1747{
1748 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1749 long *valp = ucontrol->value.integer.value;
1750
1751 snd_hda_enable_beep_device(codec, *valp);
1752 return snd_hda_mixer_amp_switch_put(kcontrol, ucontrol);
1753}
1754EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_switch_put_beep);
1755
Linus Torvalds1da177e2005-04-16 15:20:36 -07001756/*
Takashi Iwai985be542005-11-02 18:26:49 +01001757 * bound volume controls
1758 *
1759 * bind multiple volumes (# indices, from 0)
1760 */
1761
1762#define AMP_VAL_IDX_SHIFT 19
1763#define AMP_VAL_IDX_MASK (0x0f<<19)
1764
Takashi Iwai0ba21762007-04-16 11:29:14 +02001765int snd_hda_mixer_bind_switch_get(struct snd_kcontrol *kcontrol,
1766 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai985be542005-11-02 18:26:49 +01001767{
1768 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1769 unsigned long pval;
1770 int err;
1771
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001772 mutex_lock(&codec->control_mutex);
Takashi Iwai985be542005-11-02 18:26:49 +01001773 pval = kcontrol->private_value;
1774 kcontrol->private_value = pval & ~AMP_VAL_IDX_MASK; /* index 0 */
1775 err = snd_hda_mixer_amp_switch_get(kcontrol, ucontrol);
1776 kcontrol->private_value = pval;
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001777 mutex_unlock(&codec->control_mutex);
Takashi Iwai985be542005-11-02 18:26:49 +01001778 return err;
1779}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001780EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_switch_get);
Takashi Iwai985be542005-11-02 18:26:49 +01001781
Takashi Iwai0ba21762007-04-16 11:29:14 +02001782int snd_hda_mixer_bind_switch_put(struct snd_kcontrol *kcontrol,
1783 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai985be542005-11-02 18:26:49 +01001784{
1785 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1786 unsigned long pval;
1787 int i, indices, err = 0, change = 0;
1788
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001789 mutex_lock(&codec->control_mutex);
Takashi Iwai985be542005-11-02 18:26:49 +01001790 pval = kcontrol->private_value;
1791 indices = (pval & AMP_VAL_IDX_MASK) >> AMP_VAL_IDX_SHIFT;
1792 for (i = 0; i < indices; i++) {
Takashi Iwai0ba21762007-04-16 11:29:14 +02001793 kcontrol->private_value = (pval & ~AMP_VAL_IDX_MASK) |
1794 (i << AMP_VAL_IDX_SHIFT);
Takashi Iwai985be542005-11-02 18:26:49 +01001795 err = snd_hda_mixer_amp_switch_put(kcontrol, ucontrol);
1796 if (err < 0)
1797 break;
1798 change |= err;
1799 }
1800 kcontrol->private_value = pval;
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001801 mutex_unlock(&codec->control_mutex);
Takashi Iwai985be542005-11-02 18:26:49 +01001802 return err < 0 ? err : change;
1803}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001804EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_switch_put);
Takashi Iwai985be542005-11-02 18:26:49 +01001805
1806/*
Takashi Iwai532d5382007-07-27 19:02:40 +02001807 * generic bound volume/swtich controls
1808 */
1809int snd_hda_mixer_bind_ctls_info(struct snd_kcontrol *kcontrol,
1810 struct snd_ctl_elem_info *uinfo)
1811{
1812 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1813 struct hda_bind_ctls *c;
1814 int err;
1815
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001816 mutex_lock(&codec->control_mutex);
Serge A. Suchkov14c65f92008-02-22 18:43:16 +01001817 c = (struct hda_bind_ctls *)kcontrol->private_value;
Takashi Iwai532d5382007-07-27 19:02:40 +02001818 kcontrol->private_value = *c->values;
1819 err = c->ops->info(kcontrol, uinfo);
1820 kcontrol->private_value = (long)c;
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001821 mutex_unlock(&codec->control_mutex);
Takashi Iwai532d5382007-07-27 19:02:40 +02001822 return err;
1823}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001824EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_ctls_info);
Takashi Iwai532d5382007-07-27 19:02:40 +02001825
1826int snd_hda_mixer_bind_ctls_get(struct snd_kcontrol *kcontrol,
1827 struct snd_ctl_elem_value *ucontrol)
1828{
1829 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1830 struct hda_bind_ctls *c;
1831 int err;
1832
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001833 mutex_lock(&codec->control_mutex);
Serge A. Suchkov14c65f92008-02-22 18:43:16 +01001834 c = (struct hda_bind_ctls *)kcontrol->private_value;
Takashi Iwai532d5382007-07-27 19:02:40 +02001835 kcontrol->private_value = *c->values;
1836 err = c->ops->get(kcontrol, ucontrol);
1837 kcontrol->private_value = (long)c;
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001838 mutex_unlock(&codec->control_mutex);
Takashi Iwai532d5382007-07-27 19:02:40 +02001839 return err;
1840}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001841EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_ctls_get);
Takashi Iwai532d5382007-07-27 19:02:40 +02001842
1843int snd_hda_mixer_bind_ctls_put(struct snd_kcontrol *kcontrol,
1844 struct snd_ctl_elem_value *ucontrol)
1845{
1846 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1847 struct hda_bind_ctls *c;
1848 unsigned long *vals;
1849 int err = 0, change = 0;
1850
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001851 mutex_lock(&codec->control_mutex);
Serge A. Suchkov14c65f92008-02-22 18:43:16 +01001852 c = (struct hda_bind_ctls *)kcontrol->private_value;
Takashi Iwai532d5382007-07-27 19:02:40 +02001853 for (vals = c->values; *vals; vals++) {
1854 kcontrol->private_value = *vals;
1855 err = c->ops->put(kcontrol, ucontrol);
1856 if (err < 0)
1857 break;
1858 change |= err;
1859 }
1860 kcontrol->private_value = (long)c;
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001861 mutex_unlock(&codec->control_mutex);
Takashi Iwai532d5382007-07-27 19:02:40 +02001862 return err < 0 ? err : change;
1863}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001864EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_ctls_put);
Takashi Iwai532d5382007-07-27 19:02:40 +02001865
1866int snd_hda_mixer_bind_tlv(struct snd_kcontrol *kcontrol, int op_flag,
1867 unsigned int size, unsigned int __user *tlv)
1868{
1869 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1870 struct hda_bind_ctls *c;
1871 int err;
1872
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001873 mutex_lock(&codec->control_mutex);
Serge A. Suchkov14c65f92008-02-22 18:43:16 +01001874 c = (struct hda_bind_ctls *)kcontrol->private_value;
Takashi Iwai532d5382007-07-27 19:02:40 +02001875 kcontrol->private_value = *c->values;
1876 err = c->ops->tlv(kcontrol, op_flag, size, tlv);
1877 kcontrol->private_value = (long)c;
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001878 mutex_unlock(&codec->control_mutex);
Takashi Iwai532d5382007-07-27 19:02:40 +02001879 return err;
1880}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001881EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_tlv);
Takashi Iwai532d5382007-07-27 19:02:40 +02001882
1883struct hda_ctl_ops snd_hda_bind_vol = {
1884 .info = snd_hda_mixer_amp_volume_info,
1885 .get = snd_hda_mixer_amp_volume_get,
1886 .put = snd_hda_mixer_amp_volume_put,
1887 .tlv = snd_hda_mixer_amp_tlv
1888};
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001889EXPORT_SYMBOL_HDA(snd_hda_bind_vol);
Takashi Iwai532d5382007-07-27 19:02:40 +02001890
1891struct hda_ctl_ops snd_hda_bind_sw = {
1892 .info = snd_hda_mixer_amp_switch_info,
1893 .get = snd_hda_mixer_amp_switch_get,
1894 .put = snd_hda_mixer_amp_switch_put,
1895 .tlv = snd_hda_mixer_amp_tlv
1896};
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001897EXPORT_SYMBOL_HDA(snd_hda_bind_sw);
Takashi Iwai532d5382007-07-27 19:02:40 +02001898
1899/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07001900 * SPDIF out controls
1901 */
1902
Takashi Iwai0ba21762007-04-16 11:29:14 +02001903static int snd_hda_spdif_mask_info(struct snd_kcontrol *kcontrol,
1904 struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001905{
1906 uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
1907 uinfo->count = 1;
1908 return 0;
1909}
1910
Takashi Iwai0ba21762007-04-16 11:29:14 +02001911static int snd_hda_spdif_cmask_get(struct snd_kcontrol *kcontrol,
1912 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001913{
1914 ucontrol->value.iec958.status[0] = IEC958_AES0_PROFESSIONAL |
1915 IEC958_AES0_NONAUDIO |
1916 IEC958_AES0_CON_EMPHASIS_5015 |
1917 IEC958_AES0_CON_NOT_COPYRIGHT;
1918 ucontrol->value.iec958.status[1] = IEC958_AES1_CON_CATEGORY |
1919 IEC958_AES1_CON_ORIGINAL;
1920 return 0;
1921}
1922
Takashi Iwai0ba21762007-04-16 11:29:14 +02001923static int snd_hda_spdif_pmask_get(struct snd_kcontrol *kcontrol,
1924 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001925{
1926 ucontrol->value.iec958.status[0] = IEC958_AES0_PROFESSIONAL |
1927 IEC958_AES0_NONAUDIO |
1928 IEC958_AES0_PRO_EMPHASIS_5015;
1929 return 0;
1930}
1931
Takashi Iwai0ba21762007-04-16 11:29:14 +02001932static int snd_hda_spdif_default_get(struct snd_kcontrol *kcontrol,
1933 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001934{
1935 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1936
1937 ucontrol->value.iec958.status[0] = codec->spdif_status & 0xff;
1938 ucontrol->value.iec958.status[1] = (codec->spdif_status >> 8) & 0xff;
1939 ucontrol->value.iec958.status[2] = (codec->spdif_status >> 16) & 0xff;
1940 ucontrol->value.iec958.status[3] = (codec->spdif_status >> 24) & 0xff;
1941
1942 return 0;
1943}
1944
1945/* convert from SPDIF status bits to HDA SPDIF bits
1946 * bit 0 (DigEn) is always set zero (to be filled later)
1947 */
1948static unsigned short convert_from_spdif_status(unsigned int sbits)
1949{
1950 unsigned short val = 0;
1951
1952 if (sbits & IEC958_AES0_PROFESSIONAL)
Takashi Iwai0ba21762007-04-16 11:29:14 +02001953 val |= AC_DIG1_PROFESSIONAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001954 if (sbits & IEC958_AES0_NONAUDIO)
Takashi Iwai0ba21762007-04-16 11:29:14 +02001955 val |= AC_DIG1_NONAUDIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001956 if (sbits & IEC958_AES0_PROFESSIONAL) {
Takashi Iwai0ba21762007-04-16 11:29:14 +02001957 if ((sbits & IEC958_AES0_PRO_EMPHASIS) ==
1958 IEC958_AES0_PRO_EMPHASIS_5015)
1959 val |= AC_DIG1_EMPHASIS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001960 } else {
Takashi Iwai0ba21762007-04-16 11:29:14 +02001961 if ((sbits & IEC958_AES0_CON_EMPHASIS) ==
1962 IEC958_AES0_CON_EMPHASIS_5015)
1963 val |= AC_DIG1_EMPHASIS;
1964 if (!(sbits & IEC958_AES0_CON_NOT_COPYRIGHT))
1965 val |= AC_DIG1_COPYRIGHT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001966 if (sbits & (IEC958_AES1_CON_ORIGINAL << 8))
Takashi Iwai0ba21762007-04-16 11:29:14 +02001967 val |= AC_DIG1_LEVEL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001968 val |= sbits & (IEC958_AES1_CON_CATEGORY << 8);
1969 }
1970 return val;
1971}
1972
1973/* convert to SPDIF status bits from HDA SPDIF bits
1974 */
1975static unsigned int convert_to_spdif_status(unsigned short val)
1976{
1977 unsigned int sbits = 0;
1978
Takashi Iwai0ba21762007-04-16 11:29:14 +02001979 if (val & AC_DIG1_NONAUDIO)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001980 sbits |= IEC958_AES0_NONAUDIO;
Takashi Iwai0ba21762007-04-16 11:29:14 +02001981 if (val & AC_DIG1_PROFESSIONAL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001982 sbits |= IEC958_AES0_PROFESSIONAL;
1983 if (sbits & IEC958_AES0_PROFESSIONAL) {
Takashi Iwai0ba21762007-04-16 11:29:14 +02001984 if (sbits & AC_DIG1_EMPHASIS)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001985 sbits |= IEC958_AES0_PRO_EMPHASIS_5015;
1986 } else {
Takashi Iwai0ba21762007-04-16 11:29:14 +02001987 if (val & AC_DIG1_EMPHASIS)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001988 sbits |= IEC958_AES0_CON_EMPHASIS_5015;
Takashi Iwai0ba21762007-04-16 11:29:14 +02001989 if (!(val & AC_DIG1_COPYRIGHT))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001990 sbits |= IEC958_AES0_CON_NOT_COPYRIGHT;
Takashi Iwai0ba21762007-04-16 11:29:14 +02001991 if (val & AC_DIG1_LEVEL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001992 sbits |= (IEC958_AES1_CON_ORIGINAL << 8);
1993 sbits |= val & (0x7f << 8);
1994 }
1995 return sbits;
1996}
1997
Takashi Iwai2f728532008-09-25 16:32:41 +02001998/* set digital convert verbs both for the given NID and its slaves */
1999static void set_dig_out(struct hda_codec *codec, hda_nid_t nid,
2000 int verb, int val)
2001{
2002 hda_nid_t *d;
2003
Takashi Iwai9e976972008-11-25 08:17:20 +01002004 snd_hda_codec_write_cache(codec, nid, 0, verb, val);
Takashi Iwai2f728532008-09-25 16:32:41 +02002005 d = codec->slave_dig_outs;
2006 if (!d)
2007 return;
2008 for (; *d; d++)
Takashi Iwai9e976972008-11-25 08:17:20 +01002009 snd_hda_codec_write_cache(codec, *d, 0, verb, val);
Takashi Iwai2f728532008-09-25 16:32:41 +02002010}
2011
2012static inline void set_dig_out_convert(struct hda_codec *codec, hda_nid_t nid,
2013 int dig1, int dig2)
2014{
2015 if (dig1 != -1)
2016 set_dig_out(codec, nid, AC_VERB_SET_DIGI_CONVERT_1, dig1);
2017 if (dig2 != -1)
2018 set_dig_out(codec, nid, AC_VERB_SET_DIGI_CONVERT_2, dig2);
2019}
2020
Takashi Iwai0ba21762007-04-16 11:29:14 +02002021static int snd_hda_spdif_default_put(struct snd_kcontrol *kcontrol,
2022 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002023{
2024 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2025 hda_nid_t nid = kcontrol->private_value;
2026 unsigned short val;
2027 int change;
2028
Ingo Molnar62932df2006-01-16 16:34:20 +01002029 mutex_lock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002030 codec->spdif_status = ucontrol->value.iec958.status[0] |
2031 ((unsigned int)ucontrol->value.iec958.status[1] << 8) |
2032 ((unsigned int)ucontrol->value.iec958.status[2] << 16) |
2033 ((unsigned int)ucontrol->value.iec958.status[3] << 24);
2034 val = convert_from_spdif_status(codec->spdif_status);
2035 val |= codec->spdif_ctls & 1;
2036 change = codec->spdif_ctls != val;
2037 codec->spdif_ctls = val;
2038
Takashi Iwai2f728532008-09-25 16:32:41 +02002039 if (change)
2040 set_dig_out_convert(codec, nid, val & 0xff, (val >> 8) & 0xff);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002041
Ingo Molnar62932df2006-01-16 16:34:20 +01002042 mutex_unlock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002043 return change;
2044}
2045
Takashi Iwaia5ce8892007-07-23 15:42:26 +02002046#define snd_hda_spdif_out_switch_info snd_ctl_boolean_mono_info
Linus Torvalds1da177e2005-04-16 15:20:36 -07002047
Takashi Iwai0ba21762007-04-16 11:29:14 +02002048static int snd_hda_spdif_out_switch_get(struct snd_kcontrol *kcontrol,
2049 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002050{
2051 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2052
Takashi Iwai0ba21762007-04-16 11:29:14 +02002053 ucontrol->value.integer.value[0] = codec->spdif_ctls & AC_DIG1_ENABLE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002054 return 0;
2055}
2056
Takashi Iwai0ba21762007-04-16 11:29:14 +02002057static int snd_hda_spdif_out_switch_put(struct snd_kcontrol *kcontrol,
2058 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002059{
2060 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2061 hda_nid_t nid = kcontrol->private_value;
2062 unsigned short val;
2063 int change;
2064
Ingo Molnar62932df2006-01-16 16:34:20 +01002065 mutex_lock(&codec->spdif_mutex);
Takashi Iwai0ba21762007-04-16 11:29:14 +02002066 val = codec->spdif_ctls & ~AC_DIG1_ENABLE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002067 if (ucontrol->value.integer.value[0])
Takashi Iwai0ba21762007-04-16 11:29:14 +02002068 val |= AC_DIG1_ENABLE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002069 change = codec->spdif_ctls != val;
Takashi Iwai82beb8f2007-08-10 17:09:26 +02002070 if (change) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002071 codec->spdif_ctls = val;
Takashi Iwai2f728532008-09-25 16:32:41 +02002072 set_dig_out_convert(codec, nid, val & 0xff, -1);
Takashi Iwai0ba21762007-04-16 11:29:14 +02002073 /* unmute amp switch (if any) */
2074 if ((get_wcaps(codec, nid) & AC_WCAP_OUT_AMP) &&
Takashi Iwai47fd8302007-08-10 17:11:07 +02002075 (val & AC_DIG1_ENABLE))
2076 snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0,
2077 HDA_AMP_MUTE, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002078 }
Ingo Molnar62932df2006-01-16 16:34:20 +01002079 mutex_unlock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002080 return change;
2081}
2082
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01002083static struct snd_kcontrol_new dig_mixes[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002084 {
2085 .access = SNDRV_CTL_ELEM_ACCESS_READ,
2086 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2087 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,CON_MASK),
2088 .info = snd_hda_spdif_mask_info,
2089 .get = snd_hda_spdif_cmask_get,
2090 },
2091 {
2092 .access = SNDRV_CTL_ELEM_ACCESS_READ,
2093 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2094 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,PRO_MASK),
2095 .info = snd_hda_spdif_mask_info,
2096 .get = snd_hda_spdif_pmask_get,
2097 },
2098 {
2099 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2100 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT),
2101 .info = snd_hda_spdif_mask_info,
2102 .get = snd_hda_spdif_default_get,
2103 .put = snd_hda_spdif_default_put,
2104 },
2105 {
2106 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2107 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,SWITCH),
2108 .info = snd_hda_spdif_out_switch_info,
2109 .get = snd_hda_spdif_out_switch_get,
2110 .put = snd_hda_spdif_out_switch_put,
2111 },
2112 { } /* end */
2113};
2114
Takashi Iwai09f99702008-02-04 12:31:13 +01002115#define SPDIF_MAX_IDX 4 /* 4 instances should be enough to probe */
2116
Linus Torvalds1da177e2005-04-16 15:20:36 -07002117/**
2118 * snd_hda_create_spdif_out_ctls - create Output SPDIF-related controls
2119 * @codec: the HDA codec
2120 * @nid: audio out widget NID
2121 *
2122 * Creates controls related with the SPDIF output.
2123 * Called from each patch supporting the SPDIF out.
2124 *
2125 * Returns 0 if successful, or a negative error code.
2126 */
Takashi Iwai12f288b2007-08-02 15:51:59 +02002127int snd_hda_create_spdif_out_ctls(struct hda_codec *codec, hda_nid_t nid)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002128{
2129 int err;
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01002130 struct snd_kcontrol *kctl;
2131 struct snd_kcontrol_new *dig_mix;
Takashi Iwai09f99702008-02-04 12:31:13 +01002132 int idx;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002133
Takashi Iwai09f99702008-02-04 12:31:13 +01002134 for (idx = 0; idx < SPDIF_MAX_IDX; idx++) {
2135 if (!_snd_hda_find_mixer_ctl(codec, "IEC958 Playback Switch",
2136 idx))
2137 break;
2138 }
2139 if (idx >= SPDIF_MAX_IDX) {
2140 printk(KERN_ERR "hda_codec: too many IEC958 outputs\n");
2141 return -EBUSY;
2142 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002143 for (dig_mix = dig_mixes; dig_mix->name; dig_mix++) {
2144 kctl = snd_ctl_new1(dig_mix, codec);
Takashi Iwaib91f0802008-11-04 08:43:08 +01002145 if (!kctl)
2146 return -ENOMEM;
Takashi Iwai09f99702008-02-04 12:31:13 +01002147 kctl->id.index = idx;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002148 kctl->private_value = nid;
Jaroslav Kysela3911a4c2009-11-11 13:43:01 +01002149 err = snd_hda_ctl_add(codec, nid, kctl);
Takashi Iwai0ba21762007-04-16 11:29:14 +02002150 if (err < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002151 return err;
2152 }
Takashi Iwai0ba21762007-04-16 11:29:14 +02002153 codec->spdif_ctls =
Andrew Paprocki3982d172007-12-19 12:13:44 +01002154 snd_hda_codec_read(codec, nid, 0,
2155 AC_VERB_GET_DIGI_CONVERT_1, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002156 codec->spdif_status = convert_to_spdif_status(codec->spdif_ctls);
2157 return 0;
2158}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002159EXPORT_SYMBOL_HDA(snd_hda_create_spdif_out_ctls);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002160
2161/*
Takashi Iwai9a081602008-02-12 18:37:26 +01002162 * SPDIF sharing with analog output
2163 */
2164static int spdif_share_sw_get(struct snd_kcontrol *kcontrol,
2165 struct snd_ctl_elem_value *ucontrol)
2166{
2167 struct hda_multi_out *mout = snd_kcontrol_chip(kcontrol);
2168 ucontrol->value.integer.value[0] = mout->share_spdif;
2169 return 0;
2170}
2171
2172static int spdif_share_sw_put(struct snd_kcontrol *kcontrol,
2173 struct snd_ctl_elem_value *ucontrol)
2174{
2175 struct hda_multi_out *mout = snd_kcontrol_chip(kcontrol);
2176 mout->share_spdif = !!ucontrol->value.integer.value[0];
2177 return 0;
2178}
2179
2180static struct snd_kcontrol_new spdif_share_sw = {
2181 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2182 .name = "IEC958 Default PCM Playback Switch",
2183 .info = snd_ctl_boolean_mono_info,
2184 .get = spdif_share_sw_get,
2185 .put = spdif_share_sw_put,
2186};
2187
2188int snd_hda_create_spdif_share_sw(struct hda_codec *codec,
2189 struct hda_multi_out *mout)
2190{
2191 if (!mout->dig_out_nid)
2192 return 0;
2193 /* ATTENTION: here mout is passed as private_data, instead of codec */
Jaroslav Kysela3911a4c2009-11-11 13:43:01 +01002194 return snd_hda_ctl_add(codec, mout->dig_out_nid,
2195 snd_ctl_new1(&spdif_share_sw, mout));
Takashi Iwai9a081602008-02-12 18:37:26 +01002196}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002197EXPORT_SYMBOL_HDA(snd_hda_create_spdif_share_sw);
Takashi Iwai9a081602008-02-12 18:37:26 +01002198
2199/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002200 * SPDIF input
2201 */
2202
2203#define snd_hda_spdif_in_switch_info snd_hda_spdif_out_switch_info
2204
Takashi Iwai0ba21762007-04-16 11:29:14 +02002205static int snd_hda_spdif_in_switch_get(struct snd_kcontrol *kcontrol,
2206 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002207{
2208 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2209
2210 ucontrol->value.integer.value[0] = codec->spdif_in_enable;
2211 return 0;
2212}
2213
Takashi Iwai0ba21762007-04-16 11:29:14 +02002214static int snd_hda_spdif_in_switch_put(struct snd_kcontrol *kcontrol,
2215 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002216{
2217 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2218 hda_nid_t nid = kcontrol->private_value;
2219 unsigned int val = !!ucontrol->value.integer.value[0];
2220 int change;
2221
Ingo Molnar62932df2006-01-16 16:34:20 +01002222 mutex_lock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002223 change = codec->spdif_in_enable != val;
Takashi Iwai82beb8f2007-08-10 17:09:26 +02002224 if (change) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002225 codec->spdif_in_enable = val;
Takashi Iwai82beb8f2007-08-10 17:09:26 +02002226 snd_hda_codec_write_cache(codec, nid, 0,
2227 AC_VERB_SET_DIGI_CONVERT_1, val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002228 }
Ingo Molnar62932df2006-01-16 16:34:20 +01002229 mutex_unlock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002230 return change;
2231}
2232
Takashi Iwai0ba21762007-04-16 11:29:14 +02002233static int snd_hda_spdif_in_status_get(struct snd_kcontrol *kcontrol,
2234 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002235{
2236 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2237 hda_nid_t nid = kcontrol->private_value;
2238 unsigned short val;
2239 unsigned int sbits;
2240
Andrew Paprocki3982d172007-12-19 12:13:44 +01002241 val = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_DIGI_CONVERT_1, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002242 sbits = convert_to_spdif_status(val);
2243 ucontrol->value.iec958.status[0] = sbits;
2244 ucontrol->value.iec958.status[1] = sbits >> 8;
2245 ucontrol->value.iec958.status[2] = sbits >> 16;
2246 ucontrol->value.iec958.status[3] = sbits >> 24;
2247 return 0;
2248}
2249
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01002250static struct snd_kcontrol_new dig_in_ctls[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002251 {
2252 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2253 .name = SNDRV_CTL_NAME_IEC958("",CAPTURE,SWITCH),
2254 .info = snd_hda_spdif_in_switch_info,
2255 .get = snd_hda_spdif_in_switch_get,
2256 .put = snd_hda_spdif_in_switch_put,
2257 },
2258 {
2259 .access = SNDRV_CTL_ELEM_ACCESS_READ,
2260 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2261 .name = SNDRV_CTL_NAME_IEC958("",CAPTURE,DEFAULT),
2262 .info = snd_hda_spdif_mask_info,
2263 .get = snd_hda_spdif_in_status_get,
2264 },
2265 { } /* end */
2266};
2267
2268/**
2269 * snd_hda_create_spdif_in_ctls - create Input SPDIF-related controls
2270 * @codec: the HDA codec
2271 * @nid: audio in widget NID
2272 *
2273 * Creates controls related with the SPDIF input.
2274 * Called from each patch supporting the SPDIF in.
2275 *
2276 * Returns 0 if successful, or a negative error code.
2277 */
Takashi Iwai12f288b2007-08-02 15:51:59 +02002278int snd_hda_create_spdif_in_ctls(struct hda_codec *codec, hda_nid_t nid)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002279{
2280 int err;
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01002281 struct snd_kcontrol *kctl;
2282 struct snd_kcontrol_new *dig_mix;
Takashi Iwai09f99702008-02-04 12:31:13 +01002283 int idx;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002284
Takashi Iwai09f99702008-02-04 12:31:13 +01002285 for (idx = 0; idx < SPDIF_MAX_IDX; idx++) {
2286 if (!_snd_hda_find_mixer_ctl(codec, "IEC958 Capture Switch",
2287 idx))
2288 break;
2289 }
2290 if (idx >= SPDIF_MAX_IDX) {
2291 printk(KERN_ERR "hda_codec: too many IEC958 inputs\n");
2292 return -EBUSY;
2293 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002294 for (dig_mix = dig_in_ctls; dig_mix->name; dig_mix++) {
2295 kctl = snd_ctl_new1(dig_mix, codec);
Takashi Iwaic8dcdf82009-02-06 16:21:20 +01002296 if (!kctl)
2297 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002298 kctl->private_value = nid;
Jaroslav Kysela3911a4c2009-11-11 13:43:01 +01002299 err = snd_hda_ctl_add(codec, nid, kctl);
Takashi Iwai0ba21762007-04-16 11:29:14 +02002300 if (err < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002301 return err;
2302 }
Takashi Iwai0ba21762007-04-16 11:29:14 +02002303 codec->spdif_in_enable =
Andrew Paprocki3982d172007-12-19 12:13:44 +01002304 snd_hda_codec_read(codec, nid, 0,
2305 AC_VERB_GET_DIGI_CONVERT_1, 0) &
Takashi Iwai0ba21762007-04-16 11:29:14 +02002306 AC_DIG1_ENABLE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002307 return 0;
2308}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002309EXPORT_SYMBOL_HDA(snd_hda_create_spdif_in_ctls);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002310
Takashi Iwaicb53c622007-08-10 17:21:45 +02002311#ifdef SND_HDA_NEEDS_RESUME
Takashi Iwai82beb8f2007-08-10 17:09:26 +02002312/*
2313 * command cache
2314 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002315
Takashi Iwaib3ac5632007-08-10 17:03:40 +02002316/* build a 32bit cache key with the widget id and the command parameter */
2317#define build_cmd_cache_key(nid, verb) ((verb << 8) | nid)
2318#define get_cmd_cache_nid(key) ((key) & 0xff)
2319#define get_cmd_cache_cmd(key) (((key) >> 8) & 0xffff)
2320
2321/**
2322 * snd_hda_codec_write_cache - send a single command with caching
2323 * @codec: the HDA codec
2324 * @nid: NID to send the command
2325 * @direct: direct flag
2326 * @verb: the verb to send
2327 * @parm: the parameter for the verb
2328 *
2329 * Send a single command without waiting for response.
2330 *
2331 * Returns 0 if successful, or a negative error code.
2332 */
2333int snd_hda_codec_write_cache(struct hda_codec *codec, hda_nid_t nid,
2334 int direct, unsigned int verb, unsigned int parm)
2335{
Takashi Iwaiaa2936f2009-05-26 16:07:57 +02002336 int err = snd_hda_codec_write(codec, nid, direct, verb, parm);
2337 struct hda_cache_head *c;
2338 u32 key;
Takashi Iwai33fa35e2008-11-06 16:50:40 +01002339
Takashi Iwaiaa2936f2009-05-26 16:07:57 +02002340 if (err < 0)
2341 return err;
2342 /* parm may contain the verb stuff for get/set amp */
2343 verb = verb | (parm >> 8);
2344 parm &= 0xff;
2345 key = build_cmd_cache_key(nid, verb);
2346 mutex_lock(&codec->bus->cmd_mutex);
2347 c = get_alloc_hash(&codec->cmd_cache, key);
2348 if (c)
2349 c->val = parm;
2350 mutex_unlock(&codec->bus->cmd_mutex);
2351 return 0;
Takashi Iwaib3ac5632007-08-10 17:03:40 +02002352}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002353EXPORT_SYMBOL_HDA(snd_hda_codec_write_cache);
Takashi Iwaib3ac5632007-08-10 17:03:40 +02002354
2355/* resume the all commands from the cache */
2356void snd_hda_codec_resume_cache(struct hda_codec *codec)
2357{
Takashi Iwai603c4012008-07-30 15:01:44 +02002358 struct hda_cache_head *buffer = codec->cmd_cache.buf.list;
Takashi Iwaib3ac5632007-08-10 17:03:40 +02002359 int i;
2360
Takashi Iwai603c4012008-07-30 15:01:44 +02002361 for (i = 0; i < codec->cmd_cache.buf.used; i++, buffer++) {
Takashi Iwaib3ac5632007-08-10 17:03:40 +02002362 u32 key = buffer->key;
2363 if (!key)
2364 continue;
2365 snd_hda_codec_write(codec, get_cmd_cache_nid(key), 0,
2366 get_cmd_cache_cmd(key), buffer->val);
2367 }
2368}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002369EXPORT_SYMBOL_HDA(snd_hda_codec_resume_cache);
Takashi Iwaib3ac5632007-08-10 17:03:40 +02002370
2371/**
2372 * snd_hda_sequence_write_cache - sequence writes with caching
2373 * @codec: the HDA codec
2374 * @seq: VERB array to send
2375 *
2376 * Send the commands sequentially from the given array.
2377 * Thte commands are recorded on cache for power-save and resume.
2378 * The array must be terminated with NID=0.
2379 */
2380void snd_hda_sequence_write_cache(struct hda_codec *codec,
2381 const struct hda_verb *seq)
2382{
2383 for (; seq->nid; seq++)
2384 snd_hda_codec_write_cache(codec, seq->nid, 0, seq->verb,
2385 seq->param);
2386}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002387EXPORT_SYMBOL_HDA(snd_hda_sequence_write_cache);
Takashi Iwaicb53c622007-08-10 17:21:45 +02002388#endif /* SND_HDA_NEEDS_RESUME */
Takashi Iwaib3ac5632007-08-10 17:03:40 +02002389
Takashi Iwai54d17402005-11-21 16:33:22 +01002390/*
2391 * set power state of the codec
2392 */
2393static void hda_set_power_state(struct hda_codec *codec, hda_nid_t fg,
2394 unsigned int power_state)
2395{
Takashi Iwaicb53c622007-08-10 17:21:45 +02002396 hda_nid_t nid;
2397 int i;
Takashi Iwai54d17402005-11-21 16:33:22 +01002398
Takashi Iwai05ff7e12009-07-22 12:39:24 +02002399 /* this delay seems necessary to avoid click noise at power-down */
2400 if (power_state == AC_PWRST_D3)
2401 msleep(100);
2402 snd_hda_codec_read(codec, fg, 0, AC_VERB_SET_POWER_STATE,
Takashi Iwai54d17402005-11-21 16:33:22 +01002403 power_state);
Takashi Iwai05ff7e12009-07-22 12:39:24 +02002404 /* partial workaround for "azx_get_response timeout" */
2405 if (power_state == AC_PWRST_D0)
2406 msleep(10);
Takashi Iwai54d17402005-11-21 16:33:22 +01002407
Takashi Iwaicb53c622007-08-10 17:21:45 +02002408 nid = codec->start_nid;
2409 for (i = 0; i < codec->num_nodes; i++, nid++) {
Takashi Iwai7eba5c92007-11-14 14:53:42 +01002410 unsigned int wcaps = get_wcaps(codec, nid);
2411 if (wcaps & AC_WCAP_POWER) {
Takashi Iwaia22d5432009-07-27 12:54:26 +02002412 unsigned int wid_type = get_wcaps_type(wcaps);
Takashi Iwaia3b48c82009-04-21 13:37:29 +02002413 if (power_state == AC_PWRST_D3 &&
2414 wid_type == AC_WID_PIN) {
Takashi Iwai7eba5c92007-11-14 14:53:42 +01002415 unsigned int pincap;
2416 /*
2417 * don't power down the widget if it controls
2418 * eapd and EAPD_BTLENABLE is set.
2419 */
Takashi Iwai14bafe32009-03-23 16:35:39 +01002420 pincap = snd_hda_query_pin_caps(codec, nid);
Takashi Iwai7eba5c92007-11-14 14:53:42 +01002421 if (pincap & AC_PINCAP_EAPD) {
2422 int eapd = snd_hda_codec_read(codec,
2423 nid, 0,
2424 AC_VERB_GET_EAPD_BTLENABLE, 0);
2425 eapd &= 0x02;
Takashi Iwaia3b48c82009-04-21 13:37:29 +02002426 if (eapd)
Takashi Iwai7eba5c92007-11-14 14:53:42 +01002427 continue;
2428 }
Takashi Iwai1194b5b2007-10-10 10:04:26 +02002429 }
Takashi Iwai54d17402005-11-21 16:33:22 +01002430 snd_hda_codec_write(codec, nid, 0,
2431 AC_VERB_SET_POWER_STATE,
2432 power_state);
Takashi Iwai1194b5b2007-10-10 10:04:26 +02002433 }
Takashi Iwai54d17402005-11-21 16:33:22 +01002434 }
2435
Takashi Iwaicb53c622007-08-10 17:21:45 +02002436 if (power_state == AC_PWRST_D0) {
2437 unsigned long end_time;
2438 int state;
Takashi Iwai54d17402005-11-21 16:33:22 +01002439 msleep(10);
Takashi Iwaicb53c622007-08-10 17:21:45 +02002440 /* wait until the codec reachs to D0 */
2441 end_time = jiffies + msecs_to_jiffies(500);
2442 do {
2443 state = snd_hda_codec_read(codec, fg, 0,
2444 AC_VERB_GET_POWER_STATE, 0);
2445 if (state == power_state)
2446 break;
2447 msleep(1);
2448 } while (time_after_eq(end_time, jiffies));
2449 }
Takashi Iwai54d17402005-11-21 16:33:22 +01002450}
2451
Takashi Iwai11aeff02008-07-30 15:01:46 +02002452#ifdef CONFIG_SND_HDA_HWDEP
2453/* execute additional init verbs */
2454static void hda_exec_init_verbs(struct hda_codec *codec)
2455{
2456 if (codec->init_verbs.list)
2457 snd_hda_sequence_write(codec, codec->init_verbs.list);
2458}
2459#else
2460static inline void hda_exec_init_verbs(struct hda_codec *codec) {}
2461#endif
2462
Takashi Iwaicb53c622007-08-10 17:21:45 +02002463#ifdef SND_HDA_NEEDS_RESUME
2464/*
2465 * call suspend and power-down; used both from PM and power-save
2466 */
2467static void hda_call_codec_suspend(struct hda_codec *codec)
2468{
2469 if (codec->patch_ops.suspend)
2470 codec->patch_ops.suspend(codec, PMSG_SUSPEND);
2471 hda_set_power_state(codec,
2472 codec->afg ? codec->afg : codec->mfg,
2473 AC_PWRST_D3);
2474#ifdef CONFIG_SND_HDA_POWER_SAVE
Takashi Iwaia2f63092009-11-11 09:34:25 +01002475 snd_hda_update_power_acct(codec);
Takashi Iwaicb53c622007-08-10 17:21:45 +02002476 cancel_delayed_work(&codec->power_work);
Takashi Iwai95e99fd2007-08-13 15:29:04 +02002477 codec->power_on = 0;
Takashi Iwaia221e282007-08-16 16:35:33 +02002478 codec->power_transition = 0;
Takashi Iwaia2f63092009-11-11 09:34:25 +01002479 codec->power_jiffies = jiffies;
Takashi Iwaicb53c622007-08-10 17:21:45 +02002480#endif
2481}
2482
2483/*
2484 * kick up codec; used both from PM and power-save
2485 */
2486static void hda_call_codec_resume(struct hda_codec *codec)
2487{
2488 hda_set_power_state(codec,
2489 codec->afg ? codec->afg : codec->mfg,
2490 AC_PWRST_D0);
Takashi Iwai3be14142009-02-20 14:11:16 +01002491 restore_pincfgs(codec); /* restore all current pin configs */
Takashi Iwai11aeff02008-07-30 15:01:46 +02002492 hda_exec_init_verbs(codec);
Takashi Iwaicb53c622007-08-10 17:21:45 +02002493 if (codec->patch_ops.resume)
2494 codec->patch_ops.resume(codec);
2495 else {
Takashi Iwai9d99f312007-08-14 15:15:52 +02002496 if (codec->patch_ops.init)
2497 codec->patch_ops.init(codec);
Takashi Iwaicb53c622007-08-10 17:21:45 +02002498 snd_hda_codec_resume_amp(codec);
2499 snd_hda_codec_resume_cache(codec);
2500 }
2501}
2502#endif /* SND_HDA_NEEDS_RESUME */
2503
Takashi Iwai54d17402005-11-21 16:33:22 +01002504
Linus Torvalds1da177e2005-04-16 15:20:36 -07002505/**
2506 * snd_hda_build_controls - build mixer controls
2507 * @bus: the BUS
2508 *
2509 * Creates mixer controls for each codec included in the bus.
2510 *
2511 * Returns 0 if successful, otherwise a negative error code.
2512 */
Takashi Iwai1289e9e2008-11-27 15:47:11 +01002513int /*__devinit*/ snd_hda_build_controls(struct hda_bus *bus)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002514{
Takashi Iwai0ba21762007-04-16 11:29:14 +02002515 struct hda_codec *codec;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002516
Takashi Iwai0ba21762007-04-16 11:29:14 +02002517 list_for_each_entry(codec, &bus->codec_list, list) {
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02002518 int err = snd_hda_codec_build_controls(codec);
Takashi Iwaif93d4612009-03-02 10:44:15 +01002519 if (err < 0) {
2520 printk(KERN_ERR "hda_codec: cannot build controls"
2521 "for #%d (error %d)\n", codec->addr, err);
2522 err = snd_hda_codec_reset(codec);
2523 if (err < 0) {
2524 printk(KERN_ERR
2525 "hda_codec: cannot revert codec\n");
2526 return err;
2527 }
2528 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002529 }
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02002530 return 0;
2531}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002532EXPORT_SYMBOL_HDA(snd_hda_build_controls);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002533
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02002534int snd_hda_codec_build_controls(struct hda_codec *codec)
2535{
2536 int err = 0;
Takashi Iwai11aeff02008-07-30 15:01:46 +02002537 hda_exec_init_verbs(codec);
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02002538 /* continue to initialize... */
2539 if (codec->patch_ops.init)
2540 err = codec->patch_ops.init(codec);
2541 if (!err && codec->patch_ops.build_controls)
2542 err = codec->patch_ops.build_controls(codec);
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02002543 if (err < 0)
2544 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002545 return 0;
2546}
2547
Linus Torvalds1da177e2005-04-16 15:20:36 -07002548/*
2549 * stream formats
2550 */
Takashi Iwaibefdf312005-08-22 13:57:55 +02002551struct hda_rate_tbl {
2552 unsigned int hz;
2553 unsigned int alsa_bits;
2554 unsigned int hda_fmt;
2555};
2556
2557static struct hda_rate_tbl rate_bits[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002558 /* rate in Hz, ALSA rate bitmask, HDA format value */
Nicolas Graziano9d8f53f2005-08-22 13:47:16 +02002559
2560 /* autodetected value used in snd_hda_query_supported_pcm */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002561 { 8000, SNDRV_PCM_RATE_8000, 0x0500 }, /* 1/6 x 48 */
2562 { 11025, SNDRV_PCM_RATE_11025, 0x4300 }, /* 1/4 x 44 */
2563 { 16000, SNDRV_PCM_RATE_16000, 0x0200 }, /* 1/3 x 48 */
2564 { 22050, SNDRV_PCM_RATE_22050, 0x4100 }, /* 1/2 x 44 */
2565 { 32000, SNDRV_PCM_RATE_32000, 0x0a00 }, /* 2/3 x 48 */
2566 { 44100, SNDRV_PCM_RATE_44100, 0x4000 }, /* 44 */
2567 { 48000, SNDRV_PCM_RATE_48000, 0x0000 }, /* 48 */
2568 { 88200, SNDRV_PCM_RATE_88200, 0x4800 }, /* 2 x 44 */
2569 { 96000, SNDRV_PCM_RATE_96000, 0x0800 }, /* 2 x 48 */
2570 { 176400, SNDRV_PCM_RATE_176400, 0x5800 },/* 4 x 44 */
2571 { 192000, SNDRV_PCM_RATE_192000, 0x1800 }, /* 4 x 48 */
Takashi Iwaia961f9f2007-04-12 13:08:09 +02002572#define AC_PAR_PCM_RATE_BITS 11
2573 /* up to bits 10, 384kHZ isn't supported properly */
2574
2575 /* not autodetected value */
2576 { 9600, SNDRV_PCM_RATE_KNOT, 0x0400 }, /* 1/5 x 48 */
Nicolas Graziano9d8f53f2005-08-22 13:47:16 +02002577
Takashi Iwaibefdf312005-08-22 13:57:55 +02002578 { 0 } /* terminator */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002579};
2580
2581/**
2582 * snd_hda_calc_stream_format - calculate format bitset
2583 * @rate: the sample rate
2584 * @channels: the number of channels
2585 * @format: the PCM format (SNDRV_PCM_FORMAT_XXX)
2586 * @maxbps: the max. bps
2587 *
2588 * Calculate the format bitset from the given rate, channels and th PCM format.
2589 *
2590 * Return zero if invalid.
2591 */
2592unsigned int snd_hda_calc_stream_format(unsigned int rate,
2593 unsigned int channels,
2594 unsigned int format,
2595 unsigned int maxbps)
2596{
2597 int i;
2598 unsigned int val = 0;
2599
Takashi Iwaibefdf312005-08-22 13:57:55 +02002600 for (i = 0; rate_bits[i].hz; i++)
2601 if (rate_bits[i].hz == rate) {
2602 val = rate_bits[i].hda_fmt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002603 break;
2604 }
Takashi Iwai0ba21762007-04-16 11:29:14 +02002605 if (!rate_bits[i].hz) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002606 snd_printdd("invalid rate %d\n", rate);
2607 return 0;
2608 }
2609
2610 if (channels == 0 || channels > 8) {
2611 snd_printdd("invalid channels %d\n", channels);
2612 return 0;
2613 }
2614 val |= channels - 1;
2615
2616 switch (snd_pcm_format_width(format)) {
2617 case 8: val |= 0x00; break;
2618 case 16: val |= 0x10; break;
2619 case 20:
2620 case 24:
2621 case 32:
Takashi Iwaib0bb3aa2009-07-03 23:25:37 +02002622 if (maxbps >= 32 || format == SNDRV_PCM_FORMAT_FLOAT_LE)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002623 val |= 0x40;
2624 else if (maxbps >= 24)
2625 val |= 0x30;
2626 else
2627 val |= 0x20;
2628 break;
2629 default:
Takashi Iwai0ba21762007-04-16 11:29:14 +02002630 snd_printdd("invalid format width %d\n",
2631 snd_pcm_format_width(format));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002632 return 0;
2633 }
2634
2635 return val;
2636}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002637EXPORT_SYMBOL_HDA(snd_hda_calc_stream_format);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002638
Takashi Iwai92c7c8a2009-03-24 07:32:14 +01002639static unsigned int get_pcm_param(struct hda_codec *codec, hda_nid_t nid)
2640{
2641 unsigned int val = 0;
2642 if (nid != codec->afg &&
2643 (get_wcaps(codec, nid) & AC_WCAP_FORMAT_OVRD))
2644 val = snd_hda_param_read(codec, nid, AC_PAR_PCM);
2645 if (!val || val == -1)
2646 val = snd_hda_param_read(codec, codec->afg, AC_PAR_PCM);
2647 if (!val || val == -1)
2648 return 0;
2649 return val;
2650}
2651
2652static unsigned int query_pcm_param(struct hda_codec *codec, hda_nid_t nid)
2653{
2654 return query_caps_hash(codec, nid, HDA_HASH_PARPCM_KEY(nid),
2655 get_pcm_param);
2656}
2657
2658static unsigned int get_stream_param(struct hda_codec *codec, hda_nid_t nid)
2659{
2660 unsigned int streams = snd_hda_param_read(codec, nid, AC_PAR_STREAM);
2661 if (!streams || streams == -1)
2662 streams = snd_hda_param_read(codec, codec->afg, AC_PAR_STREAM);
2663 if (!streams || streams == -1)
2664 return 0;
2665 return streams;
2666}
2667
2668static unsigned int query_stream_param(struct hda_codec *codec, hda_nid_t nid)
2669{
2670 return query_caps_hash(codec, nid, HDA_HASH_PARSTR_KEY(nid),
2671 get_stream_param);
2672}
2673
Linus Torvalds1da177e2005-04-16 15:20:36 -07002674/**
2675 * snd_hda_query_supported_pcm - query the supported PCM rates and formats
2676 * @codec: the HDA codec
2677 * @nid: NID to query
2678 * @ratesp: the pointer to store the detected rate bitflags
2679 * @formatsp: the pointer to store the detected formats
2680 * @bpsp: the pointer to store the detected format widths
2681 *
2682 * Queries the supported PCM rates and formats. The NULL @ratesp, @formatsp
2683 * or @bsps argument is ignored.
2684 *
2685 * Returns 0 if successful, otherwise a negative error code.
2686 */
Takashi Iwai986862bd2008-11-27 12:40:13 +01002687static int snd_hda_query_supported_pcm(struct hda_codec *codec, hda_nid_t nid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002688 u32 *ratesp, u64 *formatsp, unsigned int *bpsp)
2689{
Jaroslav Kyselaee504712009-03-17 14:30:31 +01002690 unsigned int i, val, wcaps;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002691
Jaroslav Kyselaee504712009-03-17 14:30:31 +01002692 wcaps = get_wcaps(codec, nid);
Takashi Iwai92c7c8a2009-03-24 07:32:14 +01002693 val = query_pcm_param(codec, nid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002694
2695 if (ratesp) {
2696 u32 rates = 0;
Takashi Iwaia961f9f2007-04-12 13:08:09 +02002697 for (i = 0; i < AC_PAR_PCM_RATE_BITS; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002698 if (val & (1 << i))
Takashi Iwaibefdf312005-08-22 13:57:55 +02002699 rates |= rate_bits[i].alsa_bits;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002700 }
Jaroslav Kyselaee504712009-03-17 14:30:31 +01002701 if (rates == 0) {
2702 snd_printk(KERN_ERR "hda_codec: rates == 0 "
2703 "(nid=0x%x, val=0x%x, ovrd=%i)\n",
2704 nid, val,
2705 (wcaps & AC_WCAP_FORMAT_OVRD) ? 1 : 0);
2706 return -EIO;
2707 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002708 *ratesp = rates;
2709 }
2710
2711 if (formatsp || bpsp) {
2712 u64 formats = 0;
Jaroslav Kyselaee504712009-03-17 14:30:31 +01002713 unsigned int streams, bps;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002714
Takashi Iwai92c7c8a2009-03-24 07:32:14 +01002715 streams = query_stream_param(codec, nid);
2716 if (!streams)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002717 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002718
2719 bps = 0;
2720 if (streams & AC_SUPFMT_PCM) {
2721 if (val & AC_SUPPCM_BITS_8) {
2722 formats |= SNDRV_PCM_FMTBIT_U8;
2723 bps = 8;
2724 }
2725 if (val & AC_SUPPCM_BITS_16) {
2726 formats |= SNDRV_PCM_FMTBIT_S16_LE;
2727 bps = 16;
2728 }
2729 if (wcaps & AC_WCAP_DIGITAL) {
2730 if (val & AC_SUPPCM_BITS_32)
2731 formats |= SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_LE;
2732 if (val & (AC_SUPPCM_BITS_20|AC_SUPPCM_BITS_24))
2733 formats |= SNDRV_PCM_FMTBIT_S32_LE;
2734 if (val & AC_SUPPCM_BITS_24)
2735 bps = 24;
2736 else if (val & AC_SUPPCM_BITS_20)
2737 bps = 20;
Takashi Iwai0ba21762007-04-16 11:29:14 +02002738 } else if (val & (AC_SUPPCM_BITS_20|AC_SUPPCM_BITS_24|
2739 AC_SUPPCM_BITS_32)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002740 formats |= SNDRV_PCM_FMTBIT_S32_LE;
2741 if (val & AC_SUPPCM_BITS_32)
2742 bps = 32;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002743 else if (val & AC_SUPPCM_BITS_24)
2744 bps = 24;
Nicolas Graziano33ef76512006-09-19 14:23:14 +02002745 else if (val & AC_SUPPCM_BITS_20)
2746 bps = 20;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002747 }
2748 }
Takashi Iwaib5025c52009-07-01 18:05:27 +02002749 if (streams & AC_SUPFMT_FLOAT32) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002750 formats |= SNDRV_PCM_FMTBIT_FLOAT_LE;
Takashi Iwaib0bb3aa2009-07-03 23:25:37 +02002751 if (!bps)
2752 bps = 32;
Takashi Iwaib5025c52009-07-01 18:05:27 +02002753 }
2754 if (streams == AC_SUPFMT_AC3) {
Takashi Iwai0ba21762007-04-16 11:29:14 +02002755 /* should be exclusive */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002756 /* temporary hack: we have still no proper support
2757 * for the direct AC3 stream...
2758 */
2759 formats |= SNDRV_PCM_FMTBIT_U8;
2760 bps = 8;
2761 }
Jaroslav Kyselaee504712009-03-17 14:30:31 +01002762 if (formats == 0) {
2763 snd_printk(KERN_ERR "hda_codec: formats == 0 "
2764 "(nid=0x%x, val=0x%x, ovrd=%i, "
2765 "streams=0x%x)\n",
2766 nid, val,
2767 (wcaps & AC_WCAP_FORMAT_OVRD) ? 1 : 0,
2768 streams);
2769 return -EIO;
2770 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002771 if (formatsp)
2772 *formatsp = formats;
2773 if (bpsp)
2774 *bpsp = bps;
2775 }
2776
2777 return 0;
2778}
2779
2780/**
Takashi Iwai0ba21762007-04-16 11:29:14 +02002781 * snd_hda_is_supported_format - check whether the given node supports
2782 * the format val
Linus Torvalds1da177e2005-04-16 15:20:36 -07002783 *
2784 * Returns 1 if supported, 0 if not.
2785 */
2786int snd_hda_is_supported_format(struct hda_codec *codec, hda_nid_t nid,
2787 unsigned int format)
2788{
2789 int i;
2790 unsigned int val = 0, rate, stream;
2791
Takashi Iwai92c7c8a2009-03-24 07:32:14 +01002792 val = query_pcm_param(codec, nid);
2793 if (!val)
2794 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002795
2796 rate = format & 0xff00;
Takashi Iwaia961f9f2007-04-12 13:08:09 +02002797 for (i = 0; i < AC_PAR_PCM_RATE_BITS; i++)
Takashi Iwaibefdf312005-08-22 13:57:55 +02002798 if (rate_bits[i].hda_fmt == rate) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002799 if (val & (1 << i))
2800 break;
2801 return 0;
2802 }
Takashi Iwaia961f9f2007-04-12 13:08:09 +02002803 if (i >= AC_PAR_PCM_RATE_BITS)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002804 return 0;
2805
Takashi Iwai92c7c8a2009-03-24 07:32:14 +01002806 stream = query_stream_param(codec, nid);
2807 if (!stream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002808 return 0;
2809
2810 if (stream & AC_SUPFMT_PCM) {
2811 switch (format & 0xf0) {
2812 case 0x00:
Takashi Iwai0ba21762007-04-16 11:29:14 +02002813 if (!(val & AC_SUPPCM_BITS_8))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002814 return 0;
2815 break;
2816 case 0x10:
Takashi Iwai0ba21762007-04-16 11:29:14 +02002817 if (!(val & AC_SUPPCM_BITS_16))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002818 return 0;
2819 break;
2820 case 0x20:
Takashi Iwai0ba21762007-04-16 11:29:14 +02002821 if (!(val & AC_SUPPCM_BITS_20))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002822 return 0;
2823 break;
2824 case 0x30:
Takashi Iwai0ba21762007-04-16 11:29:14 +02002825 if (!(val & AC_SUPPCM_BITS_24))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002826 return 0;
2827 break;
2828 case 0x40:
Takashi Iwai0ba21762007-04-16 11:29:14 +02002829 if (!(val & AC_SUPPCM_BITS_32))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002830 return 0;
2831 break;
2832 default:
2833 return 0;
2834 }
2835 } else {
2836 /* FIXME: check for float32 and AC3? */
2837 }
2838
2839 return 1;
2840}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002841EXPORT_SYMBOL_HDA(snd_hda_is_supported_format);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002842
2843/*
2844 * PCM stuff
2845 */
2846static int hda_pcm_default_open_close(struct hda_pcm_stream *hinfo,
2847 struct hda_codec *codec,
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01002848 struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002849{
2850 return 0;
2851}
2852
2853static int hda_pcm_default_prepare(struct hda_pcm_stream *hinfo,
2854 struct hda_codec *codec,
2855 unsigned int stream_tag,
2856 unsigned int format,
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01002857 struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002858{
2859 snd_hda_codec_setup_stream(codec, hinfo->nid, stream_tag, 0, format);
2860 return 0;
2861}
2862
2863static int hda_pcm_default_cleanup(struct hda_pcm_stream *hinfo,
2864 struct hda_codec *codec,
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01002865 struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002866{
Takashi Iwai888afa12008-03-18 09:57:50 +01002867 snd_hda_codec_cleanup_stream(codec, hinfo->nid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002868 return 0;
2869}
2870
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02002871static int set_pcm_default_values(struct hda_codec *codec,
2872 struct hda_pcm_stream *info)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002873{
Jaroslav Kyselaee504712009-03-17 14:30:31 +01002874 int err;
2875
Takashi Iwai0ba21762007-04-16 11:29:14 +02002876 /* query support PCM information from the given NID */
2877 if (info->nid && (!info->rates || !info->formats)) {
Jaroslav Kyselaee504712009-03-17 14:30:31 +01002878 err = snd_hda_query_supported_pcm(codec, info->nid,
Takashi Iwai0ba21762007-04-16 11:29:14 +02002879 info->rates ? NULL : &info->rates,
2880 info->formats ? NULL : &info->formats,
2881 info->maxbps ? NULL : &info->maxbps);
Jaroslav Kyselaee504712009-03-17 14:30:31 +01002882 if (err < 0)
2883 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002884 }
2885 if (info->ops.open == NULL)
2886 info->ops.open = hda_pcm_default_open_close;
2887 if (info->ops.close == NULL)
2888 info->ops.close = hda_pcm_default_open_close;
2889 if (info->ops.prepare == 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.prepare = hda_pcm_default_prepare;
2893 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002894 if (info->ops.cleanup == NULL) {
Takashi Iwaida3cec32008-08-08 17:12:14 +02002895 if (snd_BUG_ON(!info->nid))
2896 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002897 info->ops.cleanup = hda_pcm_default_cleanup;
2898 }
2899 return 0;
2900}
2901
Jaroslav Kyselae3303232009-11-10 14:53:02 +01002902const char *snd_hda_pcm_type_name[HDA_PCM_NTYPES] = {
2903 "Audio", "SPDIF", "HDMI", "Modem"
2904};
2905
Takashi Iwai176d5332008-07-30 15:01:44 +02002906/*
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002907 * get the empty PCM device number to assign
2908 */
2909static int get_empty_pcm_device(struct hda_bus *bus, int type)
2910{
Wu Fengguangf5d6def2009-10-30 11:38:26 +01002911 /* audio device indices; not linear to keep compatibility */
2912 static int audio_idx[HDA_PCM_NTYPES][5] = {
2913 [HDA_PCM_TYPE_AUDIO] = { 0, 2, 4, 5, -1 },
2914 [HDA_PCM_TYPE_SPDIF] = { 1, -1 },
Wu Fengguang92608ba2009-10-30 11:40:03 +01002915 [HDA_PCM_TYPE_HDMI] = { 3, 7, 8, 9, -1 },
Wu Fengguangf5d6def2009-10-30 11:38:26 +01002916 [HDA_PCM_TYPE_MODEM] = { 6, -1 },
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002917 };
Wu Fengguangf5d6def2009-10-30 11:38:26 +01002918 int i;
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002919
Wu Fengguangf5d6def2009-10-30 11:38:26 +01002920 if (type >= HDA_PCM_NTYPES) {
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002921 snd_printk(KERN_WARNING "Invalid PCM type %d\n", type);
2922 return -EINVAL;
2923 }
Wu Fengguangf5d6def2009-10-30 11:38:26 +01002924
2925 for (i = 0; audio_idx[type][i] >= 0 ; i++)
2926 if (!test_and_set_bit(audio_idx[type][i], bus->pcm_dev_bits))
2927 return audio_idx[type][i];
2928
Jaroslav Kyselae3303232009-11-10 14:53:02 +01002929 snd_printk(KERN_WARNING "Too many %s devices\n", snd_hda_pcm_type_name[type]);
Wu Fengguangf5d6def2009-10-30 11:38:26 +01002930 return -EAGAIN;
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002931}
2932
2933/*
Takashi Iwai176d5332008-07-30 15:01:44 +02002934 * attach a new PCM stream
2935 */
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002936static int snd_hda_attach_pcm(struct hda_codec *codec, struct hda_pcm *pcm)
Takashi Iwai176d5332008-07-30 15:01:44 +02002937{
Takashi Iwai33fa35e2008-11-06 16:50:40 +01002938 struct hda_bus *bus = codec->bus;
Takashi Iwai176d5332008-07-30 15:01:44 +02002939 struct hda_pcm_stream *info;
2940 int stream, err;
2941
Takashi Iwaib91f0802008-11-04 08:43:08 +01002942 if (snd_BUG_ON(!pcm->name))
Takashi Iwai176d5332008-07-30 15:01:44 +02002943 return -EINVAL;
2944 for (stream = 0; stream < 2; stream++) {
2945 info = &pcm->stream[stream];
2946 if (info->substreams) {
2947 err = set_pcm_default_values(codec, info);
2948 if (err < 0)
2949 return err;
2950 }
2951 }
Takashi Iwai33fa35e2008-11-06 16:50:40 +01002952 return bus->ops.attach_pcm(bus, codec, pcm);
Takashi Iwai176d5332008-07-30 15:01:44 +02002953}
2954
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002955/* assign all PCMs of the given codec */
2956int snd_hda_codec_build_pcms(struct hda_codec *codec)
2957{
2958 unsigned int pcm;
2959 int err;
2960
2961 if (!codec->num_pcms) {
2962 if (!codec->patch_ops.build_pcms)
2963 return 0;
2964 err = codec->patch_ops.build_pcms(codec);
Takashi Iwai6e655bf2009-03-02 10:46:03 +01002965 if (err < 0) {
2966 printk(KERN_ERR "hda_codec: cannot build PCMs"
2967 "for #%d (error %d)\n", codec->addr, err);
2968 err = snd_hda_codec_reset(codec);
2969 if (err < 0) {
2970 printk(KERN_ERR
2971 "hda_codec: cannot revert codec\n");
2972 return err;
2973 }
2974 }
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002975 }
2976 for (pcm = 0; pcm < codec->num_pcms; pcm++) {
2977 struct hda_pcm *cpcm = &codec->pcm_info[pcm];
2978 int dev;
2979
2980 if (!cpcm->stream[0].substreams && !cpcm->stream[1].substreams)
Takashi Iwai41b5b012009-01-20 18:21:23 +01002981 continue; /* no substreams assigned */
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002982
2983 if (!cpcm->pcm) {
2984 dev = get_empty_pcm_device(codec->bus, cpcm->pcm_type);
2985 if (dev < 0)
Takashi Iwai6e655bf2009-03-02 10:46:03 +01002986 continue; /* no fatal error */
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002987 cpcm->device = dev;
2988 err = snd_hda_attach_pcm(codec, cpcm);
Takashi Iwai6e655bf2009-03-02 10:46:03 +01002989 if (err < 0) {
2990 printk(KERN_ERR "hda_codec: cannot attach "
2991 "PCM stream %d for codec #%d\n",
2992 dev, codec->addr);
2993 continue; /* no fatal error */
2994 }
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002995 }
2996 }
2997 return 0;
2998}
2999
Linus Torvalds1da177e2005-04-16 15:20:36 -07003000/**
3001 * snd_hda_build_pcms - build PCM information
3002 * @bus: the BUS
3003 *
3004 * Create PCM information for each codec included in the bus.
3005 *
3006 * The build_pcms codec patch is requested to set up codec->num_pcms and
3007 * codec->pcm_info properly. The array is referred by the top-level driver
3008 * to create its PCM instances.
3009 * The allocated codec->pcm_info should be released in codec->patch_ops.free
3010 * callback.
3011 *
3012 * At least, substreams, channels_min and channels_max must be filled for
3013 * each stream. substreams = 0 indicates that the stream doesn't exist.
3014 * When rates and/or formats are zero, the supported values are queried
3015 * from the given nid. The nid is used also by the default ops.prepare
3016 * and ops.cleanup callbacks.
3017 *
3018 * The driver needs to call ops.open in its open callback. Similarly,
3019 * ops.close is supposed to be called in the close callback.
3020 * ops.prepare should be called in the prepare or hw_params callback
3021 * with the proper parameters for set up.
3022 * ops.cleanup should be called in hw_free for clean up of streams.
3023 *
3024 * This function returns 0 if successfull, or a negative error code.
3025 */
Takashi Iwai529bd6c2008-11-27 14:17:01 +01003026int __devinit snd_hda_build_pcms(struct hda_bus *bus)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003027{
Takashi Iwai0ba21762007-04-16 11:29:14 +02003028 struct hda_codec *codec;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003029
Takashi Iwai0ba21762007-04-16 11:29:14 +02003030 list_for_each_entry(codec, &bus->codec_list, list) {
Takashi Iwai529bd6c2008-11-27 14:17:01 +01003031 int err = snd_hda_codec_build_pcms(codec);
3032 if (err < 0)
3033 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003034 }
3035 return 0;
3036}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003037EXPORT_SYMBOL_HDA(snd_hda_build_pcms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003038
Linus Torvalds1da177e2005-04-16 15:20:36 -07003039/**
3040 * snd_hda_check_board_config - compare the current codec with the config table
3041 * @codec: the HDA codec
Takashi Iwaif5fcc132006-11-24 17:07:44 +01003042 * @num_configs: number of config enums
3043 * @models: array of model name strings
Linus Torvalds1da177e2005-04-16 15:20:36 -07003044 * @tbl: configuration table, terminated by null entries
3045 *
3046 * Compares the modelname or PCI subsystem id of the current codec with the
3047 * given configuration table. If a matching entry is found, returns its
3048 * config value (supposed to be 0 or positive).
3049 *
3050 * If no entries are matching, the function returns a negative value.
3051 */
Takashi Iwai12f288b2007-08-02 15:51:59 +02003052int snd_hda_check_board_config(struct hda_codec *codec,
3053 int num_configs, const char **models,
3054 const struct snd_pci_quirk *tbl)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003055{
Takashi Iwaif44ac832008-07-30 15:01:45 +02003056 if (codec->modelname && models) {
Takashi Iwaif5fcc132006-11-24 17:07:44 +01003057 int i;
3058 for (i = 0; i < num_configs; i++) {
3059 if (models[i] &&
Takashi Iwaif44ac832008-07-30 15:01:45 +02003060 !strcmp(codec->modelname, models[i])) {
Takashi Iwaif5fcc132006-11-24 17:07:44 +01003061 snd_printd(KERN_INFO "hda_codec: model '%s' is "
3062 "selected\n", models[i]);
3063 return i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003064 }
3065 }
3066 }
3067
Takashi Iwaif5fcc132006-11-24 17:07:44 +01003068 if (!codec->bus->pci || !tbl)
3069 return -1;
3070
3071 tbl = snd_pci_quirk_lookup(codec->bus->pci, tbl);
3072 if (!tbl)
3073 return -1;
3074 if (tbl->value >= 0 && tbl->value < num_configs) {
Takashi Iwai62cf8722008-05-20 12:15:15 +02003075#ifdef CONFIG_SND_DEBUG_VERBOSE
Takashi Iwaif5fcc132006-11-24 17:07:44 +01003076 char tmp[10];
3077 const char *model = NULL;
3078 if (models)
3079 model = models[tbl->value];
3080 if (!model) {
3081 sprintf(tmp, "#%d", tbl->value);
3082 model = tmp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003083 }
Takashi Iwaif5fcc132006-11-24 17:07:44 +01003084 snd_printdd(KERN_INFO "hda_codec: model '%s' is selected "
3085 "for config %x:%x (%s)\n",
3086 model, tbl->subvendor, tbl->subdevice,
3087 (tbl->name ? tbl->name : "Unknown device"));
3088#endif
3089 return tbl->value;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003090 }
3091 return -1;
3092}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003093EXPORT_SYMBOL_HDA(snd_hda_check_board_config);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003094
3095/**
Mauro Carvalho Chehab2eda3442008-08-11 10:18:39 +02003096 * snd_hda_check_board_codec_sid_config - compare the current codec
3097 subsystem ID with the
3098 config table
3099
3100 This is important for Gateway notebooks with SB450 HDA Audio
3101 where the vendor ID of the PCI device is:
3102 ATI Technologies Inc SB450 HDA Audio [1002:437b]
3103 and the vendor/subvendor are found only at the codec.
3104
3105 * @codec: the HDA codec
3106 * @num_configs: number of config enums
3107 * @models: array of model name strings
3108 * @tbl: configuration table, terminated by null entries
3109 *
3110 * Compares the modelname or PCI subsystem id of the current codec with the
3111 * given configuration table. If a matching entry is found, returns its
3112 * config value (supposed to be 0 or positive).
3113 *
3114 * If no entries are matching, the function returns a negative value.
3115 */
3116int snd_hda_check_board_codec_sid_config(struct hda_codec *codec,
3117 int num_configs, const char **models,
3118 const struct snd_pci_quirk *tbl)
3119{
3120 const struct snd_pci_quirk *q;
3121
3122 /* Search for codec ID */
3123 for (q = tbl; q->subvendor; q++) {
3124 unsigned long vendorid = (q->subdevice) | (q->subvendor << 16);
3125
3126 if (vendorid == codec->subsystem_id)
3127 break;
3128 }
3129
3130 if (!q->subvendor)
3131 return -1;
3132
3133 tbl = q;
3134
3135 if (tbl->value >= 0 && tbl->value < num_configs) {
Takashi Iwaid94ff6b2009-09-02 00:20:21 +02003136#ifdef CONFIG_SND_DEBUG_VERBOSE
Mauro Carvalho Chehab2eda3442008-08-11 10:18:39 +02003137 char tmp[10];
3138 const char *model = NULL;
3139 if (models)
3140 model = models[tbl->value];
3141 if (!model) {
3142 sprintf(tmp, "#%d", tbl->value);
3143 model = tmp;
3144 }
3145 snd_printdd(KERN_INFO "hda_codec: model '%s' is selected "
3146 "for config %x:%x (%s)\n",
3147 model, tbl->subvendor, tbl->subdevice,
3148 (tbl->name ? tbl->name : "Unknown device"));
3149#endif
3150 return tbl->value;
3151 }
3152 return -1;
3153}
3154EXPORT_SYMBOL_HDA(snd_hda_check_board_codec_sid_config);
3155
3156/**
Linus Torvalds1da177e2005-04-16 15:20:36 -07003157 * snd_hda_add_new_ctls - create controls from the array
3158 * @codec: the HDA codec
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01003159 * @knew: the array of struct snd_kcontrol_new
Linus Torvalds1da177e2005-04-16 15:20:36 -07003160 *
3161 * This helper function creates and add new controls in the given array.
3162 * The array must be terminated with an empty entry as terminator.
3163 *
3164 * Returns 0 if successful, or a negative error code.
3165 */
Takashi Iwai12f288b2007-08-02 15:51:59 +02003166int snd_hda_add_new_ctls(struct hda_codec *codec, struct snd_kcontrol_new *knew)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003167{
Jaroslav Kysela4d02d1b2009-11-12 10:15:48 +01003168 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003169
3170 for (; knew->name; knew++) {
Takashi Iwai54d17402005-11-21 16:33:22 +01003171 struct snd_kcontrol *kctl;
3172 kctl = snd_ctl_new1(knew, codec);
Takashi Iwai0ba21762007-04-16 11:29:14 +02003173 if (!kctl)
Takashi Iwai54d17402005-11-21 16:33:22 +01003174 return -ENOMEM;
Jaroslav Kysela3911a4c2009-11-11 13:43:01 +01003175 err = snd_hda_ctl_add(codec, 0, kctl);
Takashi Iwai54d17402005-11-21 16:33:22 +01003176 if (err < 0) {
Takashi Iwai0ba21762007-04-16 11:29:14 +02003177 if (!codec->addr)
Takashi Iwai54d17402005-11-21 16:33:22 +01003178 return err;
3179 kctl = snd_ctl_new1(knew, codec);
Takashi Iwai0ba21762007-04-16 11:29:14 +02003180 if (!kctl)
Takashi Iwai54d17402005-11-21 16:33:22 +01003181 return -ENOMEM;
3182 kctl->id.device = codec->addr;
Jaroslav Kysela3911a4c2009-11-11 13:43:01 +01003183 err = snd_hda_ctl_add(codec, 0, kctl);
Takashi Iwai0ba21762007-04-16 11:29:14 +02003184 if (err < 0)
Takashi Iwai54d17402005-11-21 16:33:22 +01003185 return err;
3186 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003187 }
3188 return 0;
3189}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003190EXPORT_SYMBOL_HDA(snd_hda_add_new_ctls);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003191
Takashi Iwaicb53c622007-08-10 17:21:45 +02003192#ifdef CONFIG_SND_HDA_POWER_SAVE
3193static void hda_set_power_state(struct hda_codec *codec, hda_nid_t fg,
3194 unsigned int power_state);
3195
3196static void hda_power_work(struct work_struct *work)
3197{
3198 struct hda_codec *codec =
3199 container_of(work, struct hda_codec, power_work.work);
Takashi Iwai33fa35e2008-11-06 16:50:40 +01003200 struct hda_bus *bus = codec->bus;
Takashi Iwaicb53c622007-08-10 17:21:45 +02003201
Maxim Levitsky2e492462007-09-03 15:26:57 +02003202 if (!codec->power_on || codec->power_count) {
3203 codec->power_transition = 0;
Takashi Iwaicb53c622007-08-10 17:21:45 +02003204 return;
Maxim Levitsky2e492462007-09-03 15:26:57 +02003205 }
Takashi Iwaicb53c622007-08-10 17:21:45 +02003206
3207 hda_call_codec_suspend(codec);
Takashi Iwai33fa35e2008-11-06 16:50:40 +01003208 if (bus->ops.pm_notify)
3209 bus->ops.pm_notify(bus);
Takashi Iwaicb53c622007-08-10 17:21:45 +02003210}
3211
3212static void hda_keep_power_on(struct hda_codec *codec)
3213{
3214 codec->power_count++;
3215 codec->power_on = 1;
Takashi Iwaia2f63092009-11-11 09:34:25 +01003216 codec->power_jiffies = jiffies;
3217}
3218
3219void snd_hda_update_power_acct(struct hda_codec *codec)
3220{
3221 unsigned long delta = jiffies - codec->power_jiffies;
3222 if (codec->power_on)
3223 codec->power_on_acct += delta;
3224 else
3225 codec->power_off_acct += delta;
3226 codec->power_jiffies += delta;
Takashi Iwaicb53c622007-08-10 17:21:45 +02003227}
3228
3229void snd_hda_power_up(struct hda_codec *codec)
3230{
Takashi Iwai33fa35e2008-11-06 16:50:40 +01003231 struct hda_bus *bus = codec->bus;
3232
Takashi Iwaicb53c622007-08-10 17:21:45 +02003233 codec->power_count++;
Takashi Iwaia221e282007-08-16 16:35:33 +02003234 if (codec->power_on || codec->power_transition)
Takashi Iwaicb53c622007-08-10 17:21:45 +02003235 return;
3236
Takashi Iwaia2f63092009-11-11 09:34:25 +01003237 snd_hda_update_power_acct(codec);
Takashi Iwaicb53c622007-08-10 17:21:45 +02003238 codec->power_on = 1;
Takashi Iwaia2f63092009-11-11 09:34:25 +01003239 codec->power_jiffies = jiffies;
Takashi Iwai33fa35e2008-11-06 16:50:40 +01003240 if (bus->ops.pm_notify)
3241 bus->ops.pm_notify(bus);
Takashi Iwaicb53c622007-08-10 17:21:45 +02003242 hda_call_codec_resume(codec);
3243 cancel_delayed_work(&codec->power_work);
Takashi Iwaia221e282007-08-16 16:35:33 +02003244 codec->power_transition = 0;
Takashi Iwaicb53c622007-08-10 17:21:45 +02003245}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003246EXPORT_SYMBOL_HDA(snd_hda_power_up);
Takashi Iwai1289e9e2008-11-27 15:47:11 +01003247
3248#define power_save(codec) \
3249 ((codec)->bus->power_save ? *(codec)->bus->power_save : 0)
Takashi Iwaicb53c622007-08-10 17:21:45 +02003250
Takashi Iwaifee2fba2008-11-27 12:43:28 +01003251#define power_save(codec) \
3252 ((codec)->bus->power_save ? *(codec)->bus->power_save : 0)
3253
Takashi Iwaicb53c622007-08-10 17:21:45 +02003254void snd_hda_power_down(struct hda_codec *codec)
3255{
3256 --codec->power_count;
Takashi Iwaia221e282007-08-16 16:35:33 +02003257 if (!codec->power_on || codec->power_count || codec->power_transition)
Takashi Iwaicb53c622007-08-10 17:21:45 +02003258 return;
Takashi Iwaifee2fba2008-11-27 12:43:28 +01003259 if (power_save(codec)) {
Takashi Iwaia221e282007-08-16 16:35:33 +02003260 codec->power_transition = 1; /* avoid reentrance */
Takashi Iwaic107b412009-01-13 17:46:37 +01003261 queue_delayed_work(codec->bus->workq, &codec->power_work,
Takashi Iwaifee2fba2008-11-27 12:43:28 +01003262 msecs_to_jiffies(power_save(codec) * 1000));
Takashi Iwaia221e282007-08-16 16:35:33 +02003263 }
Takashi Iwaicb53c622007-08-10 17:21:45 +02003264}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003265EXPORT_SYMBOL_HDA(snd_hda_power_down);
Takashi Iwaicb53c622007-08-10 17:21:45 +02003266
3267int snd_hda_check_amp_list_power(struct hda_codec *codec,
3268 struct hda_loopback_check *check,
3269 hda_nid_t nid)
3270{
3271 struct hda_amp_list *p;
3272 int ch, v;
3273
3274 if (!check->amplist)
3275 return 0;
3276 for (p = check->amplist; p->nid; p++) {
3277 if (p->nid == nid)
3278 break;
3279 }
3280 if (!p->nid)
3281 return 0; /* nothing changed */
3282
3283 for (p = check->amplist; p->nid; p++) {
3284 for (ch = 0; ch < 2; ch++) {
3285 v = snd_hda_codec_amp_read(codec, p->nid, ch, p->dir,
3286 p->idx);
3287 if (!(v & HDA_AMP_MUTE) && v > 0) {
3288 if (!check->power_on) {
3289 check->power_on = 1;
3290 snd_hda_power_up(codec);
3291 }
3292 return 1;
3293 }
3294 }
3295 }
3296 if (check->power_on) {
3297 check->power_on = 0;
3298 snd_hda_power_down(codec);
3299 }
3300 return 0;
3301}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003302EXPORT_SYMBOL_HDA(snd_hda_check_amp_list_power);
Takashi Iwaicb53c622007-08-10 17:21:45 +02003303#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07003304
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01003305/*
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01003306 * Channel mode helper
3307 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003308int snd_hda_ch_mode_info(struct hda_codec *codec,
3309 struct snd_ctl_elem_info *uinfo,
3310 const struct hda_channel_mode *chmode,
3311 int num_chmodes)
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01003312{
3313 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
3314 uinfo->count = 1;
3315 uinfo->value.enumerated.items = num_chmodes;
3316 if (uinfo->value.enumerated.item >= num_chmodes)
3317 uinfo->value.enumerated.item = num_chmodes - 1;
3318 sprintf(uinfo->value.enumerated.name, "%dch",
3319 chmode[uinfo->value.enumerated.item].channels);
3320 return 0;
3321}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003322EXPORT_SYMBOL_HDA(snd_hda_ch_mode_info);
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01003323
Takashi Iwai0ba21762007-04-16 11:29:14 +02003324int snd_hda_ch_mode_get(struct hda_codec *codec,
3325 struct snd_ctl_elem_value *ucontrol,
3326 const struct hda_channel_mode *chmode,
3327 int num_chmodes,
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01003328 int max_channels)
3329{
3330 int i;
3331
3332 for (i = 0; i < num_chmodes; i++) {
3333 if (max_channels == chmode[i].channels) {
3334 ucontrol->value.enumerated.item[0] = i;
3335 break;
3336 }
3337 }
3338 return 0;
3339}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003340EXPORT_SYMBOL_HDA(snd_hda_ch_mode_get);
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01003341
Takashi Iwai0ba21762007-04-16 11:29:14 +02003342int snd_hda_ch_mode_put(struct hda_codec *codec,
3343 struct snd_ctl_elem_value *ucontrol,
3344 const struct hda_channel_mode *chmode,
3345 int num_chmodes,
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01003346 int *max_channelsp)
3347{
3348 unsigned int mode;
3349
3350 mode = ucontrol->value.enumerated.item[0];
Takashi Iwai68ea7b22007-11-15 15:54:38 +01003351 if (mode >= num_chmodes)
3352 return -EINVAL;
Takashi Iwai82beb8f2007-08-10 17:09:26 +02003353 if (*max_channelsp == chmode[mode].channels)
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01003354 return 0;
3355 /* change the current channel setting */
3356 *max_channelsp = chmode[mode].channels;
3357 if (chmode[mode].sequence)
Takashi Iwai82beb8f2007-08-10 17:09:26 +02003358 snd_hda_sequence_write_cache(codec, chmode[mode].sequence);
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01003359 return 1;
3360}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003361EXPORT_SYMBOL_HDA(snd_hda_ch_mode_put);
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01003362
Linus Torvalds1da177e2005-04-16 15:20:36 -07003363/*
3364 * input MUX helper
3365 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003366int snd_hda_input_mux_info(const struct hda_input_mux *imux,
3367 struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003368{
3369 unsigned int index;
3370
3371 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
3372 uinfo->count = 1;
3373 uinfo->value.enumerated.items = imux->num_items;
Takashi Iwai5513b0c2007-10-09 11:58:41 +02003374 if (!imux->num_items)
3375 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003376 index = uinfo->value.enumerated.item;
3377 if (index >= imux->num_items)
3378 index = imux->num_items - 1;
3379 strcpy(uinfo->value.enumerated.name, imux->items[index].label);
3380 return 0;
3381}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003382EXPORT_SYMBOL_HDA(snd_hda_input_mux_info);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003383
Takashi Iwai0ba21762007-04-16 11:29:14 +02003384int snd_hda_input_mux_put(struct hda_codec *codec,
3385 const struct hda_input_mux *imux,
3386 struct snd_ctl_elem_value *ucontrol,
3387 hda_nid_t nid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003388 unsigned int *cur_val)
3389{
3390 unsigned int idx;
3391
Takashi Iwai5513b0c2007-10-09 11:58:41 +02003392 if (!imux->num_items)
3393 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003394 idx = ucontrol->value.enumerated.item[0];
3395 if (idx >= imux->num_items)
3396 idx = imux->num_items - 1;
Takashi Iwai82beb8f2007-08-10 17:09:26 +02003397 if (*cur_val == idx)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003398 return 0;
Takashi Iwai82beb8f2007-08-10 17:09:26 +02003399 snd_hda_codec_write_cache(codec, nid, 0, AC_VERB_SET_CONNECT_SEL,
3400 imux->items[idx].index);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003401 *cur_val = idx;
3402 return 1;
3403}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003404EXPORT_SYMBOL_HDA(snd_hda_input_mux_put);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003405
3406
3407/*
3408 * Multi-channel / digital-out PCM helper functions
3409 */
3410
Takashi Iwai6b97eb42007-04-05 14:51:48 +02003411/* setup SPDIF output stream */
3412static void setup_dig_out_stream(struct hda_codec *codec, hda_nid_t nid,
3413 unsigned int stream_tag, unsigned int format)
3414{
3415 /* turn off SPDIF once; otherwise the IEC958 bits won't be updated */
Takashi Iwai2f728532008-09-25 16:32:41 +02003416 if (codec->spdif_status_reset && (codec->spdif_ctls & AC_DIG1_ENABLE))
3417 set_dig_out_convert(codec, nid,
3418 codec->spdif_ctls & ~AC_DIG1_ENABLE & 0xff,
3419 -1);
Takashi Iwai6b97eb42007-04-05 14:51:48 +02003420 snd_hda_codec_setup_stream(codec, nid, stream_tag, 0, format);
Takashi Iwai2f728532008-09-25 16:32:41 +02003421 if (codec->slave_dig_outs) {
3422 hda_nid_t *d;
3423 for (d = codec->slave_dig_outs; *d; d++)
3424 snd_hda_codec_setup_stream(codec, *d, stream_tag, 0,
3425 format);
Matthew Ranostayde51ca12008-09-07 14:31:40 -04003426 }
Takashi Iwai2f728532008-09-25 16:32:41 +02003427 /* turn on again (if needed) */
3428 if (codec->spdif_status_reset && (codec->spdif_ctls & AC_DIG1_ENABLE))
3429 set_dig_out_convert(codec, nid,
3430 codec->spdif_ctls & 0xff, -1);
3431}
Matthew Ranostayde51ca12008-09-07 14:31:40 -04003432
Takashi Iwai2f728532008-09-25 16:32:41 +02003433static void cleanup_dig_out_stream(struct hda_codec *codec, hda_nid_t nid)
3434{
3435 snd_hda_codec_cleanup_stream(codec, nid);
3436 if (codec->slave_dig_outs) {
3437 hda_nid_t *d;
3438 for (d = codec->slave_dig_outs; *d; d++)
3439 snd_hda_codec_cleanup_stream(codec, *d);
3440 }
Takashi Iwai6b97eb42007-04-05 14:51:48 +02003441}
3442
Takashi Iwaifb8d1a32009-11-10 16:02:29 +01003443/* call each reboot notifier */
3444void snd_hda_bus_reboot_notify(struct hda_bus *bus)
3445{
3446 struct hda_codec *codec;
3447
3448 if (!bus)
3449 return;
3450 list_for_each_entry(codec, &bus->codec_list, list) {
3451#ifdef CONFIG_SND_HDA_POWER_SAVE
3452 if (!codec->power_on)
3453 continue;
3454#endif
3455 if (codec->patch_ops.reboot_notify)
3456 codec->patch_ops.reboot_notify(codec);
3457 }
3458}
Takashi Iwai8f217a22009-11-10 18:26:12 +01003459EXPORT_SYMBOL_HDA(snd_hda_bus_reboot_notify);
Takashi Iwaifb8d1a32009-11-10 16:02:29 +01003460
Linus Torvalds1da177e2005-04-16 15:20:36 -07003461/*
3462 * open the digital out in the exclusive mode
3463 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003464int snd_hda_multi_out_dig_open(struct hda_codec *codec,
3465 struct hda_multi_out *mout)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003466{
Ingo Molnar62932df2006-01-16 16:34:20 +01003467 mutex_lock(&codec->spdif_mutex);
Takashi Iwai5930ca42007-04-16 11:23:56 +02003468 if (mout->dig_out_used == HDA_DIG_ANALOG_DUP)
3469 /* already opened as analog dup; reset it once */
Takashi Iwai2f728532008-09-25 16:32:41 +02003470 cleanup_dig_out_stream(codec, mout->dig_out_nid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003471 mout->dig_out_used = HDA_DIG_EXCLUSIVE;
Ingo Molnar62932df2006-01-16 16:34:20 +01003472 mutex_unlock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003473 return 0;
3474}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003475EXPORT_SYMBOL_HDA(snd_hda_multi_out_dig_open);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003476
Takashi Iwai6b97eb42007-04-05 14:51:48 +02003477int snd_hda_multi_out_dig_prepare(struct hda_codec *codec,
3478 struct hda_multi_out *mout,
3479 unsigned int stream_tag,
3480 unsigned int format,
3481 struct snd_pcm_substream *substream)
3482{
3483 mutex_lock(&codec->spdif_mutex);
3484 setup_dig_out_stream(codec, mout->dig_out_nid, stream_tag, format);
3485 mutex_unlock(&codec->spdif_mutex);
3486 return 0;
3487}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003488EXPORT_SYMBOL_HDA(snd_hda_multi_out_dig_prepare);
Takashi Iwai6b97eb42007-04-05 14:51:48 +02003489
Takashi Iwai9411e212009-02-13 11:32:28 +01003490int snd_hda_multi_out_dig_cleanup(struct hda_codec *codec,
3491 struct hda_multi_out *mout)
3492{
3493 mutex_lock(&codec->spdif_mutex);
3494 cleanup_dig_out_stream(codec, mout->dig_out_nid);
3495 mutex_unlock(&codec->spdif_mutex);
3496 return 0;
3497}
3498EXPORT_SYMBOL_HDA(snd_hda_multi_out_dig_cleanup);
3499
Linus Torvalds1da177e2005-04-16 15:20:36 -07003500/*
3501 * release the digital out
3502 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003503int snd_hda_multi_out_dig_close(struct hda_codec *codec,
3504 struct hda_multi_out *mout)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003505{
Ingo Molnar62932df2006-01-16 16:34:20 +01003506 mutex_lock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003507 mout->dig_out_used = 0;
Ingo Molnar62932df2006-01-16 16:34:20 +01003508 mutex_unlock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003509 return 0;
3510}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003511EXPORT_SYMBOL_HDA(snd_hda_multi_out_dig_close);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003512
3513/*
3514 * set up more restrictions for analog out
3515 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003516int snd_hda_multi_out_analog_open(struct hda_codec *codec,
3517 struct hda_multi_out *mout,
Takashi Iwai9a081602008-02-12 18:37:26 +01003518 struct snd_pcm_substream *substream,
3519 struct hda_pcm_stream *hinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003520{
Takashi Iwai9a081602008-02-12 18:37:26 +01003521 struct snd_pcm_runtime *runtime = substream->runtime;
3522 runtime->hw.channels_max = mout->max_channels;
3523 if (mout->dig_out_nid) {
3524 if (!mout->analog_rates) {
3525 mout->analog_rates = hinfo->rates;
3526 mout->analog_formats = hinfo->formats;
3527 mout->analog_maxbps = hinfo->maxbps;
3528 } else {
3529 runtime->hw.rates = mout->analog_rates;
3530 runtime->hw.formats = mout->analog_formats;
3531 hinfo->maxbps = mout->analog_maxbps;
3532 }
3533 if (!mout->spdif_rates) {
3534 snd_hda_query_supported_pcm(codec, mout->dig_out_nid,
3535 &mout->spdif_rates,
3536 &mout->spdif_formats,
3537 &mout->spdif_maxbps);
3538 }
3539 mutex_lock(&codec->spdif_mutex);
3540 if (mout->share_spdif) {
Takashi Iwai022b4662009-07-03 23:03:30 +02003541 if ((runtime->hw.rates & mout->spdif_rates) &&
3542 (runtime->hw.formats & mout->spdif_formats)) {
3543 runtime->hw.rates &= mout->spdif_rates;
3544 runtime->hw.formats &= mout->spdif_formats;
3545 if (mout->spdif_maxbps < hinfo->maxbps)
3546 hinfo->maxbps = mout->spdif_maxbps;
3547 } else {
3548 mout->share_spdif = 0;
3549 /* FIXME: need notify? */
3550 }
Takashi Iwai9a081602008-02-12 18:37:26 +01003551 }
Frederik Deweerdteaa99852008-04-14 13:11:44 +02003552 mutex_unlock(&codec->spdif_mutex);
Takashi Iwai9a081602008-02-12 18:37:26 +01003553 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003554 return snd_pcm_hw_constraint_step(substream->runtime, 0,
3555 SNDRV_PCM_HW_PARAM_CHANNELS, 2);
3556}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003557EXPORT_SYMBOL_HDA(snd_hda_multi_out_analog_open);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003558
3559/*
3560 * set up the i/o for analog out
3561 * when the digital out is available, copy the front out to digital out, too.
3562 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003563int snd_hda_multi_out_analog_prepare(struct hda_codec *codec,
3564 struct hda_multi_out *mout,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003565 unsigned int stream_tag,
3566 unsigned int format,
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01003567 struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003568{
3569 hda_nid_t *nids = mout->dac_nids;
3570 int chs = substream->runtime->channels;
3571 int i;
3572
Ingo Molnar62932df2006-01-16 16:34:20 +01003573 mutex_lock(&codec->spdif_mutex);
Takashi Iwai9a081602008-02-12 18:37:26 +01003574 if (mout->dig_out_nid && mout->share_spdif &&
3575 mout->dig_out_used != HDA_DIG_EXCLUSIVE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003576 if (chs == 2 &&
Takashi Iwai0ba21762007-04-16 11:29:14 +02003577 snd_hda_is_supported_format(codec, mout->dig_out_nid,
3578 format) &&
3579 !(codec->spdif_status & IEC958_AES0_NONAUDIO)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003580 mout->dig_out_used = HDA_DIG_ANALOG_DUP;
Takashi Iwai6b97eb42007-04-05 14:51:48 +02003581 setup_dig_out_stream(codec, mout->dig_out_nid,
3582 stream_tag, format);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003583 } else {
3584 mout->dig_out_used = 0;
Takashi Iwai2f728532008-09-25 16:32:41 +02003585 cleanup_dig_out_stream(codec, mout->dig_out_nid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003586 }
3587 }
Ingo Molnar62932df2006-01-16 16:34:20 +01003588 mutex_unlock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003589
3590 /* front */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003591 snd_hda_codec_setup_stream(codec, nids[HDA_FRONT], stream_tag,
3592 0, format);
Takashi Iwaid29240c2007-10-26 12:35:56 +02003593 if (!mout->no_share_stream &&
3594 mout->hp_nid && mout->hp_nid != nids[HDA_FRONT])
Linus Torvalds1da177e2005-04-16 15:20:36 -07003595 /* headphone out will just decode front left/right (stereo) */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003596 snd_hda_codec_setup_stream(codec, mout->hp_nid, stream_tag,
3597 0, format);
Takashi Iwai82bc9552006-03-21 11:24:42 +01003598 /* extra outputs copied from front */
3599 for (i = 0; i < ARRAY_SIZE(mout->extra_out_nid); i++)
Takashi Iwaid29240c2007-10-26 12:35:56 +02003600 if (!mout->no_share_stream && mout->extra_out_nid[i])
Takashi Iwai82bc9552006-03-21 11:24:42 +01003601 snd_hda_codec_setup_stream(codec,
3602 mout->extra_out_nid[i],
3603 stream_tag, 0, format);
3604
Linus Torvalds1da177e2005-04-16 15:20:36 -07003605 /* surrounds */
3606 for (i = 1; i < mout->num_dacs; i++) {
Takashi Iwai4b3acaf2005-06-10 19:48:10 +02003607 if (chs >= (i + 1) * 2) /* independent out */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003608 snd_hda_codec_setup_stream(codec, nids[i], stream_tag,
3609 i * 2, format);
Takashi Iwaid29240c2007-10-26 12:35:56 +02003610 else if (!mout->no_share_stream) /* copy front */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003611 snd_hda_codec_setup_stream(codec, nids[i], stream_tag,
3612 0, format);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003613 }
3614 return 0;
3615}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003616EXPORT_SYMBOL_HDA(snd_hda_multi_out_analog_prepare);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003617
3618/*
3619 * clean up the setting for analog out
3620 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003621int snd_hda_multi_out_analog_cleanup(struct hda_codec *codec,
3622 struct hda_multi_out *mout)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003623{
3624 hda_nid_t *nids = mout->dac_nids;
3625 int i;
3626
3627 for (i = 0; i < mout->num_dacs; i++)
Takashi Iwai888afa12008-03-18 09:57:50 +01003628 snd_hda_codec_cleanup_stream(codec, nids[i]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003629 if (mout->hp_nid)
Takashi Iwai888afa12008-03-18 09:57:50 +01003630 snd_hda_codec_cleanup_stream(codec, mout->hp_nid);
Takashi Iwai82bc9552006-03-21 11:24:42 +01003631 for (i = 0; i < ARRAY_SIZE(mout->extra_out_nid); i++)
3632 if (mout->extra_out_nid[i])
Takashi Iwai888afa12008-03-18 09:57:50 +01003633 snd_hda_codec_cleanup_stream(codec,
3634 mout->extra_out_nid[i]);
Ingo Molnar62932df2006-01-16 16:34:20 +01003635 mutex_lock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003636 if (mout->dig_out_nid && mout->dig_out_used == HDA_DIG_ANALOG_DUP) {
Takashi Iwai2f728532008-09-25 16:32:41 +02003637 cleanup_dig_out_stream(codec, mout->dig_out_nid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003638 mout->dig_out_used = 0;
3639 }
Ingo Molnar62932df2006-01-16 16:34:20 +01003640 mutex_unlock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003641 return 0;
3642}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003643EXPORT_SYMBOL_HDA(snd_hda_multi_out_analog_cleanup);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003644
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003645/*
Wu Fengguang6b345002008-10-07 14:21:41 +08003646 * Helper for automatic pin configuration
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003647 */
Kailang Yangdf694da2005-12-05 19:42:22 +01003648
Takashi Iwai12f288b2007-08-02 15:51:59 +02003649static int is_in_nid_list(hda_nid_t nid, hda_nid_t *list)
Kailang Yangdf694da2005-12-05 19:42:22 +01003650{
3651 for (; *list; list++)
3652 if (*list == nid)
3653 return 1;
3654 return 0;
3655}
3656
Steve Longerbeam81937d32007-05-08 15:33:03 +02003657
3658/*
3659 * Sort an associated group of pins according to their sequence numbers.
3660 */
3661static void sort_pins_by_sequence(hda_nid_t * pins, short * sequences,
3662 int num_pins)
3663{
3664 int i, j;
3665 short seq;
3666 hda_nid_t nid;
3667
3668 for (i = 0; i < num_pins; i++) {
3669 for (j = i + 1; j < num_pins; j++) {
3670 if (sequences[i] > sequences[j]) {
3671 seq = sequences[i];
3672 sequences[i] = sequences[j];
3673 sequences[j] = seq;
3674 nid = pins[i];
3675 pins[i] = pins[j];
3676 pins[j] = nid;
3677 }
3678 }
3679 }
3680}
3681
3682
Takashi Iwai82bc9552006-03-21 11:24:42 +01003683/*
3684 * Parse all pin widgets and store the useful pin nids to cfg
3685 *
3686 * The number of line-outs or any primary output is stored in line_outs,
3687 * and the corresponding output pins are assigned to line_out_pins[],
3688 * in the order of front, rear, CLFE, side, ...
3689 *
3690 * If more extra outputs (speaker and headphone) are found, the pins are
Takashi Iwaieb06ed82006-09-20 17:10:27 +02003691 * assisnged to hp_pins[] and speaker_pins[], respectively. If no line-out jack
Takashi Iwai82bc9552006-03-21 11:24:42 +01003692 * is detected, one of speaker of HP pins is assigned as the primary
3693 * output, i.e. to line_out_pins[0]. So, line_outs is always positive
3694 * if any analog output exists.
3695 *
3696 * The analog input pins are assigned to input_pins array.
3697 * The digital input/output pins are assigned to dig_in_pin and dig_out_pin,
3698 * respectively.
3699 */
Takashi Iwai12f288b2007-08-02 15:51:59 +02003700int snd_hda_parse_pin_def_config(struct hda_codec *codec,
3701 struct auto_pin_cfg *cfg,
3702 hda_nid_t *ignore_nids)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003703{
Takashi Iwai0ef6ce72008-01-22 15:35:37 +01003704 hda_nid_t nid, end_nid;
Steve Longerbeam81937d32007-05-08 15:33:03 +02003705 short seq, assoc_line_out, assoc_speaker;
3706 short sequences_line_out[ARRAY_SIZE(cfg->line_out_pins)];
3707 short sequences_speaker[ARRAY_SIZE(cfg->speaker_pins)];
Takashi Iwaif889fa92007-10-31 15:49:32 +01003708 short sequences_hp[ARRAY_SIZE(cfg->hp_pins)];
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003709
3710 memset(cfg, 0, sizeof(*cfg));
3711
Steve Longerbeam81937d32007-05-08 15:33:03 +02003712 memset(sequences_line_out, 0, sizeof(sequences_line_out));
3713 memset(sequences_speaker, 0, sizeof(sequences_speaker));
Takashi Iwaif889fa92007-10-31 15:49:32 +01003714 memset(sequences_hp, 0, sizeof(sequences_hp));
Steve Longerbeam81937d32007-05-08 15:33:03 +02003715 assoc_line_out = assoc_speaker = 0;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003716
Takashi Iwai0ef6ce72008-01-22 15:35:37 +01003717 end_nid = codec->start_nid + codec->num_nodes;
3718 for (nid = codec->start_nid; nid < end_nid; nid++) {
Takashi Iwai54d17402005-11-21 16:33:22 +01003719 unsigned int wid_caps = get_wcaps(codec, nid);
Takashi Iwaia22d5432009-07-27 12:54:26 +02003720 unsigned int wid_type = get_wcaps_type(wid_caps);
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003721 unsigned int def_conf;
3722 short assoc, loc;
3723
3724 /* read all default configuration for pin complex */
3725 if (wid_type != AC_WID_PIN)
3726 continue;
Kailang Yangdf694da2005-12-05 19:42:22 +01003727 /* ignore the given nids (e.g. pc-beep returns error) */
3728 if (ignore_nids && is_in_nid_list(nid, ignore_nids))
3729 continue;
3730
Takashi Iwaic17a1ab2009-02-23 09:28:12 +01003731 def_conf = snd_hda_codec_get_pincfg(codec, nid);
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003732 if (get_defcfg_connect(def_conf) == AC_JACK_PORT_NONE)
3733 continue;
3734 loc = get_defcfg_location(def_conf);
3735 switch (get_defcfg_device(def_conf)) {
3736 case AC_JACK_LINE_OUT:
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003737 seq = get_defcfg_sequence(def_conf);
3738 assoc = get_defcfg_association(def_conf);
Matthew Ranostay90da78b2008-01-24 11:48:01 +01003739
3740 if (!(wid_caps & AC_WCAP_STEREO))
3741 if (!cfg->mono_out_pin)
3742 cfg->mono_out_pin = nid;
Takashi Iwai0ba21762007-04-16 11:29:14 +02003743 if (!assoc)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003744 continue;
Takashi Iwai0ba21762007-04-16 11:29:14 +02003745 if (!assoc_line_out)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003746 assoc_line_out = assoc;
3747 else if (assoc_line_out != assoc)
3748 continue;
3749 if (cfg->line_outs >= ARRAY_SIZE(cfg->line_out_pins))
3750 continue;
3751 cfg->line_out_pins[cfg->line_outs] = nid;
Steve Longerbeam81937d32007-05-08 15:33:03 +02003752 sequences_line_out[cfg->line_outs] = seq;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003753 cfg->line_outs++;
3754 break;
Takashi Iwai8d88bc32005-11-17 11:09:23 +01003755 case AC_JACK_SPEAKER:
Steve Longerbeam81937d32007-05-08 15:33:03 +02003756 seq = get_defcfg_sequence(def_conf);
3757 assoc = get_defcfg_association(def_conf);
3758 if (! assoc)
3759 continue;
3760 if (! assoc_speaker)
3761 assoc_speaker = assoc;
3762 else if (assoc_speaker != assoc)
3763 continue;
Takashi Iwai82bc9552006-03-21 11:24:42 +01003764 if (cfg->speaker_outs >= ARRAY_SIZE(cfg->speaker_pins))
3765 continue;
3766 cfg->speaker_pins[cfg->speaker_outs] = nid;
Steve Longerbeam81937d32007-05-08 15:33:03 +02003767 sequences_speaker[cfg->speaker_outs] = seq;
Takashi Iwai82bc9552006-03-21 11:24:42 +01003768 cfg->speaker_outs++;
Takashi Iwai8d88bc32005-11-17 11:09:23 +01003769 break;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003770 case AC_JACK_HP_OUT:
Takashi Iwaif889fa92007-10-31 15:49:32 +01003771 seq = get_defcfg_sequence(def_conf);
3772 assoc = get_defcfg_association(def_conf);
Takashi Iwaieb06ed82006-09-20 17:10:27 +02003773 if (cfg->hp_outs >= ARRAY_SIZE(cfg->hp_pins))
3774 continue;
3775 cfg->hp_pins[cfg->hp_outs] = nid;
Takashi Iwaif889fa92007-10-31 15:49:32 +01003776 sequences_hp[cfg->hp_outs] = (assoc << 4) | seq;
Takashi Iwaieb06ed82006-09-20 17:10:27 +02003777 cfg->hp_outs++;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003778 break;
Takashi Iwai314634b2006-09-21 11:56:18 +02003779 case AC_JACK_MIC_IN: {
3780 int preferred, alt;
3781 if (loc == AC_JACK_LOC_FRONT) {
3782 preferred = AUTO_PIN_FRONT_MIC;
3783 alt = AUTO_PIN_MIC;
3784 } else {
3785 preferred = AUTO_PIN_MIC;
3786 alt = AUTO_PIN_FRONT_MIC;
3787 }
3788 if (!cfg->input_pins[preferred])
3789 cfg->input_pins[preferred] = nid;
3790 else if (!cfg->input_pins[alt])
3791 cfg->input_pins[alt] = nid;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003792 break;
Takashi Iwai314634b2006-09-21 11:56:18 +02003793 }
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003794 case AC_JACK_LINE_IN:
3795 if (loc == AC_JACK_LOC_FRONT)
3796 cfg->input_pins[AUTO_PIN_FRONT_LINE] = nid;
3797 else
3798 cfg->input_pins[AUTO_PIN_LINE] = nid;
3799 break;
3800 case AC_JACK_CD:
3801 cfg->input_pins[AUTO_PIN_CD] = nid;
3802 break;
3803 case AC_JACK_AUX:
3804 cfg->input_pins[AUTO_PIN_AUX] = nid;
3805 break;
3806 case AC_JACK_SPDIF_OUT:
Takashi Iwai1b52ae72009-01-20 17:17:29 +01003807 case AC_JACK_DIG_OTHER_OUT:
Takashi Iwai0852d7a2009-02-11 11:35:15 +01003808 if (cfg->dig_outs >= ARRAY_SIZE(cfg->dig_out_pins))
3809 continue;
3810 cfg->dig_out_pins[cfg->dig_outs] = nid;
3811 cfg->dig_out_type[cfg->dig_outs] =
3812 (loc == AC_JACK_LOC_HDMI) ?
3813 HDA_PCM_TYPE_HDMI : HDA_PCM_TYPE_SPDIF;
3814 cfg->dig_outs++;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003815 break;
3816 case AC_JACK_SPDIF_IN:
Takashi Iwai1b52ae72009-01-20 17:17:29 +01003817 case AC_JACK_DIG_OTHER_IN:
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003818 cfg->dig_in_pin = nid;
Takashi Iwai2297bd62009-01-20 18:24:13 +01003819 if (loc == AC_JACK_LOC_HDMI)
3820 cfg->dig_in_type = HDA_PCM_TYPE_HDMI;
3821 else
3822 cfg->dig_in_type = HDA_PCM_TYPE_SPDIF;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003823 break;
3824 }
3825 }
3826
Takashi Iwai5832fcf2008-02-12 18:30:12 +01003827 /* FIX-UP:
3828 * If no line-out is defined but multiple HPs are found,
3829 * some of them might be the real line-outs.
3830 */
3831 if (!cfg->line_outs && cfg->hp_outs > 1) {
3832 int i = 0;
3833 while (i < cfg->hp_outs) {
3834 /* The real HPs should have the sequence 0x0f */
3835 if ((sequences_hp[i] & 0x0f) == 0x0f) {
3836 i++;
3837 continue;
3838 }
3839 /* Move it to the line-out table */
3840 cfg->line_out_pins[cfg->line_outs] = cfg->hp_pins[i];
3841 sequences_line_out[cfg->line_outs] = sequences_hp[i];
3842 cfg->line_outs++;
3843 cfg->hp_outs--;
3844 memmove(cfg->hp_pins + i, cfg->hp_pins + i + 1,
3845 sizeof(cfg->hp_pins[0]) * (cfg->hp_outs - i));
3846 memmove(sequences_hp + i - 1, sequences_hp + i,
3847 sizeof(sequences_hp[0]) * (cfg->hp_outs - i));
3848 }
3849 }
3850
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003851 /* sort by sequence */
Steve Longerbeam81937d32007-05-08 15:33:03 +02003852 sort_pins_by_sequence(cfg->line_out_pins, sequences_line_out,
3853 cfg->line_outs);
3854 sort_pins_by_sequence(cfg->speaker_pins, sequences_speaker,
3855 cfg->speaker_outs);
Takashi Iwaif889fa92007-10-31 15:49:32 +01003856 sort_pins_by_sequence(cfg->hp_pins, sequences_hp,
3857 cfg->hp_outs);
Steve Longerbeam81937d32007-05-08 15:33:03 +02003858
Takashi Iwaif889fa92007-10-31 15:49:32 +01003859 /* if we have only one mic, make it AUTO_PIN_MIC */
3860 if (!cfg->input_pins[AUTO_PIN_MIC] &&
3861 cfg->input_pins[AUTO_PIN_FRONT_MIC]) {
3862 cfg->input_pins[AUTO_PIN_MIC] =
3863 cfg->input_pins[AUTO_PIN_FRONT_MIC];
3864 cfg->input_pins[AUTO_PIN_FRONT_MIC] = 0;
3865 }
3866 /* ditto for line-in */
3867 if (!cfg->input_pins[AUTO_PIN_LINE] &&
3868 cfg->input_pins[AUTO_PIN_FRONT_LINE]) {
3869 cfg->input_pins[AUTO_PIN_LINE] =
3870 cfg->input_pins[AUTO_PIN_FRONT_LINE];
3871 cfg->input_pins[AUTO_PIN_FRONT_LINE] = 0;
3872 }
3873
Steve Longerbeam81937d32007-05-08 15:33:03 +02003874 /*
3875 * FIX-UP: if no line-outs are detected, try to use speaker or HP pin
3876 * as a primary output
3877 */
3878 if (!cfg->line_outs) {
3879 if (cfg->speaker_outs) {
3880 cfg->line_outs = cfg->speaker_outs;
3881 memcpy(cfg->line_out_pins, cfg->speaker_pins,
3882 sizeof(cfg->speaker_pins));
3883 cfg->speaker_outs = 0;
3884 memset(cfg->speaker_pins, 0, sizeof(cfg->speaker_pins));
3885 cfg->line_out_type = AUTO_PIN_SPEAKER_OUT;
3886 } else if (cfg->hp_outs) {
3887 cfg->line_outs = cfg->hp_outs;
3888 memcpy(cfg->line_out_pins, cfg->hp_pins,
3889 sizeof(cfg->hp_pins));
3890 cfg->hp_outs = 0;
3891 memset(cfg->hp_pins, 0, sizeof(cfg->hp_pins));
3892 cfg->line_out_type = AUTO_PIN_HP_OUT;
3893 }
3894 }
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003895
Takashi Iwaicb8e2f82005-07-29 11:54:32 +02003896 /* Reorder the surround channels
3897 * ALSA sequence is front/surr/clfe/side
3898 * HDA sequence is:
3899 * 4-ch: front/surr => OK as it is
3900 * 6-ch: front/clfe/surr
Takashi Iwai9422db42007-04-20 16:11:43 +02003901 * 8-ch: front/clfe/rear/side|fc
Takashi Iwaicb8e2f82005-07-29 11:54:32 +02003902 */
3903 switch (cfg->line_outs) {
3904 case 3:
Takashi Iwaicb8e2f82005-07-29 11:54:32 +02003905 case 4:
3906 nid = cfg->line_out_pins[1];
Takashi Iwai9422db42007-04-20 16:11:43 +02003907 cfg->line_out_pins[1] = cfg->line_out_pins[2];
Takashi Iwaicb8e2f82005-07-29 11:54:32 +02003908 cfg->line_out_pins[2] = nid;
3909 break;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003910 }
3911
Takashi Iwai82bc9552006-03-21 11:24:42 +01003912 /*
3913 * debug prints of the parsed results
3914 */
3915 snd_printd("autoconfig: line_outs=%d (0x%x/0x%x/0x%x/0x%x/0x%x)\n",
3916 cfg->line_outs, cfg->line_out_pins[0], cfg->line_out_pins[1],
3917 cfg->line_out_pins[2], cfg->line_out_pins[3],
3918 cfg->line_out_pins[4]);
3919 snd_printd(" speaker_outs=%d (0x%x/0x%x/0x%x/0x%x/0x%x)\n",
3920 cfg->speaker_outs, cfg->speaker_pins[0],
3921 cfg->speaker_pins[1], cfg->speaker_pins[2],
3922 cfg->speaker_pins[3], cfg->speaker_pins[4]);
Takashi Iwaieb06ed82006-09-20 17:10:27 +02003923 snd_printd(" hp_outs=%d (0x%x/0x%x/0x%x/0x%x/0x%x)\n",
3924 cfg->hp_outs, cfg->hp_pins[0],
3925 cfg->hp_pins[1], cfg->hp_pins[2],
3926 cfg->hp_pins[3], cfg->hp_pins[4]);
Matthew Ranostay90da78b2008-01-24 11:48:01 +01003927 snd_printd(" mono: mono_out=0x%x\n", cfg->mono_out_pin);
Takashi Iwai0852d7a2009-02-11 11:35:15 +01003928 if (cfg->dig_outs)
3929 snd_printd(" dig-out=0x%x/0x%x\n",
3930 cfg->dig_out_pins[0], cfg->dig_out_pins[1]);
Takashi Iwai82bc9552006-03-21 11:24:42 +01003931 snd_printd(" inputs: mic=0x%x, fmic=0x%x, line=0x%x, fline=0x%x,"
3932 " cd=0x%x, aux=0x%x\n",
3933 cfg->input_pins[AUTO_PIN_MIC],
3934 cfg->input_pins[AUTO_PIN_FRONT_MIC],
3935 cfg->input_pins[AUTO_PIN_LINE],
3936 cfg->input_pins[AUTO_PIN_FRONT_LINE],
3937 cfg->input_pins[AUTO_PIN_CD],
3938 cfg->input_pins[AUTO_PIN_AUX]);
Takashi Iwai32d2c7f2009-02-11 11:33:13 +01003939 if (cfg->dig_in_pin)
Takashi Iwai89ce9e82009-01-20 17:15:57 +01003940 snd_printd(" dig-in=0x%x\n", cfg->dig_in_pin);
Takashi Iwai82bc9552006-03-21 11:24:42 +01003941
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003942 return 0;
3943}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003944EXPORT_SYMBOL_HDA(snd_hda_parse_pin_def_config);
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003945
Takashi Iwai4a471b72005-12-07 13:56:29 +01003946/* labels for input pins */
3947const char *auto_pin_cfg_labels[AUTO_PIN_LAST] = {
3948 "Mic", "Front Mic", "Line", "Front Line", "CD", "Aux"
3949};
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003950EXPORT_SYMBOL_HDA(auto_pin_cfg_labels);
Takashi Iwai4a471b72005-12-07 13:56:29 +01003951
3952
Linus Torvalds1da177e2005-04-16 15:20:36 -07003953#ifdef CONFIG_PM
3954/*
3955 * power management
3956 */
3957
3958/**
3959 * snd_hda_suspend - suspend the codecs
3960 * @bus: the HDA bus
Linus Torvalds1da177e2005-04-16 15:20:36 -07003961 *
3962 * Returns 0 if successful.
3963 */
Takashi Iwai8dd78332009-06-02 01:16:07 +02003964int snd_hda_suspend(struct hda_bus *bus)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003965{
Takashi Iwai0ba21762007-04-16 11:29:14 +02003966 struct hda_codec *codec;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003967
Takashi Iwai0ba21762007-04-16 11:29:14 +02003968 list_for_each_entry(codec, &bus->codec_list, list) {
Takashi Iwai0b7a2e92007-08-14 15:18:26 +02003969#ifdef CONFIG_SND_HDA_POWER_SAVE
3970 if (!codec->power_on)
3971 continue;
3972#endif
Takashi Iwaicb53c622007-08-10 17:21:45 +02003973 hda_call_codec_suspend(codec);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003974 }
3975 return 0;
3976}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003977EXPORT_SYMBOL_HDA(snd_hda_suspend);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003978
3979/**
3980 * snd_hda_resume - resume the codecs
3981 * @bus: the HDA bus
Linus Torvalds1da177e2005-04-16 15:20:36 -07003982 *
3983 * Returns 0 if successful.
Takashi Iwaicb53c622007-08-10 17:21:45 +02003984 *
3985 * This fucntion is defined only when POWER_SAVE isn't set.
3986 * In the power-save mode, the codec is resumed dynamically.
Linus Torvalds1da177e2005-04-16 15:20:36 -07003987 */
3988int snd_hda_resume(struct hda_bus *bus)
3989{
Takashi Iwai0ba21762007-04-16 11:29:14 +02003990 struct hda_codec *codec;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003991
Takashi Iwai0ba21762007-04-16 11:29:14 +02003992 list_for_each_entry(codec, &bus->codec_list, list) {
Maxim Levitskyd804ad92007-09-03 15:28:04 +02003993 if (snd_hda_codec_needs_resume(codec))
3994 hda_call_codec_resume(codec);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003995 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003996 return 0;
3997}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003998EXPORT_SYMBOL_HDA(snd_hda_resume);
Takashi Iwai1289e9e2008-11-27 15:47:11 +01003999#endif /* CONFIG_PM */
Takashi Iwaib2e18592008-07-30 15:01:44 +02004000
4001/*
4002 * generic arrays
4003 */
4004
4005/* get a new element from the given array
4006 * if it exceeds the pre-allocated array size, re-allocate the array
4007 */
4008void *snd_array_new(struct snd_array *array)
4009{
4010 if (array->used >= array->alloced) {
4011 int num = array->alloced + array->alloc_align;
Takashi Iwaib910d9a2008-11-07 00:26:52 +01004012 void *nlist;
4013 if (snd_BUG_ON(num >= 4096))
4014 return NULL;
4015 nlist = kcalloc(num + 1, array->elem_size, GFP_KERNEL);
Takashi Iwaib2e18592008-07-30 15:01:44 +02004016 if (!nlist)
4017 return NULL;
4018 if (array->list) {
4019 memcpy(nlist, array->list,
4020 array->elem_size * array->alloced);
4021 kfree(array->list);
4022 }
4023 array->list = nlist;
4024 array->alloced = num;
4025 }
Takashi Iwaif43aa022008-11-10 16:24:26 +01004026 return snd_array_elem(array, array->used++);
Takashi Iwaib2e18592008-07-30 15:01:44 +02004027}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01004028EXPORT_SYMBOL_HDA(snd_array_new);
Takashi Iwaib2e18592008-07-30 15:01:44 +02004029
4030/* free the given array elements */
4031void snd_array_free(struct snd_array *array)
4032{
4033 kfree(array->list);
4034 array->used = 0;
4035 array->alloced = 0;
4036 array->list = NULL;
4037}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01004038EXPORT_SYMBOL_HDA(snd_array_free);
Takashi Iwaib2022262008-11-21 21:24:03 +01004039
4040/*
4041 * used by hda_proc.c and hda_eld.c
4042 */
4043void snd_print_pcm_rates(int pcm, char *buf, int buflen)
4044{
4045 static unsigned int rates[] = {
4046 8000, 11025, 16000, 22050, 32000, 44100, 48000, 88200,
4047 96000, 176400, 192000, 384000
4048 };
4049 int i, j;
4050
4051 for (i = 0, j = 0; i < ARRAY_SIZE(rates); i++)
4052 if (pcm & (1 << i))
4053 j += snprintf(buf + j, buflen - j, " %d", rates[i]);
4054
4055 buf[j] = '\0'; /* necessary when j == 0 */
4056}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01004057EXPORT_SYMBOL_HDA(snd_print_pcm_rates);
Takashi Iwaib2022262008-11-21 21:24:03 +01004058
4059void snd_print_pcm_bits(int pcm, char *buf, int buflen)
4060{
4061 static unsigned int bits[] = { 8, 16, 20, 24, 32 };
4062 int i, j;
4063
4064 for (i = 0, j = 0; i < ARRAY_SIZE(bits); i++)
4065 if (pcm & (AC_SUPPCM_BITS_8 << i))
4066 j += snprintf(buf + j, buflen - j, " %d", bits[i]);
4067
4068 buf[j] = '\0'; /* necessary when j == 0 */
4069}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01004070EXPORT_SYMBOL_HDA(snd_print_pcm_bits);
Takashi Iwai1289e9e2008-11-27 15:47:11 +01004071
4072MODULE_DESCRIPTION("HDA codec core");
4073MODULE_LICENSE("GPL");