blob: 1736ccbebc729c03ba918e0abcb4981f82d8abb3 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * Universal Interface for Intel High Definition Audio Codec
3 *
4 * Copyright (c) 2004 Takashi Iwai <tiwai@suse.de>
5 *
6 *
7 * This driver is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This driver is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21
Linus Torvalds1da177e2005-04-16 15:20:36 -070022#include <linux/init.h>
23#include <linux/delay.h>
24#include <linux/slab.h>
25#include <linux/pci.h>
Ingo Molnar62932df2006-01-16 16:34:20 +010026#include <linux/mutex.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070027#include <sound/core.h>
28#include "hda_codec.h"
29#include <sound/asoundef.h>
Jaroslav Kysela302e9c52006-07-05 17:39:49 +020030#include <sound/tlv.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070031#include <sound/initval.h>
32#include "hda_local.h"
Takashi Iwai28073142007-07-27 18:58:06 +020033#include <sound/hda_hwdep.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070034
Linus Torvalds1da177e2005-04-16 15:20:36 -070035/*
36 * vendor / preset table
37 */
38
39struct hda_vendor_id {
40 unsigned int id;
41 const char *name;
42};
43
44/* codec vendor labels */
45static struct hda_vendor_id hda_vendor_ids[] = {
Takashi Iwaic8cd1282008-02-13 16:59:29 +010046 { 0x1002, "ATI" },
Takashi Iwaia9226252006-09-17 22:05:54 +020047 { 0x1057, "Motorola" },
Takashi Iwaic8cd1282008-02-13 16:59:29 +010048 { 0x1095, "Silicon Image" },
Takashi Iwai31117b72008-12-16 14:43:21 +010049 { 0x10de, "Nvidia" },
Takashi Iwaic8cd1282008-02-13 16:59:29 +010050 { 0x10ec, "Realtek" },
Joseph Chanc577b8a2006-11-29 15:29:40 +010051 { 0x1106, "VIA" },
Matthew Ranostay7f168592007-10-18 17:38:17 +020052 { 0x111d, "IDT" },
Takashi Iwaic8cd1282008-02-13 16:59:29 +010053 { 0x11c1, "LSI" },
Takashi Iwai54b903e2005-05-15 14:30:10 +020054 { 0x11d4, "Analog Devices" },
Linus Torvalds1da177e2005-04-16 15:20:36 -070055 { 0x13f6, "C-Media" },
Takashi Iwaia9226252006-09-17 22:05:54 +020056 { 0x14f1, "Conexant" },
Takashi Iwaic8cd1282008-02-13 16:59:29 +010057 { 0x17e8, "Chrontel" },
58 { 0x1854, "LG" },
Mark Brown8199de32008-10-28 14:50:13 +000059 { 0x1aec, "Wolfson Microelectronics" },
Linus Torvalds1da177e2005-04-16 15:20:36 -070060 { 0x434d, "C-Media" },
Takashi Iwai74c61132008-12-18 09:11:33 +010061 { 0x8086, "Intel" },
Matt2f2f4252005-04-13 14:45:30 +020062 { 0x8384, "SigmaTel" },
Linus Torvalds1da177e2005-04-16 15:20:36 -070063 {} /* terminator */
64};
65
Takashi Iwai1289e9e2008-11-27 15:47:11 +010066static DEFINE_MUTEX(preset_mutex);
67static LIST_HEAD(hda_preset_tables);
68
69int snd_hda_add_codec_preset(struct hda_codec_preset_list *preset)
70{
71 mutex_lock(&preset_mutex);
72 list_add_tail(&preset->list, &hda_preset_tables);
73 mutex_unlock(&preset_mutex);
74 return 0;
75}
Takashi Iwaiff7a3262008-11-28 15:17:06 +010076EXPORT_SYMBOL_HDA(snd_hda_add_codec_preset);
Takashi Iwai1289e9e2008-11-27 15:47:11 +010077
78int snd_hda_delete_codec_preset(struct hda_codec_preset_list *preset)
79{
80 mutex_lock(&preset_mutex);
81 list_del(&preset->list);
82 mutex_unlock(&preset_mutex);
83 return 0;
84}
Takashi Iwaiff7a3262008-11-28 15:17:06 +010085EXPORT_SYMBOL_HDA(snd_hda_delete_codec_preset);
Linus Torvalds1da177e2005-04-16 15:20:36 -070086
Takashi Iwaicb53c622007-08-10 17:21:45 +020087#ifdef CONFIG_SND_HDA_POWER_SAVE
88static void hda_power_work(struct work_struct *work);
89static void hda_keep_power_on(struct hda_codec *codec);
90#else
91static inline void hda_keep_power_on(struct hda_codec *codec) {}
92#endif
93
Matthew Ranostay50a9f792008-10-25 01:05:45 -040094const char *snd_hda_get_jack_location(u32 cfg)
95{
96 static char *bases[7] = {
97 "N/A", "Rear", "Front", "Left", "Right", "Top", "Bottom",
98 };
99 static unsigned char specials_idx[] = {
100 0x07, 0x08,
101 0x17, 0x18, 0x19,
102 0x37, 0x38
103 };
104 static char *specials[] = {
105 "Rear Panel", "Drive Bar",
106 "Riser", "HDMI", "ATAPI",
107 "Mobile-In", "Mobile-Out"
108 };
109 int i;
110 cfg = (cfg & AC_DEFCFG_LOCATION) >> AC_DEFCFG_LOCATION_SHIFT;
111 if ((cfg & 0x0f) < 7)
112 return bases[cfg & 0x0f];
113 for (i = 0; i < ARRAY_SIZE(specials_idx); i++) {
114 if (cfg == specials_idx[i])
115 return specials[i];
116 }
117 return "UNKNOWN";
118}
Takashi Iwaiff7a3262008-11-28 15:17:06 +0100119EXPORT_SYMBOL_HDA(snd_hda_get_jack_location);
Matthew Ranostay50a9f792008-10-25 01:05:45 -0400120
121const char *snd_hda_get_jack_connectivity(u32 cfg)
122{
123 static char *jack_locations[4] = { "Ext", "Int", "Sep", "Oth" };
124
125 return jack_locations[(cfg >> (AC_DEFCFG_LOCATION_SHIFT + 4)) & 3];
126}
Takashi Iwaiff7a3262008-11-28 15:17:06 +0100127EXPORT_SYMBOL_HDA(snd_hda_get_jack_connectivity);
Matthew Ranostay50a9f792008-10-25 01:05:45 -0400128
129const char *snd_hda_get_jack_type(u32 cfg)
130{
131 static char *jack_types[16] = {
132 "Line Out", "Speaker", "HP Out", "CD",
133 "SPDIF Out", "Digital Out", "Modem Line", "Modem Hand",
134 "Line In", "Aux", "Mic", "Telephony",
135 "SPDIF In", "Digitial In", "Reserved", "Other"
136 };
137
138 return jack_types[(cfg & AC_DEFCFG_DEVICE)
139 >> AC_DEFCFG_DEVICE_SHIFT];
140}
Takashi Iwaiff7a3262008-11-28 15:17:06 +0100141EXPORT_SYMBOL_HDA(snd_hda_get_jack_type);
Matthew Ranostay50a9f792008-10-25 01:05:45 -0400142
Takashi Iwai33fa35e2008-11-06 16:50:40 +0100143/*
144 * Compose a 32bit command word to be sent to the HD-audio controller
145 */
146static inline unsigned int
147make_codec_cmd(struct hda_codec *codec, hda_nid_t nid, int direct,
148 unsigned int verb, unsigned int parm)
149{
150 u32 val;
151
152 val = (u32)(codec->addr & 0x0f) << 28;
153 val |= (u32)direct << 27;
154 val |= (u32)nid << 20;
155 val |= verb << 8;
156 val |= parm;
157 return val;
158}
159
Linus Torvalds1da177e2005-04-16 15:20:36 -0700160/**
161 * snd_hda_codec_read - send a command and get the response
162 * @codec: the HDA codec
163 * @nid: NID to send the command
164 * @direct: direct flag
165 * @verb: the verb to send
166 * @parm: the parameter for the verb
167 *
168 * Send a single command and read the corresponding response.
169 *
170 * Returns the obtained response value, or -1 for an error.
171 */
Takashi Iwai0ba21762007-04-16 11:29:14 +0200172unsigned int snd_hda_codec_read(struct hda_codec *codec, hda_nid_t nid,
173 int direct,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700174 unsigned int verb, unsigned int parm)
175{
Takashi Iwai33fa35e2008-11-06 16:50:40 +0100176 struct hda_bus *bus = codec->bus;
Takashi Iwaib6132912009-03-24 07:36:09 +0100177 unsigned int cmd, res;
178 int repeated = 0;
Takashi Iwai33fa35e2008-11-06 16:50:40 +0100179
Takashi Iwaib6132912009-03-24 07:36:09 +0100180 cmd = make_codec_cmd(codec, nid, direct, verb, parm);
Takashi Iwaicb53c622007-08-10 17:21:45 +0200181 snd_hda_power_up(codec);
Takashi Iwai33fa35e2008-11-06 16:50:40 +0100182 mutex_lock(&bus->cmd_mutex);
Takashi Iwaib6132912009-03-24 07:36:09 +0100183 again:
184 if (!bus->ops.command(bus, cmd)) {
Takashi Iwai33fa35e2008-11-06 16:50:40 +0100185 res = bus->ops.get_response(bus);
Takashi Iwaib6132912009-03-24 07:36:09 +0100186 if (res == -1 && bus->rirb_error) {
187 if (repeated++ < 1) {
188 snd_printd(KERN_WARNING "hda_codec: "
189 "Trying verb 0x%08x again\n", cmd);
190 goto again;
191 }
192 }
193 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -0700194 res = (unsigned int)-1;
Takashi Iwai33fa35e2008-11-06 16:50:40 +0100195 mutex_unlock(&bus->cmd_mutex);
Takashi Iwaicb53c622007-08-10 17:21:45 +0200196 snd_hda_power_down(codec);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700197 return res;
198}
Takashi Iwaiff7a3262008-11-28 15:17:06 +0100199EXPORT_SYMBOL_HDA(snd_hda_codec_read);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700200
201/**
202 * snd_hda_codec_write - send a single command without waiting for response
203 * @codec: the HDA codec
204 * @nid: NID to send the command
205 * @direct: direct flag
206 * @verb: the verb to send
207 * @parm: the parameter for the verb
208 *
209 * Send a single command without waiting for response.
210 *
211 * Returns 0 if successful, or a negative error code.
212 */
213int snd_hda_codec_write(struct hda_codec *codec, hda_nid_t nid, int direct,
214 unsigned int verb, unsigned int parm)
215{
Takashi Iwai33fa35e2008-11-06 16:50:40 +0100216 struct hda_bus *bus = codec->bus;
217 unsigned int res;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700218 int err;
Takashi Iwai33fa35e2008-11-06 16:50:40 +0100219
220 res = make_codec_cmd(codec, nid, direct, verb, parm);
Takashi Iwaicb53c622007-08-10 17:21:45 +0200221 snd_hda_power_up(codec);
Takashi Iwai33fa35e2008-11-06 16:50:40 +0100222 mutex_lock(&bus->cmd_mutex);
223 err = bus->ops.command(bus, res);
224 mutex_unlock(&bus->cmd_mutex);
Takashi Iwaicb53c622007-08-10 17:21:45 +0200225 snd_hda_power_down(codec);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700226 return err;
227}
Takashi Iwaiff7a3262008-11-28 15:17:06 +0100228EXPORT_SYMBOL_HDA(snd_hda_codec_write);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700229
230/**
231 * snd_hda_sequence_write - sequence writes
232 * @codec: the HDA codec
233 * @seq: VERB array to send
234 *
235 * Send the commands sequentially from the given array.
236 * The array must be terminated with NID=0.
237 */
238void snd_hda_sequence_write(struct hda_codec *codec, const struct hda_verb *seq)
239{
240 for (; seq->nid; seq++)
241 snd_hda_codec_write(codec, seq->nid, 0, seq->verb, seq->param);
242}
Takashi Iwaiff7a3262008-11-28 15:17:06 +0100243EXPORT_SYMBOL_HDA(snd_hda_sequence_write);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700244
245/**
246 * snd_hda_get_sub_nodes - get the range of sub nodes
247 * @codec: the HDA codec
248 * @nid: NID to parse
249 * @start_id: the pointer to store the start NID
250 *
251 * Parse the NID and store the start NID of its sub-nodes.
252 * Returns the number of sub-nodes.
253 */
Takashi Iwai0ba21762007-04-16 11:29:14 +0200254int snd_hda_get_sub_nodes(struct hda_codec *codec, hda_nid_t nid,
255 hda_nid_t *start_id)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700256{
257 unsigned int parm;
258
259 parm = snd_hda_param_read(codec, nid, AC_PAR_NODE_COUNT);
Danny Tholene8a7f132007-09-11 21:41:56 +0200260 if (parm == -1)
261 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700262 *start_id = (parm >> 16) & 0x7fff;
263 return (int)(parm & 0x7fff);
264}
Takashi Iwaiff7a3262008-11-28 15:17:06 +0100265EXPORT_SYMBOL_HDA(snd_hda_get_sub_nodes);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700266
267/**
268 * snd_hda_get_connections - get connection list
269 * @codec: the HDA codec
270 * @nid: NID to parse
271 * @conn_list: connection list array
272 * @max_conns: max. number of connections to store
273 *
274 * Parses the connection list of the given widget and stores the list
275 * of NIDs.
276 *
277 * Returns the number of connections, or a negative error code.
278 */
279int snd_hda_get_connections(struct hda_codec *codec, hda_nid_t nid,
280 hda_nid_t *conn_list, int max_conns)
281{
282 unsigned int parm;
Takashi Iwai54d17402005-11-21 16:33:22 +0100283 int i, conn_len, conns;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700284 unsigned int shift, num_elems, mask;
Takashi Iwai54d17402005-11-21 16:33:22 +0100285 hda_nid_t prev_nid;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700286
Takashi Iwaida3cec32008-08-08 17:12:14 +0200287 if (snd_BUG_ON(!conn_list || max_conns <= 0))
288 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700289
290 parm = snd_hda_param_read(codec, nid, AC_PAR_CONNLIST_LEN);
291 if (parm & AC_CLIST_LONG) {
292 /* long form */
293 shift = 16;
294 num_elems = 2;
295 } else {
296 /* short form */
297 shift = 8;
298 num_elems = 4;
299 }
300 conn_len = parm & AC_CLIST_LENGTH;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700301 mask = (1 << (shift-1)) - 1;
302
Takashi Iwai0ba21762007-04-16 11:29:14 +0200303 if (!conn_len)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700304 return 0; /* no connection */
305
306 if (conn_len == 1) {
307 /* single connection */
Takashi Iwai0ba21762007-04-16 11:29:14 +0200308 parm = snd_hda_codec_read(codec, nid, 0,
309 AC_VERB_GET_CONNECT_LIST, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700310 conn_list[0] = parm & mask;
311 return 1;
312 }
313
314 /* multi connection */
315 conns = 0;
Takashi Iwai54d17402005-11-21 16:33:22 +0100316 prev_nid = 0;
317 for (i = 0; i < conn_len; i++) {
318 int range_val;
319 hda_nid_t val, n;
320
321 if (i % num_elems == 0)
322 parm = snd_hda_codec_read(codec, nid, 0,
323 AC_VERB_GET_CONNECT_LIST, i);
Takashi Iwai0ba21762007-04-16 11:29:14 +0200324 range_val = !!(parm & (1 << (shift-1))); /* ranges */
Takashi Iwai54d17402005-11-21 16:33:22 +0100325 val = parm & mask;
326 parm >>= shift;
327 if (range_val) {
328 /* ranges between the previous and this one */
Takashi Iwai0ba21762007-04-16 11:29:14 +0200329 if (!prev_nid || prev_nid >= val) {
330 snd_printk(KERN_WARNING "hda_codec: "
331 "invalid dep_range_val %x:%x\n",
332 prev_nid, val);
Takashi Iwai54d17402005-11-21 16:33:22 +0100333 continue;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700334 }
Takashi Iwai54d17402005-11-21 16:33:22 +0100335 for (n = prev_nid + 1; n <= val; n++) {
336 if (conns >= max_conns) {
Takashi Iwai0ba21762007-04-16 11:29:14 +0200337 snd_printk(KERN_ERR
338 "Too many connections\n");
Takashi Iwai54d17402005-11-21 16:33:22 +0100339 return -EINVAL;
340 }
341 conn_list[conns++] = n;
342 }
343 } else {
344 if (conns >= max_conns) {
345 snd_printk(KERN_ERR "Too many connections\n");
346 return -EINVAL;
347 }
348 conn_list[conns++] = val;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700349 }
Takashi Iwai54d17402005-11-21 16:33:22 +0100350 prev_nid = val;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700351 }
352 return conns;
353}
Takashi Iwaiff7a3262008-11-28 15:17:06 +0100354EXPORT_SYMBOL_HDA(snd_hda_get_connections);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700355
356
357/**
358 * snd_hda_queue_unsol_event - add an unsolicited event to queue
359 * @bus: the BUS
360 * @res: unsolicited event (lower 32bit of RIRB entry)
361 * @res_ex: codec addr and flags (upper 32bit or RIRB entry)
362 *
363 * Adds the given event to the queue. The events are processed in
364 * the workqueue asynchronously. Call this function in the interrupt
365 * hanlder when RIRB receives an unsolicited event.
366 *
367 * Returns 0 if successful, or a negative error code.
368 */
369int snd_hda_queue_unsol_event(struct hda_bus *bus, u32 res, u32 res_ex)
370{
371 struct hda_bus_unsolicited *unsol;
372 unsigned int wp;
373
Takashi Iwai0ba21762007-04-16 11:29:14 +0200374 unsol = bus->unsol;
375 if (!unsol)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700376 return 0;
377
378 wp = (unsol->wp + 1) % HDA_UNSOL_QUEUE_SIZE;
379 unsol->wp = wp;
380
381 wp <<= 1;
382 unsol->queue[wp] = res;
383 unsol->queue[wp + 1] = res_ex;
384
Takashi Iwai6acaed32009-01-12 10:09:24 +0100385 queue_work(bus->workq, &unsol->work);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700386
387 return 0;
388}
Takashi Iwaiff7a3262008-11-28 15:17:06 +0100389EXPORT_SYMBOL_HDA(snd_hda_queue_unsol_event);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700390
391/*
Wu Fengguang5c1d1a92008-10-07 14:17:53 +0800392 * process queued unsolicited events
Linus Torvalds1da177e2005-04-16 15:20:36 -0700393 */
David Howellsc4028952006-11-22 14:57:56 +0000394static void process_unsol_events(struct work_struct *work)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700395{
David Howellsc4028952006-11-22 14:57:56 +0000396 struct hda_bus_unsolicited *unsol =
397 container_of(work, struct hda_bus_unsolicited, work);
398 struct hda_bus *bus = unsol->bus;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700399 struct hda_codec *codec;
400 unsigned int rp, caddr, res;
401
402 while (unsol->rp != unsol->wp) {
403 rp = (unsol->rp + 1) % HDA_UNSOL_QUEUE_SIZE;
404 unsol->rp = rp;
405 rp <<= 1;
406 res = unsol->queue[rp];
407 caddr = unsol->queue[rp + 1];
Takashi Iwai0ba21762007-04-16 11:29:14 +0200408 if (!(caddr & (1 << 4))) /* no unsolicited event? */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700409 continue;
410 codec = bus->caddr_tbl[caddr & 0x0f];
411 if (codec && codec->patch_ops.unsol_event)
412 codec->patch_ops.unsol_event(codec, res);
413 }
414}
415
416/*
417 * initialize unsolicited queue
418 */
Takashi Iwai6c1f45e2008-07-30 15:01:45 +0200419static int init_unsol_queue(struct hda_bus *bus)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700420{
421 struct hda_bus_unsolicited *unsol;
422
Takashi Iwai9f146bb2005-11-17 11:07:49 +0100423 if (bus->unsol) /* already initialized */
424 return 0;
425
Takashi Iwaie560d8d2005-09-09 14:21:46 +0200426 unsol = kzalloc(sizeof(*unsol), GFP_KERNEL);
Takashi Iwai0ba21762007-04-16 11:29:14 +0200427 if (!unsol) {
428 snd_printk(KERN_ERR "hda_codec: "
429 "can't allocate unsolicited queue\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700430 return -ENOMEM;
431 }
David Howellsc4028952006-11-22 14:57:56 +0000432 INIT_WORK(&unsol->work, process_unsol_events);
433 unsol->bus = bus;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700434 bus->unsol = unsol;
435 return 0;
436}
437
438/*
439 * destructor
440 */
441static void snd_hda_codec_free(struct hda_codec *codec);
442
443static int snd_hda_bus_free(struct hda_bus *bus)
444{
Takashi Iwai0ba21762007-04-16 11:29:14 +0200445 struct hda_codec *codec, *n;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700446
Takashi Iwai0ba21762007-04-16 11:29:14 +0200447 if (!bus)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700448 return 0;
Takashi Iwai6acaed32009-01-12 10:09:24 +0100449 if (bus->workq)
450 flush_workqueue(bus->workq);
451 if (bus->unsol)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700452 kfree(bus->unsol);
Takashi Iwai0ba21762007-04-16 11:29:14 +0200453 list_for_each_entry_safe(codec, n, &bus->codec_list, list) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700454 snd_hda_codec_free(codec);
455 }
456 if (bus->ops.private_free)
457 bus->ops.private_free(bus);
Takashi Iwai6acaed32009-01-12 10:09:24 +0100458 if (bus->workq)
459 destroy_workqueue(bus->workq);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700460 kfree(bus);
461 return 0;
462}
463
Takashi Iwaic8b6bf92005-11-17 14:57:47 +0100464static int snd_hda_bus_dev_free(struct snd_device *device)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700465{
466 struct hda_bus *bus = device->device_data;
Takashi Iwaib94d35392008-11-21 09:08:06 +0100467 bus->shutdown = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700468 return snd_hda_bus_free(bus);
469}
470
Takashi Iwaid7ffba12008-07-30 15:01:46 +0200471#ifdef CONFIG_SND_HDA_HWDEP
472static int snd_hda_bus_dev_register(struct snd_device *device)
473{
474 struct hda_bus *bus = device->device_data;
475 struct hda_codec *codec;
476 list_for_each_entry(codec, &bus->codec_list, list) {
477 snd_hda_hwdep_add_sysfs(codec);
478 }
479 return 0;
480}
481#else
482#define snd_hda_bus_dev_register NULL
483#endif
484
Linus Torvalds1da177e2005-04-16 15:20:36 -0700485/**
486 * snd_hda_bus_new - create a HDA bus
487 * @card: the card entry
488 * @temp: the template for hda_bus information
489 * @busp: the pointer to store the created bus instance
490 *
491 * Returns 0 if successful, or a negative error code.
492 */
Takashi Iwai1289e9e2008-11-27 15:47:11 +0100493int /*__devinit*/ snd_hda_bus_new(struct snd_card *card,
Takashi Iwai756e2b02007-04-16 11:27:07 +0200494 const struct hda_bus_template *temp,
495 struct hda_bus **busp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700496{
497 struct hda_bus *bus;
498 int err;
Takashi Iwaic8b6bf92005-11-17 14:57:47 +0100499 static struct snd_device_ops dev_ops = {
Takashi Iwaid7ffba12008-07-30 15:01:46 +0200500 .dev_register = snd_hda_bus_dev_register,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700501 .dev_free = snd_hda_bus_dev_free,
502 };
503
Takashi Iwaida3cec32008-08-08 17:12:14 +0200504 if (snd_BUG_ON(!temp))
505 return -EINVAL;
506 if (snd_BUG_ON(!temp->ops.command || !temp->ops.get_response))
507 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700508
509 if (busp)
510 *busp = NULL;
511
Takashi Iwaie560d8d2005-09-09 14:21:46 +0200512 bus = kzalloc(sizeof(*bus), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700513 if (bus == NULL) {
514 snd_printk(KERN_ERR "can't allocate struct hda_bus\n");
515 return -ENOMEM;
516 }
517
518 bus->card = card;
519 bus->private_data = temp->private_data;
520 bus->pci = temp->pci;
521 bus->modelname = temp->modelname;
Takashi Iwaifee2fba2008-11-27 12:43:28 +0100522 bus->power_save = temp->power_save;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700523 bus->ops = temp->ops;
524
Ingo Molnar62932df2006-01-16 16:34:20 +0100525 mutex_init(&bus->cmd_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700526 INIT_LIST_HEAD(&bus->codec_list);
527
Takashi Iwaie8c0ee52009-02-05 07:34:28 +0100528 snprintf(bus->workq_name, sizeof(bus->workq_name),
529 "hd-audio%d", card->number);
530 bus->workq = create_singlethread_workqueue(bus->workq_name);
Takashi Iwai6acaed32009-01-12 10:09:24 +0100531 if (!bus->workq) {
Takashi Iwaie8c0ee52009-02-05 07:34:28 +0100532 snd_printk(KERN_ERR "cannot create workqueue %s\n",
533 bus->workq_name);
Takashi Iwai6acaed32009-01-12 10:09:24 +0100534 kfree(bus);
535 return -ENOMEM;
536 }
537
Takashi Iwai0ba21762007-04-16 11:29:14 +0200538 err = snd_device_new(card, SNDRV_DEV_BUS, bus, &dev_ops);
539 if (err < 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700540 snd_hda_bus_free(bus);
541 return err;
542 }
543 if (busp)
544 *busp = bus;
545 return 0;
546}
Takashi Iwaiff7a3262008-11-28 15:17:06 +0100547EXPORT_SYMBOL_HDA(snd_hda_bus_new);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700548
Takashi Iwai82467612007-07-27 19:15:54 +0200549#ifdef CONFIG_SND_HDA_GENERIC
550#define is_generic_config(codec) \
Takashi Iwaif44ac832008-07-30 15:01:45 +0200551 (codec->modelname && !strcmp(codec->modelname, "generic"))
Takashi Iwai82467612007-07-27 19:15:54 +0200552#else
553#define is_generic_config(codec) 0
554#endif
555
Takashi Iwai645f10c2008-11-28 15:07:37 +0100556#ifdef MODULE
Takashi Iwai1289e9e2008-11-27 15:47:11 +0100557#define HDA_MODREQ_MAX_COUNT 2 /* two request_modules()'s */
558#else
Takashi Iwai645f10c2008-11-28 15:07:37 +0100559#define HDA_MODREQ_MAX_COUNT 0 /* all presets are statically linked */
Takashi Iwai1289e9e2008-11-27 15:47:11 +0100560#endif
561
Linus Torvalds1da177e2005-04-16 15:20:36 -0700562/*
563 * find a matching codec preset
564 */
Takashi Iwai6c1f45e2008-07-30 15:01:45 +0200565static const struct hda_codec_preset *
Takashi Iwai756e2b02007-04-16 11:27:07 +0200566find_codec_preset(struct hda_codec *codec)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700567{
Takashi Iwai1289e9e2008-11-27 15:47:11 +0100568 struct hda_codec_preset_list *tbl;
569 const struct hda_codec_preset *preset;
570 int mod_requested = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700571
Takashi Iwai82467612007-07-27 19:15:54 +0200572 if (is_generic_config(codec))
Takashi Iwaid5ad6302007-03-07 15:55:59 +0100573 return NULL; /* use the generic parser */
574
Takashi Iwai1289e9e2008-11-27 15:47:11 +0100575 again:
576 mutex_lock(&preset_mutex);
577 list_for_each_entry(tbl, &hda_preset_tables, list) {
578 if (!try_module_get(tbl->owner)) {
579 snd_printk(KERN_ERR "hda_codec: cannot module_get\n");
580 continue;
581 }
582 for (preset = tbl->preset; preset->id; preset++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700583 u32 mask = preset->mask;
Marc Boucherca7cfae2008-01-22 15:32:25 +0100584 if (preset->afg && preset->afg != codec->afg)
585 continue;
586 if (preset->mfg && preset->mfg != codec->mfg)
587 continue;
Takashi Iwai0ba21762007-04-16 11:29:14 +0200588 if (!mask)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700589 mask = ~0;
Takashi Iwai9c7f8522006-06-28 15:08:22 +0200590 if (preset->id == (codec->vendor_id & mask) &&
Takashi Iwai0ba21762007-04-16 11:29:14 +0200591 (!preset->rev ||
Takashi Iwai1289e9e2008-11-27 15:47:11 +0100592 preset->rev == codec->revision_id)) {
593 mutex_unlock(&preset_mutex);
594 codec->owner = tbl->owner;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700595 return preset;
Takashi Iwai1289e9e2008-11-27 15:47:11 +0100596 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700597 }
Takashi Iwai1289e9e2008-11-27 15:47:11 +0100598 module_put(tbl->owner);
599 }
600 mutex_unlock(&preset_mutex);
601
602 if (mod_requested < HDA_MODREQ_MAX_COUNT) {
603 char name[32];
604 if (!mod_requested)
605 snprintf(name, sizeof(name), "snd-hda-codec-id:%08x",
606 codec->vendor_id);
607 else
608 snprintf(name, sizeof(name), "snd-hda-codec-id:%04x*",
609 (codec->vendor_id >> 16) & 0xffff);
610 request_module(name);
611 mod_requested++;
612 goto again;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700613 }
614 return NULL;
615}
616
617/*
Takashi Iwaif44ac832008-07-30 15:01:45 +0200618 * get_codec_name - store the codec name
Linus Torvalds1da177e2005-04-16 15:20:36 -0700619 */
Takashi Iwaif44ac832008-07-30 15:01:45 +0200620static int get_codec_name(struct hda_codec *codec)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700621{
622 const struct hda_vendor_id *c;
623 const char *vendor = NULL;
624 u16 vendor_id = codec->vendor_id >> 16;
Takashi Iwaif44ac832008-07-30 15:01:45 +0200625 char tmp[16], name[32];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700626
627 for (c = hda_vendor_ids; c->id; c++) {
628 if (c->id == vendor_id) {
629 vendor = c->name;
630 break;
631 }
632 }
Takashi Iwai0ba21762007-04-16 11:29:14 +0200633 if (!vendor) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700634 sprintf(tmp, "Generic %04x", vendor_id);
635 vendor = tmp;
636 }
637 if (codec->preset && codec->preset->name)
Takashi Iwaif44ac832008-07-30 15:01:45 +0200638 snprintf(name, sizeof(name), "%s %s", vendor,
639 codec->preset->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700640 else
Takashi Iwaif44ac832008-07-30 15:01:45 +0200641 snprintf(name, sizeof(name), "%s ID %x", vendor,
Takashi Iwai0ba21762007-04-16 11:29:14 +0200642 codec->vendor_id & 0xffff);
Takashi Iwaif44ac832008-07-30 15:01:45 +0200643 codec->name = kstrdup(name, GFP_KERNEL);
644 if (!codec->name)
645 return -ENOMEM;
646 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700647}
648
649/*
Sasha Khapyorsky673b6832005-08-11 11:00:16 +0200650 * look for an AFG and MFG nodes
Linus Torvalds1da177e2005-04-16 15:20:36 -0700651 */
Takashi Iwai1289e9e2008-11-27 15:47:11 +0100652static void /*__devinit*/ setup_fg_nodes(struct hda_codec *codec)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700653{
654 int i, total_nodes;
655 hda_nid_t nid;
656
657 total_nodes = snd_hda_get_sub_nodes(codec, AC_NODE_ROOT, &nid);
658 for (i = 0; i < total_nodes; i++, nid++) {
Pascal de Bruijn234b4342009-03-23 11:15:59 +0100659 codec->function_id = snd_hda_param_read(codec, nid,
660 AC_PAR_FUNCTION_TYPE) & 0xff;
661 switch (codec->function_id) {
Sasha Khapyorsky673b6832005-08-11 11:00:16 +0200662 case AC_GRP_AUDIO_FUNCTION:
663 codec->afg = nid;
664 break;
665 case AC_GRP_MODEM_FUNCTION:
666 codec->mfg = nid;
667 break;
668 default:
669 break;
670 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700671 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700672}
673
674/*
Takashi Iwai54d17402005-11-21 16:33:22 +0100675 * read widget caps for each widget and store in cache
676 */
677static int read_widget_caps(struct hda_codec *codec, hda_nid_t fg_node)
678{
679 int i;
680 hda_nid_t nid;
681
682 codec->num_nodes = snd_hda_get_sub_nodes(codec, fg_node,
683 &codec->start_nid);
684 codec->wcaps = kmalloc(codec->num_nodes * 4, GFP_KERNEL);
Takashi Iwai0ba21762007-04-16 11:29:14 +0200685 if (!codec->wcaps)
Takashi Iwai54d17402005-11-21 16:33:22 +0100686 return -ENOMEM;
687 nid = codec->start_nid;
688 for (i = 0; i < codec->num_nodes; i++, nid++)
689 codec->wcaps[i] = snd_hda_param_read(codec, nid,
690 AC_PAR_AUDIO_WIDGET_CAP);
691 return 0;
692}
693
Takashi Iwai3be14142009-02-20 14:11:16 +0100694/* read all pin default configurations and save codec->init_pins */
695static int read_pin_defaults(struct hda_codec *codec)
696{
697 int i;
698 hda_nid_t nid = codec->start_nid;
699
700 for (i = 0; i < codec->num_nodes; i++, nid++) {
701 struct hda_pincfg *pin;
702 unsigned int wcaps = get_wcaps(codec, nid);
703 unsigned int wid_type = (wcaps & AC_WCAP_TYPE) >>
704 AC_WCAP_TYPE_SHIFT;
705 if (wid_type != AC_WID_PIN)
706 continue;
707 pin = snd_array_new(&codec->init_pins);
708 if (!pin)
709 return -ENOMEM;
710 pin->nid = nid;
711 pin->cfg = snd_hda_codec_read(codec, nid, 0,
712 AC_VERB_GET_CONFIG_DEFAULT, 0);
713 }
714 return 0;
715}
716
717/* look up the given pin config list and return the item matching with NID */
718static struct hda_pincfg *look_up_pincfg(struct hda_codec *codec,
719 struct snd_array *array,
720 hda_nid_t nid)
721{
722 int i;
723 for (i = 0; i < array->used; i++) {
724 struct hda_pincfg *pin = snd_array_elem(array, i);
725 if (pin->nid == nid)
726 return pin;
727 }
728 return NULL;
729}
730
731/* write a config value for the given NID */
732static void set_pincfg(struct hda_codec *codec, hda_nid_t nid,
733 unsigned int cfg)
734{
735 int i;
736 for (i = 0; i < 4; i++) {
737 snd_hda_codec_write(codec, nid, 0,
738 AC_VERB_SET_CONFIG_DEFAULT_BYTES_0 + i,
739 cfg & 0xff);
740 cfg >>= 8;
741 }
742}
743
744/* set the current pin config value for the given NID.
745 * the value is cached, and read via snd_hda_codec_get_pincfg()
746 */
747int snd_hda_add_pincfg(struct hda_codec *codec, struct snd_array *list,
748 hda_nid_t nid, unsigned int cfg)
749{
750 struct hda_pincfg *pin;
Takashi Iwai5e7b8e02009-02-23 09:45:59 +0100751 unsigned int oldcfg;
Takashi Iwai3be14142009-02-20 14:11:16 +0100752
Takashi Iwai5e7b8e02009-02-23 09:45:59 +0100753 oldcfg = snd_hda_codec_get_pincfg(codec, nid);
Takashi Iwai3be14142009-02-20 14:11:16 +0100754 pin = look_up_pincfg(codec, list, nid);
755 if (!pin) {
756 pin = snd_array_new(list);
757 if (!pin)
758 return -ENOMEM;
759 pin->nid = nid;
760 }
761 pin->cfg = cfg;
Takashi Iwai5e7b8e02009-02-23 09:45:59 +0100762
763 /* change only when needed; e.g. if the pincfg is already present
764 * in user_pins[], don't write it
765 */
766 cfg = snd_hda_codec_get_pincfg(codec, nid);
767 if (oldcfg != cfg)
768 set_pincfg(codec, nid, cfg);
Takashi Iwai3be14142009-02-20 14:11:16 +0100769 return 0;
770}
771
772int snd_hda_codec_set_pincfg(struct hda_codec *codec,
773 hda_nid_t nid, unsigned int cfg)
774{
Takashi Iwai346ff702009-02-23 09:42:57 +0100775 return snd_hda_add_pincfg(codec, &codec->driver_pins, nid, cfg);
Takashi Iwai3be14142009-02-20 14:11:16 +0100776}
777EXPORT_SYMBOL_HDA(snd_hda_codec_set_pincfg);
778
779/* get the current pin config value of the given pin NID */
780unsigned int snd_hda_codec_get_pincfg(struct hda_codec *codec, hda_nid_t nid)
781{
782 struct hda_pincfg *pin;
783
Takashi Iwai3be14142009-02-20 14:11:16 +0100784#ifdef CONFIG_SND_HDA_HWDEP
Takashi Iwai346ff702009-02-23 09:42:57 +0100785 pin = look_up_pincfg(codec, &codec->user_pins, nid);
Takashi Iwai3be14142009-02-20 14:11:16 +0100786 if (pin)
787 return pin->cfg;
788#endif
Takashi Iwai5e7b8e02009-02-23 09:45:59 +0100789 pin = look_up_pincfg(codec, &codec->driver_pins, nid);
790 if (pin)
791 return pin->cfg;
Takashi Iwai3be14142009-02-20 14:11:16 +0100792 pin = look_up_pincfg(codec, &codec->init_pins, nid);
793 if (pin)
794 return pin->cfg;
795 return 0;
796}
797EXPORT_SYMBOL_HDA(snd_hda_codec_get_pincfg);
798
799/* restore all current pin configs */
800static void restore_pincfgs(struct hda_codec *codec)
801{
802 int i;
803 for (i = 0; i < codec->init_pins.used; i++) {
804 struct hda_pincfg *pin = snd_array_elem(&codec->init_pins, i);
805 set_pincfg(codec, pin->nid,
806 snd_hda_codec_get_pincfg(codec, pin->nid));
807 }
808}
Takashi Iwai54d17402005-11-21 16:33:22 +0100809
Takashi Iwai01751f52007-08-10 16:59:39 +0200810static void init_hda_cache(struct hda_cache_rec *cache,
811 unsigned int record_size);
Takashi Iwai1fcaee62007-08-23 00:01:09 +0200812static void free_hda_cache(struct hda_cache_rec *cache);
Takashi Iwai01751f52007-08-10 16:59:39 +0200813
Takashi Iwai3be14142009-02-20 14:11:16 +0100814/* restore the initial pin cfgs and release all pincfg lists */
815static void restore_init_pincfgs(struct hda_codec *codec)
816{
Takashi Iwai346ff702009-02-23 09:42:57 +0100817 /* first free driver_pins and user_pins, then call restore_pincfg
Takashi Iwai3be14142009-02-20 14:11:16 +0100818 * so that only the values in init_pins are restored
819 */
Takashi Iwai346ff702009-02-23 09:42:57 +0100820 snd_array_free(&codec->driver_pins);
Takashi Iwai3be14142009-02-20 14:11:16 +0100821#ifdef CONFIG_SND_HDA_HWDEP
Takashi Iwai346ff702009-02-23 09:42:57 +0100822 snd_array_free(&codec->user_pins);
Takashi Iwai3be14142009-02-20 14:11:16 +0100823#endif
824 restore_pincfgs(codec);
825 snd_array_free(&codec->init_pins);
826}
827
Takashi Iwai54d17402005-11-21 16:33:22 +0100828/*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700829 * codec destructor
830 */
831static void snd_hda_codec_free(struct hda_codec *codec)
832{
Takashi Iwai0ba21762007-04-16 11:29:14 +0200833 if (!codec)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700834 return;
Takashi Iwai3be14142009-02-20 14:11:16 +0100835 restore_init_pincfgs(codec);
Takashi Iwaicb53c622007-08-10 17:21:45 +0200836#ifdef CONFIG_SND_HDA_POWER_SAVE
837 cancel_delayed_work(&codec->power_work);
Takashi Iwai6acaed32009-01-12 10:09:24 +0100838 flush_workqueue(codec->bus->workq);
Takashi Iwaicb53c622007-08-10 17:21:45 +0200839#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700840 list_del(&codec->list);
Takashi Iwaid13bd412008-07-30 15:01:45 +0200841 snd_array_free(&codec->mixers);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700842 codec->bus->caddr_tbl[codec->addr] = NULL;
843 if (codec->patch_ops.free)
844 codec->patch_ops.free(codec);
Takashi Iwai1289e9e2008-11-27 15:47:11 +0100845 module_put(codec->owner);
Takashi Iwai01751f52007-08-10 16:59:39 +0200846 free_hda_cache(&codec->amp_cache);
Takashi Iwaib3ac5632007-08-10 17:03:40 +0200847 free_hda_cache(&codec->cmd_cache);
Takashi Iwaif44ac832008-07-30 15:01:45 +0200848 kfree(codec->name);
849 kfree(codec->modelname);
Takashi Iwai54d17402005-11-21 16:33:22 +0100850 kfree(codec->wcaps);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700851 kfree(codec);
852}
853
Takashi Iwaibb6ac722009-03-13 09:02:42 +0100854static void hda_set_power_state(struct hda_codec *codec, hda_nid_t fg,
855 unsigned int power_state);
856
Linus Torvalds1da177e2005-04-16 15:20:36 -0700857/**
858 * snd_hda_codec_new - create a HDA codec
859 * @bus: the bus to assign
860 * @codec_addr: the codec address
861 * @codecp: the pointer to store the generated codec
862 *
863 * Returns 0 if successful, or a negative error code.
864 */
Takashi Iwai1289e9e2008-11-27 15:47:11 +0100865int /*__devinit*/ snd_hda_codec_new(struct hda_bus *bus, unsigned int codec_addr,
Takashi Iwaid4d9cd032008-12-19 15:19:11 +0100866 int do_init, struct hda_codec **codecp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700867{
868 struct hda_codec *codec;
Jaroslav Kyselaba443682008-08-13 20:55:32 +0200869 char component[31];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700870 int err;
871
Takashi Iwaida3cec32008-08-08 17:12:14 +0200872 if (snd_BUG_ON(!bus))
873 return -EINVAL;
874 if (snd_BUG_ON(codec_addr > HDA_MAX_CODEC_ADDRESS))
875 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700876
877 if (bus->caddr_tbl[codec_addr]) {
Takashi Iwai0ba21762007-04-16 11:29:14 +0200878 snd_printk(KERN_ERR "hda_codec: "
879 "address 0x%x is already occupied\n", codec_addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700880 return -EBUSY;
881 }
882
Takashi Iwaie560d8d2005-09-09 14:21:46 +0200883 codec = kzalloc(sizeof(*codec), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700884 if (codec == NULL) {
885 snd_printk(KERN_ERR "can't allocate struct hda_codec\n");
886 return -ENOMEM;
887 }
888
889 codec->bus = bus;
890 codec->addr = codec_addr;
Ingo Molnar62932df2006-01-16 16:34:20 +0100891 mutex_init(&codec->spdif_mutex);
Wu Fengguang5a9e02e2009-01-09 16:45:24 +0800892 mutex_init(&codec->control_mutex);
Takashi Iwai01751f52007-08-10 16:59:39 +0200893 init_hda_cache(&codec->amp_cache, sizeof(struct hda_amp_info));
Takashi Iwaib3ac5632007-08-10 17:03:40 +0200894 init_hda_cache(&codec->cmd_cache, sizeof(struct hda_cache_head));
Takashi Iwaid13bd412008-07-30 15:01:45 +0200895 snd_array_init(&codec->mixers, sizeof(struct snd_kcontrol *), 32);
Takashi Iwai3be14142009-02-20 14:11:16 +0100896 snd_array_init(&codec->init_pins, sizeof(struct hda_pincfg), 16);
Takashi Iwai346ff702009-02-23 09:42:57 +0100897 snd_array_init(&codec->driver_pins, sizeof(struct hda_pincfg), 16);
Takashi Iwai6c1f45e2008-07-30 15:01:45 +0200898 if (codec->bus->modelname) {
899 codec->modelname = kstrdup(codec->bus->modelname, GFP_KERNEL);
900 if (!codec->modelname) {
901 snd_hda_codec_free(codec);
902 return -ENODEV;
903 }
904 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700905
Takashi Iwaicb53c622007-08-10 17:21:45 +0200906#ifdef CONFIG_SND_HDA_POWER_SAVE
907 INIT_DELAYED_WORK(&codec->power_work, hda_power_work);
908 /* snd_hda_codec_new() marks the codec as power-up, and leave it as is.
909 * the caller has to power down appropriatley after initialization
910 * phase.
911 */
912 hda_keep_power_on(codec);
913#endif
914
Linus Torvalds1da177e2005-04-16 15:20:36 -0700915 list_add_tail(&codec->list, &bus->codec_list);
916 bus->caddr_tbl[codec_addr] = codec;
917
Takashi Iwai0ba21762007-04-16 11:29:14 +0200918 codec->vendor_id = snd_hda_param_read(codec, AC_NODE_ROOT,
919 AC_PAR_VENDOR_ID);
Takashi Iwai111d3af2006-02-16 18:17:58 +0100920 if (codec->vendor_id == -1)
921 /* read again, hopefully the access method was corrected
922 * in the last read...
923 */
924 codec->vendor_id = snd_hda_param_read(codec, AC_NODE_ROOT,
925 AC_PAR_VENDOR_ID);
Takashi Iwai0ba21762007-04-16 11:29:14 +0200926 codec->subsystem_id = snd_hda_param_read(codec, AC_NODE_ROOT,
927 AC_PAR_SUBSYSTEM_ID);
928 codec->revision_id = snd_hda_param_read(codec, AC_NODE_ROOT,
929 AC_PAR_REV_ID);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700930
Sasha Khapyorsky673b6832005-08-11 11:00:16 +0200931 setup_fg_nodes(codec);
Takashi Iwai0ba21762007-04-16 11:29:14 +0200932 if (!codec->afg && !codec->mfg) {
Sasha Khapyorsky673b6832005-08-11 11:00:16 +0200933 snd_printdd("hda_codec: no AFG or MFG node found\n");
Takashi Iwai3be14142009-02-20 14:11:16 +0100934 err = -ENODEV;
935 goto error;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700936 }
937
Takashi Iwai3be14142009-02-20 14:11:16 +0100938 err = read_widget_caps(codec, codec->afg ? codec->afg : codec->mfg);
939 if (err < 0) {
Takashi Iwai54d17402005-11-21 16:33:22 +0100940 snd_printk(KERN_ERR "hda_codec: cannot malloc\n");
Takashi Iwai3be14142009-02-20 14:11:16 +0100941 goto error;
Takashi Iwai54d17402005-11-21 16:33:22 +0100942 }
Takashi Iwai3be14142009-02-20 14:11:16 +0100943 err = read_pin_defaults(codec);
944 if (err < 0)
945 goto error;
Takashi Iwai54d17402005-11-21 16:33:22 +0100946
Takashi Iwai0ba21762007-04-16 11:29:14 +0200947 if (!codec->subsystem_id) {
Takashi Iwai86284e42005-10-11 15:05:54 +0200948 hda_nid_t nid = codec->afg ? codec->afg : codec->mfg;
Takashi Iwai0ba21762007-04-16 11:29:14 +0200949 codec->subsystem_id =
950 snd_hda_codec_read(codec, nid, 0,
951 AC_VERB_GET_SUBSYSTEM_ID, 0);
Takashi Iwai86284e42005-10-11 15:05:54 +0200952 }
Takashi Iwaif44ac832008-07-30 15:01:45 +0200953 if (bus->modelname)
954 codec->modelname = kstrdup(bus->modelname, GFP_KERNEL);
Takashi Iwai86284e42005-10-11 15:05:54 +0200955
Takashi Iwaibb6ac722009-03-13 09:02:42 +0100956 /* power-up all before initialization */
957 hda_set_power_state(codec,
958 codec->afg ? codec->afg : codec->mfg,
959 AC_PWRST_D0);
960
Takashi Iwaid4d9cd032008-12-19 15:19:11 +0100961 if (do_init) {
962 err = snd_hda_codec_configure(codec);
Takashi Iwai3be14142009-02-20 14:11:16 +0100963 if (err < 0)
964 goto error;
Takashi Iwai6c1f45e2008-07-30 15:01:45 +0200965 }
966 snd_hda_codec_proc_new(codec);
967
Takashi Iwai6c1f45e2008-07-30 15:01:45 +0200968 snd_hda_create_hwdep(codec);
Takashi Iwai6c1f45e2008-07-30 15:01:45 +0200969
970 sprintf(component, "HDA:%08x,%08x,%08x", codec->vendor_id,
971 codec->subsystem_id, codec->revision_id);
972 snd_component_add(codec->bus->card, component);
973
974 if (codecp)
975 *codecp = codec;
976 return 0;
Takashi Iwai3be14142009-02-20 14:11:16 +0100977
978 error:
979 snd_hda_codec_free(codec);
980 return err;
Takashi Iwai6c1f45e2008-07-30 15:01:45 +0200981}
Takashi Iwaiff7a3262008-11-28 15:17:06 +0100982EXPORT_SYMBOL_HDA(snd_hda_codec_new);
Takashi Iwai6c1f45e2008-07-30 15:01:45 +0200983
984int snd_hda_codec_configure(struct hda_codec *codec)
985{
986 int err;
987
Takashi Iwaid5ad6302007-03-07 15:55:59 +0100988 codec->preset = find_codec_preset(codec);
Takashi Iwaif44ac832008-07-30 15:01:45 +0200989 if (!codec->name) {
990 err = get_codec_name(codec);
991 if (err < 0)
992 return err;
993 }
Takashi Iwai43ea1d42007-04-26 19:12:08 +0200994 /* audio codec should override the mixer name */
Takashi Iwaif44ac832008-07-30 15:01:45 +0200995 if (codec->afg || !*codec->bus->card->mixername)
996 strlcpy(codec->bus->card->mixername, codec->name,
997 sizeof(codec->bus->card->mixername));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700998
Takashi Iwai82467612007-07-27 19:15:54 +0200999 if (is_generic_config(codec)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001000 err = snd_hda_parse_generic_codec(codec);
Takashi Iwai82467612007-07-27 19:15:54 +02001001 goto patched;
1002 }
Takashi Iwai82467612007-07-27 19:15:54 +02001003 if (codec->preset && codec->preset->patch) {
1004 err = codec->preset->patch(codec);
1005 goto patched;
1006 }
1007
1008 /* call the default parser */
Takashi Iwai82467612007-07-27 19:15:54 +02001009 err = snd_hda_parse_generic_codec(codec);
Takashi Iwai35a1e0c2007-10-19 08:13:40 +02001010 if (err < 0)
1011 printk(KERN_ERR "hda-codec: No codec parser is available\n");
Takashi Iwai82467612007-07-27 19:15:54 +02001012
1013 patched:
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001014 if (!err && codec->patch_ops.unsol_event)
1015 err = init_unsol_queue(codec->bus);
1016 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001017}
1018
1019/**
1020 * snd_hda_codec_setup_stream - set up the codec for streaming
1021 * @codec: the CODEC to set up
1022 * @nid: the NID to set up
1023 * @stream_tag: stream tag to pass, it's between 0x1 and 0xf.
1024 * @channel_id: channel id to pass, zero based.
1025 * @format: stream format.
1026 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02001027void snd_hda_codec_setup_stream(struct hda_codec *codec, hda_nid_t nid,
1028 u32 stream_tag,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001029 int channel_id, int format)
1030{
Takashi Iwai0ba21762007-04-16 11:29:14 +02001031 if (!nid)
Takashi Iwaid21b37e2005-04-20 13:45:55 +02001032 return;
1033
Takashi Iwai0ba21762007-04-16 11:29:14 +02001034 snd_printdd("hda_codec_setup_stream: "
1035 "NID=0x%x, stream=0x%x, channel=%d, format=0x%x\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07001036 nid, stream_tag, channel_id, format);
1037 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CHANNEL_STREAMID,
1038 (stream_tag << 4) | channel_id);
1039 msleep(1);
1040 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_STREAM_FORMAT, format);
1041}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001042EXPORT_SYMBOL_HDA(snd_hda_codec_setup_stream);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001043
Takashi Iwai888afa12008-03-18 09:57:50 +01001044void snd_hda_codec_cleanup_stream(struct hda_codec *codec, hda_nid_t nid)
1045{
1046 if (!nid)
1047 return;
1048
1049 snd_printdd("hda_codec_cleanup_stream: NID=0x%x\n", nid);
1050 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CHANNEL_STREAMID, 0);
1051#if 0 /* keep the format */
1052 msleep(1);
1053 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_STREAM_FORMAT, 0);
1054#endif
1055}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001056EXPORT_SYMBOL_HDA(snd_hda_codec_cleanup_stream);
Takashi Iwai888afa12008-03-18 09:57:50 +01001057
Linus Torvalds1da177e2005-04-16 15:20:36 -07001058/*
1059 * amp access functions
1060 */
1061
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001062/* FIXME: more better hash key? */
1063#define HDA_HASH_KEY(nid,dir,idx) (u32)((nid) + ((idx) << 16) + ((dir) << 24))
Takashi Iwai1327a322009-03-23 13:07:47 +01001064#define HDA_HASH_PINCAP_KEY(nid) (u32)((nid) + (0x02 << 24))
Takashi Iwai92c7c8a2009-03-24 07:32:14 +01001065#define HDA_HASH_PARPCM_KEY(nid) (u32)((nid) + (0x03 << 24))
1066#define HDA_HASH_PARSTR_KEY(nid) (u32)((nid) + (0x04 << 24))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001067#define INFO_AMP_CAPS (1<<0)
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001068#define INFO_AMP_VOL(ch) (1 << (1 + (ch)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001069
1070/* initialize the hash table */
Takashi Iwai1289e9e2008-11-27 15:47:11 +01001071static void /*__devinit*/ init_hda_cache(struct hda_cache_rec *cache,
Takashi Iwai01751f52007-08-10 16:59:39 +02001072 unsigned int record_size)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001073{
Takashi Iwai01751f52007-08-10 16:59:39 +02001074 memset(cache, 0, sizeof(*cache));
1075 memset(cache->hash, 0xff, sizeof(cache->hash));
Takashi Iwai603c4012008-07-30 15:01:44 +02001076 snd_array_init(&cache->buf, record_size, 64);
Takashi Iwai01751f52007-08-10 16:59:39 +02001077}
1078
Takashi Iwai1fcaee62007-08-23 00:01:09 +02001079static void free_hda_cache(struct hda_cache_rec *cache)
Takashi Iwai01751f52007-08-10 16:59:39 +02001080{
Takashi Iwai603c4012008-07-30 15:01:44 +02001081 snd_array_free(&cache->buf);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001082}
1083
1084/* query the hash. allocate an entry if not found. */
Takashi Iwai01751f52007-08-10 16:59:39 +02001085static struct hda_cache_head *get_alloc_hash(struct hda_cache_rec *cache,
1086 u32 key)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001087{
Takashi Iwai01751f52007-08-10 16:59:39 +02001088 u16 idx = key % (u16)ARRAY_SIZE(cache->hash);
1089 u16 cur = cache->hash[idx];
1090 struct hda_cache_head *info;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001091
1092 while (cur != 0xffff) {
Takashi Iwaif43aa022008-11-10 16:24:26 +01001093 info = snd_array_elem(&cache->buf, cur);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001094 if (info->key == key)
1095 return info;
1096 cur = info->next;
1097 }
1098
1099 /* add a new hash entry */
Takashi Iwai603c4012008-07-30 15:01:44 +02001100 info = snd_array_new(&cache->buf);
Takashi Iwaic2174292008-11-07 00:23:30 +01001101 if (!info)
1102 return NULL;
Takashi Iwaif43aa022008-11-10 16:24:26 +01001103 cur = snd_array_index(&cache->buf, info);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001104 info->key = key;
Takashi Iwai01751f52007-08-10 16:59:39 +02001105 info->val = 0;
1106 info->next = cache->hash[idx];
1107 cache->hash[idx] = cur;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001108
1109 return info;
1110}
1111
Takashi Iwai01751f52007-08-10 16:59:39 +02001112/* query and allocate an amp hash entry */
1113static inline struct hda_amp_info *
1114get_alloc_amp_hash(struct hda_codec *codec, u32 key)
1115{
1116 return (struct hda_amp_info *)get_alloc_hash(&codec->amp_cache, key);
1117}
1118
Linus Torvalds1da177e2005-04-16 15:20:36 -07001119/*
1120 * query AMP capabilities for the given widget and direction
1121 */
Matthew Ranostay09a99952008-01-24 11:49:21 +01001122u32 query_amp_caps(struct hda_codec *codec, hda_nid_t nid, int direction)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001123{
Takashi Iwai0ba21762007-04-16 11:29:14 +02001124 struct hda_amp_info *info;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001125
Takashi Iwai0ba21762007-04-16 11:29:14 +02001126 info = get_alloc_amp_hash(codec, HDA_HASH_KEY(nid, direction, 0));
1127 if (!info)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001128 return 0;
Takashi Iwai01751f52007-08-10 16:59:39 +02001129 if (!(info->head.val & INFO_AMP_CAPS)) {
Takashi Iwai0ba21762007-04-16 11:29:14 +02001130 if (!(get_wcaps(codec, nid) & AC_WCAP_AMP_OVRD))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001131 nid = codec->afg;
Takashi Iwai0ba21762007-04-16 11:29:14 +02001132 info->amp_caps = snd_hda_param_read(codec, nid,
1133 direction == HDA_OUTPUT ?
1134 AC_PAR_AMP_OUT_CAP :
1135 AC_PAR_AMP_IN_CAP);
Takashi Iwaib75e53f2007-05-10 16:56:09 +02001136 if (info->amp_caps)
Takashi Iwai01751f52007-08-10 16:59:39 +02001137 info->head.val |= INFO_AMP_CAPS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001138 }
1139 return info->amp_caps;
1140}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001141EXPORT_SYMBOL_HDA(query_amp_caps);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001142
Takashi Iwai897cc182007-05-29 19:01:37 +02001143int snd_hda_override_amp_caps(struct hda_codec *codec, hda_nid_t nid, int dir,
1144 unsigned int caps)
1145{
1146 struct hda_amp_info *info;
1147
1148 info = get_alloc_amp_hash(codec, HDA_HASH_KEY(nid, dir, 0));
1149 if (!info)
1150 return -EINVAL;
1151 info->amp_caps = caps;
Takashi Iwai01751f52007-08-10 16:59:39 +02001152 info->head.val |= INFO_AMP_CAPS;
Takashi Iwai897cc182007-05-29 19:01:37 +02001153 return 0;
1154}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001155EXPORT_SYMBOL_HDA(snd_hda_override_amp_caps);
Takashi Iwai897cc182007-05-29 19:01:37 +02001156
Takashi Iwai92c7c8a2009-03-24 07:32:14 +01001157static unsigned int
1158query_caps_hash(struct hda_codec *codec, hda_nid_t nid, u32 key,
1159 unsigned int (*func)(struct hda_codec *, hda_nid_t))
Takashi Iwai1327a322009-03-23 13:07:47 +01001160{
1161 struct hda_amp_info *info;
1162
Takashi Iwai92c7c8a2009-03-24 07:32:14 +01001163 info = get_alloc_amp_hash(codec, key);
Takashi Iwai1327a322009-03-23 13:07:47 +01001164 if (!info)
1165 return 0;
1166 if (!info->head.val) {
Takashi Iwai1327a322009-03-23 13:07:47 +01001167 info->head.val |= INFO_AMP_CAPS;
Takashi Iwai92c7c8a2009-03-24 07:32:14 +01001168 info->amp_caps = func(codec, nid);
Takashi Iwai1327a322009-03-23 13:07:47 +01001169 }
1170 return info->amp_caps;
1171}
Takashi Iwai92c7c8a2009-03-24 07:32:14 +01001172
1173static unsigned int read_pin_cap(struct hda_codec *codec, hda_nid_t nid)
1174{
1175 return snd_hda_param_read(codec, nid, AC_PAR_PIN_CAP);
1176}
1177
1178u32 snd_hda_query_pin_caps(struct hda_codec *codec, hda_nid_t nid)
1179{
1180 return query_caps_hash(codec, nid, HDA_HASH_PINCAP_KEY(nid),
1181 read_pin_cap);
1182}
Takashi Iwai1327a322009-03-23 13:07:47 +01001183EXPORT_SYMBOL_HDA(snd_hda_query_pin_caps);
1184
Linus Torvalds1da177e2005-04-16 15:20:36 -07001185/*
1186 * read the current volume to info
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001187 * if the cache exists, read the cache value.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001188 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02001189static unsigned int get_vol_mute(struct hda_codec *codec,
1190 struct hda_amp_info *info, hda_nid_t nid,
1191 int ch, int direction, int index)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001192{
1193 u32 val, parm;
1194
Takashi Iwai01751f52007-08-10 16:59:39 +02001195 if (info->head.val & INFO_AMP_VOL(ch))
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001196 return info->vol[ch];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001197
1198 parm = ch ? AC_AMP_GET_RIGHT : AC_AMP_GET_LEFT;
1199 parm |= direction == HDA_OUTPUT ? AC_AMP_GET_OUTPUT : AC_AMP_GET_INPUT;
1200 parm |= index;
Takashi Iwai0ba21762007-04-16 11:29:14 +02001201 val = snd_hda_codec_read(codec, nid, 0,
1202 AC_VERB_GET_AMP_GAIN_MUTE, parm);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001203 info->vol[ch] = val & 0xff;
Takashi Iwai01751f52007-08-10 16:59:39 +02001204 info->head.val |= INFO_AMP_VOL(ch);
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001205 return info->vol[ch];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001206}
1207
1208/*
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001209 * write the current volume in info to the h/w and update the cache
Linus Torvalds1da177e2005-04-16 15:20:36 -07001210 */
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001211static void put_vol_mute(struct hda_codec *codec, struct hda_amp_info *info,
Takashi Iwai0ba21762007-04-16 11:29:14 +02001212 hda_nid_t nid, int ch, int direction, int index,
1213 int val)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001214{
1215 u32 parm;
1216
1217 parm = ch ? AC_AMP_SET_RIGHT : AC_AMP_SET_LEFT;
1218 parm |= direction == HDA_OUTPUT ? AC_AMP_SET_OUTPUT : AC_AMP_SET_INPUT;
1219 parm |= index << AC_AMP_SET_INDEX_SHIFT;
1220 parm |= val;
1221 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, parm);
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001222 info->vol[ch] = val;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001223}
1224
1225/*
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001226 * read AMP value. The volume is between 0 to 0x7f, 0x80 = mute bit.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001227 */
Takashi Iwai834be882006-03-01 14:16:17 +01001228int snd_hda_codec_amp_read(struct hda_codec *codec, hda_nid_t nid, int ch,
1229 int direction, int index)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001230{
Takashi Iwai0ba21762007-04-16 11:29:14 +02001231 struct hda_amp_info *info;
1232 info = get_alloc_amp_hash(codec, HDA_HASH_KEY(nid, direction, index));
1233 if (!info)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001234 return 0;
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001235 return get_vol_mute(codec, info, nid, ch, direction, index);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001236}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001237EXPORT_SYMBOL_HDA(snd_hda_codec_amp_read);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001238
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001239/*
1240 * update the AMP value, mask = bit mask to set, val = the value
1241 */
Takashi Iwai834be882006-03-01 14:16:17 +01001242int snd_hda_codec_amp_update(struct hda_codec *codec, hda_nid_t nid, int ch,
1243 int direction, int idx, int mask, int val)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001244{
Takashi Iwai0ba21762007-04-16 11:29:14 +02001245 struct hda_amp_info *info;
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001246
Takashi Iwai0ba21762007-04-16 11:29:14 +02001247 info = get_alloc_amp_hash(codec, HDA_HASH_KEY(nid, direction, idx));
1248 if (!info)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001249 return 0;
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001250 val &= mask;
1251 val |= get_vol_mute(codec, info, nid, ch, direction, idx) & ~mask;
Takashi Iwai82beb8f2007-08-10 17:09:26 +02001252 if (info->vol[ch] == val)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001253 return 0;
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001254 put_vol_mute(codec, info, nid, ch, direction, idx, val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001255 return 1;
1256}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001257EXPORT_SYMBOL_HDA(snd_hda_codec_amp_update);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001258
Takashi Iwai47fd8302007-08-10 17:11:07 +02001259/*
1260 * update the AMP stereo with the same mask and value
1261 */
1262int snd_hda_codec_amp_stereo(struct hda_codec *codec, hda_nid_t nid,
1263 int direction, int idx, int mask, int val)
1264{
1265 int ch, ret = 0;
1266 for (ch = 0; ch < 2; ch++)
1267 ret |= snd_hda_codec_amp_update(codec, nid, ch, direction,
1268 idx, mask, val);
1269 return ret;
1270}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001271EXPORT_SYMBOL_HDA(snd_hda_codec_amp_stereo);
Takashi Iwai47fd8302007-08-10 17:11:07 +02001272
Takashi Iwaicb53c622007-08-10 17:21:45 +02001273#ifdef SND_HDA_NEEDS_RESUME
Takashi Iwaib3ac5632007-08-10 17:03:40 +02001274/* resume the all amp commands from the cache */
1275void snd_hda_codec_resume_amp(struct hda_codec *codec)
1276{
Takashi Iwai603c4012008-07-30 15:01:44 +02001277 struct hda_amp_info *buffer = codec->amp_cache.buf.list;
Takashi Iwaib3ac5632007-08-10 17:03:40 +02001278 int i;
1279
Takashi Iwai603c4012008-07-30 15:01:44 +02001280 for (i = 0; i < codec->amp_cache.buf.used; i++, buffer++) {
Takashi Iwaib3ac5632007-08-10 17:03:40 +02001281 u32 key = buffer->head.key;
1282 hda_nid_t nid;
1283 unsigned int idx, dir, ch;
1284 if (!key)
1285 continue;
1286 nid = key & 0xff;
1287 idx = (key >> 16) & 0xff;
1288 dir = (key >> 24) & 0xff;
1289 for (ch = 0; ch < 2; ch++) {
1290 if (!(buffer->head.val & INFO_AMP_VOL(ch)))
1291 continue;
1292 put_vol_mute(codec, buffer, nid, ch, dir, idx,
1293 buffer->vol[ch]);
1294 }
1295 }
1296}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001297EXPORT_SYMBOL_HDA(snd_hda_codec_resume_amp);
Takashi Iwaicb53c622007-08-10 17:21:45 +02001298#endif /* SND_HDA_NEEDS_RESUME */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001299
Linus Torvalds1da177e2005-04-16 15:20:36 -07001300/* volume */
Takashi Iwai0ba21762007-04-16 11:29:14 +02001301int snd_hda_mixer_amp_volume_info(struct snd_kcontrol *kcontrol,
1302 struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001303{
1304 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1305 u16 nid = get_amp_nid(kcontrol);
1306 u8 chs = get_amp_channels(kcontrol);
1307 int dir = get_amp_direction(kcontrol);
Takashi Iwai29fdbec2009-01-20 13:07:55 +01001308 unsigned int ofs = get_amp_offset(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001309 u32 caps;
1310
1311 caps = query_amp_caps(codec, nid, dir);
Takashi Iwai0ba21762007-04-16 11:29:14 +02001312 /* num steps */
1313 caps = (caps & AC_AMPCAP_NUM_STEPS) >> AC_AMPCAP_NUM_STEPS_SHIFT;
1314 if (!caps) {
1315 printk(KERN_WARNING "hda_codec: "
Takashi Iwai9c8f2ab2008-01-11 16:12:23 +01001316 "num_steps = 0 for NID=0x%x (ctl = %s)\n", nid,
1317 kcontrol->id.name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001318 return -EINVAL;
1319 }
Takashi Iwai29fdbec2009-01-20 13:07:55 +01001320 if (ofs < caps)
1321 caps -= ofs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001322 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
1323 uinfo->count = chs == 3 ? 2 : 1;
1324 uinfo->value.integer.min = 0;
1325 uinfo->value.integer.max = caps;
1326 return 0;
1327}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001328EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_volume_info);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001329
Takashi Iwai29fdbec2009-01-20 13:07:55 +01001330
1331static inline unsigned int
1332read_amp_value(struct hda_codec *codec, hda_nid_t nid,
1333 int ch, int dir, int idx, unsigned int ofs)
1334{
1335 unsigned int val;
1336 val = snd_hda_codec_amp_read(codec, nid, ch, dir, idx);
1337 val &= HDA_AMP_VOLMASK;
1338 if (val >= ofs)
1339 val -= ofs;
1340 else
1341 val = 0;
1342 return val;
1343}
1344
1345static inline int
1346update_amp_value(struct hda_codec *codec, hda_nid_t nid,
1347 int ch, int dir, int idx, unsigned int ofs,
1348 unsigned int val)
1349{
1350 if (val > 0)
1351 val += ofs;
1352 return snd_hda_codec_amp_update(codec, nid, ch, dir, idx,
1353 HDA_AMP_VOLMASK, val);
1354}
1355
Takashi Iwai0ba21762007-04-16 11:29:14 +02001356int snd_hda_mixer_amp_volume_get(struct snd_kcontrol *kcontrol,
1357 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001358{
1359 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1360 hda_nid_t nid = get_amp_nid(kcontrol);
1361 int chs = get_amp_channels(kcontrol);
1362 int dir = get_amp_direction(kcontrol);
1363 int idx = get_amp_index(kcontrol);
Takashi Iwai29fdbec2009-01-20 13:07:55 +01001364 unsigned int ofs = get_amp_offset(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001365 long *valp = ucontrol->value.integer.value;
1366
1367 if (chs & 1)
Takashi Iwai29fdbec2009-01-20 13:07:55 +01001368 *valp++ = read_amp_value(codec, nid, 0, dir, idx, ofs);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001369 if (chs & 2)
Takashi Iwai29fdbec2009-01-20 13:07:55 +01001370 *valp = read_amp_value(codec, nid, 1, dir, idx, ofs);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001371 return 0;
1372}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001373EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_volume_get);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001374
Takashi Iwai0ba21762007-04-16 11:29:14 +02001375int snd_hda_mixer_amp_volume_put(struct snd_kcontrol *kcontrol,
1376 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001377{
1378 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1379 hda_nid_t nid = get_amp_nid(kcontrol);
1380 int chs = get_amp_channels(kcontrol);
1381 int dir = get_amp_direction(kcontrol);
1382 int idx = get_amp_index(kcontrol);
Takashi Iwai29fdbec2009-01-20 13:07:55 +01001383 unsigned int ofs = get_amp_offset(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001384 long *valp = ucontrol->value.integer.value;
1385 int change = 0;
1386
Takashi Iwaicb53c622007-08-10 17:21:45 +02001387 snd_hda_power_up(codec);
Nicolas Grazianob9f5a892005-07-29 12:17:20 +02001388 if (chs & 1) {
Takashi Iwai29fdbec2009-01-20 13:07:55 +01001389 change = update_amp_value(codec, nid, 0, dir, idx, ofs, *valp);
Nicolas Grazianob9f5a892005-07-29 12:17:20 +02001390 valp++;
1391 }
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001392 if (chs & 2)
Takashi Iwai29fdbec2009-01-20 13:07:55 +01001393 change |= update_amp_value(codec, nid, 1, dir, idx, ofs, *valp);
Takashi Iwaicb53c622007-08-10 17:21:45 +02001394 snd_hda_power_down(codec);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001395 return change;
1396}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001397EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_volume_put);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001398
Jaroslav Kysela302e9c52006-07-05 17:39:49 +02001399int snd_hda_mixer_amp_tlv(struct snd_kcontrol *kcontrol, int op_flag,
1400 unsigned int size, unsigned int __user *_tlv)
1401{
1402 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1403 hda_nid_t nid = get_amp_nid(kcontrol);
1404 int dir = get_amp_direction(kcontrol);
Takashi Iwai29fdbec2009-01-20 13:07:55 +01001405 unsigned int ofs = get_amp_offset(kcontrol);
Jaroslav Kysela302e9c52006-07-05 17:39:49 +02001406 u32 caps, val1, val2;
1407
1408 if (size < 4 * sizeof(unsigned int))
1409 return -ENOMEM;
1410 caps = query_amp_caps(codec, nid, dir);
Takashi Iwai0ba21762007-04-16 11:29:14 +02001411 val2 = (caps & AC_AMPCAP_STEP_SIZE) >> AC_AMPCAP_STEP_SIZE_SHIFT;
1412 val2 = (val2 + 1) * 25;
Jaroslav Kysela302e9c52006-07-05 17:39:49 +02001413 val1 = -((caps & AC_AMPCAP_OFFSET) >> AC_AMPCAP_OFFSET_SHIFT);
Takashi Iwai29fdbec2009-01-20 13:07:55 +01001414 val1 += ofs;
Jaroslav Kysela302e9c52006-07-05 17:39:49 +02001415 val1 = ((int)val1) * ((int)val2);
Jaroslav Kysela302e9c52006-07-05 17:39:49 +02001416 if (put_user(SNDRV_CTL_TLVT_DB_SCALE, _tlv))
1417 return -EFAULT;
1418 if (put_user(2 * sizeof(unsigned int), _tlv + 1))
1419 return -EFAULT;
1420 if (put_user(val1, _tlv + 2))
1421 return -EFAULT;
1422 if (put_user(val2, _tlv + 3))
1423 return -EFAULT;
1424 return 0;
1425}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001426EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_tlv);
Jaroslav Kysela302e9c52006-07-05 17:39:49 +02001427
Takashi Iwai2134ea42008-01-10 16:53:55 +01001428/*
1429 * set (static) TLV for virtual master volume; recalculated as max 0dB
1430 */
1431void snd_hda_set_vmaster_tlv(struct hda_codec *codec, hda_nid_t nid, int dir,
1432 unsigned int *tlv)
1433{
1434 u32 caps;
1435 int nums, step;
1436
1437 caps = query_amp_caps(codec, nid, dir);
1438 nums = (caps & AC_AMPCAP_NUM_STEPS) >> AC_AMPCAP_NUM_STEPS_SHIFT;
1439 step = (caps & AC_AMPCAP_STEP_SIZE) >> AC_AMPCAP_STEP_SIZE_SHIFT;
1440 step = (step + 1) * 25;
1441 tlv[0] = SNDRV_CTL_TLVT_DB_SCALE;
1442 tlv[1] = 2 * sizeof(unsigned int);
1443 tlv[2] = -nums * step;
1444 tlv[3] = step;
1445}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001446EXPORT_SYMBOL_HDA(snd_hda_set_vmaster_tlv);
Takashi Iwai2134ea42008-01-10 16:53:55 +01001447
1448/* find a mixer control element with the given name */
Takashi Iwai09f99702008-02-04 12:31:13 +01001449static struct snd_kcontrol *
1450_snd_hda_find_mixer_ctl(struct hda_codec *codec,
1451 const char *name, int idx)
Takashi Iwai2134ea42008-01-10 16:53:55 +01001452{
1453 struct snd_ctl_elem_id id;
1454 memset(&id, 0, sizeof(id));
1455 id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
Takashi Iwai09f99702008-02-04 12:31:13 +01001456 id.index = idx;
Takashi Iwai2134ea42008-01-10 16:53:55 +01001457 strcpy(id.name, name);
1458 return snd_ctl_find_id(codec->bus->card, &id);
1459}
1460
Takashi Iwai09f99702008-02-04 12:31:13 +01001461struct snd_kcontrol *snd_hda_find_mixer_ctl(struct hda_codec *codec,
1462 const char *name)
1463{
1464 return _snd_hda_find_mixer_ctl(codec, name, 0);
1465}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001466EXPORT_SYMBOL_HDA(snd_hda_find_mixer_ctl);
Takashi Iwai09f99702008-02-04 12:31:13 +01001467
Takashi Iwaid13bd412008-07-30 15:01:45 +02001468/* Add a control element and assign to the codec */
1469int snd_hda_ctl_add(struct hda_codec *codec, struct snd_kcontrol *kctl)
1470{
1471 int err;
1472 struct snd_kcontrol **knewp;
1473
1474 err = snd_ctl_add(codec->bus->card, kctl);
1475 if (err < 0)
1476 return err;
1477 knewp = snd_array_new(&codec->mixers);
1478 if (!knewp)
1479 return -ENOMEM;
1480 *knewp = kctl;
1481 return 0;
1482}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001483EXPORT_SYMBOL_HDA(snd_hda_ctl_add);
Takashi Iwaid13bd412008-07-30 15:01:45 +02001484
1485/* Clear all controls assigned to the given codec */
1486void snd_hda_ctls_clear(struct hda_codec *codec)
1487{
1488 int i;
1489 struct snd_kcontrol **kctls = codec->mixers.list;
1490 for (i = 0; i < codec->mixers.used; i++)
1491 snd_ctl_remove(codec->bus->card, kctls[i]);
1492 snd_array_free(&codec->mixers);
1493}
1494
Takashi Iwaia65d6292009-02-23 16:57:04 +01001495/* pseudo device locking
1496 * toggle card->shutdown to allow/disallow the device access (as a hack)
1497 */
1498static int hda_lock_devices(struct snd_card *card)
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001499{
Takashi Iwaia65d6292009-02-23 16:57:04 +01001500 spin_lock(&card->files_lock);
1501 if (card->shutdown) {
1502 spin_unlock(&card->files_lock);
1503 return -EINVAL;
1504 }
1505 card->shutdown = 1;
1506 spin_unlock(&card->files_lock);
1507 return 0;
1508}
1509
1510static void hda_unlock_devices(struct snd_card *card)
1511{
1512 spin_lock(&card->files_lock);
1513 card->shutdown = 0;
1514 spin_unlock(&card->files_lock);
1515}
1516
1517int snd_hda_codec_reset(struct hda_codec *codec)
1518{
1519 struct snd_card *card = codec->bus->card;
1520 int i, pcm;
1521
1522 if (hda_lock_devices(card) < 0)
1523 return -EBUSY;
1524 /* check whether the codec isn't used by any mixer or PCM streams */
1525 if (!list_empty(&card->ctl_files)) {
1526 hda_unlock_devices(card);
1527 return -EBUSY;
1528 }
1529 for (pcm = 0; pcm < codec->num_pcms; pcm++) {
1530 struct hda_pcm *cpcm = &codec->pcm_info[pcm];
1531 if (!cpcm->pcm)
1532 continue;
1533 if (cpcm->pcm->streams[0].substream_opened ||
1534 cpcm->pcm->streams[1].substream_opened) {
1535 hda_unlock_devices(card);
1536 return -EBUSY;
1537 }
1538 }
1539
1540 /* OK, let it free */
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001541
1542#ifdef CONFIG_SND_HDA_POWER_SAVE
1543 cancel_delayed_work(&codec->power_work);
Takashi Iwai6acaed32009-01-12 10:09:24 +01001544 flush_workqueue(codec->bus->workq);
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001545#endif
1546 snd_hda_ctls_clear(codec);
1547 /* relase PCMs */
1548 for (i = 0; i < codec->num_pcms; i++) {
Takashi Iwai529bd6c2008-11-27 14:17:01 +01001549 if (codec->pcm_info[i].pcm) {
Takashi Iwaia65d6292009-02-23 16:57:04 +01001550 snd_device_free(card, codec->pcm_info[i].pcm);
Takashi Iwai529bd6c2008-11-27 14:17:01 +01001551 clear_bit(codec->pcm_info[i].device,
1552 codec->bus->pcm_dev_bits);
1553 }
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001554 }
1555 if (codec->patch_ops.free)
1556 codec->patch_ops.free(codec);
Takashi Iwai56d17712008-11-28 14:36:23 +01001557 codec->proc_widget_hook = NULL;
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001558 codec->spec = NULL;
1559 free_hda_cache(&codec->amp_cache);
1560 free_hda_cache(&codec->cmd_cache);
Takashi Iwai827057f2008-12-19 10:12:02 +01001561 init_hda_cache(&codec->amp_cache, sizeof(struct hda_amp_info));
1562 init_hda_cache(&codec->cmd_cache, sizeof(struct hda_cache_head));
Takashi Iwai346ff702009-02-23 09:42:57 +01001563 /* free only driver_pins so that init_pins + user_pins are restored */
1564 snd_array_free(&codec->driver_pins);
Takashi Iwai3be14142009-02-20 14:11:16 +01001565 restore_pincfgs(codec);
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001566 codec->num_pcms = 0;
1567 codec->pcm_info = NULL;
1568 codec->preset = NULL;
Takashi Iwaid1f1af22009-03-02 10:35:29 +01001569 memset(&codec->patch_ops, 0, sizeof(codec->patch_ops));
1570 codec->slave_dig_outs = NULL;
1571 codec->spdif_status_reset = 0;
Takashi Iwai1289e9e2008-11-27 15:47:11 +01001572 module_put(codec->owner);
1573 codec->owner = NULL;
Takashi Iwaia65d6292009-02-23 16:57:04 +01001574
1575 /* allow device access again */
1576 hda_unlock_devices(card);
1577 return 0;
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001578}
1579
Takashi Iwai2134ea42008-01-10 16:53:55 +01001580/* create a virtual master control and add slaves */
1581int snd_hda_add_vmaster(struct hda_codec *codec, char *name,
1582 unsigned int *tlv, const char **slaves)
1583{
1584 struct snd_kcontrol *kctl;
1585 const char **s;
1586 int err;
1587
Takashi Iwai2f085542008-02-22 18:43:50 +01001588 for (s = slaves; *s && !snd_hda_find_mixer_ctl(codec, *s); s++)
1589 ;
1590 if (!*s) {
1591 snd_printdd("No slave found for %s\n", name);
1592 return 0;
1593 }
Takashi Iwai2134ea42008-01-10 16:53:55 +01001594 kctl = snd_ctl_make_virtual_master(name, tlv);
1595 if (!kctl)
1596 return -ENOMEM;
Takashi Iwaid13bd412008-07-30 15:01:45 +02001597 err = snd_hda_ctl_add(codec, kctl);
Takashi Iwai2134ea42008-01-10 16:53:55 +01001598 if (err < 0)
1599 return err;
1600
1601 for (s = slaves; *s; s++) {
1602 struct snd_kcontrol *sctl;
Takashi Iwai7a411ee2009-03-06 10:08:14 +01001603 int i = 0;
1604 for (;;) {
1605 sctl = _snd_hda_find_mixer_ctl(codec, *s, i);
1606 if (!sctl) {
1607 if (!i)
1608 snd_printdd("Cannot find slave %s, "
1609 "skipped\n", *s);
1610 break;
1611 }
1612 err = snd_ctl_add_slave(kctl, sctl);
1613 if (err < 0)
1614 return err;
1615 i++;
Takashi Iwai2134ea42008-01-10 16:53:55 +01001616 }
Takashi Iwai2134ea42008-01-10 16:53:55 +01001617 }
1618 return 0;
1619}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001620EXPORT_SYMBOL_HDA(snd_hda_add_vmaster);
Takashi Iwai2134ea42008-01-10 16:53:55 +01001621
Linus Torvalds1da177e2005-04-16 15:20:36 -07001622/* switch */
Takashi Iwai0ba21762007-04-16 11:29:14 +02001623int snd_hda_mixer_amp_switch_info(struct snd_kcontrol *kcontrol,
1624 struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001625{
1626 int chs = get_amp_channels(kcontrol);
1627
1628 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
1629 uinfo->count = chs == 3 ? 2 : 1;
1630 uinfo->value.integer.min = 0;
1631 uinfo->value.integer.max = 1;
1632 return 0;
1633}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001634EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_switch_info);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001635
Takashi Iwai0ba21762007-04-16 11:29:14 +02001636int snd_hda_mixer_amp_switch_get(struct snd_kcontrol *kcontrol,
1637 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001638{
1639 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1640 hda_nid_t nid = get_amp_nid(kcontrol);
1641 int chs = get_amp_channels(kcontrol);
1642 int dir = get_amp_direction(kcontrol);
1643 int idx = get_amp_index(kcontrol);
1644 long *valp = ucontrol->value.integer.value;
1645
1646 if (chs & 1)
Takashi Iwai0ba21762007-04-16 11:29:14 +02001647 *valp++ = (snd_hda_codec_amp_read(codec, nid, 0, dir, idx) &
Takashi Iwai47fd8302007-08-10 17:11:07 +02001648 HDA_AMP_MUTE) ? 0 : 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001649 if (chs & 2)
Takashi Iwai0ba21762007-04-16 11:29:14 +02001650 *valp = (snd_hda_codec_amp_read(codec, nid, 1, dir, idx) &
Takashi Iwai47fd8302007-08-10 17:11:07 +02001651 HDA_AMP_MUTE) ? 0 : 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001652 return 0;
1653}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001654EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_switch_get);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001655
Takashi Iwai0ba21762007-04-16 11:29:14 +02001656int snd_hda_mixer_amp_switch_put(struct snd_kcontrol *kcontrol,
1657 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001658{
1659 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1660 hda_nid_t nid = get_amp_nid(kcontrol);
1661 int chs = get_amp_channels(kcontrol);
1662 int dir = get_amp_direction(kcontrol);
1663 int idx = get_amp_index(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001664 long *valp = ucontrol->value.integer.value;
1665 int change = 0;
1666
Takashi Iwaicb53c622007-08-10 17:21:45 +02001667 snd_hda_power_up(codec);
Nicolas Grazianob9f5a892005-07-29 12:17:20 +02001668 if (chs & 1) {
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001669 change = snd_hda_codec_amp_update(codec, nid, 0, dir, idx,
Takashi Iwai47fd8302007-08-10 17:11:07 +02001670 HDA_AMP_MUTE,
1671 *valp ? 0 : HDA_AMP_MUTE);
Nicolas Grazianob9f5a892005-07-29 12:17:20 +02001672 valp++;
1673 }
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001674 if (chs & 2)
1675 change |= snd_hda_codec_amp_update(codec, nid, 1, dir, idx,
Takashi Iwai47fd8302007-08-10 17:11:07 +02001676 HDA_AMP_MUTE,
1677 *valp ? 0 : HDA_AMP_MUTE);
Takashi Iwaicb53c622007-08-10 17:21:45 +02001678#ifdef CONFIG_SND_HDA_POWER_SAVE
1679 if (codec->patch_ops.check_power_status)
1680 codec->patch_ops.check_power_status(codec, nid);
1681#endif
1682 snd_hda_power_down(codec);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001683 return change;
1684}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001685EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_switch_put);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001686
1687/*
Takashi Iwai985be542005-11-02 18:26:49 +01001688 * bound volume controls
1689 *
1690 * bind multiple volumes (# indices, from 0)
1691 */
1692
1693#define AMP_VAL_IDX_SHIFT 19
1694#define AMP_VAL_IDX_MASK (0x0f<<19)
1695
Takashi Iwai0ba21762007-04-16 11:29:14 +02001696int snd_hda_mixer_bind_switch_get(struct snd_kcontrol *kcontrol,
1697 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai985be542005-11-02 18:26:49 +01001698{
1699 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1700 unsigned long pval;
1701 int err;
1702
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001703 mutex_lock(&codec->control_mutex);
Takashi Iwai985be542005-11-02 18:26:49 +01001704 pval = kcontrol->private_value;
1705 kcontrol->private_value = pval & ~AMP_VAL_IDX_MASK; /* index 0 */
1706 err = snd_hda_mixer_amp_switch_get(kcontrol, ucontrol);
1707 kcontrol->private_value = pval;
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001708 mutex_unlock(&codec->control_mutex);
Takashi Iwai985be542005-11-02 18:26:49 +01001709 return err;
1710}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001711EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_switch_get);
Takashi Iwai985be542005-11-02 18:26:49 +01001712
Takashi Iwai0ba21762007-04-16 11:29:14 +02001713int snd_hda_mixer_bind_switch_put(struct snd_kcontrol *kcontrol,
1714 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai985be542005-11-02 18:26:49 +01001715{
1716 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1717 unsigned long pval;
1718 int i, indices, err = 0, change = 0;
1719
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001720 mutex_lock(&codec->control_mutex);
Takashi Iwai985be542005-11-02 18:26:49 +01001721 pval = kcontrol->private_value;
1722 indices = (pval & AMP_VAL_IDX_MASK) >> AMP_VAL_IDX_SHIFT;
1723 for (i = 0; i < indices; i++) {
Takashi Iwai0ba21762007-04-16 11:29:14 +02001724 kcontrol->private_value = (pval & ~AMP_VAL_IDX_MASK) |
1725 (i << AMP_VAL_IDX_SHIFT);
Takashi Iwai985be542005-11-02 18:26:49 +01001726 err = snd_hda_mixer_amp_switch_put(kcontrol, ucontrol);
1727 if (err < 0)
1728 break;
1729 change |= err;
1730 }
1731 kcontrol->private_value = pval;
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001732 mutex_unlock(&codec->control_mutex);
Takashi Iwai985be542005-11-02 18:26:49 +01001733 return err < 0 ? err : change;
1734}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001735EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_switch_put);
Takashi Iwai985be542005-11-02 18:26:49 +01001736
1737/*
Takashi Iwai532d5382007-07-27 19:02:40 +02001738 * generic bound volume/swtich controls
1739 */
1740int snd_hda_mixer_bind_ctls_info(struct snd_kcontrol *kcontrol,
1741 struct snd_ctl_elem_info *uinfo)
1742{
1743 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1744 struct hda_bind_ctls *c;
1745 int err;
1746
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001747 mutex_lock(&codec->control_mutex);
Serge A. Suchkov14c65f92008-02-22 18:43:16 +01001748 c = (struct hda_bind_ctls *)kcontrol->private_value;
Takashi Iwai532d5382007-07-27 19:02:40 +02001749 kcontrol->private_value = *c->values;
1750 err = c->ops->info(kcontrol, uinfo);
1751 kcontrol->private_value = (long)c;
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001752 mutex_unlock(&codec->control_mutex);
Takashi Iwai532d5382007-07-27 19:02:40 +02001753 return err;
1754}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001755EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_ctls_info);
Takashi Iwai532d5382007-07-27 19:02:40 +02001756
1757int snd_hda_mixer_bind_ctls_get(struct snd_kcontrol *kcontrol,
1758 struct snd_ctl_elem_value *ucontrol)
1759{
1760 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1761 struct hda_bind_ctls *c;
1762 int err;
1763
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001764 mutex_lock(&codec->control_mutex);
Serge A. Suchkov14c65f92008-02-22 18:43:16 +01001765 c = (struct hda_bind_ctls *)kcontrol->private_value;
Takashi Iwai532d5382007-07-27 19:02:40 +02001766 kcontrol->private_value = *c->values;
1767 err = c->ops->get(kcontrol, ucontrol);
1768 kcontrol->private_value = (long)c;
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001769 mutex_unlock(&codec->control_mutex);
Takashi Iwai532d5382007-07-27 19:02:40 +02001770 return err;
1771}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001772EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_ctls_get);
Takashi Iwai532d5382007-07-27 19:02:40 +02001773
1774int snd_hda_mixer_bind_ctls_put(struct snd_kcontrol *kcontrol,
1775 struct snd_ctl_elem_value *ucontrol)
1776{
1777 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1778 struct hda_bind_ctls *c;
1779 unsigned long *vals;
1780 int err = 0, change = 0;
1781
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001782 mutex_lock(&codec->control_mutex);
Serge A. Suchkov14c65f92008-02-22 18:43:16 +01001783 c = (struct hda_bind_ctls *)kcontrol->private_value;
Takashi Iwai532d5382007-07-27 19:02:40 +02001784 for (vals = c->values; *vals; vals++) {
1785 kcontrol->private_value = *vals;
1786 err = c->ops->put(kcontrol, ucontrol);
1787 if (err < 0)
1788 break;
1789 change |= err;
1790 }
1791 kcontrol->private_value = (long)c;
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001792 mutex_unlock(&codec->control_mutex);
Takashi Iwai532d5382007-07-27 19:02:40 +02001793 return err < 0 ? err : change;
1794}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001795EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_ctls_put);
Takashi Iwai532d5382007-07-27 19:02:40 +02001796
1797int snd_hda_mixer_bind_tlv(struct snd_kcontrol *kcontrol, int op_flag,
1798 unsigned int size, unsigned int __user *tlv)
1799{
1800 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1801 struct hda_bind_ctls *c;
1802 int err;
1803
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001804 mutex_lock(&codec->control_mutex);
Serge A. Suchkov14c65f92008-02-22 18:43:16 +01001805 c = (struct hda_bind_ctls *)kcontrol->private_value;
Takashi Iwai532d5382007-07-27 19:02:40 +02001806 kcontrol->private_value = *c->values;
1807 err = c->ops->tlv(kcontrol, op_flag, size, tlv);
1808 kcontrol->private_value = (long)c;
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001809 mutex_unlock(&codec->control_mutex);
Takashi Iwai532d5382007-07-27 19:02:40 +02001810 return err;
1811}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001812EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_tlv);
Takashi Iwai532d5382007-07-27 19:02:40 +02001813
1814struct hda_ctl_ops snd_hda_bind_vol = {
1815 .info = snd_hda_mixer_amp_volume_info,
1816 .get = snd_hda_mixer_amp_volume_get,
1817 .put = snd_hda_mixer_amp_volume_put,
1818 .tlv = snd_hda_mixer_amp_tlv
1819};
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001820EXPORT_SYMBOL_HDA(snd_hda_bind_vol);
Takashi Iwai532d5382007-07-27 19:02:40 +02001821
1822struct hda_ctl_ops snd_hda_bind_sw = {
1823 .info = snd_hda_mixer_amp_switch_info,
1824 .get = snd_hda_mixer_amp_switch_get,
1825 .put = snd_hda_mixer_amp_switch_put,
1826 .tlv = snd_hda_mixer_amp_tlv
1827};
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001828EXPORT_SYMBOL_HDA(snd_hda_bind_sw);
Takashi Iwai532d5382007-07-27 19:02:40 +02001829
1830/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07001831 * SPDIF out controls
1832 */
1833
Takashi Iwai0ba21762007-04-16 11:29:14 +02001834static int snd_hda_spdif_mask_info(struct snd_kcontrol *kcontrol,
1835 struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001836{
1837 uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
1838 uinfo->count = 1;
1839 return 0;
1840}
1841
Takashi Iwai0ba21762007-04-16 11:29:14 +02001842static int snd_hda_spdif_cmask_get(struct snd_kcontrol *kcontrol,
1843 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001844{
1845 ucontrol->value.iec958.status[0] = IEC958_AES0_PROFESSIONAL |
1846 IEC958_AES0_NONAUDIO |
1847 IEC958_AES0_CON_EMPHASIS_5015 |
1848 IEC958_AES0_CON_NOT_COPYRIGHT;
1849 ucontrol->value.iec958.status[1] = IEC958_AES1_CON_CATEGORY |
1850 IEC958_AES1_CON_ORIGINAL;
1851 return 0;
1852}
1853
Takashi Iwai0ba21762007-04-16 11:29:14 +02001854static int snd_hda_spdif_pmask_get(struct snd_kcontrol *kcontrol,
1855 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001856{
1857 ucontrol->value.iec958.status[0] = IEC958_AES0_PROFESSIONAL |
1858 IEC958_AES0_NONAUDIO |
1859 IEC958_AES0_PRO_EMPHASIS_5015;
1860 return 0;
1861}
1862
Takashi Iwai0ba21762007-04-16 11:29:14 +02001863static int snd_hda_spdif_default_get(struct snd_kcontrol *kcontrol,
1864 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001865{
1866 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1867
1868 ucontrol->value.iec958.status[0] = codec->spdif_status & 0xff;
1869 ucontrol->value.iec958.status[1] = (codec->spdif_status >> 8) & 0xff;
1870 ucontrol->value.iec958.status[2] = (codec->spdif_status >> 16) & 0xff;
1871 ucontrol->value.iec958.status[3] = (codec->spdif_status >> 24) & 0xff;
1872
1873 return 0;
1874}
1875
1876/* convert from SPDIF status bits to HDA SPDIF bits
1877 * bit 0 (DigEn) is always set zero (to be filled later)
1878 */
1879static unsigned short convert_from_spdif_status(unsigned int sbits)
1880{
1881 unsigned short val = 0;
1882
1883 if (sbits & IEC958_AES0_PROFESSIONAL)
Takashi Iwai0ba21762007-04-16 11:29:14 +02001884 val |= AC_DIG1_PROFESSIONAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001885 if (sbits & IEC958_AES0_NONAUDIO)
Takashi Iwai0ba21762007-04-16 11:29:14 +02001886 val |= AC_DIG1_NONAUDIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001887 if (sbits & IEC958_AES0_PROFESSIONAL) {
Takashi Iwai0ba21762007-04-16 11:29:14 +02001888 if ((sbits & IEC958_AES0_PRO_EMPHASIS) ==
1889 IEC958_AES0_PRO_EMPHASIS_5015)
1890 val |= AC_DIG1_EMPHASIS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001891 } else {
Takashi Iwai0ba21762007-04-16 11:29:14 +02001892 if ((sbits & IEC958_AES0_CON_EMPHASIS) ==
1893 IEC958_AES0_CON_EMPHASIS_5015)
1894 val |= AC_DIG1_EMPHASIS;
1895 if (!(sbits & IEC958_AES0_CON_NOT_COPYRIGHT))
1896 val |= AC_DIG1_COPYRIGHT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001897 if (sbits & (IEC958_AES1_CON_ORIGINAL << 8))
Takashi Iwai0ba21762007-04-16 11:29:14 +02001898 val |= AC_DIG1_LEVEL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001899 val |= sbits & (IEC958_AES1_CON_CATEGORY << 8);
1900 }
1901 return val;
1902}
1903
1904/* convert to SPDIF status bits from HDA SPDIF bits
1905 */
1906static unsigned int convert_to_spdif_status(unsigned short val)
1907{
1908 unsigned int sbits = 0;
1909
Takashi Iwai0ba21762007-04-16 11:29:14 +02001910 if (val & AC_DIG1_NONAUDIO)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001911 sbits |= IEC958_AES0_NONAUDIO;
Takashi Iwai0ba21762007-04-16 11:29:14 +02001912 if (val & AC_DIG1_PROFESSIONAL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001913 sbits |= IEC958_AES0_PROFESSIONAL;
1914 if (sbits & IEC958_AES0_PROFESSIONAL) {
Takashi Iwai0ba21762007-04-16 11:29:14 +02001915 if (sbits & AC_DIG1_EMPHASIS)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001916 sbits |= IEC958_AES0_PRO_EMPHASIS_5015;
1917 } else {
Takashi Iwai0ba21762007-04-16 11:29:14 +02001918 if (val & AC_DIG1_EMPHASIS)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001919 sbits |= IEC958_AES0_CON_EMPHASIS_5015;
Takashi Iwai0ba21762007-04-16 11:29:14 +02001920 if (!(val & AC_DIG1_COPYRIGHT))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001921 sbits |= IEC958_AES0_CON_NOT_COPYRIGHT;
Takashi Iwai0ba21762007-04-16 11:29:14 +02001922 if (val & AC_DIG1_LEVEL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001923 sbits |= (IEC958_AES1_CON_ORIGINAL << 8);
1924 sbits |= val & (0x7f << 8);
1925 }
1926 return sbits;
1927}
1928
Takashi Iwai2f728532008-09-25 16:32:41 +02001929/* set digital convert verbs both for the given NID and its slaves */
1930static void set_dig_out(struct hda_codec *codec, hda_nid_t nid,
1931 int verb, int val)
1932{
1933 hda_nid_t *d;
1934
Takashi Iwai9e976972008-11-25 08:17:20 +01001935 snd_hda_codec_write_cache(codec, nid, 0, verb, val);
Takashi Iwai2f728532008-09-25 16:32:41 +02001936 d = codec->slave_dig_outs;
1937 if (!d)
1938 return;
1939 for (; *d; d++)
Takashi Iwai9e976972008-11-25 08:17:20 +01001940 snd_hda_codec_write_cache(codec, *d, 0, verb, val);
Takashi Iwai2f728532008-09-25 16:32:41 +02001941}
1942
1943static inline void set_dig_out_convert(struct hda_codec *codec, hda_nid_t nid,
1944 int dig1, int dig2)
1945{
1946 if (dig1 != -1)
1947 set_dig_out(codec, nid, AC_VERB_SET_DIGI_CONVERT_1, dig1);
1948 if (dig2 != -1)
1949 set_dig_out(codec, nid, AC_VERB_SET_DIGI_CONVERT_2, dig2);
1950}
1951
Takashi Iwai0ba21762007-04-16 11:29:14 +02001952static int snd_hda_spdif_default_put(struct snd_kcontrol *kcontrol,
1953 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001954{
1955 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1956 hda_nid_t nid = kcontrol->private_value;
1957 unsigned short val;
1958 int change;
1959
Ingo Molnar62932df2006-01-16 16:34:20 +01001960 mutex_lock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001961 codec->spdif_status = ucontrol->value.iec958.status[0] |
1962 ((unsigned int)ucontrol->value.iec958.status[1] << 8) |
1963 ((unsigned int)ucontrol->value.iec958.status[2] << 16) |
1964 ((unsigned int)ucontrol->value.iec958.status[3] << 24);
1965 val = convert_from_spdif_status(codec->spdif_status);
1966 val |= codec->spdif_ctls & 1;
1967 change = codec->spdif_ctls != val;
1968 codec->spdif_ctls = val;
1969
Takashi Iwai2f728532008-09-25 16:32:41 +02001970 if (change)
1971 set_dig_out_convert(codec, nid, val & 0xff, (val >> 8) & 0xff);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001972
Ingo Molnar62932df2006-01-16 16:34:20 +01001973 mutex_unlock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001974 return change;
1975}
1976
Takashi Iwaia5ce8892007-07-23 15:42:26 +02001977#define snd_hda_spdif_out_switch_info snd_ctl_boolean_mono_info
Linus Torvalds1da177e2005-04-16 15:20:36 -07001978
Takashi Iwai0ba21762007-04-16 11:29:14 +02001979static int snd_hda_spdif_out_switch_get(struct snd_kcontrol *kcontrol,
1980 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001981{
1982 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1983
Takashi Iwai0ba21762007-04-16 11:29:14 +02001984 ucontrol->value.integer.value[0] = codec->spdif_ctls & AC_DIG1_ENABLE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001985 return 0;
1986}
1987
Takashi Iwai0ba21762007-04-16 11:29:14 +02001988static int snd_hda_spdif_out_switch_put(struct snd_kcontrol *kcontrol,
1989 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001990{
1991 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1992 hda_nid_t nid = kcontrol->private_value;
1993 unsigned short val;
1994 int change;
1995
Ingo Molnar62932df2006-01-16 16:34:20 +01001996 mutex_lock(&codec->spdif_mutex);
Takashi Iwai0ba21762007-04-16 11:29:14 +02001997 val = codec->spdif_ctls & ~AC_DIG1_ENABLE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001998 if (ucontrol->value.integer.value[0])
Takashi Iwai0ba21762007-04-16 11:29:14 +02001999 val |= AC_DIG1_ENABLE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002000 change = codec->spdif_ctls != val;
Takashi Iwai82beb8f2007-08-10 17:09:26 +02002001 if (change) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002002 codec->spdif_ctls = val;
Takashi Iwai2f728532008-09-25 16:32:41 +02002003 set_dig_out_convert(codec, nid, val & 0xff, -1);
Takashi Iwai0ba21762007-04-16 11:29:14 +02002004 /* unmute amp switch (if any) */
2005 if ((get_wcaps(codec, nid) & AC_WCAP_OUT_AMP) &&
Takashi Iwai47fd8302007-08-10 17:11:07 +02002006 (val & AC_DIG1_ENABLE))
2007 snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0,
2008 HDA_AMP_MUTE, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002009 }
Ingo Molnar62932df2006-01-16 16:34:20 +01002010 mutex_unlock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002011 return change;
2012}
2013
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01002014static struct snd_kcontrol_new dig_mixes[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002015 {
2016 .access = SNDRV_CTL_ELEM_ACCESS_READ,
2017 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2018 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,CON_MASK),
2019 .info = snd_hda_spdif_mask_info,
2020 .get = snd_hda_spdif_cmask_get,
2021 },
2022 {
2023 .access = SNDRV_CTL_ELEM_ACCESS_READ,
2024 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2025 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,PRO_MASK),
2026 .info = snd_hda_spdif_mask_info,
2027 .get = snd_hda_spdif_pmask_get,
2028 },
2029 {
2030 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2031 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT),
2032 .info = snd_hda_spdif_mask_info,
2033 .get = snd_hda_spdif_default_get,
2034 .put = snd_hda_spdif_default_put,
2035 },
2036 {
2037 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2038 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,SWITCH),
2039 .info = snd_hda_spdif_out_switch_info,
2040 .get = snd_hda_spdif_out_switch_get,
2041 .put = snd_hda_spdif_out_switch_put,
2042 },
2043 { } /* end */
2044};
2045
Takashi Iwai09f99702008-02-04 12:31:13 +01002046#define SPDIF_MAX_IDX 4 /* 4 instances should be enough to probe */
2047
Linus Torvalds1da177e2005-04-16 15:20:36 -07002048/**
2049 * snd_hda_create_spdif_out_ctls - create Output SPDIF-related controls
2050 * @codec: the HDA codec
2051 * @nid: audio out widget NID
2052 *
2053 * Creates controls related with the SPDIF output.
2054 * Called from each patch supporting the SPDIF out.
2055 *
2056 * Returns 0 if successful, or a negative error code.
2057 */
Takashi Iwai12f288b2007-08-02 15:51:59 +02002058int snd_hda_create_spdif_out_ctls(struct hda_codec *codec, hda_nid_t nid)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002059{
2060 int err;
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01002061 struct snd_kcontrol *kctl;
2062 struct snd_kcontrol_new *dig_mix;
Takashi Iwai09f99702008-02-04 12:31:13 +01002063 int idx;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002064
Takashi Iwai09f99702008-02-04 12:31:13 +01002065 for (idx = 0; idx < SPDIF_MAX_IDX; idx++) {
2066 if (!_snd_hda_find_mixer_ctl(codec, "IEC958 Playback Switch",
2067 idx))
2068 break;
2069 }
2070 if (idx >= SPDIF_MAX_IDX) {
2071 printk(KERN_ERR "hda_codec: too many IEC958 outputs\n");
2072 return -EBUSY;
2073 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002074 for (dig_mix = dig_mixes; dig_mix->name; dig_mix++) {
2075 kctl = snd_ctl_new1(dig_mix, codec);
Takashi Iwaib91f0802008-11-04 08:43:08 +01002076 if (!kctl)
2077 return -ENOMEM;
Takashi Iwai09f99702008-02-04 12:31:13 +01002078 kctl->id.index = idx;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002079 kctl->private_value = nid;
Takashi Iwaid13bd412008-07-30 15:01:45 +02002080 err = snd_hda_ctl_add(codec, kctl);
Takashi Iwai0ba21762007-04-16 11:29:14 +02002081 if (err < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002082 return err;
2083 }
Takashi Iwai0ba21762007-04-16 11:29:14 +02002084 codec->spdif_ctls =
Andrew Paprocki3982d172007-12-19 12:13:44 +01002085 snd_hda_codec_read(codec, nid, 0,
2086 AC_VERB_GET_DIGI_CONVERT_1, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002087 codec->spdif_status = convert_to_spdif_status(codec->spdif_ctls);
2088 return 0;
2089}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002090EXPORT_SYMBOL_HDA(snd_hda_create_spdif_out_ctls);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002091
2092/*
Takashi Iwai9a081602008-02-12 18:37:26 +01002093 * SPDIF sharing with analog output
2094 */
2095static int spdif_share_sw_get(struct snd_kcontrol *kcontrol,
2096 struct snd_ctl_elem_value *ucontrol)
2097{
2098 struct hda_multi_out *mout = snd_kcontrol_chip(kcontrol);
2099 ucontrol->value.integer.value[0] = mout->share_spdif;
2100 return 0;
2101}
2102
2103static int spdif_share_sw_put(struct snd_kcontrol *kcontrol,
2104 struct snd_ctl_elem_value *ucontrol)
2105{
2106 struct hda_multi_out *mout = snd_kcontrol_chip(kcontrol);
2107 mout->share_spdif = !!ucontrol->value.integer.value[0];
2108 return 0;
2109}
2110
2111static struct snd_kcontrol_new spdif_share_sw = {
2112 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2113 .name = "IEC958 Default PCM Playback Switch",
2114 .info = snd_ctl_boolean_mono_info,
2115 .get = spdif_share_sw_get,
2116 .put = spdif_share_sw_put,
2117};
2118
2119int snd_hda_create_spdif_share_sw(struct hda_codec *codec,
2120 struct hda_multi_out *mout)
2121{
2122 if (!mout->dig_out_nid)
2123 return 0;
2124 /* ATTENTION: here mout is passed as private_data, instead of codec */
Takashi Iwaid13bd412008-07-30 15:01:45 +02002125 return snd_hda_ctl_add(codec,
Takashi Iwai9a081602008-02-12 18:37:26 +01002126 snd_ctl_new1(&spdif_share_sw, mout));
2127}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002128EXPORT_SYMBOL_HDA(snd_hda_create_spdif_share_sw);
Takashi Iwai9a081602008-02-12 18:37:26 +01002129
2130/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002131 * SPDIF input
2132 */
2133
2134#define snd_hda_spdif_in_switch_info snd_hda_spdif_out_switch_info
2135
Takashi Iwai0ba21762007-04-16 11:29:14 +02002136static int snd_hda_spdif_in_switch_get(struct snd_kcontrol *kcontrol,
2137 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002138{
2139 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2140
2141 ucontrol->value.integer.value[0] = codec->spdif_in_enable;
2142 return 0;
2143}
2144
Takashi Iwai0ba21762007-04-16 11:29:14 +02002145static int snd_hda_spdif_in_switch_put(struct snd_kcontrol *kcontrol,
2146 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002147{
2148 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2149 hda_nid_t nid = kcontrol->private_value;
2150 unsigned int val = !!ucontrol->value.integer.value[0];
2151 int change;
2152
Ingo Molnar62932df2006-01-16 16:34:20 +01002153 mutex_lock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002154 change = codec->spdif_in_enable != val;
Takashi Iwai82beb8f2007-08-10 17:09:26 +02002155 if (change) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002156 codec->spdif_in_enable = val;
Takashi Iwai82beb8f2007-08-10 17:09:26 +02002157 snd_hda_codec_write_cache(codec, nid, 0,
2158 AC_VERB_SET_DIGI_CONVERT_1, val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002159 }
Ingo Molnar62932df2006-01-16 16:34:20 +01002160 mutex_unlock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002161 return change;
2162}
2163
Takashi Iwai0ba21762007-04-16 11:29:14 +02002164static int snd_hda_spdif_in_status_get(struct snd_kcontrol *kcontrol,
2165 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002166{
2167 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2168 hda_nid_t nid = kcontrol->private_value;
2169 unsigned short val;
2170 unsigned int sbits;
2171
Andrew Paprocki3982d172007-12-19 12:13:44 +01002172 val = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_DIGI_CONVERT_1, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002173 sbits = convert_to_spdif_status(val);
2174 ucontrol->value.iec958.status[0] = sbits;
2175 ucontrol->value.iec958.status[1] = sbits >> 8;
2176 ucontrol->value.iec958.status[2] = sbits >> 16;
2177 ucontrol->value.iec958.status[3] = sbits >> 24;
2178 return 0;
2179}
2180
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01002181static struct snd_kcontrol_new dig_in_ctls[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002182 {
2183 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2184 .name = SNDRV_CTL_NAME_IEC958("",CAPTURE,SWITCH),
2185 .info = snd_hda_spdif_in_switch_info,
2186 .get = snd_hda_spdif_in_switch_get,
2187 .put = snd_hda_spdif_in_switch_put,
2188 },
2189 {
2190 .access = SNDRV_CTL_ELEM_ACCESS_READ,
2191 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2192 .name = SNDRV_CTL_NAME_IEC958("",CAPTURE,DEFAULT),
2193 .info = snd_hda_spdif_mask_info,
2194 .get = snd_hda_spdif_in_status_get,
2195 },
2196 { } /* end */
2197};
2198
2199/**
2200 * snd_hda_create_spdif_in_ctls - create Input SPDIF-related controls
2201 * @codec: the HDA codec
2202 * @nid: audio in widget NID
2203 *
2204 * Creates controls related with the SPDIF input.
2205 * Called from each patch supporting the SPDIF in.
2206 *
2207 * Returns 0 if successful, or a negative error code.
2208 */
Takashi Iwai12f288b2007-08-02 15:51:59 +02002209int snd_hda_create_spdif_in_ctls(struct hda_codec *codec, hda_nid_t nid)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002210{
2211 int err;
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01002212 struct snd_kcontrol *kctl;
2213 struct snd_kcontrol_new *dig_mix;
Takashi Iwai09f99702008-02-04 12:31:13 +01002214 int idx;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002215
Takashi Iwai09f99702008-02-04 12:31:13 +01002216 for (idx = 0; idx < SPDIF_MAX_IDX; idx++) {
2217 if (!_snd_hda_find_mixer_ctl(codec, "IEC958 Capture Switch",
2218 idx))
2219 break;
2220 }
2221 if (idx >= SPDIF_MAX_IDX) {
2222 printk(KERN_ERR "hda_codec: too many IEC958 inputs\n");
2223 return -EBUSY;
2224 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002225 for (dig_mix = dig_in_ctls; dig_mix->name; dig_mix++) {
2226 kctl = snd_ctl_new1(dig_mix, codec);
Takashi Iwaic8dcdf82009-02-06 16:21:20 +01002227 if (!kctl)
2228 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002229 kctl->private_value = nid;
Takashi Iwaid13bd412008-07-30 15:01:45 +02002230 err = snd_hda_ctl_add(codec, kctl);
Takashi Iwai0ba21762007-04-16 11:29:14 +02002231 if (err < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002232 return err;
2233 }
Takashi Iwai0ba21762007-04-16 11:29:14 +02002234 codec->spdif_in_enable =
Andrew Paprocki3982d172007-12-19 12:13:44 +01002235 snd_hda_codec_read(codec, nid, 0,
2236 AC_VERB_GET_DIGI_CONVERT_1, 0) &
Takashi Iwai0ba21762007-04-16 11:29:14 +02002237 AC_DIG1_ENABLE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002238 return 0;
2239}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002240EXPORT_SYMBOL_HDA(snd_hda_create_spdif_in_ctls);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002241
Takashi Iwaicb53c622007-08-10 17:21:45 +02002242#ifdef SND_HDA_NEEDS_RESUME
Takashi Iwai82beb8f2007-08-10 17:09:26 +02002243/*
2244 * command cache
2245 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002246
Takashi Iwaib3ac5632007-08-10 17:03:40 +02002247/* build a 32bit cache key with the widget id and the command parameter */
2248#define build_cmd_cache_key(nid, verb) ((verb << 8) | nid)
2249#define get_cmd_cache_nid(key) ((key) & 0xff)
2250#define get_cmd_cache_cmd(key) (((key) >> 8) & 0xffff)
2251
2252/**
2253 * snd_hda_codec_write_cache - send a single command with caching
2254 * @codec: the HDA codec
2255 * @nid: NID to send the command
2256 * @direct: direct flag
2257 * @verb: the verb to send
2258 * @parm: the parameter for the verb
2259 *
2260 * Send a single command without waiting for response.
2261 *
2262 * Returns 0 if successful, or a negative error code.
2263 */
2264int snd_hda_codec_write_cache(struct hda_codec *codec, hda_nid_t nid,
2265 int direct, unsigned int verb, unsigned int parm)
2266{
Takashi Iwai33fa35e2008-11-06 16:50:40 +01002267 struct hda_bus *bus = codec->bus;
2268 unsigned int res;
Takashi Iwaib3ac5632007-08-10 17:03:40 +02002269 int err;
Takashi Iwai33fa35e2008-11-06 16:50:40 +01002270
2271 res = make_codec_cmd(codec, nid, direct, verb, parm);
Takashi Iwaicb53c622007-08-10 17:21:45 +02002272 snd_hda_power_up(codec);
Takashi Iwai33fa35e2008-11-06 16:50:40 +01002273 mutex_lock(&bus->cmd_mutex);
2274 err = bus->ops.command(bus, res);
Takashi Iwaib3ac5632007-08-10 17:03:40 +02002275 if (!err) {
2276 struct hda_cache_head *c;
2277 u32 key = build_cmd_cache_key(nid, verb);
2278 c = get_alloc_hash(&codec->cmd_cache, key);
2279 if (c)
2280 c->val = parm;
2281 }
Takashi Iwai33fa35e2008-11-06 16:50:40 +01002282 mutex_unlock(&bus->cmd_mutex);
Takashi Iwaicb53c622007-08-10 17:21:45 +02002283 snd_hda_power_down(codec);
Takashi Iwaib3ac5632007-08-10 17:03:40 +02002284 return err;
2285}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002286EXPORT_SYMBOL_HDA(snd_hda_codec_write_cache);
Takashi Iwaib3ac5632007-08-10 17:03:40 +02002287
2288/* resume the all commands from the cache */
2289void snd_hda_codec_resume_cache(struct hda_codec *codec)
2290{
Takashi Iwai603c4012008-07-30 15:01:44 +02002291 struct hda_cache_head *buffer = codec->cmd_cache.buf.list;
Takashi Iwaib3ac5632007-08-10 17:03:40 +02002292 int i;
2293
Takashi Iwai603c4012008-07-30 15:01:44 +02002294 for (i = 0; i < codec->cmd_cache.buf.used; i++, buffer++) {
Takashi Iwaib3ac5632007-08-10 17:03:40 +02002295 u32 key = buffer->key;
2296 if (!key)
2297 continue;
2298 snd_hda_codec_write(codec, get_cmd_cache_nid(key), 0,
2299 get_cmd_cache_cmd(key), buffer->val);
2300 }
2301}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002302EXPORT_SYMBOL_HDA(snd_hda_codec_resume_cache);
Takashi Iwaib3ac5632007-08-10 17:03:40 +02002303
2304/**
2305 * snd_hda_sequence_write_cache - sequence writes with caching
2306 * @codec: the HDA codec
2307 * @seq: VERB array to send
2308 *
2309 * Send the commands sequentially from the given array.
2310 * Thte commands are recorded on cache for power-save and resume.
2311 * The array must be terminated with NID=0.
2312 */
2313void snd_hda_sequence_write_cache(struct hda_codec *codec,
2314 const struct hda_verb *seq)
2315{
2316 for (; seq->nid; seq++)
2317 snd_hda_codec_write_cache(codec, seq->nid, 0, seq->verb,
2318 seq->param);
2319}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002320EXPORT_SYMBOL_HDA(snd_hda_sequence_write_cache);
Takashi Iwaicb53c622007-08-10 17:21:45 +02002321#endif /* SND_HDA_NEEDS_RESUME */
Takashi Iwaib3ac5632007-08-10 17:03:40 +02002322
Takashi Iwai54d17402005-11-21 16:33:22 +01002323/*
2324 * set power state of the codec
2325 */
2326static void hda_set_power_state(struct hda_codec *codec, hda_nid_t fg,
2327 unsigned int power_state)
2328{
Takashi Iwaicb53c622007-08-10 17:21:45 +02002329 hda_nid_t nid;
2330 int i;
Takashi Iwai54d17402005-11-21 16:33:22 +01002331
2332 snd_hda_codec_write(codec, fg, 0, AC_VERB_SET_POWER_STATE,
2333 power_state);
Marc Boucherd2595d82008-01-22 15:23:30 +01002334 msleep(10); /* partial workaround for "azx_get_response timeout" */
Takashi Iwai54d17402005-11-21 16:33:22 +01002335
Takashi Iwaicb53c622007-08-10 17:21:45 +02002336 nid = codec->start_nid;
2337 for (i = 0; i < codec->num_nodes; i++, nid++) {
Takashi Iwai7eba5c92007-11-14 14:53:42 +01002338 unsigned int wcaps = get_wcaps(codec, nid);
2339 if (wcaps & AC_WCAP_POWER) {
2340 unsigned int wid_type = (wcaps & AC_WCAP_TYPE) >>
2341 AC_WCAP_TYPE_SHIFT;
2342 if (wid_type == AC_WID_PIN) {
2343 unsigned int pincap;
2344 /*
2345 * don't power down the widget if it controls
2346 * eapd and EAPD_BTLENABLE is set.
2347 */
Takashi Iwai14bafe32009-03-23 16:35:39 +01002348 pincap = snd_hda_query_pin_caps(codec, nid);
Takashi Iwai7eba5c92007-11-14 14:53:42 +01002349 if (pincap & AC_PINCAP_EAPD) {
2350 int eapd = snd_hda_codec_read(codec,
2351 nid, 0,
2352 AC_VERB_GET_EAPD_BTLENABLE, 0);
2353 eapd &= 0x02;
2354 if (power_state == AC_PWRST_D3 && eapd)
2355 continue;
2356 }
Takashi Iwai1194b5b2007-10-10 10:04:26 +02002357 }
Takashi Iwai54d17402005-11-21 16:33:22 +01002358 snd_hda_codec_write(codec, nid, 0,
2359 AC_VERB_SET_POWER_STATE,
2360 power_state);
Takashi Iwai1194b5b2007-10-10 10:04:26 +02002361 }
Takashi Iwai54d17402005-11-21 16:33:22 +01002362 }
2363
Takashi Iwaicb53c622007-08-10 17:21:45 +02002364 if (power_state == AC_PWRST_D0) {
2365 unsigned long end_time;
2366 int state;
Takashi Iwai54d17402005-11-21 16:33:22 +01002367 msleep(10);
Takashi Iwaicb53c622007-08-10 17:21:45 +02002368 /* wait until the codec reachs to D0 */
2369 end_time = jiffies + msecs_to_jiffies(500);
2370 do {
2371 state = snd_hda_codec_read(codec, fg, 0,
2372 AC_VERB_GET_POWER_STATE, 0);
2373 if (state == power_state)
2374 break;
2375 msleep(1);
2376 } while (time_after_eq(end_time, jiffies));
2377 }
Takashi Iwai54d17402005-11-21 16:33:22 +01002378}
2379
Takashi Iwai11aeff02008-07-30 15:01:46 +02002380#ifdef CONFIG_SND_HDA_HWDEP
2381/* execute additional init verbs */
2382static void hda_exec_init_verbs(struct hda_codec *codec)
2383{
2384 if (codec->init_verbs.list)
2385 snd_hda_sequence_write(codec, codec->init_verbs.list);
2386}
2387#else
2388static inline void hda_exec_init_verbs(struct hda_codec *codec) {}
2389#endif
2390
Takashi Iwaicb53c622007-08-10 17:21:45 +02002391#ifdef SND_HDA_NEEDS_RESUME
2392/*
2393 * call suspend and power-down; used both from PM and power-save
2394 */
2395static void hda_call_codec_suspend(struct hda_codec *codec)
2396{
2397 if (codec->patch_ops.suspend)
2398 codec->patch_ops.suspend(codec, PMSG_SUSPEND);
2399 hda_set_power_state(codec,
2400 codec->afg ? codec->afg : codec->mfg,
2401 AC_PWRST_D3);
2402#ifdef CONFIG_SND_HDA_POWER_SAVE
2403 cancel_delayed_work(&codec->power_work);
Takashi Iwai95e99fd2007-08-13 15:29:04 +02002404 codec->power_on = 0;
Takashi Iwaia221e282007-08-16 16:35:33 +02002405 codec->power_transition = 0;
Takashi Iwaicb53c622007-08-10 17:21:45 +02002406#endif
2407}
2408
2409/*
2410 * kick up codec; used both from PM and power-save
2411 */
2412static void hda_call_codec_resume(struct hda_codec *codec)
2413{
2414 hda_set_power_state(codec,
2415 codec->afg ? codec->afg : codec->mfg,
2416 AC_PWRST_D0);
Takashi Iwai3be14142009-02-20 14:11:16 +01002417 restore_pincfgs(codec); /* restore all current pin configs */
Takashi Iwai11aeff02008-07-30 15:01:46 +02002418 hda_exec_init_verbs(codec);
Takashi Iwaicb53c622007-08-10 17:21:45 +02002419 if (codec->patch_ops.resume)
2420 codec->patch_ops.resume(codec);
2421 else {
Takashi Iwai9d99f312007-08-14 15:15:52 +02002422 if (codec->patch_ops.init)
2423 codec->patch_ops.init(codec);
Takashi Iwaicb53c622007-08-10 17:21:45 +02002424 snd_hda_codec_resume_amp(codec);
2425 snd_hda_codec_resume_cache(codec);
2426 }
2427}
2428#endif /* SND_HDA_NEEDS_RESUME */
2429
Takashi Iwai54d17402005-11-21 16:33:22 +01002430
Linus Torvalds1da177e2005-04-16 15:20:36 -07002431/**
2432 * snd_hda_build_controls - build mixer controls
2433 * @bus: the BUS
2434 *
2435 * Creates mixer controls for each codec included in the bus.
2436 *
2437 * Returns 0 if successful, otherwise a negative error code.
2438 */
Takashi Iwai1289e9e2008-11-27 15:47:11 +01002439int /*__devinit*/ snd_hda_build_controls(struct hda_bus *bus)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002440{
Takashi Iwai0ba21762007-04-16 11:29:14 +02002441 struct hda_codec *codec;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002442
Takashi Iwai0ba21762007-04-16 11:29:14 +02002443 list_for_each_entry(codec, &bus->codec_list, list) {
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02002444 int err = snd_hda_codec_build_controls(codec);
Takashi Iwaif93d4612009-03-02 10:44:15 +01002445 if (err < 0) {
2446 printk(KERN_ERR "hda_codec: cannot build controls"
2447 "for #%d (error %d)\n", codec->addr, err);
2448 err = snd_hda_codec_reset(codec);
2449 if (err < 0) {
2450 printk(KERN_ERR
2451 "hda_codec: cannot revert codec\n");
2452 return err;
2453 }
2454 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002455 }
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02002456 return 0;
2457}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002458EXPORT_SYMBOL_HDA(snd_hda_build_controls);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002459
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02002460int snd_hda_codec_build_controls(struct hda_codec *codec)
2461{
2462 int err = 0;
Takashi Iwai11aeff02008-07-30 15:01:46 +02002463 hda_exec_init_verbs(codec);
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02002464 /* continue to initialize... */
2465 if (codec->patch_ops.init)
2466 err = codec->patch_ops.init(codec);
2467 if (!err && codec->patch_ops.build_controls)
2468 err = codec->patch_ops.build_controls(codec);
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02002469 if (err < 0)
2470 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002471 return 0;
2472}
2473
Linus Torvalds1da177e2005-04-16 15:20:36 -07002474/*
2475 * stream formats
2476 */
Takashi Iwaibefdf312005-08-22 13:57:55 +02002477struct hda_rate_tbl {
2478 unsigned int hz;
2479 unsigned int alsa_bits;
2480 unsigned int hda_fmt;
2481};
2482
2483static struct hda_rate_tbl rate_bits[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002484 /* rate in Hz, ALSA rate bitmask, HDA format value */
Nicolas Graziano9d8f53f2005-08-22 13:47:16 +02002485
2486 /* autodetected value used in snd_hda_query_supported_pcm */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002487 { 8000, SNDRV_PCM_RATE_8000, 0x0500 }, /* 1/6 x 48 */
2488 { 11025, SNDRV_PCM_RATE_11025, 0x4300 }, /* 1/4 x 44 */
2489 { 16000, SNDRV_PCM_RATE_16000, 0x0200 }, /* 1/3 x 48 */
2490 { 22050, SNDRV_PCM_RATE_22050, 0x4100 }, /* 1/2 x 44 */
2491 { 32000, SNDRV_PCM_RATE_32000, 0x0a00 }, /* 2/3 x 48 */
2492 { 44100, SNDRV_PCM_RATE_44100, 0x4000 }, /* 44 */
2493 { 48000, SNDRV_PCM_RATE_48000, 0x0000 }, /* 48 */
2494 { 88200, SNDRV_PCM_RATE_88200, 0x4800 }, /* 2 x 44 */
2495 { 96000, SNDRV_PCM_RATE_96000, 0x0800 }, /* 2 x 48 */
2496 { 176400, SNDRV_PCM_RATE_176400, 0x5800 },/* 4 x 44 */
2497 { 192000, SNDRV_PCM_RATE_192000, 0x1800 }, /* 4 x 48 */
Takashi Iwaia961f9f2007-04-12 13:08:09 +02002498#define AC_PAR_PCM_RATE_BITS 11
2499 /* up to bits 10, 384kHZ isn't supported properly */
2500
2501 /* not autodetected value */
2502 { 9600, SNDRV_PCM_RATE_KNOT, 0x0400 }, /* 1/5 x 48 */
Nicolas Graziano9d8f53f2005-08-22 13:47:16 +02002503
Takashi Iwaibefdf312005-08-22 13:57:55 +02002504 { 0 } /* terminator */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002505};
2506
2507/**
2508 * snd_hda_calc_stream_format - calculate format bitset
2509 * @rate: the sample rate
2510 * @channels: the number of channels
2511 * @format: the PCM format (SNDRV_PCM_FORMAT_XXX)
2512 * @maxbps: the max. bps
2513 *
2514 * Calculate the format bitset from the given rate, channels and th PCM format.
2515 *
2516 * Return zero if invalid.
2517 */
2518unsigned int snd_hda_calc_stream_format(unsigned int rate,
2519 unsigned int channels,
2520 unsigned int format,
2521 unsigned int maxbps)
2522{
2523 int i;
2524 unsigned int val = 0;
2525
Takashi Iwaibefdf312005-08-22 13:57:55 +02002526 for (i = 0; rate_bits[i].hz; i++)
2527 if (rate_bits[i].hz == rate) {
2528 val = rate_bits[i].hda_fmt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002529 break;
2530 }
Takashi Iwai0ba21762007-04-16 11:29:14 +02002531 if (!rate_bits[i].hz) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002532 snd_printdd("invalid rate %d\n", rate);
2533 return 0;
2534 }
2535
2536 if (channels == 0 || channels > 8) {
2537 snd_printdd("invalid channels %d\n", channels);
2538 return 0;
2539 }
2540 val |= channels - 1;
2541
2542 switch (snd_pcm_format_width(format)) {
2543 case 8: val |= 0x00; break;
2544 case 16: val |= 0x10; break;
2545 case 20:
2546 case 24:
2547 case 32:
2548 if (maxbps >= 32)
2549 val |= 0x40;
2550 else if (maxbps >= 24)
2551 val |= 0x30;
2552 else
2553 val |= 0x20;
2554 break;
2555 default:
Takashi Iwai0ba21762007-04-16 11:29:14 +02002556 snd_printdd("invalid format width %d\n",
2557 snd_pcm_format_width(format));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002558 return 0;
2559 }
2560
2561 return val;
2562}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002563EXPORT_SYMBOL_HDA(snd_hda_calc_stream_format);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002564
Takashi Iwai92c7c8a2009-03-24 07:32:14 +01002565static unsigned int get_pcm_param(struct hda_codec *codec, hda_nid_t nid)
2566{
2567 unsigned int val = 0;
2568 if (nid != codec->afg &&
2569 (get_wcaps(codec, nid) & AC_WCAP_FORMAT_OVRD))
2570 val = snd_hda_param_read(codec, nid, AC_PAR_PCM);
2571 if (!val || val == -1)
2572 val = snd_hda_param_read(codec, codec->afg, AC_PAR_PCM);
2573 if (!val || val == -1)
2574 return 0;
2575 return val;
2576}
2577
2578static unsigned int query_pcm_param(struct hda_codec *codec, hda_nid_t nid)
2579{
2580 return query_caps_hash(codec, nid, HDA_HASH_PARPCM_KEY(nid),
2581 get_pcm_param);
2582}
2583
2584static unsigned int get_stream_param(struct hda_codec *codec, hda_nid_t nid)
2585{
2586 unsigned int streams = snd_hda_param_read(codec, nid, AC_PAR_STREAM);
2587 if (!streams || streams == -1)
2588 streams = snd_hda_param_read(codec, codec->afg, AC_PAR_STREAM);
2589 if (!streams || streams == -1)
2590 return 0;
2591 return streams;
2592}
2593
2594static unsigned int query_stream_param(struct hda_codec *codec, hda_nid_t nid)
2595{
2596 return query_caps_hash(codec, nid, HDA_HASH_PARSTR_KEY(nid),
2597 get_stream_param);
2598}
2599
Linus Torvalds1da177e2005-04-16 15:20:36 -07002600/**
2601 * snd_hda_query_supported_pcm - query the supported PCM rates and formats
2602 * @codec: the HDA codec
2603 * @nid: NID to query
2604 * @ratesp: the pointer to store the detected rate bitflags
2605 * @formatsp: the pointer to store the detected formats
2606 * @bpsp: the pointer to store the detected format widths
2607 *
2608 * Queries the supported PCM rates and formats. The NULL @ratesp, @formatsp
2609 * or @bsps argument is ignored.
2610 *
2611 * Returns 0 if successful, otherwise a negative error code.
2612 */
Takashi Iwai986862bd2008-11-27 12:40:13 +01002613static int snd_hda_query_supported_pcm(struct hda_codec *codec, hda_nid_t nid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002614 u32 *ratesp, u64 *formatsp, unsigned int *bpsp)
2615{
Jaroslav Kyselaee504712009-03-17 14:30:31 +01002616 unsigned int i, val, wcaps;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002617
Jaroslav Kyselaee504712009-03-17 14:30:31 +01002618 wcaps = get_wcaps(codec, nid);
Takashi Iwai92c7c8a2009-03-24 07:32:14 +01002619 val = query_pcm_param(codec, nid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002620
2621 if (ratesp) {
2622 u32 rates = 0;
Takashi Iwaia961f9f2007-04-12 13:08:09 +02002623 for (i = 0; i < AC_PAR_PCM_RATE_BITS; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002624 if (val & (1 << i))
Takashi Iwaibefdf312005-08-22 13:57:55 +02002625 rates |= rate_bits[i].alsa_bits;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002626 }
Jaroslav Kyselaee504712009-03-17 14:30:31 +01002627 if (rates == 0) {
2628 snd_printk(KERN_ERR "hda_codec: rates == 0 "
2629 "(nid=0x%x, val=0x%x, ovrd=%i)\n",
2630 nid, val,
2631 (wcaps & AC_WCAP_FORMAT_OVRD) ? 1 : 0);
2632 return -EIO;
2633 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002634 *ratesp = rates;
2635 }
2636
2637 if (formatsp || bpsp) {
2638 u64 formats = 0;
Jaroslav Kyselaee504712009-03-17 14:30:31 +01002639 unsigned int streams, bps;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002640
Takashi Iwai92c7c8a2009-03-24 07:32:14 +01002641 streams = query_stream_param(codec, nid);
2642 if (!streams)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002643 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002644
2645 bps = 0;
2646 if (streams & AC_SUPFMT_PCM) {
2647 if (val & AC_SUPPCM_BITS_8) {
2648 formats |= SNDRV_PCM_FMTBIT_U8;
2649 bps = 8;
2650 }
2651 if (val & AC_SUPPCM_BITS_16) {
2652 formats |= SNDRV_PCM_FMTBIT_S16_LE;
2653 bps = 16;
2654 }
2655 if (wcaps & AC_WCAP_DIGITAL) {
2656 if (val & AC_SUPPCM_BITS_32)
2657 formats |= SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_LE;
2658 if (val & (AC_SUPPCM_BITS_20|AC_SUPPCM_BITS_24))
2659 formats |= SNDRV_PCM_FMTBIT_S32_LE;
2660 if (val & AC_SUPPCM_BITS_24)
2661 bps = 24;
2662 else if (val & AC_SUPPCM_BITS_20)
2663 bps = 20;
Takashi Iwai0ba21762007-04-16 11:29:14 +02002664 } else if (val & (AC_SUPPCM_BITS_20|AC_SUPPCM_BITS_24|
2665 AC_SUPPCM_BITS_32)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002666 formats |= SNDRV_PCM_FMTBIT_S32_LE;
2667 if (val & AC_SUPPCM_BITS_32)
2668 bps = 32;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002669 else if (val & AC_SUPPCM_BITS_24)
2670 bps = 24;
Nicolas Graziano33ef76512006-09-19 14:23:14 +02002671 else if (val & AC_SUPPCM_BITS_20)
2672 bps = 20;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002673 }
2674 }
Takashi Iwai0ba21762007-04-16 11:29:14 +02002675 else if (streams == AC_SUPFMT_FLOAT32) {
2676 /* should be exclusive */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002677 formats |= SNDRV_PCM_FMTBIT_FLOAT_LE;
2678 bps = 32;
Takashi Iwai0ba21762007-04-16 11:29:14 +02002679 } else if (streams == AC_SUPFMT_AC3) {
2680 /* should be exclusive */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002681 /* temporary hack: we have still no proper support
2682 * for the direct AC3 stream...
2683 */
2684 formats |= SNDRV_PCM_FMTBIT_U8;
2685 bps = 8;
2686 }
Jaroslav Kyselaee504712009-03-17 14:30:31 +01002687 if (formats == 0) {
2688 snd_printk(KERN_ERR "hda_codec: formats == 0 "
2689 "(nid=0x%x, val=0x%x, ovrd=%i, "
2690 "streams=0x%x)\n",
2691 nid, val,
2692 (wcaps & AC_WCAP_FORMAT_OVRD) ? 1 : 0,
2693 streams);
2694 return -EIO;
2695 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002696 if (formatsp)
2697 *formatsp = formats;
2698 if (bpsp)
2699 *bpsp = bps;
2700 }
2701
2702 return 0;
2703}
2704
2705/**
Takashi Iwai0ba21762007-04-16 11:29:14 +02002706 * snd_hda_is_supported_format - check whether the given node supports
2707 * the format val
Linus Torvalds1da177e2005-04-16 15:20:36 -07002708 *
2709 * Returns 1 if supported, 0 if not.
2710 */
2711int snd_hda_is_supported_format(struct hda_codec *codec, hda_nid_t nid,
2712 unsigned int format)
2713{
2714 int i;
2715 unsigned int val = 0, rate, stream;
2716
Takashi Iwai92c7c8a2009-03-24 07:32:14 +01002717 val = query_pcm_param(codec, nid);
2718 if (!val)
2719 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002720
2721 rate = format & 0xff00;
Takashi Iwaia961f9f2007-04-12 13:08:09 +02002722 for (i = 0; i < AC_PAR_PCM_RATE_BITS; i++)
Takashi Iwaibefdf312005-08-22 13:57:55 +02002723 if (rate_bits[i].hda_fmt == rate) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002724 if (val & (1 << i))
2725 break;
2726 return 0;
2727 }
Takashi Iwaia961f9f2007-04-12 13:08:09 +02002728 if (i >= AC_PAR_PCM_RATE_BITS)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002729 return 0;
2730
Takashi Iwai92c7c8a2009-03-24 07:32:14 +01002731 stream = query_stream_param(codec, nid);
2732 if (!stream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002733 return 0;
2734
2735 if (stream & AC_SUPFMT_PCM) {
2736 switch (format & 0xf0) {
2737 case 0x00:
Takashi Iwai0ba21762007-04-16 11:29:14 +02002738 if (!(val & AC_SUPPCM_BITS_8))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002739 return 0;
2740 break;
2741 case 0x10:
Takashi Iwai0ba21762007-04-16 11:29:14 +02002742 if (!(val & AC_SUPPCM_BITS_16))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002743 return 0;
2744 break;
2745 case 0x20:
Takashi Iwai0ba21762007-04-16 11:29:14 +02002746 if (!(val & AC_SUPPCM_BITS_20))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002747 return 0;
2748 break;
2749 case 0x30:
Takashi Iwai0ba21762007-04-16 11:29:14 +02002750 if (!(val & AC_SUPPCM_BITS_24))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002751 return 0;
2752 break;
2753 case 0x40:
Takashi Iwai0ba21762007-04-16 11:29:14 +02002754 if (!(val & AC_SUPPCM_BITS_32))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002755 return 0;
2756 break;
2757 default:
2758 return 0;
2759 }
2760 } else {
2761 /* FIXME: check for float32 and AC3? */
2762 }
2763
2764 return 1;
2765}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002766EXPORT_SYMBOL_HDA(snd_hda_is_supported_format);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002767
2768/*
2769 * PCM stuff
2770 */
2771static int hda_pcm_default_open_close(struct hda_pcm_stream *hinfo,
2772 struct hda_codec *codec,
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01002773 struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002774{
2775 return 0;
2776}
2777
2778static int hda_pcm_default_prepare(struct hda_pcm_stream *hinfo,
2779 struct hda_codec *codec,
2780 unsigned int stream_tag,
2781 unsigned int format,
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01002782 struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002783{
2784 snd_hda_codec_setup_stream(codec, hinfo->nid, stream_tag, 0, format);
2785 return 0;
2786}
2787
2788static int hda_pcm_default_cleanup(struct hda_pcm_stream *hinfo,
2789 struct hda_codec *codec,
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01002790 struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002791{
Takashi Iwai888afa12008-03-18 09:57:50 +01002792 snd_hda_codec_cleanup_stream(codec, hinfo->nid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002793 return 0;
2794}
2795
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02002796static int set_pcm_default_values(struct hda_codec *codec,
2797 struct hda_pcm_stream *info)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002798{
Jaroslav Kyselaee504712009-03-17 14:30:31 +01002799 int err;
2800
Takashi Iwai0ba21762007-04-16 11:29:14 +02002801 /* query support PCM information from the given NID */
2802 if (info->nid && (!info->rates || !info->formats)) {
Jaroslav Kyselaee504712009-03-17 14:30:31 +01002803 err = snd_hda_query_supported_pcm(codec, info->nid,
Takashi Iwai0ba21762007-04-16 11:29:14 +02002804 info->rates ? NULL : &info->rates,
2805 info->formats ? NULL : &info->formats,
2806 info->maxbps ? NULL : &info->maxbps);
Jaroslav Kyselaee504712009-03-17 14:30:31 +01002807 if (err < 0)
2808 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002809 }
2810 if (info->ops.open == NULL)
2811 info->ops.open = hda_pcm_default_open_close;
2812 if (info->ops.close == NULL)
2813 info->ops.close = hda_pcm_default_open_close;
2814 if (info->ops.prepare == NULL) {
Takashi Iwaida3cec32008-08-08 17:12:14 +02002815 if (snd_BUG_ON(!info->nid))
2816 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002817 info->ops.prepare = hda_pcm_default_prepare;
2818 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002819 if (info->ops.cleanup == NULL) {
Takashi Iwaida3cec32008-08-08 17:12:14 +02002820 if (snd_BUG_ON(!info->nid))
2821 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002822 info->ops.cleanup = hda_pcm_default_cleanup;
2823 }
2824 return 0;
2825}
2826
Takashi Iwai176d5332008-07-30 15:01:44 +02002827/*
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002828 * get the empty PCM device number to assign
2829 */
2830static int get_empty_pcm_device(struct hda_bus *bus, int type)
2831{
2832 static const char *dev_name[HDA_PCM_NTYPES] = {
2833 "Audio", "SPDIF", "HDMI", "Modem"
2834 };
2835 /* starting device index for each PCM type */
2836 static int dev_idx[HDA_PCM_NTYPES] = {
2837 [HDA_PCM_TYPE_AUDIO] = 0,
2838 [HDA_PCM_TYPE_SPDIF] = 1,
2839 [HDA_PCM_TYPE_HDMI] = 3,
2840 [HDA_PCM_TYPE_MODEM] = 6
2841 };
2842 /* normal audio device indices; not linear to keep compatibility */
2843 static int audio_idx[4] = { 0, 2, 4, 5 };
2844 int i, dev;
2845
2846 switch (type) {
2847 case HDA_PCM_TYPE_AUDIO:
2848 for (i = 0; i < ARRAY_SIZE(audio_idx); i++) {
2849 dev = audio_idx[i];
2850 if (!test_bit(dev, bus->pcm_dev_bits))
Takashi Iwai82ad39f2009-03-03 15:00:35 +01002851 goto ok;
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002852 }
Takashi Iwai82ad39f2009-03-03 15:00:35 +01002853 snd_printk(KERN_WARNING "Too many audio devices\n");
2854 return -EAGAIN;
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002855 case HDA_PCM_TYPE_SPDIF:
2856 case HDA_PCM_TYPE_HDMI:
2857 case HDA_PCM_TYPE_MODEM:
2858 dev = dev_idx[type];
2859 if (test_bit(dev, bus->pcm_dev_bits)) {
2860 snd_printk(KERN_WARNING "%s already defined\n",
2861 dev_name[type]);
2862 return -EAGAIN;
2863 }
2864 break;
2865 default:
2866 snd_printk(KERN_WARNING "Invalid PCM type %d\n", type);
2867 return -EINVAL;
2868 }
Takashi Iwai82ad39f2009-03-03 15:00:35 +01002869 ok:
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002870 set_bit(dev, bus->pcm_dev_bits);
2871 return dev;
2872}
2873
2874/*
Takashi Iwai176d5332008-07-30 15:01:44 +02002875 * attach a new PCM stream
2876 */
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002877static int snd_hda_attach_pcm(struct hda_codec *codec, struct hda_pcm *pcm)
Takashi Iwai176d5332008-07-30 15:01:44 +02002878{
Takashi Iwai33fa35e2008-11-06 16:50:40 +01002879 struct hda_bus *bus = codec->bus;
Takashi Iwai176d5332008-07-30 15:01:44 +02002880 struct hda_pcm_stream *info;
2881 int stream, err;
2882
Takashi Iwaib91f0802008-11-04 08:43:08 +01002883 if (snd_BUG_ON(!pcm->name))
Takashi Iwai176d5332008-07-30 15:01:44 +02002884 return -EINVAL;
2885 for (stream = 0; stream < 2; stream++) {
2886 info = &pcm->stream[stream];
2887 if (info->substreams) {
2888 err = set_pcm_default_values(codec, info);
2889 if (err < 0)
2890 return err;
2891 }
2892 }
Takashi Iwai33fa35e2008-11-06 16:50:40 +01002893 return bus->ops.attach_pcm(bus, codec, pcm);
Takashi Iwai176d5332008-07-30 15:01:44 +02002894}
2895
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002896/* assign all PCMs of the given codec */
2897int snd_hda_codec_build_pcms(struct hda_codec *codec)
2898{
2899 unsigned int pcm;
2900 int err;
2901
2902 if (!codec->num_pcms) {
2903 if (!codec->patch_ops.build_pcms)
2904 return 0;
2905 err = codec->patch_ops.build_pcms(codec);
Takashi Iwai6e655bf2009-03-02 10:46:03 +01002906 if (err < 0) {
2907 printk(KERN_ERR "hda_codec: cannot build PCMs"
2908 "for #%d (error %d)\n", codec->addr, err);
2909 err = snd_hda_codec_reset(codec);
2910 if (err < 0) {
2911 printk(KERN_ERR
2912 "hda_codec: cannot revert codec\n");
2913 return err;
2914 }
2915 }
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002916 }
2917 for (pcm = 0; pcm < codec->num_pcms; pcm++) {
2918 struct hda_pcm *cpcm = &codec->pcm_info[pcm];
2919 int dev;
2920
2921 if (!cpcm->stream[0].substreams && !cpcm->stream[1].substreams)
Takashi Iwai41b5b012009-01-20 18:21:23 +01002922 continue; /* no substreams assigned */
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002923
2924 if (!cpcm->pcm) {
2925 dev = get_empty_pcm_device(codec->bus, cpcm->pcm_type);
2926 if (dev < 0)
Takashi Iwai6e655bf2009-03-02 10:46:03 +01002927 continue; /* no fatal error */
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002928 cpcm->device = dev;
2929 err = snd_hda_attach_pcm(codec, cpcm);
Takashi Iwai6e655bf2009-03-02 10:46:03 +01002930 if (err < 0) {
2931 printk(KERN_ERR "hda_codec: cannot attach "
2932 "PCM stream %d for codec #%d\n",
2933 dev, codec->addr);
2934 continue; /* no fatal error */
2935 }
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002936 }
2937 }
2938 return 0;
2939}
2940
Linus Torvalds1da177e2005-04-16 15:20:36 -07002941/**
2942 * snd_hda_build_pcms - build PCM information
2943 * @bus: the BUS
2944 *
2945 * Create PCM information for each codec included in the bus.
2946 *
2947 * The build_pcms codec patch is requested to set up codec->num_pcms and
2948 * codec->pcm_info properly. The array is referred by the top-level driver
2949 * to create its PCM instances.
2950 * The allocated codec->pcm_info should be released in codec->patch_ops.free
2951 * callback.
2952 *
2953 * At least, substreams, channels_min and channels_max must be filled for
2954 * each stream. substreams = 0 indicates that the stream doesn't exist.
2955 * When rates and/or formats are zero, the supported values are queried
2956 * from the given nid. The nid is used also by the default ops.prepare
2957 * and ops.cleanup callbacks.
2958 *
2959 * The driver needs to call ops.open in its open callback. Similarly,
2960 * ops.close is supposed to be called in the close callback.
2961 * ops.prepare should be called in the prepare or hw_params callback
2962 * with the proper parameters for set up.
2963 * ops.cleanup should be called in hw_free for clean up of streams.
2964 *
2965 * This function returns 0 if successfull, or a negative error code.
2966 */
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002967int __devinit snd_hda_build_pcms(struct hda_bus *bus)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002968{
Takashi Iwai0ba21762007-04-16 11:29:14 +02002969 struct hda_codec *codec;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002970
Takashi Iwai0ba21762007-04-16 11:29:14 +02002971 list_for_each_entry(codec, &bus->codec_list, list) {
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002972 int err = snd_hda_codec_build_pcms(codec);
2973 if (err < 0)
2974 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002975 }
2976 return 0;
2977}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002978EXPORT_SYMBOL_HDA(snd_hda_build_pcms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002979
Linus Torvalds1da177e2005-04-16 15:20:36 -07002980/**
2981 * snd_hda_check_board_config - compare the current codec with the config table
2982 * @codec: the HDA codec
Takashi Iwaif5fcc132006-11-24 17:07:44 +01002983 * @num_configs: number of config enums
2984 * @models: array of model name strings
Linus Torvalds1da177e2005-04-16 15:20:36 -07002985 * @tbl: configuration table, terminated by null entries
2986 *
2987 * Compares the modelname or PCI subsystem id of the current codec with the
2988 * given configuration table. If a matching entry is found, returns its
2989 * config value (supposed to be 0 or positive).
2990 *
2991 * If no entries are matching, the function returns a negative value.
2992 */
Takashi Iwai12f288b2007-08-02 15:51:59 +02002993int snd_hda_check_board_config(struct hda_codec *codec,
2994 int num_configs, const char **models,
2995 const struct snd_pci_quirk *tbl)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002996{
Takashi Iwaif44ac832008-07-30 15:01:45 +02002997 if (codec->modelname && models) {
Takashi Iwaif5fcc132006-11-24 17:07:44 +01002998 int i;
2999 for (i = 0; i < num_configs; i++) {
3000 if (models[i] &&
Takashi Iwaif44ac832008-07-30 15:01:45 +02003001 !strcmp(codec->modelname, models[i])) {
Takashi Iwaif5fcc132006-11-24 17:07:44 +01003002 snd_printd(KERN_INFO "hda_codec: model '%s' is "
3003 "selected\n", models[i]);
3004 return i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003005 }
3006 }
3007 }
3008
Takashi Iwaif5fcc132006-11-24 17:07:44 +01003009 if (!codec->bus->pci || !tbl)
3010 return -1;
3011
3012 tbl = snd_pci_quirk_lookup(codec->bus->pci, tbl);
3013 if (!tbl)
3014 return -1;
3015 if (tbl->value >= 0 && tbl->value < num_configs) {
Takashi Iwai62cf8722008-05-20 12:15:15 +02003016#ifdef CONFIG_SND_DEBUG_VERBOSE
Takashi Iwaif5fcc132006-11-24 17:07:44 +01003017 char tmp[10];
3018 const char *model = NULL;
3019 if (models)
3020 model = models[tbl->value];
3021 if (!model) {
3022 sprintf(tmp, "#%d", tbl->value);
3023 model = tmp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003024 }
Takashi Iwaif5fcc132006-11-24 17:07:44 +01003025 snd_printdd(KERN_INFO "hda_codec: model '%s' is selected "
3026 "for config %x:%x (%s)\n",
3027 model, tbl->subvendor, tbl->subdevice,
3028 (tbl->name ? tbl->name : "Unknown device"));
3029#endif
3030 return tbl->value;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003031 }
3032 return -1;
3033}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003034EXPORT_SYMBOL_HDA(snd_hda_check_board_config);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003035
3036/**
Mauro Carvalho Chehab2eda3442008-08-11 10:18:39 +02003037 * snd_hda_check_board_codec_sid_config - compare the current codec
3038 subsystem ID with the
3039 config table
3040
3041 This is important for Gateway notebooks with SB450 HDA Audio
3042 where the vendor ID of the PCI device is:
3043 ATI Technologies Inc SB450 HDA Audio [1002:437b]
3044 and the vendor/subvendor are found only at the codec.
3045
3046 * @codec: the HDA codec
3047 * @num_configs: number of config enums
3048 * @models: array of model name strings
3049 * @tbl: configuration table, terminated by null entries
3050 *
3051 * Compares the modelname or PCI subsystem id of the current codec with the
3052 * given configuration table. If a matching entry is found, returns its
3053 * config value (supposed to be 0 or positive).
3054 *
3055 * If no entries are matching, the function returns a negative value.
3056 */
3057int snd_hda_check_board_codec_sid_config(struct hda_codec *codec,
3058 int num_configs, const char **models,
3059 const struct snd_pci_quirk *tbl)
3060{
3061 const struct snd_pci_quirk *q;
3062
3063 /* Search for codec ID */
3064 for (q = tbl; q->subvendor; q++) {
3065 unsigned long vendorid = (q->subdevice) | (q->subvendor << 16);
3066
3067 if (vendorid == codec->subsystem_id)
3068 break;
3069 }
3070
3071 if (!q->subvendor)
3072 return -1;
3073
3074 tbl = q;
3075
3076 if (tbl->value >= 0 && tbl->value < num_configs) {
3077#ifdef CONFIG_SND_DEBUG_DETECT
3078 char tmp[10];
3079 const char *model = NULL;
3080 if (models)
3081 model = models[tbl->value];
3082 if (!model) {
3083 sprintf(tmp, "#%d", tbl->value);
3084 model = tmp;
3085 }
3086 snd_printdd(KERN_INFO "hda_codec: model '%s' is selected "
3087 "for config %x:%x (%s)\n",
3088 model, tbl->subvendor, tbl->subdevice,
3089 (tbl->name ? tbl->name : "Unknown device"));
3090#endif
3091 return tbl->value;
3092 }
3093 return -1;
3094}
3095EXPORT_SYMBOL_HDA(snd_hda_check_board_codec_sid_config);
3096
3097/**
Linus Torvalds1da177e2005-04-16 15:20:36 -07003098 * snd_hda_add_new_ctls - create controls from the array
3099 * @codec: the HDA codec
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01003100 * @knew: the array of struct snd_kcontrol_new
Linus Torvalds1da177e2005-04-16 15:20:36 -07003101 *
3102 * This helper function creates and add new controls in the given array.
3103 * The array must be terminated with an empty entry as terminator.
3104 *
3105 * Returns 0 if successful, or a negative error code.
3106 */
Takashi Iwai12f288b2007-08-02 15:51:59 +02003107int snd_hda_add_new_ctls(struct hda_codec *codec, struct snd_kcontrol_new *knew)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003108{
Takashi Iwaicb53c622007-08-10 17:21:45 +02003109 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003110
3111 for (; knew->name; knew++) {
Takashi Iwai54d17402005-11-21 16:33:22 +01003112 struct snd_kcontrol *kctl;
3113 kctl = snd_ctl_new1(knew, codec);
Takashi Iwai0ba21762007-04-16 11:29:14 +02003114 if (!kctl)
Takashi Iwai54d17402005-11-21 16:33:22 +01003115 return -ENOMEM;
Takashi Iwaid13bd412008-07-30 15:01:45 +02003116 err = snd_hda_ctl_add(codec, kctl);
Takashi Iwai54d17402005-11-21 16:33:22 +01003117 if (err < 0) {
Takashi Iwai0ba21762007-04-16 11:29:14 +02003118 if (!codec->addr)
Takashi Iwai54d17402005-11-21 16:33:22 +01003119 return err;
3120 kctl = snd_ctl_new1(knew, codec);
Takashi Iwai0ba21762007-04-16 11:29:14 +02003121 if (!kctl)
Takashi Iwai54d17402005-11-21 16:33:22 +01003122 return -ENOMEM;
3123 kctl->id.device = codec->addr;
Takashi Iwaid13bd412008-07-30 15:01:45 +02003124 err = snd_hda_ctl_add(codec, kctl);
Takashi Iwai0ba21762007-04-16 11:29:14 +02003125 if (err < 0)
Takashi Iwai54d17402005-11-21 16:33:22 +01003126 return err;
3127 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003128 }
3129 return 0;
3130}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003131EXPORT_SYMBOL_HDA(snd_hda_add_new_ctls);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003132
Takashi Iwaicb53c622007-08-10 17:21:45 +02003133#ifdef CONFIG_SND_HDA_POWER_SAVE
3134static void hda_set_power_state(struct hda_codec *codec, hda_nid_t fg,
3135 unsigned int power_state);
3136
3137static void hda_power_work(struct work_struct *work)
3138{
3139 struct hda_codec *codec =
3140 container_of(work, struct hda_codec, power_work.work);
Takashi Iwai33fa35e2008-11-06 16:50:40 +01003141 struct hda_bus *bus = codec->bus;
Takashi Iwaicb53c622007-08-10 17:21:45 +02003142
Maxim Levitsky2e492462007-09-03 15:26:57 +02003143 if (!codec->power_on || codec->power_count) {
3144 codec->power_transition = 0;
Takashi Iwaicb53c622007-08-10 17:21:45 +02003145 return;
Maxim Levitsky2e492462007-09-03 15:26:57 +02003146 }
Takashi Iwaicb53c622007-08-10 17:21:45 +02003147
3148 hda_call_codec_suspend(codec);
Takashi Iwai33fa35e2008-11-06 16:50:40 +01003149 if (bus->ops.pm_notify)
3150 bus->ops.pm_notify(bus);
Takashi Iwaicb53c622007-08-10 17:21:45 +02003151}
3152
3153static void hda_keep_power_on(struct hda_codec *codec)
3154{
3155 codec->power_count++;
3156 codec->power_on = 1;
3157}
3158
3159void snd_hda_power_up(struct hda_codec *codec)
3160{
Takashi Iwai33fa35e2008-11-06 16:50:40 +01003161 struct hda_bus *bus = codec->bus;
3162
Takashi Iwaicb53c622007-08-10 17:21:45 +02003163 codec->power_count++;
Takashi Iwaia221e282007-08-16 16:35:33 +02003164 if (codec->power_on || codec->power_transition)
Takashi Iwaicb53c622007-08-10 17:21:45 +02003165 return;
3166
3167 codec->power_on = 1;
Takashi Iwai33fa35e2008-11-06 16:50:40 +01003168 if (bus->ops.pm_notify)
3169 bus->ops.pm_notify(bus);
Takashi Iwaicb53c622007-08-10 17:21:45 +02003170 hda_call_codec_resume(codec);
3171 cancel_delayed_work(&codec->power_work);
Takashi Iwaia221e282007-08-16 16:35:33 +02003172 codec->power_transition = 0;
Takashi Iwaicb53c622007-08-10 17:21:45 +02003173}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003174EXPORT_SYMBOL_HDA(snd_hda_power_up);
Takashi Iwai1289e9e2008-11-27 15:47:11 +01003175
3176#define power_save(codec) \
3177 ((codec)->bus->power_save ? *(codec)->bus->power_save : 0)
Takashi Iwaicb53c622007-08-10 17:21:45 +02003178
Takashi Iwaifee2fba2008-11-27 12:43:28 +01003179#define power_save(codec) \
3180 ((codec)->bus->power_save ? *(codec)->bus->power_save : 0)
3181
Takashi Iwaicb53c622007-08-10 17:21:45 +02003182void snd_hda_power_down(struct hda_codec *codec)
3183{
3184 --codec->power_count;
Takashi Iwaia221e282007-08-16 16:35:33 +02003185 if (!codec->power_on || codec->power_count || codec->power_transition)
Takashi Iwaicb53c622007-08-10 17:21:45 +02003186 return;
Takashi Iwaifee2fba2008-11-27 12:43:28 +01003187 if (power_save(codec)) {
Takashi Iwaia221e282007-08-16 16:35:33 +02003188 codec->power_transition = 1; /* avoid reentrance */
Takashi Iwaic107b412009-01-13 17:46:37 +01003189 queue_delayed_work(codec->bus->workq, &codec->power_work,
Takashi Iwaifee2fba2008-11-27 12:43:28 +01003190 msecs_to_jiffies(power_save(codec) * 1000));
Takashi Iwaia221e282007-08-16 16:35:33 +02003191 }
Takashi Iwaicb53c622007-08-10 17:21:45 +02003192}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003193EXPORT_SYMBOL_HDA(snd_hda_power_down);
Takashi Iwaicb53c622007-08-10 17:21:45 +02003194
3195int snd_hda_check_amp_list_power(struct hda_codec *codec,
3196 struct hda_loopback_check *check,
3197 hda_nid_t nid)
3198{
3199 struct hda_amp_list *p;
3200 int ch, v;
3201
3202 if (!check->amplist)
3203 return 0;
3204 for (p = check->amplist; p->nid; p++) {
3205 if (p->nid == nid)
3206 break;
3207 }
3208 if (!p->nid)
3209 return 0; /* nothing changed */
3210
3211 for (p = check->amplist; p->nid; p++) {
3212 for (ch = 0; ch < 2; ch++) {
3213 v = snd_hda_codec_amp_read(codec, p->nid, ch, p->dir,
3214 p->idx);
3215 if (!(v & HDA_AMP_MUTE) && v > 0) {
3216 if (!check->power_on) {
3217 check->power_on = 1;
3218 snd_hda_power_up(codec);
3219 }
3220 return 1;
3221 }
3222 }
3223 }
3224 if (check->power_on) {
3225 check->power_on = 0;
3226 snd_hda_power_down(codec);
3227 }
3228 return 0;
3229}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003230EXPORT_SYMBOL_HDA(snd_hda_check_amp_list_power);
Takashi Iwaicb53c622007-08-10 17:21:45 +02003231#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07003232
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01003233/*
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01003234 * Channel mode helper
3235 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003236int snd_hda_ch_mode_info(struct hda_codec *codec,
3237 struct snd_ctl_elem_info *uinfo,
3238 const struct hda_channel_mode *chmode,
3239 int num_chmodes)
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01003240{
3241 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
3242 uinfo->count = 1;
3243 uinfo->value.enumerated.items = num_chmodes;
3244 if (uinfo->value.enumerated.item >= num_chmodes)
3245 uinfo->value.enumerated.item = num_chmodes - 1;
3246 sprintf(uinfo->value.enumerated.name, "%dch",
3247 chmode[uinfo->value.enumerated.item].channels);
3248 return 0;
3249}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003250EXPORT_SYMBOL_HDA(snd_hda_ch_mode_info);
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01003251
Takashi Iwai0ba21762007-04-16 11:29:14 +02003252int snd_hda_ch_mode_get(struct hda_codec *codec,
3253 struct snd_ctl_elem_value *ucontrol,
3254 const struct hda_channel_mode *chmode,
3255 int num_chmodes,
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01003256 int max_channels)
3257{
3258 int i;
3259
3260 for (i = 0; i < num_chmodes; i++) {
3261 if (max_channels == chmode[i].channels) {
3262 ucontrol->value.enumerated.item[0] = i;
3263 break;
3264 }
3265 }
3266 return 0;
3267}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003268EXPORT_SYMBOL_HDA(snd_hda_ch_mode_get);
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01003269
Takashi Iwai0ba21762007-04-16 11:29:14 +02003270int snd_hda_ch_mode_put(struct hda_codec *codec,
3271 struct snd_ctl_elem_value *ucontrol,
3272 const struct hda_channel_mode *chmode,
3273 int num_chmodes,
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01003274 int *max_channelsp)
3275{
3276 unsigned int mode;
3277
3278 mode = ucontrol->value.enumerated.item[0];
Takashi Iwai68ea7b22007-11-15 15:54:38 +01003279 if (mode >= num_chmodes)
3280 return -EINVAL;
Takashi Iwai82beb8f2007-08-10 17:09:26 +02003281 if (*max_channelsp == chmode[mode].channels)
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01003282 return 0;
3283 /* change the current channel setting */
3284 *max_channelsp = chmode[mode].channels;
3285 if (chmode[mode].sequence)
Takashi Iwai82beb8f2007-08-10 17:09:26 +02003286 snd_hda_sequence_write_cache(codec, chmode[mode].sequence);
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01003287 return 1;
3288}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003289EXPORT_SYMBOL_HDA(snd_hda_ch_mode_put);
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01003290
Linus Torvalds1da177e2005-04-16 15:20:36 -07003291/*
3292 * input MUX helper
3293 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003294int snd_hda_input_mux_info(const struct hda_input_mux *imux,
3295 struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003296{
3297 unsigned int index;
3298
3299 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
3300 uinfo->count = 1;
3301 uinfo->value.enumerated.items = imux->num_items;
Takashi Iwai5513b0c2007-10-09 11:58:41 +02003302 if (!imux->num_items)
3303 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003304 index = uinfo->value.enumerated.item;
3305 if (index >= imux->num_items)
3306 index = imux->num_items - 1;
3307 strcpy(uinfo->value.enumerated.name, imux->items[index].label);
3308 return 0;
3309}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003310EXPORT_SYMBOL_HDA(snd_hda_input_mux_info);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003311
Takashi Iwai0ba21762007-04-16 11:29:14 +02003312int snd_hda_input_mux_put(struct hda_codec *codec,
3313 const struct hda_input_mux *imux,
3314 struct snd_ctl_elem_value *ucontrol,
3315 hda_nid_t nid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003316 unsigned int *cur_val)
3317{
3318 unsigned int idx;
3319
Takashi Iwai5513b0c2007-10-09 11:58:41 +02003320 if (!imux->num_items)
3321 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003322 idx = ucontrol->value.enumerated.item[0];
3323 if (idx >= imux->num_items)
3324 idx = imux->num_items - 1;
Takashi Iwai82beb8f2007-08-10 17:09:26 +02003325 if (*cur_val == idx)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003326 return 0;
Takashi Iwai82beb8f2007-08-10 17:09:26 +02003327 snd_hda_codec_write_cache(codec, nid, 0, AC_VERB_SET_CONNECT_SEL,
3328 imux->items[idx].index);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003329 *cur_val = idx;
3330 return 1;
3331}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003332EXPORT_SYMBOL_HDA(snd_hda_input_mux_put);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003333
3334
3335/*
3336 * Multi-channel / digital-out PCM helper functions
3337 */
3338
Takashi Iwai6b97eb42007-04-05 14:51:48 +02003339/* setup SPDIF output stream */
3340static void setup_dig_out_stream(struct hda_codec *codec, hda_nid_t nid,
3341 unsigned int stream_tag, unsigned int format)
3342{
3343 /* turn off SPDIF once; otherwise the IEC958 bits won't be updated */
Takashi Iwai2f728532008-09-25 16:32:41 +02003344 if (codec->spdif_status_reset && (codec->spdif_ctls & AC_DIG1_ENABLE))
3345 set_dig_out_convert(codec, nid,
3346 codec->spdif_ctls & ~AC_DIG1_ENABLE & 0xff,
3347 -1);
Takashi Iwai6b97eb42007-04-05 14:51:48 +02003348 snd_hda_codec_setup_stream(codec, nid, stream_tag, 0, format);
Takashi Iwai2f728532008-09-25 16:32:41 +02003349 if (codec->slave_dig_outs) {
3350 hda_nid_t *d;
3351 for (d = codec->slave_dig_outs; *d; d++)
3352 snd_hda_codec_setup_stream(codec, *d, stream_tag, 0,
3353 format);
Matthew Ranostayde51ca12008-09-07 14:31:40 -04003354 }
Takashi Iwai2f728532008-09-25 16:32:41 +02003355 /* turn on again (if needed) */
3356 if (codec->spdif_status_reset && (codec->spdif_ctls & AC_DIG1_ENABLE))
3357 set_dig_out_convert(codec, nid,
3358 codec->spdif_ctls & 0xff, -1);
3359}
Matthew Ranostayde51ca12008-09-07 14:31:40 -04003360
Takashi Iwai2f728532008-09-25 16:32:41 +02003361static void cleanup_dig_out_stream(struct hda_codec *codec, hda_nid_t nid)
3362{
3363 snd_hda_codec_cleanup_stream(codec, nid);
3364 if (codec->slave_dig_outs) {
3365 hda_nid_t *d;
3366 for (d = codec->slave_dig_outs; *d; d++)
3367 snd_hda_codec_cleanup_stream(codec, *d);
3368 }
Takashi Iwai6b97eb42007-04-05 14:51:48 +02003369}
3370
Linus Torvalds1da177e2005-04-16 15:20:36 -07003371/*
3372 * open the digital out in the exclusive mode
3373 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003374int snd_hda_multi_out_dig_open(struct hda_codec *codec,
3375 struct hda_multi_out *mout)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003376{
Ingo Molnar62932df2006-01-16 16:34:20 +01003377 mutex_lock(&codec->spdif_mutex);
Takashi Iwai5930ca42007-04-16 11:23:56 +02003378 if (mout->dig_out_used == HDA_DIG_ANALOG_DUP)
3379 /* already opened as analog dup; reset it once */
Takashi Iwai2f728532008-09-25 16:32:41 +02003380 cleanup_dig_out_stream(codec, mout->dig_out_nid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003381 mout->dig_out_used = HDA_DIG_EXCLUSIVE;
Ingo Molnar62932df2006-01-16 16:34:20 +01003382 mutex_unlock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003383 return 0;
3384}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003385EXPORT_SYMBOL_HDA(snd_hda_multi_out_dig_open);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003386
Takashi Iwai6b97eb42007-04-05 14:51:48 +02003387int snd_hda_multi_out_dig_prepare(struct hda_codec *codec,
3388 struct hda_multi_out *mout,
3389 unsigned int stream_tag,
3390 unsigned int format,
3391 struct snd_pcm_substream *substream)
3392{
3393 mutex_lock(&codec->spdif_mutex);
3394 setup_dig_out_stream(codec, mout->dig_out_nid, stream_tag, format);
3395 mutex_unlock(&codec->spdif_mutex);
3396 return 0;
3397}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003398EXPORT_SYMBOL_HDA(snd_hda_multi_out_dig_prepare);
Takashi Iwai6b97eb42007-04-05 14:51:48 +02003399
Takashi Iwai9411e212009-02-13 11:32:28 +01003400int snd_hda_multi_out_dig_cleanup(struct hda_codec *codec,
3401 struct hda_multi_out *mout)
3402{
3403 mutex_lock(&codec->spdif_mutex);
3404 cleanup_dig_out_stream(codec, mout->dig_out_nid);
3405 mutex_unlock(&codec->spdif_mutex);
3406 return 0;
3407}
3408EXPORT_SYMBOL_HDA(snd_hda_multi_out_dig_cleanup);
3409
Linus Torvalds1da177e2005-04-16 15:20:36 -07003410/*
3411 * release the digital out
3412 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003413int snd_hda_multi_out_dig_close(struct hda_codec *codec,
3414 struct hda_multi_out *mout)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003415{
Ingo Molnar62932df2006-01-16 16:34:20 +01003416 mutex_lock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003417 mout->dig_out_used = 0;
Ingo Molnar62932df2006-01-16 16:34:20 +01003418 mutex_unlock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003419 return 0;
3420}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003421EXPORT_SYMBOL_HDA(snd_hda_multi_out_dig_close);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003422
3423/*
3424 * set up more restrictions for analog out
3425 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003426int snd_hda_multi_out_analog_open(struct hda_codec *codec,
3427 struct hda_multi_out *mout,
Takashi Iwai9a081602008-02-12 18:37:26 +01003428 struct snd_pcm_substream *substream,
3429 struct hda_pcm_stream *hinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003430{
Takashi Iwai9a081602008-02-12 18:37:26 +01003431 struct snd_pcm_runtime *runtime = substream->runtime;
3432 runtime->hw.channels_max = mout->max_channels;
3433 if (mout->dig_out_nid) {
3434 if (!mout->analog_rates) {
3435 mout->analog_rates = hinfo->rates;
3436 mout->analog_formats = hinfo->formats;
3437 mout->analog_maxbps = hinfo->maxbps;
3438 } else {
3439 runtime->hw.rates = mout->analog_rates;
3440 runtime->hw.formats = mout->analog_formats;
3441 hinfo->maxbps = mout->analog_maxbps;
3442 }
3443 if (!mout->spdif_rates) {
3444 snd_hda_query_supported_pcm(codec, mout->dig_out_nid,
3445 &mout->spdif_rates,
3446 &mout->spdif_formats,
3447 &mout->spdif_maxbps);
3448 }
3449 mutex_lock(&codec->spdif_mutex);
3450 if (mout->share_spdif) {
3451 runtime->hw.rates &= mout->spdif_rates;
3452 runtime->hw.formats &= mout->spdif_formats;
3453 if (mout->spdif_maxbps < hinfo->maxbps)
3454 hinfo->maxbps = mout->spdif_maxbps;
3455 }
Frederik Deweerdteaa99852008-04-14 13:11:44 +02003456 mutex_unlock(&codec->spdif_mutex);
Takashi Iwai9a081602008-02-12 18:37:26 +01003457 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003458 return snd_pcm_hw_constraint_step(substream->runtime, 0,
3459 SNDRV_PCM_HW_PARAM_CHANNELS, 2);
3460}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003461EXPORT_SYMBOL_HDA(snd_hda_multi_out_analog_open);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003462
3463/*
3464 * set up the i/o for analog out
3465 * when the digital out is available, copy the front out to digital out, too.
3466 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003467int snd_hda_multi_out_analog_prepare(struct hda_codec *codec,
3468 struct hda_multi_out *mout,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003469 unsigned int stream_tag,
3470 unsigned int format,
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01003471 struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003472{
3473 hda_nid_t *nids = mout->dac_nids;
3474 int chs = substream->runtime->channels;
3475 int i;
3476
Ingo Molnar62932df2006-01-16 16:34:20 +01003477 mutex_lock(&codec->spdif_mutex);
Takashi Iwai9a081602008-02-12 18:37:26 +01003478 if (mout->dig_out_nid && mout->share_spdif &&
3479 mout->dig_out_used != HDA_DIG_EXCLUSIVE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003480 if (chs == 2 &&
Takashi Iwai0ba21762007-04-16 11:29:14 +02003481 snd_hda_is_supported_format(codec, mout->dig_out_nid,
3482 format) &&
3483 !(codec->spdif_status & IEC958_AES0_NONAUDIO)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003484 mout->dig_out_used = HDA_DIG_ANALOG_DUP;
Takashi Iwai6b97eb42007-04-05 14:51:48 +02003485 setup_dig_out_stream(codec, mout->dig_out_nid,
3486 stream_tag, format);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003487 } else {
3488 mout->dig_out_used = 0;
Takashi Iwai2f728532008-09-25 16:32:41 +02003489 cleanup_dig_out_stream(codec, mout->dig_out_nid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003490 }
3491 }
Ingo Molnar62932df2006-01-16 16:34:20 +01003492 mutex_unlock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003493
3494 /* front */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003495 snd_hda_codec_setup_stream(codec, nids[HDA_FRONT], stream_tag,
3496 0, format);
Takashi Iwaid29240c2007-10-26 12:35:56 +02003497 if (!mout->no_share_stream &&
3498 mout->hp_nid && mout->hp_nid != nids[HDA_FRONT])
Linus Torvalds1da177e2005-04-16 15:20:36 -07003499 /* headphone out will just decode front left/right (stereo) */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003500 snd_hda_codec_setup_stream(codec, mout->hp_nid, stream_tag,
3501 0, format);
Takashi Iwai82bc9552006-03-21 11:24:42 +01003502 /* extra outputs copied from front */
3503 for (i = 0; i < ARRAY_SIZE(mout->extra_out_nid); i++)
Takashi Iwaid29240c2007-10-26 12:35:56 +02003504 if (!mout->no_share_stream && mout->extra_out_nid[i])
Takashi Iwai82bc9552006-03-21 11:24:42 +01003505 snd_hda_codec_setup_stream(codec,
3506 mout->extra_out_nid[i],
3507 stream_tag, 0, format);
3508
Linus Torvalds1da177e2005-04-16 15:20:36 -07003509 /* surrounds */
3510 for (i = 1; i < mout->num_dacs; i++) {
Takashi Iwai4b3acaf2005-06-10 19:48:10 +02003511 if (chs >= (i + 1) * 2) /* independent out */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003512 snd_hda_codec_setup_stream(codec, nids[i], stream_tag,
3513 i * 2, format);
Takashi Iwaid29240c2007-10-26 12:35:56 +02003514 else if (!mout->no_share_stream) /* copy front */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003515 snd_hda_codec_setup_stream(codec, nids[i], stream_tag,
3516 0, format);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003517 }
3518 return 0;
3519}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003520EXPORT_SYMBOL_HDA(snd_hda_multi_out_analog_prepare);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003521
3522/*
3523 * clean up the setting for analog out
3524 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003525int snd_hda_multi_out_analog_cleanup(struct hda_codec *codec,
3526 struct hda_multi_out *mout)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003527{
3528 hda_nid_t *nids = mout->dac_nids;
3529 int i;
3530
3531 for (i = 0; i < mout->num_dacs; i++)
Takashi Iwai888afa12008-03-18 09:57:50 +01003532 snd_hda_codec_cleanup_stream(codec, nids[i]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003533 if (mout->hp_nid)
Takashi Iwai888afa12008-03-18 09:57:50 +01003534 snd_hda_codec_cleanup_stream(codec, mout->hp_nid);
Takashi Iwai82bc9552006-03-21 11:24:42 +01003535 for (i = 0; i < ARRAY_SIZE(mout->extra_out_nid); i++)
3536 if (mout->extra_out_nid[i])
Takashi Iwai888afa12008-03-18 09:57:50 +01003537 snd_hda_codec_cleanup_stream(codec,
3538 mout->extra_out_nid[i]);
Ingo Molnar62932df2006-01-16 16:34:20 +01003539 mutex_lock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003540 if (mout->dig_out_nid && mout->dig_out_used == HDA_DIG_ANALOG_DUP) {
Takashi Iwai2f728532008-09-25 16:32:41 +02003541 cleanup_dig_out_stream(codec, mout->dig_out_nid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003542 mout->dig_out_used = 0;
3543 }
Ingo Molnar62932df2006-01-16 16:34:20 +01003544 mutex_unlock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003545 return 0;
3546}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003547EXPORT_SYMBOL_HDA(snd_hda_multi_out_analog_cleanup);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003548
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003549/*
Wu Fengguang6b345002008-10-07 14:21:41 +08003550 * Helper for automatic pin configuration
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003551 */
Kailang Yangdf694da2005-12-05 19:42:22 +01003552
Takashi Iwai12f288b2007-08-02 15:51:59 +02003553static int is_in_nid_list(hda_nid_t nid, hda_nid_t *list)
Kailang Yangdf694da2005-12-05 19:42:22 +01003554{
3555 for (; *list; list++)
3556 if (*list == nid)
3557 return 1;
3558 return 0;
3559}
3560
Steve Longerbeam81937d32007-05-08 15:33:03 +02003561
3562/*
3563 * Sort an associated group of pins according to their sequence numbers.
3564 */
3565static void sort_pins_by_sequence(hda_nid_t * pins, short * sequences,
3566 int num_pins)
3567{
3568 int i, j;
3569 short seq;
3570 hda_nid_t nid;
3571
3572 for (i = 0; i < num_pins; i++) {
3573 for (j = i + 1; j < num_pins; j++) {
3574 if (sequences[i] > sequences[j]) {
3575 seq = sequences[i];
3576 sequences[i] = sequences[j];
3577 sequences[j] = seq;
3578 nid = pins[i];
3579 pins[i] = pins[j];
3580 pins[j] = nid;
3581 }
3582 }
3583 }
3584}
3585
3586
Takashi Iwai82bc9552006-03-21 11:24:42 +01003587/*
3588 * Parse all pin widgets and store the useful pin nids to cfg
3589 *
3590 * The number of line-outs or any primary output is stored in line_outs,
3591 * and the corresponding output pins are assigned to line_out_pins[],
3592 * in the order of front, rear, CLFE, side, ...
3593 *
3594 * If more extra outputs (speaker and headphone) are found, the pins are
Takashi Iwaieb06ed82006-09-20 17:10:27 +02003595 * assisnged to hp_pins[] and speaker_pins[], respectively. If no line-out jack
Takashi Iwai82bc9552006-03-21 11:24:42 +01003596 * is detected, one of speaker of HP pins is assigned as the primary
3597 * output, i.e. to line_out_pins[0]. So, line_outs is always positive
3598 * if any analog output exists.
3599 *
3600 * The analog input pins are assigned to input_pins array.
3601 * The digital input/output pins are assigned to dig_in_pin and dig_out_pin,
3602 * respectively.
3603 */
Takashi Iwai12f288b2007-08-02 15:51:59 +02003604int snd_hda_parse_pin_def_config(struct hda_codec *codec,
3605 struct auto_pin_cfg *cfg,
3606 hda_nid_t *ignore_nids)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003607{
Takashi Iwai0ef6ce72008-01-22 15:35:37 +01003608 hda_nid_t nid, end_nid;
Steve Longerbeam81937d32007-05-08 15:33:03 +02003609 short seq, assoc_line_out, assoc_speaker;
3610 short sequences_line_out[ARRAY_SIZE(cfg->line_out_pins)];
3611 short sequences_speaker[ARRAY_SIZE(cfg->speaker_pins)];
Takashi Iwaif889fa92007-10-31 15:49:32 +01003612 short sequences_hp[ARRAY_SIZE(cfg->hp_pins)];
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003613
3614 memset(cfg, 0, sizeof(*cfg));
3615
Steve Longerbeam81937d32007-05-08 15:33:03 +02003616 memset(sequences_line_out, 0, sizeof(sequences_line_out));
3617 memset(sequences_speaker, 0, sizeof(sequences_speaker));
Takashi Iwaif889fa92007-10-31 15:49:32 +01003618 memset(sequences_hp, 0, sizeof(sequences_hp));
Steve Longerbeam81937d32007-05-08 15:33:03 +02003619 assoc_line_out = assoc_speaker = 0;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003620
Takashi Iwai0ef6ce72008-01-22 15:35:37 +01003621 end_nid = codec->start_nid + codec->num_nodes;
3622 for (nid = codec->start_nid; nid < end_nid; nid++) {
Takashi Iwai54d17402005-11-21 16:33:22 +01003623 unsigned int wid_caps = get_wcaps(codec, nid);
Takashi Iwai0ba21762007-04-16 11:29:14 +02003624 unsigned int wid_type =
3625 (wid_caps & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003626 unsigned int def_conf;
3627 short assoc, loc;
3628
3629 /* read all default configuration for pin complex */
3630 if (wid_type != AC_WID_PIN)
3631 continue;
Kailang Yangdf694da2005-12-05 19:42:22 +01003632 /* ignore the given nids (e.g. pc-beep returns error) */
3633 if (ignore_nids && is_in_nid_list(nid, ignore_nids))
3634 continue;
3635
Takashi Iwaic17a1ab2009-02-23 09:28:12 +01003636 def_conf = snd_hda_codec_get_pincfg(codec, nid);
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003637 if (get_defcfg_connect(def_conf) == AC_JACK_PORT_NONE)
3638 continue;
3639 loc = get_defcfg_location(def_conf);
3640 switch (get_defcfg_device(def_conf)) {
3641 case AC_JACK_LINE_OUT:
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003642 seq = get_defcfg_sequence(def_conf);
3643 assoc = get_defcfg_association(def_conf);
Matthew Ranostay90da78b2008-01-24 11:48:01 +01003644
3645 if (!(wid_caps & AC_WCAP_STEREO))
3646 if (!cfg->mono_out_pin)
3647 cfg->mono_out_pin = nid;
Takashi Iwai0ba21762007-04-16 11:29:14 +02003648 if (!assoc)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003649 continue;
Takashi Iwai0ba21762007-04-16 11:29:14 +02003650 if (!assoc_line_out)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003651 assoc_line_out = assoc;
3652 else if (assoc_line_out != assoc)
3653 continue;
3654 if (cfg->line_outs >= ARRAY_SIZE(cfg->line_out_pins))
3655 continue;
3656 cfg->line_out_pins[cfg->line_outs] = nid;
Steve Longerbeam81937d32007-05-08 15:33:03 +02003657 sequences_line_out[cfg->line_outs] = seq;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003658 cfg->line_outs++;
3659 break;
Takashi Iwai8d88bc32005-11-17 11:09:23 +01003660 case AC_JACK_SPEAKER:
Steve Longerbeam81937d32007-05-08 15:33:03 +02003661 seq = get_defcfg_sequence(def_conf);
3662 assoc = get_defcfg_association(def_conf);
3663 if (! assoc)
3664 continue;
3665 if (! assoc_speaker)
3666 assoc_speaker = assoc;
3667 else if (assoc_speaker != assoc)
3668 continue;
Takashi Iwai82bc9552006-03-21 11:24:42 +01003669 if (cfg->speaker_outs >= ARRAY_SIZE(cfg->speaker_pins))
3670 continue;
3671 cfg->speaker_pins[cfg->speaker_outs] = nid;
Steve Longerbeam81937d32007-05-08 15:33:03 +02003672 sequences_speaker[cfg->speaker_outs] = seq;
Takashi Iwai82bc9552006-03-21 11:24:42 +01003673 cfg->speaker_outs++;
Takashi Iwai8d88bc32005-11-17 11:09:23 +01003674 break;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003675 case AC_JACK_HP_OUT:
Takashi Iwaif889fa92007-10-31 15:49:32 +01003676 seq = get_defcfg_sequence(def_conf);
3677 assoc = get_defcfg_association(def_conf);
Takashi Iwaieb06ed82006-09-20 17:10:27 +02003678 if (cfg->hp_outs >= ARRAY_SIZE(cfg->hp_pins))
3679 continue;
3680 cfg->hp_pins[cfg->hp_outs] = nid;
Takashi Iwaif889fa92007-10-31 15:49:32 +01003681 sequences_hp[cfg->hp_outs] = (assoc << 4) | seq;
Takashi Iwaieb06ed82006-09-20 17:10:27 +02003682 cfg->hp_outs++;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003683 break;
Takashi Iwai314634b2006-09-21 11:56:18 +02003684 case AC_JACK_MIC_IN: {
3685 int preferred, alt;
3686 if (loc == AC_JACK_LOC_FRONT) {
3687 preferred = AUTO_PIN_FRONT_MIC;
3688 alt = AUTO_PIN_MIC;
3689 } else {
3690 preferred = AUTO_PIN_MIC;
3691 alt = AUTO_PIN_FRONT_MIC;
3692 }
3693 if (!cfg->input_pins[preferred])
3694 cfg->input_pins[preferred] = nid;
3695 else if (!cfg->input_pins[alt])
3696 cfg->input_pins[alt] = nid;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003697 break;
Takashi Iwai314634b2006-09-21 11:56:18 +02003698 }
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003699 case AC_JACK_LINE_IN:
3700 if (loc == AC_JACK_LOC_FRONT)
3701 cfg->input_pins[AUTO_PIN_FRONT_LINE] = nid;
3702 else
3703 cfg->input_pins[AUTO_PIN_LINE] = nid;
3704 break;
3705 case AC_JACK_CD:
3706 cfg->input_pins[AUTO_PIN_CD] = nid;
3707 break;
3708 case AC_JACK_AUX:
3709 cfg->input_pins[AUTO_PIN_AUX] = nid;
3710 break;
3711 case AC_JACK_SPDIF_OUT:
Takashi Iwai1b52ae72009-01-20 17:17:29 +01003712 case AC_JACK_DIG_OTHER_OUT:
Takashi Iwai0852d7a2009-02-11 11:35:15 +01003713 if (cfg->dig_outs >= ARRAY_SIZE(cfg->dig_out_pins))
3714 continue;
3715 cfg->dig_out_pins[cfg->dig_outs] = nid;
3716 cfg->dig_out_type[cfg->dig_outs] =
3717 (loc == AC_JACK_LOC_HDMI) ?
3718 HDA_PCM_TYPE_HDMI : HDA_PCM_TYPE_SPDIF;
3719 cfg->dig_outs++;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003720 break;
3721 case AC_JACK_SPDIF_IN:
Takashi Iwai1b52ae72009-01-20 17:17:29 +01003722 case AC_JACK_DIG_OTHER_IN:
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003723 cfg->dig_in_pin = nid;
Takashi Iwai2297bd62009-01-20 18:24:13 +01003724 if (loc == AC_JACK_LOC_HDMI)
3725 cfg->dig_in_type = HDA_PCM_TYPE_HDMI;
3726 else
3727 cfg->dig_in_type = HDA_PCM_TYPE_SPDIF;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003728 break;
3729 }
3730 }
3731
Takashi Iwai5832fcf82008-02-12 18:30:12 +01003732 /* FIX-UP:
3733 * If no line-out is defined but multiple HPs are found,
3734 * some of them might be the real line-outs.
3735 */
3736 if (!cfg->line_outs && cfg->hp_outs > 1) {
3737 int i = 0;
3738 while (i < cfg->hp_outs) {
3739 /* The real HPs should have the sequence 0x0f */
3740 if ((sequences_hp[i] & 0x0f) == 0x0f) {
3741 i++;
3742 continue;
3743 }
3744 /* Move it to the line-out table */
3745 cfg->line_out_pins[cfg->line_outs] = cfg->hp_pins[i];
3746 sequences_line_out[cfg->line_outs] = sequences_hp[i];
3747 cfg->line_outs++;
3748 cfg->hp_outs--;
3749 memmove(cfg->hp_pins + i, cfg->hp_pins + i + 1,
3750 sizeof(cfg->hp_pins[0]) * (cfg->hp_outs - i));
3751 memmove(sequences_hp + i - 1, sequences_hp + i,
3752 sizeof(sequences_hp[0]) * (cfg->hp_outs - i));
3753 }
3754 }
3755
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003756 /* sort by sequence */
Steve Longerbeam81937d32007-05-08 15:33:03 +02003757 sort_pins_by_sequence(cfg->line_out_pins, sequences_line_out,
3758 cfg->line_outs);
3759 sort_pins_by_sequence(cfg->speaker_pins, sequences_speaker,
3760 cfg->speaker_outs);
Takashi Iwaif889fa92007-10-31 15:49:32 +01003761 sort_pins_by_sequence(cfg->hp_pins, sequences_hp,
3762 cfg->hp_outs);
Steve Longerbeam81937d32007-05-08 15:33:03 +02003763
Takashi Iwaif889fa92007-10-31 15:49:32 +01003764 /* if we have only one mic, make it AUTO_PIN_MIC */
3765 if (!cfg->input_pins[AUTO_PIN_MIC] &&
3766 cfg->input_pins[AUTO_PIN_FRONT_MIC]) {
3767 cfg->input_pins[AUTO_PIN_MIC] =
3768 cfg->input_pins[AUTO_PIN_FRONT_MIC];
3769 cfg->input_pins[AUTO_PIN_FRONT_MIC] = 0;
3770 }
3771 /* ditto for line-in */
3772 if (!cfg->input_pins[AUTO_PIN_LINE] &&
3773 cfg->input_pins[AUTO_PIN_FRONT_LINE]) {
3774 cfg->input_pins[AUTO_PIN_LINE] =
3775 cfg->input_pins[AUTO_PIN_FRONT_LINE];
3776 cfg->input_pins[AUTO_PIN_FRONT_LINE] = 0;
3777 }
3778
Steve Longerbeam81937d32007-05-08 15:33:03 +02003779 /*
3780 * FIX-UP: if no line-outs are detected, try to use speaker or HP pin
3781 * as a primary output
3782 */
3783 if (!cfg->line_outs) {
3784 if (cfg->speaker_outs) {
3785 cfg->line_outs = cfg->speaker_outs;
3786 memcpy(cfg->line_out_pins, cfg->speaker_pins,
3787 sizeof(cfg->speaker_pins));
3788 cfg->speaker_outs = 0;
3789 memset(cfg->speaker_pins, 0, sizeof(cfg->speaker_pins));
3790 cfg->line_out_type = AUTO_PIN_SPEAKER_OUT;
3791 } else if (cfg->hp_outs) {
3792 cfg->line_outs = cfg->hp_outs;
3793 memcpy(cfg->line_out_pins, cfg->hp_pins,
3794 sizeof(cfg->hp_pins));
3795 cfg->hp_outs = 0;
3796 memset(cfg->hp_pins, 0, sizeof(cfg->hp_pins));
3797 cfg->line_out_type = AUTO_PIN_HP_OUT;
3798 }
3799 }
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003800
Takashi Iwaicb8e2f82005-07-29 11:54:32 +02003801 /* Reorder the surround channels
3802 * ALSA sequence is front/surr/clfe/side
3803 * HDA sequence is:
3804 * 4-ch: front/surr => OK as it is
3805 * 6-ch: front/clfe/surr
Takashi Iwai9422db42007-04-20 16:11:43 +02003806 * 8-ch: front/clfe/rear/side|fc
Takashi Iwaicb8e2f82005-07-29 11:54:32 +02003807 */
3808 switch (cfg->line_outs) {
3809 case 3:
Takashi Iwaicb8e2f82005-07-29 11:54:32 +02003810 case 4:
3811 nid = cfg->line_out_pins[1];
Takashi Iwai9422db42007-04-20 16:11:43 +02003812 cfg->line_out_pins[1] = cfg->line_out_pins[2];
Takashi Iwaicb8e2f82005-07-29 11:54:32 +02003813 cfg->line_out_pins[2] = nid;
3814 break;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003815 }
3816
Takashi Iwai82bc9552006-03-21 11:24:42 +01003817 /*
3818 * debug prints of the parsed results
3819 */
3820 snd_printd("autoconfig: line_outs=%d (0x%x/0x%x/0x%x/0x%x/0x%x)\n",
3821 cfg->line_outs, cfg->line_out_pins[0], cfg->line_out_pins[1],
3822 cfg->line_out_pins[2], cfg->line_out_pins[3],
3823 cfg->line_out_pins[4]);
3824 snd_printd(" speaker_outs=%d (0x%x/0x%x/0x%x/0x%x/0x%x)\n",
3825 cfg->speaker_outs, cfg->speaker_pins[0],
3826 cfg->speaker_pins[1], cfg->speaker_pins[2],
3827 cfg->speaker_pins[3], cfg->speaker_pins[4]);
Takashi Iwaieb06ed82006-09-20 17:10:27 +02003828 snd_printd(" hp_outs=%d (0x%x/0x%x/0x%x/0x%x/0x%x)\n",
3829 cfg->hp_outs, cfg->hp_pins[0],
3830 cfg->hp_pins[1], cfg->hp_pins[2],
3831 cfg->hp_pins[3], cfg->hp_pins[4]);
Matthew Ranostay90da78b2008-01-24 11:48:01 +01003832 snd_printd(" mono: mono_out=0x%x\n", cfg->mono_out_pin);
Takashi Iwai0852d7a2009-02-11 11:35:15 +01003833 if (cfg->dig_outs)
3834 snd_printd(" dig-out=0x%x/0x%x\n",
3835 cfg->dig_out_pins[0], cfg->dig_out_pins[1]);
Takashi Iwai82bc9552006-03-21 11:24:42 +01003836 snd_printd(" inputs: mic=0x%x, fmic=0x%x, line=0x%x, fline=0x%x,"
3837 " cd=0x%x, aux=0x%x\n",
3838 cfg->input_pins[AUTO_PIN_MIC],
3839 cfg->input_pins[AUTO_PIN_FRONT_MIC],
3840 cfg->input_pins[AUTO_PIN_LINE],
3841 cfg->input_pins[AUTO_PIN_FRONT_LINE],
3842 cfg->input_pins[AUTO_PIN_CD],
3843 cfg->input_pins[AUTO_PIN_AUX]);
Takashi Iwai32d2c7f2009-02-11 11:33:13 +01003844 if (cfg->dig_in_pin)
Takashi Iwai89ce9e82009-01-20 17:15:57 +01003845 snd_printd(" dig-in=0x%x\n", cfg->dig_in_pin);
Takashi Iwai82bc9552006-03-21 11:24:42 +01003846
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003847 return 0;
3848}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003849EXPORT_SYMBOL_HDA(snd_hda_parse_pin_def_config);
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003850
Takashi Iwai4a471b72005-12-07 13:56:29 +01003851/* labels for input pins */
3852const char *auto_pin_cfg_labels[AUTO_PIN_LAST] = {
3853 "Mic", "Front Mic", "Line", "Front Line", "CD", "Aux"
3854};
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003855EXPORT_SYMBOL_HDA(auto_pin_cfg_labels);
Takashi Iwai4a471b72005-12-07 13:56:29 +01003856
3857
Linus Torvalds1da177e2005-04-16 15:20:36 -07003858#ifdef CONFIG_PM
3859/*
3860 * power management
3861 */
3862
3863/**
3864 * snd_hda_suspend - suspend the codecs
3865 * @bus: the HDA bus
3866 * @state: suspsend state
3867 *
3868 * Returns 0 if successful.
3869 */
3870int snd_hda_suspend(struct hda_bus *bus, pm_message_t state)
3871{
Takashi Iwai0ba21762007-04-16 11:29:14 +02003872 struct hda_codec *codec;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003873
Takashi Iwai0ba21762007-04-16 11:29:14 +02003874 list_for_each_entry(codec, &bus->codec_list, list) {
Takashi Iwai0b7a2e92007-08-14 15:18:26 +02003875#ifdef CONFIG_SND_HDA_POWER_SAVE
3876 if (!codec->power_on)
3877 continue;
3878#endif
Takashi Iwaicb53c622007-08-10 17:21:45 +02003879 hda_call_codec_suspend(codec);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003880 }
3881 return 0;
3882}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003883EXPORT_SYMBOL_HDA(snd_hda_suspend);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003884
3885/**
3886 * snd_hda_resume - resume the codecs
3887 * @bus: the HDA bus
Linus Torvalds1da177e2005-04-16 15:20:36 -07003888 *
3889 * Returns 0 if successful.
Takashi Iwaicb53c622007-08-10 17:21:45 +02003890 *
3891 * This fucntion is defined only when POWER_SAVE isn't set.
3892 * In the power-save mode, the codec is resumed dynamically.
Linus Torvalds1da177e2005-04-16 15:20:36 -07003893 */
3894int snd_hda_resume(struct hda_bus *bus)
3895{
Takashi Iwai0ba21762007-04-16 11:29:14 +02003896 struct hda_codec *codec;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003897
Takashi Iwai0ba21762007-04-16 11:29:14 +02003898 list_for_each_entry(codec, &bus->codec_list, list) {
Maxim Levitskyd804ad92007-09-03 15:28:04 +02003899 if (snd_hda_codec_needs_resume(codec))
3900 hda_call_codec_resume(codec);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003901 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003902 return 0;
3903}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003904EXPORT_SYMBOL_HDA(snd_hda_resume);
Takashi Iwai1289e9e2008-11-27 15:47:11 +01003905#endif /* CONFIG_PM */
Takashi Iwaib2e18592008-07-30 15:01:44 +02003906
3907/*
3908 * generic arrays
3909 */
3910
3911/* get a new element from the given array
3912 * if it exceeds the pre-allocated array size, re-allocate the array
3913 */
3914void *snd_array_new(struct snd_array *array)
3915{
3916 if (array->used >= array->alloced) {
3917 int num = array->alloced + array->alloc_align;
Takashi Iwaib910d9a2008-11-07 00:26:52 +01003918 void *nlist;
3919 if (snd_BUG_ON(num >= 4096))
3920 return NULL;
3921 nlist = kcalloc(num + 1, array->elem_size, GFP_KERNEL);
Takashi Iwaib2e18592008-07-30 15:01:44 +02003922 if (!nlist)
3923 return NULL;
3924 if (array->list) {
3925 memcpy(nlist, array->list,
3926 array->elem_size * array->alloced);
3927 kfree(array->list);
3928 }
3929 array->list = nlist;
3930 array->alloced = num;
3931 }
Takashi Iwaif43aa022008-11-10 16:24:26 +01003932 return snd_array_elem(array, array->used++);
Takashi Iwaib2e18592008-07-30 15:01:44 +02003933}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003934EXPORT_SYMBOL_HDA(snd_array_new);
Takashi Iwaib2e18592008-07-30 15:01:44 +02003935
3936/* free the given array elements */
3937void snd_array_free(struct snd_array *array)
3938{
3939 kfree(array->list);
3940 array->used = 0;
3941 array->alloced = 0;
3942 array->list = NULL;
3943}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003944EXPORT_SYMBOL_HDA(snd_array_free);
Takashi Iwaib2022262008-11-21 21:24:03 +01003945
3946/*
3947 * used by hda_proc.c and hda_eld.c
3948 */
3949void snd_print_pcm_rates(int pcm, char *buf, int buflen)
3950{
3951 static unsigned int rates[] = {
3952 8000, 11025, 16000, 22050, 32000, 44100, 48000, 88200,
3953 96000, 176400, 192000, 384000
3954 };
3955 int i, j;
3956
3957 for (i = 0, j = 0; i < ARRAY_SIZE(rates); i++)
3958 if (pcm & (1 << i))
3959 j += snprintf(buf + j, buflen - j, " %d", rates[i]);
3960
3961 buf[j] = '\0'; /* necessary when j == 0 */
3962}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003963EXPORT_SYMBOL_HDA(snd_print_pcm_rates);
Takashi Iwaib2022262008-11-21 21:24:03 +01003964
3965void snd_print_pcm_bits(int pcm, char *buf, int buflen)
3966{
3967 static unsigned int bits[] = { 8, 16, 20, 24, 32 };
3968 int i, j;
3969
3970 for (i = 0, j = 0; i < ARRAY_SIZE(bits); i++)
3971 if (pcm & (AC_SUPPCM_BITS_8 << i))
3972 j += snprintf(buf + j, buflen - j, " %d", bits[i]);
3973
3974 buf[j] = '\0'; /* necessary when j == 0 */
3975}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003976EXPORT_SYMBOL_HDA(snd_print_pcm_bits);
Takashi Iwai1289e9e2008-11-27 15:47:11 +01003977
3978MODULE_DESCRIPTION("HDA codec core");
3979MODULE_LICENSE("GPL");