blob: b91f6ed5cc58d5c30c82e506a5879b0fb9c4ea6a [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * Universal Interface for Intel High Definition Audio Codec
3 *
4 * Copyright (c) 2004 Takashi Iwai <tiwai@suse.de>
5 *
6 *
7 * This driver is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This driver is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21
Linus Torvalds1da177e2005-04-16 15:20:36 -070022#include <linux/init.h>
23#include <linux/delay.h>
24#include <linux/slab.h>
25#include <linux/pci.h>
Ingo Molnar62932df2006-01-16 16:34:20 +010026#include <linux/mutex.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070027#include <sound/core.h>
28#include "hda_codec.h"
29#include <sound/asoundef.h>
Jaroslav Kysela302e9c52006-07-05 17:39:49 +020030#include <sound/tlv.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070031#include <sound/initval.h>
32#include "hda_local.h"
Takashi Iwai28073142007-07-27 18:58:06 +020033#include <sound/hda_hwdep.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070034
Linus Torvalds1da177e2005-04-16 15:20:36 -070035/*
36 * vendor / preset table
37 */
38
39struct hda_vendor_id {
40 unsigned int id;
41 const char *name;
42};
43
44/* codec vendor labels */
45static struct hda_vendor_id hda_vendor_ids[] = {
Takashi Iwaic8cd1282008-02-13 16:59:29 +010046 { 0x1002, "ATI" },
Takashi Iwaia9226252006-09-17 22:05:54 +020047 { 0x1057, "Motorola" },
Takashi Iwaic8cd1282008-02-13 16:59:29 +010048 { 0x1095, "Silicon Image" },
Takashi Iwai31117b72008-12-16 14:43:21 +010049 { 0x10de, "Nvidia" },
Takashi Iwaic8cd1282008-02-13 16:59:29 +010050 { 0x10ec, "Realtek" },
Takashi Iwai4e01f542009-04-16 08:53:34 +020051 { 0x1102, "Creative" },
Joseph Chanc577b8a2006-11-29 15:29:40 +010052 { 0x1106, "VIA" },
Matthew Ranostay7f168592007-10-18 17:38:17 +020053 { 0x111d, "IDT" },
Takashi Iwaic8cd1282008-02-13 16:59:29 +010054 { 0x11c1, "LSI" },
Takashi Iwai54b903e2005-05-15 14:30:10 +020055 { 0x11d4, "Analog Devices" },
Linus Torvalds1da177e2005-04-16 15:20:36 -070056 { 0x13f6, "C-Media" },
Takashi Iwaia9226252006-09-17 22:05:54 +020057 { 0x14f1, "Conexant" },
Takashi Iwaic8cd1282008-02-13 16:59:29 +010058 { 0x17e8, "Chrontel" },
59 { 0x1854, "LG" },
Mark Brown8199de32008-10-28 14:50:13 +000060 { 0x1aec, "Wolfson Microelectronics" },
Linus Torvalds1da177e2005-04-16 15:20:36 -070061 { 0x434d, "C-Media" },
Takashi Iwai74c61132008-12-18 09:11:33 +010062 { 0x8086, "Intel" },
Matt2f2f4252005-04-13 14:45:30 +020063 { 0x8384, "SigmaTel" },
Linus Torvalds1da177e2005-04-16 15:20:36 -070064 {} /* terminator */
65};
66
Takashi Iwai1289e9e2008-11-27 15:47:11 +010067static DEFINE_MUTEX(preset_mutex);
68static LIST_HEAD(hda_preset_tables);
69
70int snd_hda_add_codec_preset(struct hda_codec_preset_list *preset)
71{
72 mutex_lock(&preset_mutex);
73 list_add_tail(&preset->list, &hda_preset_tables);
74 mutex_unlock(&preset_mutex);
75 return 0;
76}
Takashi Iwaiff7a3262008-11-28 15:17:06 +010077EXPORT_SYMBOL_HDA(snd_hda_add_codec_preset);
Takashi Iwai1289e9e2008-11-27 15:47:11 +010078
79int snd_hda_delete_codec_preset(struct hda_codec_preset_list *preset)
80{
81 mutex_lock(&preset_mutex);
82 list_del(&preset->list);
83 mutex_unlock(&preset_mutex);
84 return 0;
85}
Takashi Iwaiff7a3262008-11-28 15:17:06 +010086EXPORT_SYMBOL_HDA(snd_hda_delete_codec_preset);
Linus Torvalds1da177e2005-04-16 15:20:36 -070087
Takashi Iwaicb53c622007-08-10 17:21:45 +020088#ifdef CONFIG_SND_HDA_POWER_SAVE
89static void hda_power_work(struct work_struct *work);
90static void hda_keep_power_on(struct hda_codec *codec);
91#else
92static inline void hda_keep_power_on(struct hda_codec *codec) {}
93#endif
94
Matthew Ranostay50a9f792008-10-25 01:05:45 -040095const char *snd_hda_get_jack_location(u32 cfg)
96{
97 static char *bases[7] = {
98 "N/A", "Rear", "Front", "Left", "Right", "Top", "Bottom",
99 };
100 static unsigned char specials_idx[] = {
101 0x07, 0x08,
102 0x17, 0x18, 0x19,
103 0x37, 0x38
104 };
105 static char *specials[] = {
106 "Rear Panel", "Drive Bar",
107 "Riser", "HDMI", "ATAPI",
108 "Mobile-In", "Mobile-Out"
109 };
110 int i;
111 cfg = (cfg & AC_DEFCFG_LOCATION) >> AC_DEFCFG_LOCATION_SHIFT;
112 if ((cfg & 0x0f) < 7)
113 return bases[cfg & 0x0f];
114 for (i = 0; i < ARRAY_SIZE(specials_idx); i++) {
115 if (cfg == specials_idx[i])
116 return specials[i];
117 }
118 return "UNKNOWN";
119}
Takashi Iwaiff7a3262008-11-28 15:17:06 +0100120EXPORT_SYMBOL_HDA(snd_hda_get_jack_location);
Matthew Ranostay50a9f792008-10-25 01:05:45 -0400121
122const char *snd_hda_get_jack_connectivity(u32 cfg)
123{
124 static char *jack_locations[4] = { "Ext", "Int", "Sep", "Oth" };
125
126 return jack_locations[(cfg >> (AC_DEFCFG_LOCATION_SHIFT + 4)) & 3];
127}
Takashi Iwaiff7a3262008-11-28 15:17:06 +0100128EXPORT_SYMBOL_HDA(snd_hda_get_jack_connectivity);
Matthew Ranostay50a9f792008-10-25 01:05:45 -0400129
130const char *snd_hda_get_jack_type(u32 cfg)
131{
132 static char *jack_types[16] = {
133 "Line Out", "Speaker", "HP Out", "CD",
134 "SPDIF Out", "Digital Out", "Modem Line", "Modem Hand",
135 "Line In", "Aux", "Mic", "Telephony",
136 "SPDIF In", "Digitial In", "Reserved", "Other"
137 };
138
139 return jack_types[(cfg & AC_DEFCFG_DEVICE)
140 >> AC_DEFCFG_DEVICE_SHIFT];
141}
Takashi Iwaiff7a3262008-11-28 15:17:06 +0100142EXPORT_SYMBOL_HDA(snd_hda_get_jack_type);
Matthew Ranostay50a9f792008-10-25 01:05:45 -0400143
Takashi Iwai33fa35e2008-11-06 16:50:40 +0100144/*
145 * Compose a 32bit command word to be sent to the HD-audio controller
146 */
147static inline unsigned int
148make_codec_cmd(struct hda_codec *codec, hda_nid_t nid, int direct,
149 unsigned int verb, unsigned int parm)
150{
151 u32 val;
152
153 val = (u32)(codec->addr & 0x0f) << 28;
154 val |= (u32)direct << 27;
155 val |= (u32)nid << 20;
156 val |= verb << 8;
157 val |= parm;
158 return val;
159}
160
Linus Torvalds1da177e2005-04-16 15:20:36 -0700161/**
162 * snd_hda_codec_read - send a command and get the response
163 * @codec: the HDA codec
164 * @nid: NID to send the command
165 * @direct: direct flag
166 * @verb: the verb to send
167 * @parm: the parameter for the verb
168 *
169 * Send a single command and read the corresponding response.
170 *
171 * Returns the obtained response value, or -1 for an error.
172 */
Takashi Iwai0ba21762007-04-16 11:29:14 +0200173unsigned int snd_hda_codec_read(struct hda_codec *codec, hda_nid_t nid,
174 int direct,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700175 unsigned int verb, unsigned int parm)
176{
Takashi Iwai33fa35e2008-11-06 16:50:40 +0100177 struct hda_bus *bus = codec->bus;
Takashi Iwaib6132912009-03-24 07:36:09 +0100178 unsigned int cmd, res;
179 int repeated = 0;
Takashi Iwai33fa35e2008-11-06 16:50:40 +0100180
Takashi Iwaib6132912009-03-24 07:36:09 +0100181 cmd = make_codec_cmd(codec, nid, direct, verb, parm);
Takashi Iwaicb53c622007-08-10 17:21:45 +0200182 snd_hda_power_up(codec);
Takashi Iwai33fa35e2008-11-06 16:50:40 +0100183 mutex_lock(&bus->cmd_mutex);
Takashi Iwaib6132912009-03-24 07:36:09 +0100184 again:
185 if (!bus->ops.command(bus, cmd)) {
Takashi Iwai33fa35e2008-11-06 16:50:40 +0100186 res = bus->ops.get_response(bus);
Takashi Iwaib6132912009-03-24 07:36:09 +0100187 if (res == -1 && bus->rirb_error) {
188 if (repeated++ < 1) {
189 snd_printd(KERN_WARNING "hda_codec: "
190 "Trying verb 0x%08x again\n", cmd);
191 goto again;
192 }
193 }
194 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -0700195 res = (unsigned int)-1;
Takashi Iwai33fa35e2008-11-06 16:50:40 +0100196 mutex_unlock(&bus->cmd_mutex);
Takashi Iwaicb53c622007-08-10 17:21:45 +0200197 snd_hda_power_down(codec);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700198 return res;
199}
Takashi Iwaiff7a3262008-11-28 15:17:06 +0100200EXPORT_SYMBOL_HDA(snd_hda_codec_read);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700201
202/**
203 * snd_hda_codec_write - send a single command without waiting for response
204 * @codec: the HDA codec
205 * @nid: NID to send the command
206 * @direct: direct flag
207 * @verb: the verb to send
208 * @parm: the parameter for the verb
209 *
210 * Send a single command without waiting for response.
211 *
212 * Returns 0 if successful, or a negative error code.
213 */
214int snd_hda_codec_write(struct hda_codec *codec, hda_nid_t nid, int direct,
215 unsigned int verb, unsigned int parm)
216{
Takashi Iwai33fa35e2008-11-06 16:50:40 +0100217 struct hda_bus *bus = codec->bus;
218 unsigned int res;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700219 int err;
Takashi Iwai33fa35e2008-11-06 16:50:40 +0100220
221 res = make_codec_cmd(codec, nid, direct, verb, parm);
Takashi Iwaicb53c622007-08-10 17:21:45 +0200222 snd_hda_power_up(codec);
Takashi Iwai33fa35e2008-11-06 16:50:40 +0100223 mutex_lock(&bus->cmd_mutex);
224 err = bus->ops.command(bus, res);
225 mutex_unlock(&bus->cmd_mutex);
Takashi Iwaicb53c622007-08-10 17:21:45 +0200226 snd_hda_power_down(codec);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700227 return err;
228}
Takashi Iwaiff7a3262008-11-28 15:17:06 +0100229EXPORT_SYMBOL_HDA(snd_hda_codec_write);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700230
231/**
232 * snd_hda_sequence_write - sequence writes
233 * @codec: the HDA codec
234 * @seq: VERB array to send
235 *
236 * Send the commands sequentially from the given array.
237 * The array must be terminated with NID=0.
238 */
239void snd_hda_sequence_write(struct hda_codec *codec, const struct hda_verb *seq)
240{
241 for (; seq->nid; seq++)
242 snd_hda_codec_write(codec, seq->nid, 0, seq->verb, seq->param);
243}
Takashi Iwaiff7a3262008-11-28 15:17:06 +0100244EXPORT_SYMBOL_HDA(snd_hda_sequence_write);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700245
246/**
247 * snd_hda_get_sub_nodes - get the range of sub nodes
248 * @codec: the HDA codec
249 * @nid: NID to parse
250 * @start_id: the pointer to store the start NID
251 *
252 * Parse the NID and store the start NID of its sub-nodes.
253 * Returns the number of sub-nodes.
254 */
Takashi Iwai0ba21762007-04-16 11:29:14 +0200255int snd_hda_get_sub_nodes(struct hda_codec *codec, hda_nid_t nid,
256 hda_nid_t *start_id)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700257{
258 unsigned int parm;
259
260 parm = snd_hda_param_read(codec, nid, AC_PAR_NODE_COUNT);
Danny Tholene8a7f132007-09-11 21:41:56 +0200261 if (parm == -1)
262 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700263 *start_id = (parm >> 16) & 0x7fff;
264 return (int)(parm & 0x7fff);
265}
Takashi Iwaiff7a3262008-11-28 15:17:06 +0100266EXPORT_SYMBOL_HDA(snd_hda_get_sub_nodes);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700267
268/**
269 * snd_hda_get_connections - get connection list
270 * @codec: the HDA codec
271 * @nid: NID to parse
272 * @conn_list: connection list array
273 * @max_conns: max. number of connections to store
274 *
275 * Parses the connection list of the given widget and stores the list
276 * of NIDs.
277 *
278 * Returns the number of connections, or a negative error code.
279 */
280int snd_hda_get_connections(struct hda_codec *codec, hda_nid_t nid,
281 hda_nid_t *conn_list, int max_conns)
282{
283 unsigned int parm;
Takashi Iwai54d17402005-11-21 16:33:22 +0100284 int i, conn_len, conns;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700285 unsigned int shift, num_elems, mask;
Takashi Iwai54d17402005-11-21 16:33:22 +0100286 hda_nid_t prev_nid;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700287
Takashi Iwaida3cec32008-08-08 17:12:14 +0200288 if (snd_BUG_ON(!conn_list || max_conns <= 0))
289 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700290
291 parm = snd_hda_param_read(codec, nid, AC_PAR_CONNLIST_LEN);
292 if (parm & AC_CLIST_LONG) {
293 /* long form */
294 shift = 16;
295 num_elems = 2;
296 } else {
297 /* short form */
298 shift = 8;
299 num_elems = 4;
300 }
301 conn_len = parm & AC_CLIST_LENGTH;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700302 mask = (1 << (shift-1)) - 1;
303
Takashi Iwai0ba21762007-04-16 11:29:14 +0200304 if (!conn_len)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700305 return 0; /* no connection */
306
307 if (conn_len == 1) {
308 /* single connection */
Takashi Iwai0ba21762007-04-16 11:29:14 +0200309 parm = snd_hda_codec_read(codec, nid, 0,
310 AC_VERB_GET_CONNECT_LIST, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700311 conn_list[0] = parm & mask;
312 return 1;
313 }
314
315 /* multi connection */
316 conns = 0;
Takashi Iwai54d17402005-11-21 16:33:22 +0100317 prev_nid = 0;
318 for (i = 0; i < conn_len; i++) {
319 int range_val;
320 hda_nid_t val, n;
321
322 if (i % num_elems == 0)
323 parm = snd_hda_codec_read(codec, nid, 0,
324 AC_VERB_GET_CONNECT_LIST, i);
Takashi Iwai0ba21762007-04-16 11:29:14 +0200325 range_val = !!(parm & (1 << (shift-1))); /* ranges */
Takashi Iwai54d17402005-11-21 16:33:22 +0100326 val = parm & mask;
327 parm >>= shift;
328 if (range_val) {
329 /* ranges between the previous and this one */
Takashi Iwai0ba21762007-04-16 11:29:14 +0200330 if (!prev_nid || prev_nid >= val) {
331 snd_printk(KERN_WARNING "hda_codec: "
332 "invalid dep_range_val %x:%x\n",
333 prev_nid, val);
Takashi Iwai54d17402005-11-21 16:33:22 +0100334 continue;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700335 }
Takashi Iwai54d17402005-11-21 16:33:22 +0100336 for (n = prev_nid + 1; n <= val; n++) {
337 if (conns >= max_conns) {
Takashi Iwai0ba21762007-04-16 11:29:14 +0200338 snd_printk(KERN_ERR
339 "Too many connections\n");
Takashi Iwai54d17402005-11-21 16:33:22 +0100340 return -EINVAL;
341 }
342 conn_list[conns++] = n;
343 }
344 } else {
345 if (conns >= max_conns) {
346 snd_printk(KERN_ERR "Too many connections\n");
347 return -EINVAL;
348 }
349 conn_list[conns++] = val;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700350 }
Takashi Iwai54d17402005-11-21 16:33:22 +0100351 prev_nid = val;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700352 }
353 return conns;
354}
Takashi Iwaiff7a3262008-11-28 15:17:06 +0100355EXPORT_SYMBOL_HDA(snd_hda_get_connections);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700356
357
358/**
359 * snd_hda_queue_unsol_event - add an unsolicited event to queue
360 * @bus: the BUS
361 * @res: unsolicited event (lower 32bit of RIRB entry)
362 * @res_ex: codec addr and flags (upper 32bit or RIRB entry)
363 *
364 * Adds the given event to the queue. The events are processed in
365 * the workqueue asynchronously. Call this function in the interrupt
366 * hanlder when RIRB receives an unsolicited event.
367 *
368 * Returns 0 if successful, or a negative error code.
369 */
370int snd_hda_queue_unsol_event(struct hda_bus *bus, u32 res, u32 res_ex)
371{
372 struct hda_bus_unsolicited *unsol;
373 unsigned int wp;
374
Takashi Iwai0ba21762007-04-16 11:29:14 +0200375 unsol = bus->unsol;
376 if (!unsol)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700377 return 0;
378
379 wp = (unsol->wp + 1) % HDA_UNSOL_QUEUE_SIZE;
380 unsol->wp = wp;
381
382 wp <<= 1;
383 unsol->queue[wp] = res;
384 unsol->queue[wp + 1] = res_ex;
385
Takashi Iwai6acaed32009-01-12 10:09:24 +0100386 queue_work(bus->workq, &unsol->work);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700387
388 return 0;
389}
Takashi Iwaiff7a3262008-11-28 15:17:06 +0100390EXPORT_SYMBOL_HDA(snd_hda_queue_unsol_event);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700391
392/*
Wu Fengguang5c1d1a92008-10-07 14:17:53 +0800393 * process queued unsolicited events
Linus Torvalds1da177e2005-04-16 15:20:36 -0700394 */
David Howellsc4028952006-11-22 14:57:56 +0000395static void process_unsol_events(struct work_struct *work)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700396{
David Howellsc4028952006-11-22 14:57:56 +0000397 struct hda_bus_unsolicited *unsol =
398 container_of(work, struct hda_bus_unsolicited, work);
399 struct hda_bus *bus = unsol->bus;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700400 struct hda_codec *codec;
401 unsigned int rp, caddr, res;
402
403 while (unsol->rp != unsol->wp) {
404 rp = (unsol->rp + 1) % HDA_UNSOL_QUEUE_SIZE;
405 unsol->rp = rp;
406 rp <<= 1;
407 res = unsol->queue[rp];
408 caddr = unsol->queue[rp + 1];
Takashi Iwai0ba21762007-04-16 11:29:14 +0200409 if (!(caddr & (1 << 4))) /* no unsolicited event? */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700410 continue;
411 codec = bus->caddr_tbl[caddr & 0x0f];
412 if (codec && codec->patch_ops.unsol_event)
413 codec->patch_ops.unsol_event(codec, res);
414 }
415}
416
417/*
418 * initialize unsolicited queue
419 */
Takashi Iwai6c1f45e2008-07-30 15:01:45 +0200420static int init_unsol_queue(struct hda_bus *bus)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700421{
422 struct hda_bus_unsolicited *unsol;
423
Takashi Iwai9f146bb2005-11-17 11:07:49 +0100424 if (bus->unsol) /* already initialized */
425 return 0;
426
Takashi Iwaie560d8d2005-09-09 14:21:46 +0200427 unsol = kzalloc(sizeof(*unsol), GFP_KERNEL);
Takashi Iwai0ba21762007-04-16 11:29:14 +0200428 if (!unsol) {
429 snd_printk(KERN_ERR "hda_codec: "
430 "can't allocate unsolicited queue\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700431 return -ENOMEM;
432 }
David Howellsc4028952006-11-22 14:57:56 +0000433 INIT_WORK(&unsol->work, process_unsol_events);
434 unsol->bus = bus;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700435 bus->unsol = unsol;
436 return 0;
437}
438
439/*
440 * destructor
441 */
442static void snd_hda_codec_free(struct hda_codec *codec);
443
444static int snd_hda_bus_free(struct hda_bus *bus)
445{
Takashi Iwai0ba21762007-04-16 11:29:14 +0200446 struct hda_codec *codec, *n;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700447
Takashi Iwai0ba21762007-04-16 11:29:14 +0200448 if (!bus)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700449 return 0;
Takashi Iwai6acaed32009-01-12 10:09:24 +0100450 if (bus->workq)
451 flush_workqueue(bus->workq);
452 if (bus->unsol)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700453 kfree(bus->unsol);
Takashi Iwai0ba21762007-04-16 11:29:14 +0200454 list_for_each_entry_safe(codec, n, &bus->codec_list, list) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700455 snd_hda_codec_free(codec);
456 }
457 if (bus->ops.private_free)
458 bus->ops.private_free(bus);
Takashi Iwai6acaed32009-01-12 10:09:24 +0100459 if (bus->workq)
460 destroy_workqueue(bus->workq);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700461 kfree(bus);
462 return 0;
463}
464
Takashi Iwaic8b6bf92005-11-17 14:57:47 +0100465static int snd_hda_bus_dev_free(struct snd_device *device)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700466{
467 struct hda_bus *bus = device->device_data;
Takashi Iwaib94d35392008-11-21 09:08:06 +0100468 bus->shutdown = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700469 return snd_hda_bus_free(bus);
470}
471
Takashi Iwaid7ffba12008-07-30 15:01:46 +0200472#ifdef CONFIG_SND_HDA_HWDEP
473static int snd_hda_bus_dev_register(struct snd_device *device)
474{
475 struct hda_bus *bus = device->device_data;
476 struct hda_codec *codec;
477 list_for_each_entry(codec, &bus->codec_list, list) {
478 snd_hda_hwdep_add_sysfs(codec);
479 }
480 return 0;
481}
482#else
483#define snd_hda_bus_dev_register NULL
484#endif
485
Linus Torvalds1da177e2005-04-16 15:20:36 -0700486/**
487 * snd_hda_bus_new - create a HDA bus
488 * @card: the card entry
489 * @temp: the template for hda_bus information
490 * @busp: the pointer to store the created bus instance
491 *
492 * Returns 0 if successful, or a negative error code.
493 */
Takashi Iwai1289e9e2008-11-27 15:47:11 +0100494int /*__devinit*/ snd_hda_bus_new(struct snd_card *card,
Takashi Iwai756e2b02007-04-16 11:27:07 +0200495 const struct hda_bus_template *temp,
496 struct hda_bus **busp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700497{
498 struct hda_bus *bus;
499 int err;
Takashi Iwaic8b6bf92005-11-17 14:57:47 +0100500 static struct snd_device_ops dev_ops = {
Takashi Iwaid7ffba12008-07-30 15:01:46 +0200501 .dev_register = snd_hda_bus_dev_register,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700502 .dev_free = snd_hda_bus_dev_free,
503 };
504
Takashi Iwaida3cec32008-08-08 17:12:14 +0200505 if (snd_BUG_ON(!temp))
506 return -EINVAL;
507 if (snd_BUG_ON(!temp->ops.command || !temp->ops.get_response))
508 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700509
510 if (busp)
511 *busp = NULL;
512
Takashi Iwaie560d8d2005-09-09 14:21:46 +0200513 bus = kzalloc(sizeof(*bus), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700514 if (bus == NULL) {
515 snd_printk(KERN_ERR "can't allocate struct hda_bus\n");
516 return -ENOMEM;
517 }
518
519 bus->card = card;
520 bus->private_data = temp->private_data;
521 bus->pci = temp->pci;
522 bus->modelname = temp->modelname;
Takashi Iwaifee2fba2008-11-27 12:43:28 +0100523 bus->power_save = temp->power_save;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700524 bus->ops = temp->ops;
525
Ingo Molnar62932df2006-01-16 16:34:20 +0100526 mutex_init(&bus->cmd_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700527 INIT_LIST_HEAD(&bus->codec_list);
528
Takashi Iwaie8c0ee52009-02-05 07:34:28 +0100529 snprintf(bus->workq_name, sizeof(bus->workq_name),
530 "hd-audio%d", card->number);
531 bus->workq = create_singlethread_workqueue(bus->workq_name);
Takashi Iwai6acaed32009-01-12 10:09:24 +0100532 if (!bus->workq) {
Takashi Iwaie8c0ee52009-02-05 07:34:28 +0100533 snd_printk(KERN_ERR "cannot create workqueue %s\n",
534 bus->workq_name);
Takashi Iwai6acaed32009-01-12 10:09:24 +0100535 kfree(bus);
536 return -ENOMEM;
537 }
538
Takashi Iwai0ba21762007-04-16 11:29:14 +0200539 err = snd_device_new(card, SNDRV_DEV_BUS, bus, &dev_ops);
540 if (err < 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700541 snd_hda_bus_free(bus);
542 return err;
543 }
544 if (busp)
545 *busp = bus;
546 return 0;
547}
Takashi Iwaiff7a3262008-11-28 15:17:06 +0100548EXPORT_SYMBOL_HDA(snd_hda_bus_new);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700549
Takashi Iwai82467612007-07-27 19:15:54 +0200550#ifdef CONFIG_SND_HDA_GENERIC
551#define is_generic_config(codec) \
Takashi Iwaif44ac832008-07-30 15:01:45 +0200552 (codec->modelname && !strcmp(codec->modelname, "generic"))
Takashi Iwai82467612007-07-27 19:15:54 +0200553#else
554#define is_generic_config(codec) 0
555#endif
556
Takashi Iwai645f10c2008-11-28 15:07:37 +0100557#ifdef MODULE
Takashi Iwai1289e9e2008-11-27 15:47:11 +0100558#define HDA_MODREQ_MAX_COUNT 2 /* two request_modules()'s */
559#else
Takashi Iwai645f10c2008-11-28 15:07:37 +0100560#define HDA_MODREQ_MAX_COUNT 0 /* all presets are statically linked */
Takashi Iwai1289e9e2008-11-27 15:47:11 +0100561#endif
562
Linus Torvalds1da177e2005-04-16 15:20:36 -0700563/*
564 * find a matching codec preset
565 */
Takashi Iwai6c1f45e2008-07-30 15:01:45 +0200566static const struct hda_codec_preset *
Takashi Iwai756e2b02007-04-16 11:27:07 +0200567find_codec_preset(struct hda_codec *codec)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700568{
Takashi Iwai1289e9e2008-11-27 15:47:11 +0100569 struct hda_codec_preset_list *tbl;
570 const struct hda_codec_preset *preset;
571 int mod_requested = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700572
Takashi Iwai82467612007-07-27 19:15:54 +0200573 if (is_generic_config(codec))
Takashi Iwaid5ad6302007-03-07 15:55:59 +0100574 return NULL; /* use the generic parser */
575
Takashi Iwai1289e9e2008-11-27 15:47:11 +0100576 again:
577 mutex_lock(&preset_mutex);
578 list_for_each_entry(tbl, &hda_preset_tables, list) {
579 if (!try_module_get(tbl->owner)) {
580 snd_printk(KERN_ERR "hda_codec: cannot module_get\n");
581 continue;
582 }
583 for (preset = tbl->preset; preset->id; preset++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700584 u32 mask = preset->mask;
Marc Boucherca7cfae2008-01-22 15:32:25 +0100585 if (preset->afg && preset->afg != codec->afg)
586 continue;
587 if (preset->mfg && preset->mfg != codec->mfg)
588 continue;
Takashi Iwai0ba21762007-04-16 11:29:14 +0200589 if (!mask)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700590 mask = ~0;
Takashi Iwai9c7f8522006-06-28 15:08:22 +0200591 if (preset->id == (codec->vendor_id & mask) &&
Takashi Iwai0ba21762007-04-16 11:29:14 +0200592 (!preset->rev ||
Takashi Iwai1289e9e2008-11-27 15:47:11 +0100593 preset->rev == codec->revision_id)) {
594 mutex_unlock(&preset_mutex);
595 codec->owner = tbl->owner;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700596 return preset;
Takashi Iwai1289e9e2008-11-27 15:47:11 +0100597 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700598 }
Takashi Iwai1289e9e2008-11-27 15:47:11 +0100599 module_put(tbl->owner);
600 }
601 mutex_unlock(&preset_mutex);
602
603 if (mod_requested < HDA_MODREQ_MAX_COUNT) {
604 char name[32];
605 if (!mod_requested)
606 snprintf(name, sizeof(name), "snd-hda-codec-id:%08x",
607 codec->vendor_id);
608 else
609 snprintf(name, sizeof(name), "snd-hda-codec-id:%04x*",
610 (codec->vendor_id >> 16) & 0xffff);
611 request_module(name);
612 mod_requested++;
613 goto again;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700614 }
615 return NULL;
616}
617
618/*
Takashi Iwaif44ac832008-07-30 15:01:45 +0200619 * get_codec_name - store the codec name
Linus Torvalds1da177e2005-04-16 15:20:36 -0700620 */
Takashi Iwaif44ac832008-07-30 15:01:45 +0200621static int get_codec_name(struct hda_codec *codec)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700622{
623 const struct hda_vendor_id *c;
624 const char *vendor = NULL;
625 u16 vendor_id = codec->vendor_id >> 16;
Takashi Iwaif44ac832008-07-30 15:01:45 +0200626 char tmp[16], name[32];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700627
628 for (c = hda_vendor_ids; c->id; c++) {
629 if (c->id == vendor_id) {
630 vendor = c->name;
631 break;
632 }
633 }
Takashi Iwai0ba21762007-04-16 11:29:14 +0200634 if (!vendor) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700635 sprintf(tmp, "Generic %04x", vendor_id);
636 vendor = tmp;
637 }
638 if (codec->preset && codec->preset->name)
Takashi Iwaif44ac832008-07-30 15:01:45 +0200639 snprintf(name, sizeof(name), "%s %s", vendor,
640 codec->preset->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700641 else
Takashi Iwaif44ac832008-07-30 15:01:45 +0200642 snprintf(name, sizeof(name), "%s ID %x", vendor,
Takashi Iwai0ba21762007-04-16 11:29:14 +0200643 codec->vendor_id & 0xffff);
Takashi Iwaif44ac832008-07-30 15:01:45 +0200644 codec->name = kstrdup(name, GFP_KERNEL);
645 if (!codec->name)
646 return -ENOMEM;
647 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700648}
649
650/*
Sasha Khapyorsky673b6832005-08-11 11:00:16 +0200651 * look for an AFG and MFG nodes
Linus Torvalds1da177e2005-04-16 15:20:36 -0700652 */
Takashi Iwai1289e9e2008-11-27 15:47:11 +0100653static void /*__devinit*/ setup_fg_nodes(struct hda_codec *codec)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700654{
Takashi Iwai93e82ae2009-04-17 18:04:41 +0200655 int i, total_nodes, function_id;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700656 hda_nid_t nid;
657
658 total_nodes = snd_hda_get_sub_nodes(codec, AC_NODE_ROOT, &nid);
659 for (i = 0; i < total_nodes; i++, nid++) {
Takashi Iwai93e82ae2009-04-17 18:04:41 +0200660 function_id = snd_hda_param_read(codec, nid,
Pascal de Bruijn234b4342009-03-23 11:15:59 +0100661 AC_PAR_FUNCTION_TYPE) & 0xff;
Takashi Iwai93e82ae2009-04-17 18:04:41 +0200662 switch (function_id) {
Sasha Khapyorsky673b6832005-08-11 11:00:16 +0200663 case AC_GRP_AUDIO_FUNCTION:
664 codec->afg = nid;
Takashi Iwai93e82ae2009-04-17 18:04:41 +0200665 codec->function_id = function_id;
Sasha Khapyorsky673b6832005-08-11 11:00:16 +0200666 break;
667 case AC_GRP_MODEM_FUNCTION:
668 codec->mfg = nid;
Takashi Iwai93e82ae2009-04-17 18:04:41 +0200669 codec->function_id = function_id;
Sasha Khapyorsky673b6832005-08-11 11:00:16 +0200670 break;
671 default:
672 break;
673 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700674 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700675}
676
677/*
Takashi Iwai54d17402005-11-21 16:33:22 +0100678 * read widget caps for each widget and store in cache
679 */
680static int read_widget_caps(struct hda_codec *codec, hda_nid_t fg_node)
681{
682 int i;
683 hda_nid_t nid;
684
685 codec->num_nodes = snd_hda_get_sub_nodes(codec, fg_node,
686 &codec->start_nid);
687 codec->wcaps = kmalloc(codec->num_nodes * 4, GFP_KERNEL);
Takashi Iwai0ba21762007-04-16 11:29:14 +0200688 if (!codec->wcaps)
Takashi Iwai54d17402005-11-21 16:33:22 +0100689 return -ENOMEM;
690 nid = codec->start_nid;
691 for (i = 0; i < codec->num_nodes; i++, nid++)
692 codec->wcaps[i] = snd_hda_param_read(codec, nid,
693 AC_PAR_AUDIO_WIDGET_CAP);
694 return 0;
695}
696
Takashi Iwai3be14142009-02-20 14:11:16 +0100697/* read all pin default configurations and save codec->init_pins */
698static int read_pin_defaults(struct hda_codec *codec)
699{
700 int i;
701 hda_nid_t nid = codec->start_nid;
702
703 for (i = 0; i < codec->num_nodes; i++, nid++) {
704 struct hda_pincfg *pin;
705 unsigned int wcaps = get_wcaps(codec, nid);
706 unsigned int wid_type = (wcaps & AC_WCAP_TYPE) >>
707 AC_WCAP_TYPE_SHIFT;
708 if (wid_type != AC_WID_PIN)
709 continue;
710 pin = snd_array_new(&codec->init_pins);
711 if (!pin)
712 return -ENOMEM;
713 pin->nid = nid;
714 pin->cfg = snd_hda_codec_read(codec, nid, 0,
715 AC_VERB_GET_CONFIG_DEFAULT, 0);
716 }
717 return 0;
718}
719
720/* look up the given pin config list and return the item matching with NID */
721static struct hda_pincfg *look_up_pincfg(struct hda_codec *codec,
722 struct snd_array *array,
723 hda_nid_t nid)
724{
725 int i;
726 for (i = 0; i < array->used; i++) {
727 struct hda_pincfg *pin = snd_array_elem(array, i);
728 if (pin->nid == nid)
729 return pin;
730 }
731 return NULL;
732}
733
734/* write a config value for the given NID */
735static void set_pincfg(struct hda_codec *codec, hda_nid_t nid,
736 unsigned int cfg)
737{
738 int i;
739 for (i = 0; i < 4; i++) {
740 snd_hda_codec_write(codec, nid, 0,
741 AC_VERB_SET_CONFIG_DEFAULT_BYTES_0 + i,
742 cfg & 0xff);
743 cfg >>= 8;
744 }
745}
746
747/* set the current pin config value for the given NID.
748 * the value is cached, and read via snd_hda_codec_get_pincfg()
749 */
750int snd_hda_add_pincfg(struct hda_codec *codec, struct snd_array *list,
751 hda_nid_t nid, unsigned int cfg)
752{
753 struct hda_pincfg *pin;
Takashi Iwai5e7b8e02009-02-23 09:45:59 +0100754 unsigned int oldcfg;
Takashi Iwai3be14142009-02-20 14:11:16 +0100755
Takashi Iwai5e7b8e02009-02-23 09:45:59 +0100756 oldcfg = snd_hda_codec_get_pincfg(codec, nid);
Takashi Iwai3be14142009-02-20 14:11:16 +0100757 pin = look_up_pincfg(codec, list, nid);
758 if (!pin) {
759 pin = snd_array_new(list);
760 if (!pin)
761 return -ENOMEM;
762 pin->nid = nid;
763 }
764 pin->cfg = cfg;
Takashi Iwai5e7b8e02009-02-23 09:45:59 +0100765
766 /* change only when needed; e.g. if the pincfg is already present
767 * in user_pins[], don't write it
768 */
769 cfg = snd_hda_codec_get_pincfg(codec, nid);
770 if (oldcfg != cfg)
771 set_pincfg(codec, nid, cfg);
Takashi Iwai3be14142009-02-20 14:11:16 +0100772 return 0;
773}
774
775int snd_hda_codec_set_pincfg(struct hda_codec *codec,
776 hda_nid_t nid, unsigned int cfg)
777{
Takashi Iwai346ff702009-02-23 09:42:57 +0100778 return snd_hda_add_pincfg(codec, &codec->driver_pins, nid, cfg);
Takashi Iwai3be14142009-02-20 14:11:16 +0100779}
780EXPORT_SYMBOL_HDA(snd_hda_codec_set_pincfg);
781
782/* get the current pin config value of the given pin NID */
783unsigned int snd_hda_codec_get_pincfg(struct hda_codec *codec, hda_nid_t nid)
784{
785 struct hda_pincfg *pin;
786
Takashi Iwai3be14142009-02-20 14:11:16 +0100787#ifdef CONFIG_SND_HDA_HWDEP
Takashi Iwai346ff702009-02-23 09:42:57 +0100788 pin = look_up_pincfg(codec, &codec->user_pins, nid);
Takashi Iwai3be14142009-02-20 14:11:16 +0100789 if (pin)
790 return pin->cfg;
791#endif
Takashi Iwai5e7b8e02009-02-23 09:45:59 +0100792 pin = look_up_pincfg(codec, &codec->driver_pins, nid);
793 if (pin)
794 return pin->cfg;
Takashi Iwai3be14142009-02-20 14:11:16 +0100795 pin = look_up_pincfg(codec, &codec->init_pins, nid);
796 if (pin)
797 return pin->cfg;
798 return 0;
799}
800EXPORT_SYMBOL_HDA(snd_hda_codec_get_pincfg);
801
802/* restore all current pin configs */
803static void restore_pincfgs(struct hda_codec *codec)
804{
805 int i;
806 for (i = 0; i < codec->init_pins.used; i++) {
807 struct hda_pincfg *pin = snd_array_elem(&codec->init_pins, i);
808 set_pincfg(codec, pin->nid,
809 snd_hda_codec_get_pincfg(codec, pin->nid));
810 }
811}
Takashi Iwai54d17402005-11-21 16:33:22 +0100812
Takashi Iwai01751f52007-08-10 16:59:39 +0200813static void init_hda_cache(struct hda_cache_rec *cache,
814 unsigned int record_size);
Takashi Iwai1fcaee62007-08-23 00:01:09 +0200815static void free_hda_cache(struct hda_cache_rec *cache);
Takashi Iwai01751f52007-08-10 16:59:39 +0200816
Takashi Iwai3be14142009-02-20 14:11:16 +0100817/* restore the initial pin cfgs and release all pincfg lists */
818static void restore_init_pincfgs(struct hda_codec *codec)
819{
Takashi Iwai346ff702009-02-23 09:42:57 +0100820 /* first free driver_pins and user_pins, then call restore_pincfg
Takashi Iwai3be14142009-02-20 14:11:16 +0100821 * so that only the values in init_pins are restored
822 */
Takashi Iwai346ff702009-02-23 09:42:57 +0100823 snd_array_free(&codec->driver_pins);
Takashi Iwai3be14142009-02-20 14:11:16 +0100824#ifdef CONFIG_SND_HDA_HWDEP
Takashi Iwai346ff702009-02-23 09:42:57 +0100825 snd_array_free(&codec->user_pins);
Takashi Iwai3be14142009-02-20 14:11:16 +0100826#endif
827 restore_pincfgs(codec);
828 snd_array_free(&codec->init_pins);
829}
830
Takashi Iwai54d17402005-11-21 16:33:22 +0100831/*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700832 * codec destructor
833 */
834static void snd_hda_codec_free(struct hda_codec *codec)
835{
Takashi Iwai0ba21762007-04-16 11:29:14 +0200836 if (!codec)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700837 return;
Takashi Iwai3be14142009-02-20 14:11:16 +0100838 restore_init_pincfgs(codec);
Takashi Iwaicb53c622007-08-10 17:21:45 +0200839#ifdef CONFIG_SND_HDA_POWER_SAVE
840 cancel_delayed_work(&codec->power_work);
Takashi Iwai6acaed32009-01-12 10:09:24 +0100841 flush_workqueue(codec->bus->workq);
Takashi Iwaicb53c622007-08-10 17:21:45 +0200842#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700843 list_del(&codec->list);
Takashi Iwaid13bd412008-07-30 15:01:45 +0200844 snd_array_free(&codec->mixers);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700845 codec->bus->caddr_tbl[codec->addr] = NULL;
846 if (codec->patch_ops.free)
847 codec->patch_ops.free(codec);
Takashi Iwai1289e9e2008-11-27 15:47:11 +0100848 module_put(codec->owner);
Takashi Iwai01751f52007-08-10 16:59:39 +0200849 free_hda_cache(&codec->amp_cache);
Takashi Iwaib3ac5632007-08-10 17:03:40 +0200850 free_hda_cache(&codec->cmd_cache);
Takashi Iwaif44ac832008-07-30 15:01:45 +0200851 kfree(codec->name);
852 kfree(codec->modelname);
Takashi Iwai54d17402005-11-21 16:33:22 +0100853 kfree(codec->wcaps);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700854 kfree(codec);
855}
856
Takashi Iwaibb6ac722009-03-13 09:02:42 +0100857static void hda_set_power_state(struct hda_codec *codec, hda_nid_t fg,
858 unsigned int power_state);
859
Linus Torvalds1da177e2005-04-16 15:20:36 -0700860/**
861 * snd_hda_codec_new - create a HDA codec
862 * @bus: the bus to assign
863 * @codec_addr: the codec address
864 * @codecp: the pointer to store the generated codec
865 *
866 * Returns 0 if successful, or a negative error code.
867 */
Takashi Iwai1289e9e2008-11-27 15:47:11 +0100868int /*__devinit*/ snd_hda_codec_new(struct hda_bus *bus, unsigned int codec_addr,
Takashi Iwaid4d9cd032008-12-19 15:19:11 +0100869 int do_init, struct hda_codec **codecp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700870{
871 struct hda_codec *codec;
Jaroslav Kyselaba443682008-08-13 20:55:32 +0200872 char component[31];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700873 int err;
874
Takashi Iwaida3cec32008-08-08 17:12:14 +0200875 if (snd_BUG_ON(!bus))
876 return -EINVAL;
877 if (snd_BUG_ON(codec_addr > HDA_MAX_CODEC_ADDRESS))
878 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700879
880 if (bus->caddr_tbl[codec_addr]) {
Takashi Iwai0ba21762007-04-16 11:29:14 +0200881 snd_printk(KERN_ERR "hda_codec: "
882 "address 0x%x is already occupied\n", codec_addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700883 return -EBUSY;
884 }
885
Takashi Iwaie560d8d2005-09-09 14:21:46 +0200886 codec = kzalloc(sizeof(*codec), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700887 if (codec == NULL) {
888 snd_printk(KERN_ERR "can't allocate struct hda_codec\n");
889 return -ENOMEM;
890 }
891
892 codec->bus = bus;
893 codec->addr = codec_addr;
Ingo Molnar62932df2006-01-16 16:34:20 +0100894 mutex_init(&codec->spdif_mutex);
Wu Fengguang5a9e02e2009-01-09 16:45:24 +0800895 mutex_init(&codec->control_mutex);
Takashi Iwai01751f52007-08-10 16:59:39 +0200896 init_hda_cache(&codec->amp_cache, sizeof(struct hda_amp_info));
Takashi Iwaib3ac5632007-08-10 17:03:40 +0200897 init_hda_cache(&codec->cmd_cache, sizeof(struct hda_cache_head));
Takashi Iwaid13bd412008-07-30 15:01:45 +0200898 snd_array_init(&codec->mixers, sizeof(struct snd_kcontrol *), 32);
Takashi Iwai3be14142009-02-20 14:11:16 +0100899 snd_array_init(&codec->init_pins, sizeof(struct hda_pincfg), 16);
Takashi Iwai346ff702009-02-23 09:42:57 +0100900 snd_array_init(&codec->driver_pins, sizeof(struct hda_pincfg), 16);
Takashi Iwai6c1f45e2008-07-30 15:01:45 +0200901 if (codec->bus->modelname) {
902 codec->modelname = kstrdup(codec->bus->modelname, GFP_KERNEL);
903 if (!codec->modelname) {
904 snd_hda_codec_free(codec);
905 return -ENODEV;
906 }
907 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700908
Takashi Iwaicb53c622007-08-10 17:21:45 +0200909#ifdef CONFIG_SND_HDA_POWER_SAVE
910 INIT_DELAYED_WORK(&codec->power_work, hda_power_work);
911 /* snd_hda_codec_new() marks the codec as power-up, and leave it as is.
912 * the caller has to power down appropriatley after initialization
913 * phase.
914 */
915 hda_keep_power_on(codec);
916#endif
917
Linus Torvalds1da177e2005-04-16 15:20:36 -0700918 list_add_tail(&codec->list, &bus->codec_list);
919 bus->caddr_tbl[codec_addr] = codec;
920
Takashi Iwai0ba21762007-04-16 11:29:14 +0200921 codec->vendor_id = snd_hda_param_read(codec, AC_NODE_ROOT,
922 AC_PAR_VENDOR_ID);
Takashi Iwai111d3af2006-02-16 18:17:58 +0100923 if (codec->vendor_id == -1)
924 /* read again, hopefully the access method was corrected
925 * in the last read...
926 */
927 codec->vendor_id = snd_hda_param_read(codec, AC_NODE_ROOT,
928 AC_PAR_VENDOR_ID);
Takashi Iwai0ba21762007-04-16 11:29:14 +0200929 codec->subsystem_id = snd_hda_param_read(codec, AC_NODE_ROOT,
930 AC_PAR_SUBSYSTEM_ID);
931 codec->revision_id = snd_hda_param_read(codec, AC_NODE_ROOT,
932 AC_PAR_REV_ID);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700933
Sasha Khapyorsky673b6832005-08-11 11:00:16 +0200934 setup_fg_nodes(codec);
Takashi Iwai0ba21762007-04-16 11:29:14 +0200935 if (!codec->afg && !codec->mfg) {
Sasha Khapyorsky673b6832005-08-11 11:00:16 +0200936 snd_printdd("hda_codec: no AFG or MFG node found\n");
Takashi Iwai3be14142009-02-20 14:11:16 +0100937 err = -ENODEV;
938 goto error;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700939 }
940
Takashi Iwai3be14142009-02-20 14:11:16 +0100941 err = read_widget_caps(codec, codec->afg ? codec->afg : codec->mfg);
942 if (err < 0) {
Takashi Iwai54d17402005-11-21 16:33:22 +0100943 snd_printk(KERN_ERR "hda_codec: cannot malloc\n");
Takashi Iwai3be14142009-02-20 14:11:16 +0100944 goto error;
Takashi Iwai54d17402005-11-21 16:33:22 +0100945 }
Takashi Iwai3be14142009-02-20 14:11:16 +0100946 err = read_pin_defaults(codec);
947 if (err < 0)
948 goto error;
Takashi Iwai54d17402005-11-21 16:33:22 +0100949
Takashi Iwai0ba21762007-04-16 11:29:14 +0200950 if (!codec->subsystem_id) {
Takashi Iwai86284e42005-10-11 15:05:54 +0200951 hda_nid_t nid = codec->afg ? codec->afg : codec->mfg;
Takashi Iwai0ba21762007-04-16 11:29:14 +0200952 codec->subsystem_id =
953 snd_hda_codec_read(codec, nid, 0,
954 AC_VERB_GET_SUBSYSTEM_ID, 0);
Takashi Iwai86284e42005-10-11 15:05:54 +0200955 }
Takashi Iwaif44ac832008-07-30 15:01:45 +0200956 if (bus->modelname)
957 codec->modelname = kstrdup(bus->modelname, GFP_KERNEL);
Takashi Iwai86284e42005-10-11 15:05:54 +0200958
Takashi Iwaibb6ac722009-03-13 09:02:42 +0100959 /* power-up all before initialization */
960 hda_set_power_state(codec,
961 codec->afg ? codec->afg : codec->mfg,
962 AC_PWRST_D0);
963
Takashi Iwaid4d9cd032008-12-19 15:19:11 +0100964 if (do_init) {
965 err = snd_hda_codec_configure(codec);
Takashi Iwai3be14142009-02-20 14:11:16 +0100966 if (err < 0)
967 goto error;
Takashi Iwai6c1f45e2008-07-30 15:01:45 +0200968 }
969 snd_hda_codec_proc_new(codec);
970
Takashi Iwai6c1f45e2008-07-30 15:01:45 +0200971 snd_hda_create_hwdep(codec);
Takashi Iwai6c1f45e2008-07-30 15:01:45 +0200972
973 sprintf(component, "HDA:%08x,%08x,%08x", codec->vendor_id,
974 codec->subsystem_id, codec->revision_id);
975 snd_component_add(codec->bus->card, component);
976
977 if (codecp)
978 *codecp = codec;
979 return 0;
Takashi Iwai3be14142009-02-20 14:11:16 +0100980
981 error:
982 snd_hda_codec_free(codec);
983 return err;
Takashi Iwai6c1f45e2008-07-30 15:01:45 +0200984}
Takashi Iwaiff7a3262008-11-28 15:17:06 +0100985EXPORT_SYMBOL_HDA(snd_hda_codec_new);
Takashi Iwai6c1f45e2008-07-30 15:01:45 +0200986
987int snd_hda_codec_configure(struct hda_codec *codec)
988{
989 int err;
990
Takashi Iwaid5ad6302007-03-07 15:55:59 +0100991 codec->preset = find_codec_preset(codec);
Takashi Iwaif44ac832008-07-30 15:01:45 +0200992 if (!codec->name) {
993 err = get_codec_name(codec);
994 if (err < 0)
995 return err;
996 }
Takashi Iwai43ea1d42007-04-26 19:12:08 +0200997 /* audio codec should override the mixer name */
Takashi Iwaif44ac832008-07-30 15:01:45 +0200998 if (codec->afg || !*codec->bus->card->mixername)
999 strlcpy(codec->bus->card->mixername, codec->name,
1000 sizeof(codec->bus->card->mixername));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001001
Takashi Iwai82467612007-07-27 19:15:54 +02001002 if (is_generic_config(codec)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001003 err = snd_hda_parse_generic_codec(codec);
Takashi Iwai82467612007-07-27 19:15:54 +02001004 goto patched;
1005 }
Takashi Iwai82467612007-07-27 19:15:54 +02001006 if (codec->preset && codec->preset->patch) {
1007 err = codec->preset->patch(codec);
1008 goto patched;
1009 }
1010
1011 /* call the default parser */
Takashi Iwai82467612007-07-27 19:15:54 +02001012 err = snd_hda_parse_generic_codec(codec);
Takashi Iwai35a1e0c2007-10-19 08:13:40 +02001013 if (err < 0)
1014 printk(KERN_ERR "hda-codec: No codec parser is available\n");
Takashi Iwai82467612007-07-27 19:15:54 +02001015
1016 patched:
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001017 if (!err && codec->patch_ops.unsol_event)
1018 err = init_unsol_queue(codec->bus);
1019 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001020}
1021
1022/**
1023 * snd_hda_codec_setup_stream - set up the codec for streaming
1024 * @codec: the CODEC to set up
1025 * @nid: the NID to set up
1026 * @stream_tag: stream tag to pass, it's between 0x1 and 0xf.
1027 * @channel_id: channel id to pass, zero based.
1028 * @format: stream format.
1029 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02001030void snd_hda_codec_setup_stream(struct hda_codec *codec, hda_nid_t nid,
1031 u32 stream_tag,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001032 int channel_id, int format)
1033{
Takashi Iwai0ba21762007-04-16 11:29:14 +02001034 if (!nid)
Takashi Iwaid21b37e2005-04-20 13:45:55 +02001035 return;
1036
Takashi Iwai0ba21762007-04-16 11:29:14 +02001037 snd_printdd("hda_codec_setup_stream: "
1038 "NID=0x%x, stream=0x%x, channel=%d, format=0x%x\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07001039 nid, stream_tag, channel_id, format);
1040 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CHANNEL_STREAMID,
1041 (stream_tag << 4) | channel_id);
1042 msleep(1);
1043 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_STREAM_FORMAT, format);
1044}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001045EXPORT_SYMBOL_HDA(snd_hda_codec_setup_stream);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001046
Takashi Iwai888afa12008-03-18 09:57:50 +01001047void snd_hda_codec_cleanup_stream(struct hda_codec *codec, hda_nid_t nid)
1048{
1049 if (!nid)
1050 return;
1051
1052 snd_printdd("hda_codec_cleanup_stream: NID=0x%x\n", nid);
1053 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CHANNEL_STREAMID, 0);
1054#if 0 /* keep the format */
1055 msleep(1);
1056 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_STREAM_FORMAT, 0);
1057#endif
1058}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001059EXPORT_SYMBOL_HDA(snd_hda_codec_cleanup_stream);
Takashi Iwai888afa12008-03-18 09:57:50 +01001060
Linus Torvalds1da177e2005-04-16 15:20:36 -07001061/*
1062 * amp access functions
1063 */
1064
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001065/* FIXME: more better hash key? */
1066#define HDA_HASH_KEY(nid,dir,idx) (u32)((nid) + ((idx) << 16) + ((dir) << 24))
Takashi Iwai1327a322009-03-23 13:07:47 +01001067#define HDA_HASH_PINCAP_KEY(nid) (u32)((nid) + (0x02 << 24))
Takashi Iwai92c7c8a2009-03-24 07:32:14 +01001068#define HDA_HASH_PARPCM_KEY(nid) (u32)((nid) + (0x03 << 24))
1069#define HDA_HASH_PARSTR_KEY(nid) (u32)((nid) + (0x04 << 24))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001070#define INFO_AMP_CAPS (1<<0)
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001071#define INFO_AMP_VOL(ch) (1 << (1 + (ch)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001072
1073/* initialize the hash table */
Takashi Iwai1289e9e2008-11-27 15:47:11 +01001074static void /*__devinit*/ init_hda_cache(struct hda_cache_rec *cache,
Takashi Iwai01751f52007-08-10 16:59:39 +02001075 unsigned int record_size)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001076{
Takashi Iwai01751f52007-08-10 16:59:39 +02001077 memset(cache, 0, sizeof(*cache));
1078 memset(cache->hash, 0xff, sizeof(cache->hash));
Takashi Iwai603c4012008-07-30 15:01:44 +02001079 snd_array_init(&cache->buf, record_size, 64);
Takashi Iwai01751f52007-08-10 16:59:39 +02001080}
1081
Takashi Iwai1fcaee62007-08-23 00:01:09 +02001082static void free_hda_cache(struct hda_cache_rec *cache)
Takashi Iwai01751f52007-08-10 16:59:39 +02001083{
Takashi Iwai603c4012008-07-30 15:01:44 +02001084 snd_array_free(&cache->buf);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001085}
1086
1087/* query the hash. allocate an entry if not found. */
Takashi Iwai01751f52007-08-10 16:59:39 +02001088static struct hda_cache_head *get_alloc_hash(struct hda_cache_rec *cache,
1089 u32 key)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001090{
Takashi Iwai01751f52007-08-10 16:59:39 +02001091 u16 idx = key % (u16)ARRAY_SIZE(cache->hash);
1092 u16 cur = cache->hash[idx];
1093 struct hda_cache_head *info;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001094
1095 while (cur != 0xffff) {
Takashi Iwaif43aa022008-11-10 16:24:26 +01001096 info = snd_array_elem(&cache->buf, cur);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001097 if (info->key == key)
1098 return info;
1099 cur = info->next;
1100 }
1101
1102 /* add a new hash entry */
Takashi Iwai603c4012008-07-30 15:01:44 +02001103 info = snd_array_new(&cache->buf);
Takashi Iwaic2174292008-11-07 00:23:30 +01001104 if (!info)
1105 return NULL;
Takashi Iwaif43aa022008-11-10 16:24:26 +01001106 cur = snd_array_index(&cache->buf, info);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001107 info->key = key;
Takashi Iwai01751f52007-08-10 16:59:39 +02001108 info->val = 0;
1109 info->next = cache->hash[idx];
1110 cache->hash[idx] = cur;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001111
1112 return info;
1113}
1114
Takashi Iwai01751f52007-08-10 16:59:39 +02001115/* query and allocate an amp hash entry */
1116static inline struct hda_amp_info *
1117get_alloc_amp_hash(struct hda_codec *codec, u32 key)
1118{
1119 return (struct hda_amp_info *)get_alloc_hash(&codec->amp_cache, key);
1120}
1121
Linus Torvalds1da177e2005-04-16 15:20:36 -07001122/*
1123 * query AMP capabilities for the given widget and direction
1124 */
Matthew Ranostay09a99952008-01-24 11:49:21 +01001125u32 query_amp_caps(struct hda_codec *codec, hda_nid_t nid, int direction)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001126{
Takashi Iwai0ba21762007-04-16 11:29:14 +02001127 struct hda_amp_info *info;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001128
Takashi Iwai0ba21762007-04-16 11:29:14 +02001129 info = get_alloc_amp_hash(codec, HDA_HASH_KEY(nid, direction, 0));
1130 if (!info)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001131 return 0;
Takashi Iwai01751f52007-08-10 16:59:39 +02001132 if (!(info->head.val & INFO_AMP_CAPS)) {
Takashi Iwai0ba21762007-04-16 11:29:14 +02001133 if (!(get_wcaps(codec, nid) & AC_WCAP_AMP_OVRD))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001134 nid = codec->afg;
Takashi Iwai0ba21762007-04-16 11:29:14 +02001135 info->amp_caps = snd_hda_param_read(codec, nid,
1136 direction == HDA_OUTPUT ?
1137 AC_PAR_AMP_OUT_CAP :
1138 AC_PAR_AMP_IN_CAP);
Takashi Iwaib75e53f2007-05-10 16:56:09 +02001139 if (info->amp_caps)
Takashi Iwai01751f52007-08-10 16:59:39 +02001140 info->head.val |= INFO_AMP_CAPS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001141 }
1142 return info->amp_caps;
1143}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001144EXPORT_SYMBOL_HDA(query_amp_caps);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001145
Takashi Iwai897cc182007-05-29 19:01:37 +02001146int snd_hda_override_amp_caps(struct hda_codec *codec, hda_nid_t nid, int dir,
1147 unsigned int caps)
1148{
1149 struct hda_amp_info *info;
1150
1151 info = get_alloc_amp_hash(codec, HDA_HASH_KEY(nid, dir, 0));
1152 if (!info)
1153 return -EINVAL;
1154 info->amp_caps = caps;
Takashi Iwai01751f52007-08-10 16:59:39 +02001155 info->head.val |= INFO_AMP_CAPS;
Takashi Iwai897cc182007-05-29 19:01:37 +02001156 return 0;
1157}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001158EXPORT_SYMBOL_HDA(snd_hda_override_amp_caps);
Takashi Iwai897cc182007-05-29 19:01:37 +02001159
Takashi Iwai92c7c8a2009-03-24 07:32:14 +01001160static unsigned int
1161query_caps_hash(struct hda_codec *codec, hda_nid_t nid, u32 key,
1162 unsigned int (*func)(struct hda_codec *, hda_nid_t))
Takashi Iwai1327a322009-03-23 13:07:47 +01001163{
1164 struct hda_amp_info *info;
1165
Takashi Iwai92c7c8a2009-03-24 07:32:14 +01001166 info = get_alloc_amp_hash(codec, key);
Takashi Iwai1327a322009-03-23 13:07:47 +01001167 if (!info)
1168 return 0;
1169 if (!info->head.val) {
Takashi Iwai1327a322009-03-23 13:07:47 +01001170 info->head.val |= INFO_AMP_CAPS;
Takashi Iwai92c7c8a2009-03-24 07:32:14 +01001171 info->amp_caps = func(codec, nid);
Takashi Iwai1327a322009-03-23 13:07:47 +01001172 }
1173 return info->amp_caps;
1174}
Takashi Iwai92c7c8a2009-03-24 07:32:14 +01001175
1176static unsigned int read_pin_cap(struct hda_codec *codec, hda_nid_t nid)
1177{
1178 return snd_hda_param_read(codec, nid, AC_PAR_PIN_CAP);
1179}
1180
1181u32 snd_hda_query_pin_caps(struct hda_codec *codec, hda_nid_t nid)
1182{
1183 return query_caps_hash(codec, nid, HDA_HASH_PINCAP_KEY(nid),
1184 read_pin_cap);
1185}
Takashi Iwai1327a322009-03-23 13:07:47 +01001186EXPORT_SYMBOL_HDA(snd_hda_query_pin_caps);
1187
Linus Torvalds1da177e2005-04-16 15:20:36 -07001188/*
1189 * read the current volume to info
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001190 * if the cache exists, read the cache value.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001191 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02001192static unsigned int get_vol_mute(struct hda_codec *codec,
1193 struct hda_amp_info *info, hda_nid_t nid,
1194 int ch, int direction, int index)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001195{
1196 u32 val, parm;
1197
Takashi Iwai01751f52007-08-10 16:59:39 +02001198 if (info->head.val & INFO_AMP_VOL(ch))
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001199 return info->vol[ch];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001200
1201 parm = ch ? AC_AMP_GET_RIGHT : AC_AMP_GET_LEFT;
1202 parm |= direction == HDA_OUTPUT ? AC_AMP_GET_OUTPUT : AC_AMP_GET_INPUT;
1203 parm |= index;
Takashi Iwai0ba21762007-04-16 11:29:14 +02001204 val = snd_hda_codec_read(codec, nid, 0,
1205 AC_VERB_GET_AMP_GAIN_MUTE, parm);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001206 info->vol[ch] = val & 0xff;
Takashi Iwai01751f52007-08-10 16:59:39 +02001207 info->head.val |= INFO_AMP_VOL(ch);
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001208 return info->vol[ch];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001209}
1210
1211/*
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001212 * write the current volume in info to the h/w and update the cache
Linus Torvalds1da177e2005-04-16 15:20:36 -07001213 */
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001214static void put_vol_mute(struct hda_codec *codec, struct hda_amp_info *info,
Takashi Iwai0ba21762007-04-16 11:29:14 +02001215 hda_nid_t nid, int ch, int direction, int index,
1216 int val)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001217{
1218 u32 parm;
1219
1220 parm = ch ? AC_AMP_SET_RIGHT : AC_AMP_SET_LEFT;
1221 parm |= direction == HDA_OUTPUT ? AC_AMP_SET_OUTPUT : AC_AMP_SET_INPUT;
1222 parm |= index << AC_AMP_SET_INDEX_SHIFT;
1223 parm |= val;
1224 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, parm);
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001225 info->vol[ch] = val;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001226}
1227
1228/*
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001229 * read AMP value. The volume is between 0 to 0x7f, 0x80 = mute bit.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001230 */
Takashi Iwai834be882006-03-01 14:16:17 +01001231int snd_hda_codec_amp_read(struct hda_codec *codec, hda_nid_t nid, int ch,
1232 int direction, int index)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001233{
Takashi Iwai0ba21762007-04-16 11:29:14 +02001234 struct hda_amp_info *info;
1235 info = get_alloc_amp_hash(codec, HDA_HASH_KEY(nid, direction, index));
1236 if (!info)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001237 return 0;
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001238 return get_vol_mute(codec, info, nid, ch, direction, index);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001239}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001240EXPORT_SYMBOL_HDA(snd_hda_codec_amp_read);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001241
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001242/*
1243 * update the AMP value, mask = bit mask to set, val = the value
1244 */
Takashi Iwai834be882006-03-01 14:16:17 +01001245int snd_hda_codec_amp_update(struct hda_codec *codec, hda_nid_t nid, int ch,
1246 int direction, int idx, int mask, int val)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001247{
Takashi Iwai0ba21762007-04-16 11:29:14 +02001248 struct hda_amp_info *info;
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001249
Takashi Iwai0ba21762007-04-16 11:29:14 +02001250 info = get_alloc_amp_hash(codec, HDA_HASH_KEY(nid, direction, idx));
1251 if (!info)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001252 return 0;
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001253 val &= mask;
1254 val |= get_vol_mute(codec, info, nid, ch, direction, idx) & ~mask;
Takashi Iwai82beb8f2007-08-10 17:09:26 +02001255 if (info->vol[ch] == val)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001256 return 0;
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001257 put_vol_mute(codec, info, nid, ch, direction, idx, val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001258 return 1;
1259}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001260EXPORT_SYMBOL_HDA(snd_hda_codec_amp_update);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001261
Takashi Iwai47fd8302007-08-10 17:11:07 +02001262/*
1263 * update the AMP stereo with the same mask and value
1264 */
1265int snd_hda_codec_amp_stereo(struct hda_codec *codec, hda_nid_t nid,
1266 int direction, int idx, int mask, int val)
1267{
1268 int ch, ret = 0;
1269 for (ch = 0; ch < 2; ch++)
1270 ret |= snd_hda_codec_amp_update(codec, nid, ch, direction,
1271 idx, mask, val);
1272 return ret;
1273}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001274EXPORT_SYMBOL_HDA(snd_hda_codec_amp_stereo);
Takashi Iwai47fd8302007-08-10 17:11:07 +02001275
Takashi Iwaicb53c622007-08-10 17:21:45 +02001276#ifdef SND_HDA_NEEDS_RESUME
Takashi Iwaib3ac5632007-08-10 17:03:40 +02001277/* resume the all amp commands from the cache */
1278void snd_hda_codec_resume_amp(struct hda_codec *codec)
1279{
Takashi Iwai603c4012008-07-30 15:01:44 +02001280 struct hda_amp_info *buffer = codec->amp_cache.buf.list;
Takashi Iwaib3ac5632007-08-10 17:03:40 +02001281 int i;
1282
Takashi Iwai603c4012008-07-30 15:01:44 +02001283 for (i = 0; i < codec->amp_cache.buf.used; i++, buffer++) {
Takashi Iwaib3ac5632007-08-10 17:03:40 +02001284 u32 key = buffer->head.key;
1285 hda_nid_t nid;
1286 unsigned int idx, dir, ch;
1287 if (!key)
1288 continue;
1289 nid = key & 0xff;
1290 idx = (key >> 16) & 0xff;
1291 dir = (key >> 24) & 0xff;
1292 for (ch = 0; ch < 2; ch++) {
1293 if (!(buffer->head.val & INFO_AMP_VOL(ch)))
1294 continue;
1295 put_vol_mute(codec, buffer, nid, ch, dir, idx,
1296 buffer->vol[ch]);
1297 }
1298 }
1299}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001300EXPORT_SYMBOL_HDA(snd_hda_codec_resume_amp);
Takashi Iwaicb53c622007-08-10 17:21:45 +02001301#endif /* SND_HDA_NEEDS_RESUME */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001302
Linus Torvalds1da177e2005-04-16 15:20:36 -07001303/* volume */
Takashi Iwai0ba21762007-04-16 11:29:14 +02001304int snd_hda_mixer_amp_volume_info(struct snd_kcontrol *kcontrol,
1305 struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001306{
1307 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1308 u16 nid = get_amp_nid(kcontrol);
1309 u8 chs = get_amp_channels(kcontrol);
1310 int dir = get_amp_direction(kcontrol);
Takashi Iwai29fdbec2009-01-20 13:07:55 +01001311 unsigned int ofs = get_amp_offset(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001312 u32 caps;
1313
1314 caps = query_amp_caps(codec, nid, dir);
Takashi Iwai0ba21762007-04-16 11:29:14 +02001315 /* num steps */
1316 caps = (caps & AC_AMPCAP_NUM_STEPS) >> AC_AMPCAP_NUM_STEPS_SHIFT;
1317 if (!caps) {
1318 printk(KERN_WARNING "hda_codec: "
Takashi Iwai9c8f2ab2008-01-11 16:12:23 +01001319 "num_steps = 0 for NID=0x%x (ctl = %s)\n", nid,
1320 kcontrol->id.name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001321 return -EINVAL;
1322 }
Takashi Iwai29fdbec2009-01-20 13:07:55 +01001323 if (ofs < caps)
1324 caps -= ofs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001325 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
1326 uinfo->count = chs == 3 ? 2 : 1;
1327 uinfo->value.integer.min = 0;
1328 uinfo->value.integer.max = caps;
1329 return 0;
1330}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001331EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_volume_info);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001332
Takashi Iwai29fdbec2009-01-20 13:07:55 +01001333
1334static inline unsigned int
1335read_amp_value(struct hda_codec *codec, hda_nid_t nid,
1336 int ch, int dir, int idx, unsigned int ofs)
1337{
1338 unsigned int val;
1339 val = snd_hda_codec_amp_read(codec, nid, ch, dir, idx);
1340 val &= HDA_AMP_VOLMASK;
1341 if (val >= ofs)
1342 val -= ofs;
1343 else
1344 val = 0;
1345 return val;
1346}
1347
1348static inline int
1349update_amp_value(struct hda_codec *codec, hda_nid_t nid,
1350 int ch, int dir, int idx, unsigned int ofs,
1351 unsigned int val)
1352{
1353 if (val > 0)
1354 val += ofs;
1355 return snd_hda_codec_amp_update(codec, nid, ch, dir, idx,
1356 HDA_AMP_VOLMASK, val);
1357}
1358
Takashi Iwai0ba21762007-04-16 11:29:14 +02001359int snd_hda_mixer_amp_volume_get(struct snd_kcontrol *kcontrol,
1360 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001361{
1362 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1363 hda_nid_t nid = get_amp_nid(kcontrol);
1364 int chs = get_amp_channels(kcontrol);
1365 int dir = get_amp_direction(kcontrol);
1366 int idx = get_amp_index(kcontrol);
Takashi Iwai29fdbec2009-01-20 13:07:55 +01001367 unsigned int ofs = get_amp_offset(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001368 long *valp = ucontrol->value.integer.value;
1369
1370 if (chs & 1)
Takashi Iwai29fdbec2009-01-20 13:07:55 +01001371 *valp++ = read_amp_value(codec, nid, 0, dir, idx, ofs);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001372 if (chs & 2)
Takashi Iwai29fdbec2009-01-20 13:07:55 +01001373 *valp = read_amp_value(codec, nid, 1, dir, idx, ofs);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001374 return 0;
1375}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001376EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_volume_get);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001377
Takashi Iwai0ba21762007-04-16 11:29:14 +02001378int snd_hda_mixer_amp_volume_put(struct snd_kcontrol *kcontrol,
1379 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001380{
1381 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1382 hda_nid_t nid = get_amp_nid(kcontrol);
1383 int chs = get_amp_channels(kcontrol);
1384 int dir = get_amp_direction(kcontrol);
1385 int idx = get_amp_index(kcontrol);
Takashi Iwai29fdbec2009-01-20 13:07:55 +01001386 unsigned int ofs = get_amp_offset(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001387 long *valp = ucontrol->value.integer.value;
1388 int change = 0;
1389
Takashi Iwaicb53c622007-08-10 17:21:45 +02001390 snd_hda_power_up(codec);
Nicolas Grazianob9f5a892005-07-29 12:17:20 +02001391 if (chs & 1) {
Takashi Iwai29fdbec2009-01-20 13:07:55 +01001392 change = update_amp_value(codec, nid, 0, dir, idx, ofs, *valp);
Nicolas Grazianob9f5a892005-07-29 12:17:20 +02001393 valp++;
1394 }
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001395 if (chs & 2)
Takashi Iwai29fdbec2009-01-20 13:07:55 +01001396 change |= update_amp_value(codec, nid, 1, dir, idx, ofs, *valp);
Takashi Iwaicb53c622007-08-10 17:21:45 +02001397 snd_hda_power_down(codec);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001398 return change;
1399}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001400EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_volume_put);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001401
Jaroslav Kysela302e9c52006-07-05 17:39:49 +02001402int snd_hda_mixer_amp_tlv(struct snd_kcontrol *kcontrol, int op_flag,
1403 unsigned int size, unsigned int __user *_tlv)
1404{
1405 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1406 hda_nid_t nid = get_amp_nid(kcontrol);
1407 int dir = get_amp_direction(kcontrol);
Takashi Iwai29fdbec2009-01-20 13:07:55 +01001408 unsigned int ofs = get_amp_offset(kcontrol);
Jaroslav Kysela302e9c52006-07-05 17:39:49 +02001409 u32 caps, val1, val2;
1410
1411 if (size < 4 * sizeof(unsigned int))
1412 return -ENOMEM;
1413 caps = query_amp_caps(codec, nid, dir);
Takashi Iwai0ba21762007-04-16 11:29:14 +02001414 val2 = (caps & AC_AMPCAP_STEP_SIZE) >> AC_AMPCAP_STEP_SIZE_SHIFT;
1415 val2 = (val2 + 1) * 25;
Jaroslav Kysela302e9c52006-07-05 17:39:49 +02001416 val1 = -((caps & AC_AMPCAP_OFFSET) >> AC_AMPCAP_OFFSET_SHIFT);
Takashi Iwai29fdbec2009-01-20 13:07:55 +01001417 val1 += ofs;
Jaroslav Kysela302e9c52006-07-05 17:39:49 +02001418 val1 = ((int)val1) * ((int)val2);
Jaroslav Kysela302e9c52006-07-05 17:39:49 +02001419 if (put_user(SNDRV_CTL_TLVT_DB_SCALE, _tlv))
1420 return -EFAULT;
1421 if (put_user(2 * sizeof(unsigned int), _tlv + 1))
1422 return -EFAULT;
1423 if (put_user(val1, _tlv + 2))
1424 return -EFAULT;
1425 if (put_user(val2, _tlv + 3))
1426 return -EFAULT;
1427 return 0;
1428}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001429EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_tlv);
Jaroslav Kysela302e9c52006-07-05 17:39:49 +02001430
Takashi Iwai2134ea42008-01-10 16:53:55 +01001431/*
1432 * set (static) TLV for virtual master volume; recalculated as max 0dB
1433 */
1434void snd_hda_set_vmaster_tlv(struct hda_codec *codec, hda_nid_t nid, int dir,
1435 unsigned int *tlv)
1436{
1437 u32 caps;
1438 int nums, step;
1439
1440 caps = query_amp_caps(codec, nid, dir);
1441 nums = (caps & AC_AMPCAP_NUM_STEPS) >> AC_AMPCAP_NUM_STEPS_SHIFT;
1442 step = (caps & AC_AMPCAP_STEP_SIZE) >> AC_AMPCAP_STEP_SIZE_SHIFT;
1443 step = (step + 1) * 25;
1444 tlv[0] = SNDRV_CTL_TLVT_DB_SCALE;
1445 tlv[1] = 2 * sizeof(unsigned int);
1446 tlv[2] = -nums * step;
1447 tlv[3] = step;
1448}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001449EXPORT_SYMBOL_HDA(snd_hda_set_vmaster_tlv);
Takashi Iwai2134ea42008-01-10 16:53:55 +01001450
1451/* find a mixer control element with the given name */
Takashi Iwai09f99702008-02-04 12:31:13 +01001452static struct snd_kcontrol *
1453_snd_hda_find_mixer_ctl(struct hda_codec *codec,
1454 const char *name, int idx)
Takashi Iwai2134ea42008-01-10 16:53:55 +01001455{
1456 struct snd_ctl_elem_id id;
1457 memset(&id, 0, sizeof(id));
1458 id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
Takashi Iwai09f99702008-02-04 12:31:13 +01001459 id.index = idx;
Takashi Iwai18cb7102009-04-16 10:22:24 +02001460 if (snd_BUG_ON(strlen(name) >= sizeof(id.name)))
1461 return NULL;
Takashi Iwai2134ea42008-01-10 16:53:55 +01001462 strcpy(id.name, name);
1463 return snd_ctl_find_id(codec->bus->card, &id);
1464}
1465
Takashi Iwai09f99702008-02-04 12:31:13 +01001466struct snd_kcontrol *snd_hda_find_mixer_ctl(struct hda_codec *codec,
1467 const char *name)
1468{
1469 return _snd_hda_find_mixer_ctl(codec, name, 0);
1470}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001471EXPORT_SYMBOL_HDA(snd_hda_find_mixer_ctl);
Takashi Iwai09f99702008-02-04 12:31:13 +01001472
Takashi Iwaid13bd412008-07-30 15:01:45 +02001473/* Add a control element and assign to the codec */
1474int snd_hda_ctl_add(struct hda_codec *codec, struct snd_kcontrol *kctl)
1475{
1476 int err;
1477 struct snd_kcontrol **knewp;
1478
1479 err = snd_ctl_add(codec->bus->card, kctl);
1480 if (err < 0)
1481 return err;
1482 knewp = snd_array_new(&codec->mixers);
1483 if (!knewp)
1484 return -ENOMEM;
1485 *knewp = kctl;
1486 return 0;
1487}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001488EXPORT_SYMBOL_HDA(snd_hda_ctl_add);
Takashi Iwaid13bd412008-07-30 15:01:45 +02001489
1490/* Clear all controls assigned to the given codec */
1491void snd_hda_ctls_clear(struct hda_codec *codec)
1492{
1493 int i;
1494 struct snd_kcontrol **kctls = codec->mixers.list;
1495 for (i = 0; i < codec->mixers.used; i++)
1496 snd_ctl_remove(codec->bus->card, kctls[i]);
1497 snd_array_free(&codec->mixers);
1498}
1499
Takashi Iwaia65d6292009-02-23 16:57:04 +01001500/* pseudo device locking
1501 * toggle card->shutdown to allow/disallow the device access (as a hack)
1502 */
1503static int hda_lock_devices(struct snd_card *card)
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001504{
Takashi Iwaia65d6292009-02-23 16:57:04 +01001505 spin_lock(&card->files_lock);
1506 if (card->shutdown) {
1507 spin_unlock(&card->files_lock);
1508 return -EINVAL;
1509 }
1510 card->shutdown = 1;
1511 spin_unlock(&card->files_lock);
1512 return 0;
1513}
1514
1515static void hda_unlock_devices(struct snd_card *card)
1516{
1517 spin_lock(&card->files_lock);
1518 card->shutdown = 0;
1519 spin_unlock(&card->files_lock);
1520}
1521
1522int snd_hda_codec_reset(struct hda_codec *codec)
1523{
1524 struct snd_card *card = codec->bus->card;
1525 int i, pcm;
1526
1527 if (hda_lock_devices(card) < 0)
1528 return -EBUSY;
1529 /* check whether the codec isn't used by any mixer or PCM streams */
1530 if (!list_empty(&card->ctl_files)) {
1531 hda_unlock_devices(card);
1532 return -EBUSY;
1533 }
1534 for (pcm = 0; pcm < codec->num_pcms; pcm++) {
1535 struct hda_pcm *cpcm = &codec->pcm_info[pcm];
1536 if (!cpcm->pcm)
1537 continue;
1538 if (cpcm->pcm->streams[0].substream_opened ||
1539 cpcm->pcm->streams[1].substream_opened) {
1540 hda_unlock_devices(card);
1541 return -EBUSY;
1542 }
1543 }
1544
1545 /* OK, let it free */
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001546
1547#ifdef CONFIG_SND_HDA_POWER_SAVE
1548 cancel_delayed_work(&codec->power_work);
Takashi Iwai6acaed32009-01-12 10:09:24 +01001549 flush_workqueue(codec->bus->workq);
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001550#endif
1551 snd_hda_ctls_clear(codec);
1552 /* relase PCMs */
1553 for (i = 0; i < codec->num_pcms; i++) {
Takashi Iwai529bd6c2008-11-27 14:17:01 +01001554 if (codec->pcm_info[i].pcm) {
Takashi Iwaia65d6292009-02-23 16:57:04 +01001555 snd_device_free(card, codec->pcm_info[i].pcm);
Takashi Iwai529bd6c2008-11-27 14:17:01 +01001556 clear_bit(codec->pcm_info[i].device,
1557 codec->bus->pcm_dev_bits);
1558 }
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001559 }
1560 if (codec->patch_ops.free)
1561 codec->patch_ops.free(codec);
Takashi Iwai56d17712008-11-28 14:36:23 +01001562 codec->proc_widget_hook = NULL;
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001563 codec->spec = NULL;
1564 free_hda_cache(&codec->amp_cache);
1565 free_hda_cache(&codec->cmd_cache);
Takashi Iwai827057f2008-12-19 10:12:02 +01001566 init_hda_cache(&codec->amp_cache, sizeof(struct hda_amp_info));
1567 init_hda_cache(&codec->cmd_cache, sizeof(struct hda_cache_head));
Takashi Iwai346ff702009-02-23 09:42:57 +01001568 /* free only driver_pins so that init_pins + user_pins are restored */
1569 snd_array_free(&codec->driver_pins);
Takashi Iwai3be14142009-02-20 14:11:16 +01001570 restore_pincfgs(codec);
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001571 codec->num_pcms = 0;
1572 codec->pcm_info = NULL;
1573 codec->preset = NULL;
Takashi Iwaid1f1af22009-03-02 10:35:29 +01001574 memset(&codec->patch_ops, 0, sizeof(codec->patch_ops));
1575 codec->slave_dig_outs = NULL;
1576 codec->spdif_status_reset = 0;
Takashi Iwai1289e9e2008-11-27 15:47:11 +01001577 module_put(codec->owner);
1578 codec->owner = NULL;
Takashi Iwaia65d6292009-02-23 16:57:04 +01001579
1580 /* allow device access again */
1581 hda_unlock_devices(card);
1582 return 0;
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001583}
1584
Takashi Iwai2134ea42008-01-10 16:53:55 +01001585/* create a virtual master control and add slaves */
1586int snd_hda_add_vmaster(struct hda_codec *codec, char *name,
1587 unsigned int *tlv, const char **slaves)
1588{
1589 struct snd_kcontrol *kctl;
1590 const char **s;
1591 int err;
1592
Takashi Iwai2f085542008-02-22 18:43:50 +01001593 for (s = slaves; *s && !snd_hda_find_mixer_ctl(codec, *s); s++)
1594 ;
1595 if (!*s) {
1596 snd_printdd("No slave found for %s\n", name);
1597 return 0;
1598 }
Takashi Iwai2134ea42008-01-10 16:53:55 +01001599 kctl = snd_ctl_make_virtual_master(name, tlv);
1600 if (!kctl)
1601 return -ENOMEM;
Takashi Iwaid13bd412008-07-30 15:01:45 +02001602 err = snd_hda_ctl_add(codec, kctl);
Takashi Iwai2134ea42008-01-10 16:53:55 +01001603 if (err < 0)
1604 return err;
1605
1606 for (s = slaves; *s; s++) {
1607 struct snd_kcontrol *sctl;
Takashi Iwai7a411ee2009-03-06 10:08:14 +01001608 int i = 0;
1609 for (;;) {
1610 sctl = _snd_hda_find_mixer_ctl(codec, *s, i);
1611 if (!sctl) {
1612 if (!i)
1613 snd_printdd("Cannot find slave %s, "
1614 "skipped\n", *s);
1615 break;
1616 }
1617 err = snd_ctl_add_slave(kctl, sctl);
1618 if (err < 0)
1619 return err;
1620 i++;
Takashi Iwai2134ea42008-01-10 16:53:55 +01001621 }
Takashi Iwai2134ea42008-01-10 16:53:55 +01001622 }
1623 return 0;
1624}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001625EXPORT_SYMBOL_HDA(snd_hda_add_vmaster);
Takashi Iwai2134ea42008-01-10 16:53:55 +01001626
Linus Torvalds1da177e2005-04-16 15:20:36 -07001627/* switch */
Takashi Iwai0ba21762007-04-16 11:29:14 +02001628int snd_hda_mixer_amp_switch_info(struct snd_kcontrol *kcontrol,
1629 struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001630{
1631 int chs = get_amp_channels(kcontrol);
1632
1633 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
1634 uinfo->count = chs == 3 ? 2 : 1;
1635 uinfo->value.integer.min = 0;
1636 uinfo->value.integer.max = 1;
1637 return 0;
1638}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001639EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_switch_info);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001640
Takashi Iwai0ba21762007-04-16 11:29:14 +02001641int snd_hda_mixer_amp_switch_get(struct snd_kcontrol *kcontrol,
1642 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001643{
1644 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1645 hda_nid_t nid = get_amp_nid(kcontrol);
1646 int chs = get_amp_channels(kcontrol);
1647 int dir = get_amp_direction(kcontrol);
1648 int idx = get_amp_index(kcontrol);
1649 long *valp = ucontrol->value.integer.value;
1650
1651 if (chs & 1)
Takashi Iwai0ba21762007-04-16 11:29:14 +02001652 *valp++ = (snd_hda_codec_amp_read(codec, nid, 0, dir, idx) &
Takashi Iwai47fd8302007-08-10 17:11:07 +02001653 HDA_AMP_MUTE) ? 0 : 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001654 if (chs & 2)
Takashi Iwai0ba21762007-04-16 11:29:14 +02001655 *valp = (snd_hda_codec_amp_read(codec, nid, 1, dir, idx) &
Takashi Iwai47fd8302007-08-10 17:11:07 +02001656 HDA_AMP_MUTE) ? 0 : 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001657 return 0;
1658}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001659EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_switch_get);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001660
Takashi Iwai0ba21762007-04-16 11:29:14 +02001661int snd_hda_mixer_amp_switch_put(struct snd_kcontrol *kcontrol,
1662 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001663{
1664 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1665 hda_nid_t nid = get_amp_nid(kcontrol);
1666 int chs = get_amp_channels(kcontrol);
1667 int dir = get_amp_direction(kcontrol);
1668 int idx = get_amp_index(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001669 long *valp = ucontrol->value.integer.value;
1670 int change = 0;
1671
Takashi Iwaicb53c622007-08-10 17:21:45 +02001672 snd_hda_power_up(codec);
Nicolas Grazianob9f5a892005-07-29 12:17:20 +02001673 if (chs & 1) {
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001674 change = snd_hda_codec_amp_update(codec, nid, 0, dir, idx,
Takashi Iwai47fd8302007-08-10 17:11:07 +02001675 HDA_AMP_MUTE,
1676 *valp ? 0 : HDA_AMP_MUTE);
Nicolas Grazianob9f5a892005-07-29 12:17:20 +02001677 valp++;
1678 }
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001679 if (chs & 2)
1680 change |= snd_hda_codec_amp_update(codec, nid, 1, dir, idx,
Takashi Iwai47fd8302007-08-10 17:11:07 +02001681 HDA_AMP_MUTE,
1682 *valp ? 0 : HDA_AMP_MUTE);
Takashi Iwaicb53c622007-08-10 17:21:45 +02001683#ifdef CONFIG_SND_HDA_POWER_SAVE
1684 if (codec->patch_ops.check_power_status)
1685 codec->patch_ops.check_power_status(codec, nid);
1686#endif
1687 snd_hda_power_down(codec);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001688 return change;
1689}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001690EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_switch_put);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001691
1692/*
Takashi Iwai985be542005-11-02 18:26:49 +01001693 * bound volume controls
1694 *
1695 * bind multiple volumes (# indices, from 0)
1696 */
1697
1698#define AMP_VAL_IDX_SHIFT 19
1699#define AMP_VAL_IDX_MASK (0x0f<<19)
1700
Takashi Iwai0ba21762007-04-16 11:29:14 +02001701int snd_hda_mixer_bind_switch_get(struct snd_kcontrol *kcontrol,
1702 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai985be542005-11-02 18:26:49 +01001703{
1704 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1705 unsigned long pval;
1706 int err;
1707
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001708 mutex_lock(&codec->control_mutex);
Takashi Iwai985be542005-11-02 18:26:49 +01001709 pval = kcontrol->private_value;
1710 kcontrol->private_value = pval & ~AMP_VAL_IDX_MASK; /* index 0 */
1711 err = snd_hda_mixer_amp_switch_get(kcontrol, ucontrol);
1712 kcontrol->private_value = pval;
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001713 mutex_unlock(&codec->control_mutex);
Takashi Iwai985be542005-11-02 18:26:49 +01001714 return err;
1715}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001716EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_switch_get);
Takashi Iwai985be542005-11-02 18:26:49 +01001717
Takashi Iwai0ba21762007-04-16 11:29:14 +02001718int snd_hda_mixer_bind_switch_put(struct snd_kcontrol *kcontrol,
1719 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai985be542005-11-02 18:26:49 +01001720{
1721 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1722 unsigned long pval;
1723 int i, indices, err = 0, change = 0;
1724
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001725 mutex_lock(&codec->control_mutex);
Takashi Iwai985be542005-11-02 18:26:49 +01001726 pval = kcontrol->private_value;
1727 indices = (pval & AMP_VAL_IDX_MASK) >> AMP_VAL_IDX_SHIFT;
1728 for (i = 0; i < indices; i++) {
Takashi Iwai0ba21762007-04-16 11:29:14 +02001729 kcontrol->private_value = (pval & ~AMP_VAL_IDX_MASK) |
1730 (i << AMP_VAL_IDX_SHIFT);
Takashi Iwai985be542005-11-02 18:26:49 +01001731 err = snd_hda_mixer_amp_switch_put(kcontrol, ucontrol);
1732 if (err < 0)
1733 break;
1734 change |= err;
1735 }
1736 kcontrol->private_value = pval;
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001737 mutex_unlock(&codec->control_mutex);
Takashi Iwai985be542005-11-02 18:26:49 +01001738 return err < 0 ? err : change;
1739}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001740EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_switch_put);
Takashi Iwai985be542005-11-02 18:26:49 +01001741
1742/*
Takashi Iwai532d5382007-07-27 19:02:40 +02001743 * generic bound volume/swtich controls
1744 */
1745int snd_hda_mixer_bind_ctls_info(struct snd_kcontrol *kcontrol,
1746 struct snd_ctl_elem_info *uinfo)
1747{
1748 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1749 struct hda_bind_ctls *c;
1750 int err;
1751
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001752 mutex_lock(&codec->control_mutex);
Serge A. Suchkov14c65f92008-02-22 18:43:16 +01001753 c = (struct hda_bind_ctls *)kcontrol->private_value;
Takashi Iwai532d5382007-07-27 19:02:40 +02001754 kcontrol->private_value = *c->values;
1755 err = c->ops->info(kcontrol, uinfo);
1756 kcontrol->private_value = (long)c;
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001757 mutex_unlock(&codec->control_mutex);
Takashi Iwai532d5382007-07-27 19:02:40 +02001758 return err;
1759}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001760EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_ctls_info);
Takashi Iwai532d5382007-07-27 19:02:40 +02001761
1762int snd_hda_mixer_bind_ctls_get(struct snd_kcontrol *kcontrol,
1763 struct snd_ctl_elem_value *ucontrol)
1764{
1765 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1766 struct hda_bind_ctls *c;
1767 int err;
1768
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001769 mutex_lock(&codec->control_mutex);
Serge A. Suchkov14c65f92008-02-22 18:43:16 +01001770 c = (struct hda_bind_ctls *)kcontrol->private_value;
Takashi Iwai532d5382007-07-27 19:02:40 +02001771 kcontrol->private_value = *c->values;
1772 err = c->ops->get(kcontrol, ucontrol);
1773 kcontrol->private_value = (long)c;
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001774 mutex_unlock(&codec->control_mutex);
Takashi Iwai532d5382007-07-27 19:02:40 +02001775 return err;
1776}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001777EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_ctls_get);
Takashi Iwai532d5382007-07-27 19:02:40 +02001778
1779int snd_hda_mixer_bind_ctls_put(struct snd_kcontrol *kcontrol,
1780 struct snd_ctl_elem_value *ucontrol)
1781{
1782 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1783 struct hda_bind_ctls *c;
1784 unsigned long *vals;
1785 int err = 0, change = 0;
1786
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001787 mutex_lock(&codec->control_mutex);
Serge A. Suchkov14c65f92008-02-22 18:43:16 +01001788 c = (struct hda_bind_ctls *)kcontrol->private_value;
Takashi Iwai532d5382007-07-27 19:02:40 +02001789 for (vals = c->values; *vals; vals++) {
1790 kcontrol->private_value = *vals;
1791 err = c->ops->put(kcontrol, ucontrol);
1792 if (err < 0)
1793 break;
1794 change |= err;
1795 }
1796 kcontrol->private_value = (long)c;
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001797 mutex_unlock(&codec->control_mutex);
Takashi Iwai532d5382007-07-27 19:02:40 +02001798 return err < 0 ? err : change;
1799}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001800EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_ctls_put);
Takashi Iwai532d5382007-07-27 19:02:40 +02001801
1802int snd_hda_mixer_bind_tlv(struct snd_kcontrol *kcontrol, int op_flag,
1803 unsigned int size, unsigned int __user *tlv)
1804{
1805 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1806 struct hda_bind_ctls *c;
1807 int err;
1808
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001809 mutex_lock(&codec->control_mutex);
Serge A. Suchkov14c65f92008-02-22 18:43:16 +01001810 c = (struct hda_bind_ctls *)kcontrol->private_value;
Takashi Iwai532d5382007-07-27 19:02:40 +02001811 kcontrol->private_value = *c->values;
1812 err = c->ops->tlv(kcontrol, op_flag, size, tlv);
1813 kcontrol->private_value = (long)c;
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001814 mutex_unlock(&codec->control_mutex);
Takashi Iwai532d5382007-07-27 19:02:40 +02001815 return err;
1816}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001817EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_tlv);
Takashi Iwai532d5382007-07-27 19:02:40 +02001818
1819struct hda_ctl_ops snd_hda_bind_vol = {
1820 .info = snd_hda_mixer_amp_volume_info,
1821 .get = snd_hda_mixer_amp_volume_get,
1822 .put = snd_hda_mixer_amp_volume_put,
1823 .tlv = snd_hda_mixer_amp_tlv
1824};
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001825EXPORT_SYMBOL_HDA(snd_hda_bind_vol);
Takashi Iwai532d5382007-07-27 19:02:40 +02001826
1827struct hda_ctl_ops snd_hda_bind_sw = {
1828 .info = snd_hda_mixer_amp_switch_info,
1829 .get = snd_hda_mixer_amp_switch_get,
1830 .put = snd_hda_mixer_amp_switch_put,
1831 .tlv = snd_hda_mixer_amp_tlv
1832};
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001833EXPORT_SYMBOL_HDA(snd_hda_bind_sw);
Takashi Iwai532d5382007-07-27 19:02:40 +02001834
1835/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07001836 * SPDIF out controls
1837 */
1838
Takashi Iwai0ba21762007-04-16 11:29:14 +02001839static int snd_hda_spdif_mask_info(struct snd_kcontrol *kcontrol,
1840 struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001841{
1842 uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
1843 uinfo->count = 1;
1844 return 0;
1845}
1846
Takashi Iwai0ba21762007-04-16 11:29:14 +02001847static int snd_hda_spdif_cmask_get(struct snd_kcontrol *kcontrol,
1848 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001849{
1850 ucontrol->value.iec958.status[0] = IEC958_AES0_PROFESSIONAL |
1851 IEC958_AES0_NONAUDIO |
1852 IEC958_AES0_CON_EMPHASIS_5015 |
1853 IEC958_AES0_CON_NOT_COPYRIGHT;
1854 ucontrol->value.iec958.status[1] = IEC958_AES1_CON_CATEGORY |
1855 IEC958_AES1_CON_ORIGINAL;
1856 return 0;
1857}
1858
Takashi Iwai0ba21762007-04-16 11:29:14 +02001859static int snd_hda_spdif_pmask_get(struct snd_kcontrol *kcontrol,
1860 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001861{
1862 ucontrol->value.iec958.status[0] = IEC958_AES0_PROFESSIONAL |
1863 IEC958_AES0_NONAUDIO |
1864 IEC958_AES0_PRO_EMPHASIS_5015;
1865 return 0;
1866}
1867
Takashi Iwai0ba21762007-04-16 11:29:14 +02001868static int snd_hda_spdif_default_get(struct snd_kcontrol *kcontrol,
1869 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001870{
1871 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1872
1873 ucontrol->value.iec958.status[0] = codec->spdif_status & 0xff;
1874 ucontrol->value.iec958.status[1] = (codec->spdif_status >> 8) & 0xff;
1875 ucontrol->value.iec958.status[2] = (codec->spdif_status >> 16) & 0xff;
1876 ucontrol->value.iec958.status[3] = (codec->spdif_status >> 24) & 0xff;
1877
1878 return 0;
1879}
1880
1881/* convert from SPDIF status bits to HDA SPDIF bits
1882 * bit 0 (DigEn) is always set zero (to be filled later)
1883 */
1884static unsigned short convert_from_spdif_status(unsigned int sbits)
1885{
1886 unsigned short val = 0;
1887
1888 if (sbits & IEC958_AES0_PROFESSIONAL)
Takashi Iwai0ba21762007-04-16 11:29:14 +02001889 val |= AC_DIG1_PROFESSIONAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001890 if (sbits & IEC958_AES0_NONAUDIO)
Takashi Iwai0ba21762007-04-16 11:29:14 +02001891 val |= AC_DIG1_NONAUDIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001892 if (sbits & IEC958_AES0_PROFESSIONAL) {
Takashi Iwai0ba21762007-04-16 11:29:14 +02001893 if ((sbits & IEC958_AES0_PRO_EMPHASIS) ==
1894 IEC958_AES0_PRO_EMPHASIS_5015)
1895 val |= AC_DIG1_EMPHASIS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001896 } else {
Takashi Iwai0ba21762007-04-16 11:29:14 +02001897 if ((sbits & IEC958_AES0_CON_EMPHASIS) ==
1898 IEC958_AES0_CON_EMPHASIS_5015)
1899 val |= AC_DIG1_EMPHASIS;
1900 if (!(sbits & IEC958_AES0_CON_NOT_COPYRIGHT))
1901 val |= AC_DIG1_COPYRIGHT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001902 if (sbits & (IEC958_AES1_CON_ORIGINAL << 8))
Takashi Iwai0ba21762007-04-16 11:29:14 +02001903 val |= AC_DIG1_LEVEL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001904 val |= sbits & (IEC958_AES1_CON_CATEGORY << 8);
1905 }
1906 return val;
1907}
1908
1909/* convert to SPDIF status bits from HDA SPDIF bits
1910 */
1911static unsigned int convert_to_spdif_status(unsigned short val)
1912{
1913 unsigned int sbits = 0;
1914
Takashi Iwai0ba21762007-04-16 11:29:14 +02001915 if (val & AC_DIG1_NONAUDIO)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001916 sbits |= IEC958_AES0_NONAUDIO;
Takashi Iwai0ba21762007-04-16 11:29:14 +02001917 if (val & AC_DIG1_PROFESSIONAL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001918 sbits |= IEC958_AES0_PROFESSIONAL;
1919 if (sbits & IEC958_AES0_PROFESSIONAL) {
Takashi Iwai0ba21762007-04-16 11:29:14 +02001920 if (sbits & AC_DIG1_EMPHASIS)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001921 sbits |= IEC958_AES0_PRO_EMPHASIS_5015;
1922 } else {
Takashi Iwai0ba21762007-04-16 11:29:14 +02001923 if (val & AC_DIG1_EMPHASIS)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001924 sbits |= IEC958_AES0_CON_EMPHASIS_5015;
Takashi Iwai0ba21762007-04-16 11:29:14 +02001925 if (!(val & AC_DIG1_COPYRIGHT))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001926 sbits |= IEC958_AES0_CON_NOT_COPYRIGHT;
Takashi Iwai0ba21762007-04-16 11:29:14 +02001927 if (val & AC_DIG1_LEVEL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001928 sbits |= (IEC958_AES1_CON_ORIGINAL << 8);
1929 sbits |= val & (0x7f << 8);
1930 }
1931 return sbits;
1932}
1933
Takashi Iwai2f728532008-09-25 16:32:41 +02001934/* set digital convert verbs both for the given NID and its slaves */
1935static void set_dig_out(struct hda_codec *codec, hda_nid_t nid,
1936 int verb, int val)
1937{
1938 hda_nid_t *d;
1939
Takashi Iwai9e976972008-11-25 08:17:20 +01001940 snd_hda_codec_write_cache(codec, nid, 0, verb, val);
Takashi Iwai2f728532008-09-25 16:32:41 +02001941 d = codec->slave_dig_outs;
1942 if (!d)
1943 return;
1944 for (; *d; d++)
Takashi Iwai9e976972008-11-25 08:17:20 +01001945 snd_hda_codec_write_cache(codec, *d, 0, verb, val);
Takashi Iwai2f728532008-09-25 16:32:41 +02001946}
1947
1948static inline void set_dig_out_convert(struct hda_codec *codec, hda_nid_t nid,
1949 int dig1, int dig2)
1950{
1951 if (dig1 != -1)
1952 set_dig_out(codec, nid, AC_VERB_SET_DIGI_CONVERT_1, dig1);
1953 if (dig2 != -1)
1954 set_dig_out(codec, nid, AC_VERB_SET_DIGI_CONVERT_2, dig2);
1955}
1956
Takashi Iwai0ba21762007-04-16 11:29:14 +02001957static int snd_hda_spdif_default_put(struct snd_kcontrol *kcontrol,
1958 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001959{
1960 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1961 hda_nid_t nid = kcontrol->private_value;
1962 unsigned short val;
1963 int change;
1964
Ingo Molnar62932df2006-01-16 16:34:20 +01001965 mutex_lock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001966 codec->spdif_status = ucontrol->value.iec958.status[0] |
1967 ((unsigned int)ucontrol->value.iec958.status[1] << 8) |
1968 ((unsigned int)ucontrol->value.iec958.status[2] << 16) |
1969 ((unsigned int)ucontrol->value.iec958.status[3] << 24);
1970 val = convert_from_spdif_status(codec->spdif_status);
1971 val |= codec->spdif_ctls & 1;
1972 change = codec->spdif_ctls != val;
1973 codec->spdif_ctls = val;
1974
Takashi Iwai2f728532008-09-25 16:32:41 +02001975 if (change)
1976 set_dig_out_convert(codec, nid, val & 0xff, (val >> 8) & 0xff);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001977
Ingo Molnar62932df2006-01-16 16:34:20 +01001978 mutex_unlock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001979 return change;
1980}
1981
Takashi Iwaia5ce8892007-07-23 15:42:26 +02001982#define snd_hda_spdif_out_switch_info snd_ctl_boolean_mono_info
Linus Torvalds1da177e2005-04-16 15:20:36 -07001983
Takashi Iwai0ba21762007-04-16 11:29:14 +02001984static int snd_hda_spdif_out_switch_get(struct snd_kcontrol *kcontrol,
1985 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001986{
1987 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1988
Takashi Iwai0ba21762007-04-16 11:29:14 +02001989 ucontrol->value.integer.value[0] = codec->spdif_ctls & AC_DIG1_ENABLE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001990 return 0;
1991}
1992
Takashi Iwai0ba21762007-04-16 11:29:14 +02001993static int snd_hda_spdif_out_switch_put(struct snd_kcontrol *kcontrol,
1994 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001995{
1996 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1997 hda_nid_t nid = kcontrol->private_value;
1998 unsigned short val;
1999 int change;
2000
Ingo Molnar62932df2006-01-16 16:34:20 +01002001 mutex_lock(&codec->spdif_mutex);
Takashi Iwai0ba21762007-04-16 11:29:14 +02002002 val = codec->spdif_ctls & ~AC_DIG1_ENABLE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002003 if (ucontrol->value.integer.value[0])
Takashi Iwai0ba21762007-04-16 11:29:14 +02002004 val |= AC_DIG1_ENABLE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002005 change = codec->spdif_ctls != val;
Takashi Iwai82beb8f2007-08-10 17:09:26 +02002006 if (change) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002007 codec->spdif_ctls = val;
Takashi Iwai2f728532008-09-25 16:32:41 +02002008 set_dig_out_convert(codec, nid, val & 0xff, -1);
Takashi Iwai0ba21762007-04-16 11:29:14 +02002009 /* unmute amp switch (if any) */
2010 if ((get_wcaps(codec, nid) & AC_WCAP_OUT_AMP) &&
Takashi Iwai47fd8302007-08-10 17:11:07 +02002011 (val & AC_DIG1_ENABLE))
2012 snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0,
2013 HDA_AMP_MUTE, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002014 }
Ingo Molnar62932df2006-01-16 16:34:20 +01002015 mutex_unlock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002016 return change;
2017}
2018
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01002019static struct snd_kcontrol_new dig_mixes[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002020 {
2021 .access = SNDRV_CTL_ELEM_ACCESS_READ,
2022 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2023 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,CON_MASK),
2024 .info = snd_hda_spdif_mask_info,
2025 .get = snd_hda_spdif_cmask_get,
2026 },
2027 {
2028 .access = SNDRV_CTL_ELEM_ACCESS_READ,
2029 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2030 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,PRO_MASK),
2031 .info = snd_hda_spdif_mask_info,
2032 .get = snd_hda_spdif_pmask_get,
2033 },
2034 {
2035 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2036 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT),
2037 .info = snd_hda_spdif_mask_info,
2038 .get = snd_hda_spdif_default_get,
2039 .put = snd_hda_spdif_default_put,
2040 },
2041 {
2042 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2043 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,SWITCH),
2044 .info = snd_hda_spdif_out_switch_info,
2045 .get = snd_hda_spdif_out_switch_get,
2046 .put = snd_hda_spdif_out_switch_put,
2047 },
2048 { } /* end */
2049};
2050
Takashi Iwai09f99702008-02-04 12:31:13 +01002051#define SPDIF_MAX_IDX 4 /* 4 instances should be enough to probe */
2052
Linus Torvalds1da177e2005-04-16 15:20:36 -07002053/**
2054 * snd_hda_create_spdif_out_ctls - create Output SPDIF-related controls
2055 * @codec: the HDA codec
2056 * @nid: audio out widget NID
2057 *
2058 * Creates controls related with the SPDIF output.
2059 * Called from each patch supporting the SPDIF out.
2060 *
2061 * Returns 0 if successful, or a negative error code.
2062 */
Takashi Iwai12f288b2007-08-02 15:51:59 +02002063int snd_hda_create_spdif_out_ctls(struct hda_codec *codec, hda_nid_t nid)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002064{
2065 int err;
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01002066 struct snd_kcontrol *kctl;
2067 struct snd_kcontrol_new *dig_mix;
Takashi Iwai09f99702008-02-04 12:31:13 +01002068 int idx;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002069
Takashi Iwai09f99702008-02-04 12:31:13 +01002070 for (idx = 0; idx < SPDIF_MAX_IDX; idx++) {
2071 if (!_snd_hda_find_mixer_ctl(codec, "IEC958 Playback Switch",
2072 idx))
2073 break;
2074 }
2075 if (idx >= SPDIF_MAX_IDX) {
2076 printk(KERN_ERR "hda_codec: too many IEC958 outputs\n");
2077 return -EBUSY;
2078 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002079 for (dig_mix = dig_mixes; dig_mix->name; dig_mix++) {
2080 kctl = snd_ctl_new1(dig_mix, codec);
Takashi Iwaib91f0802008-11-04 08:43:08 +01002081 if (!kctl)
2082 return -ENOMEM;
Takashi Iwai09f99702008-02-04 12:31:13 +01002083 kctl->id.index = idx;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002084 kctl->private_value = nid;
Takashi Iwaid13bd412008-07-30 15:01:45 +02002085 err = snd_hda_ctl_add(codec, kctl);
Takashi Iwai0ba21762007-04-16 11:29:14 +02002086 if (err < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002087 return err;
2088 }
Takashi Iwai0ba21762007-04-16 11:29:14 +02002089 codec->spdif_ctls =
Andrew Paprocki3982d172007-12-19 12:13:44 +01002090 snd_hda_codec_read(codec, nid, 0,
2091 AC_VERB_GET_DIGI_CONVERT_1, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002092 codec->spdif_status = convert_to_spdif_status(codec->spdif_ctls);
2093 return 0;
2094}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002095EXPORT_SYMBOL_HDA(snd_hda_create_spdif_out_ctls);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002096
2097/*
Takashi Iwai9a081602008-02-12 18:37:26 +01002098 * SPDIF sharing with analog output
2099 */
2100static int spdif_share_sw_get(struct snd_kcontrol *kcontrol,
2101 struct snd_ctl_elem_value *ucontrol)
2102{
2103 struct hda_multi_out *mout = snd_kcontrol_chip(kcontrol);
2104 ucontrol->value.integer.value[0] = mout->share_spdif;
2105 return 0;
2106}
2107
2108static int spdif_share_sw_put(struct snd_kcontrol *kcontrol,
2109 struct snd_ctl_elem_value *ucontrol)
2110{
2111 struct hda_multi_out *mout = snd_kcontrol_chip(kcontrol);
2112 mout->share_spdif = !!ucontrol->value.integer.value[0];
2113 return 0;
2114}
2115
2116static struct snd_kcontrol_new spdif_share_sw = {
2117 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2118 .name = "IEC958 Default PCM Playback Switch",
2119 .info = snd_ctl_boolean_mono_info,
2120 .get = spdif_share_sw_get,
2121 .put = spdif_share_sw_put,
2122};
2123
2124int snd_hda_create_spdif_share_sw(struct hda_codec *codec,
2125 struct hda_multi_out *mout)
2126{
2127 if (!mout->dig_out_nid)
2128 return 0;
2129 /* ATTENTION: here mout is passed as private_data, instead of codec */
Takashi Iwaid13bd412008-07-30 15:01:45 +02002130 return snd_hda_ctl_add(codec,
Takashi Iwai9a081602008-02-12 18:37:26 +01002131 snd_ctl_new1(&spdif_share_sw, mout));
2132}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002133EXPORT_SYMBOL_HDA(snd_hda_create_spdif_share_sw);
Takashi Iwai9a081602008-02-12 18:37:26 +01002134
2135/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002136 * SPDIF input
2137 */
2138
2139#define snd_hda_spdif_in_switch_info snd_hda_spdif_out_switch_info
2140
Takashi Iwai0ba21762007-04-16 11:29:14 +02002141static int snd_hda_spdif_in_switch_get(struct snd_kcontrol *kcontrol,
2142 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002143{
2144 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2145
2146 ucontrol->value.integer.value[0] = codec->spdif_in_enable;
2147 return 0;
2148}
2149
Takashi Iwai0ba21762007-04-16 11:29:14 +02002150static int snd_hda_spdif_in_switch_put(struct snd_kcontrol *kcontrol,
2151 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002152{
2153 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2154 hda_nid_t nid = kcontrol->private_value;
2155 unsigned int val = !!ucontrol->value.integer.value[0];
2156 int change;
2157
Ingo Molnar62932df2006-01-16 16:34:20 +01002158 mutex_lock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002159 change = codec->spdif_in_enable != val;
Takashi Iwai82beb8f2007-08-10 17:09:26 +02002160 if (change) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002161 codec->spdif_in_enable = val;
Takashi Iwai82beb8f2007-08-10 17:09:26 +02002162 snd_hda_codec_write_cache(codec, nid, 0,
2163 AC_VERB_SET_DIGI_CONVERT_1, val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002164 }
Ingo Molnar62932df2006-01-16 16:34:20 +01002165 mutex_unlock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002166 return change;
2167}
2168
Takashi Iwai0ba21762007-04-16 11:29:14 +02002169static int snd_hda_spdif_in_status_get(struct snd_kcontrol *kcontrol,
2170 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002171{
2172 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2173 hda_nid_t nid = kcontrol->private_value;
2174 unsigned short val;
2175 unsigned int sbits;
2176
Andrew Paprocki3982d172007-12-19 12:13:44 +01002177 val = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_DIGI_CONVERT_1, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002178 sbits = convert_to_spdif_status(val);
2179 ucontrol->value.iec958.status[0] = sbits;
2180 ucontrol->value.iec958.status[1] = sbits >> 8;
2181 ucontrol->value.iec958.status[2] = sbits >> 16;
2182 ucontrol->value.iec958.status[3] = sbits >> 24;
2183 return 0;
2184}
2185
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01002186static struct snd_kcontrol_new dig_in_ctls[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002187 {
2188 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2189 .name = SNDRV_CTL_NAME_IEC958("",CAPTURE,SWITCH),
2190 .info = snd_hda_spdif_in_switch_info,
2191 .get = snd_hda_spdif_in_switch_get,
2192 .put = snd_hda_spdif_in_switch_put,
2193 },
2194 {
2195 .access = SNDRV_CTL_ELEM_ACCESS_READ,
2196 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2197 .name = SNDRV_CTL_NAME_IEC958("",CAPTURE,DEFAULT),
2198 .info = snd_hda_spdif_mask_info,
2199 .get = snd_hda_spdif_in_status_get,
2200 },
2201 { } /* end */
2202};
2203
2204/**
2205 * snd_hda_create_spdif_in_ctls - create Input SPDIF-related controls
2206 * @codec: the HDA codec
2207 * @nid: audio in widget NID
2208 *
2209 * Creates controls related with the SPDIF input.
2210 * Called from each patch supporting the SPDIF in.
2211 *
2212 * Returns 0 if successful, or a negative error code.
2213 */
Takashi Iwai12f288b2007-08-02 15:51:59 +02002214int snd_hda_create_spdif_in_ctls(struct hda_codec *codec, hda_nid_t nid)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002215{
2216 int err;
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01002217 struct snd_kcontrol *kctl;
2218 struct snd_kcontrol_new *dig_mix;
Takashi Iwai09f99702008-02-04 12:31:13 +01002219 int idx;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002220
Takashi Iwai09f99702008-02-04 12:31:13 +01002221 for (idx = 0; idx < SPDIF_MAX_IDX; idx++) {
2222 if (!_snd_hda_find_mixer_ctl(codec, "IEC958 Capture Switch",
2223 idx))
2224 break;
2225 }
2226 if (idx >= SPDIF_MAX_IDX) {
2227 printk(KERN_ERR "hda_codec: too many IEC958 inputs\n");
2228 return -EBUSY;
2229 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002230 for (dig_mix = dig_in_ctls; dig_mix->name; dig_mix++) {
2231 kctl = snd_ctl_new1(dig_mix, codec);
Takashi Iwaic8dcdf82009-02-06 16:21:20 +01002232 if (!kctl)
2233 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002234 kctl->private_value = nid;
Takashi Iwaid13bd412008-07-30 15:01:45 +02002235 err = snd_hda_ctl_add(codec, kctl);
Takashi Iwai0ba21762007-04-16 11:29:14 +02002236 if (err < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002237 return err;
2238 }
Takashi Iwai0ba21762007-04-16 11:29:14 +02002239 codec->spdif_in_enable =
Andrew Paprocki3982d172007-12-19 12:13:44 +01002240 snd_hda_codec_read(codec, nid, 0,
2241 AC_VERB_GET_DIGI_CONVERT_1, 0) &
Takashi Iwai0ba21762007-04-16 11:29:14 +02002242 AC_DIG1_ENABLE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002243 return 0;
2244}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002245EXPORT_SYMBOL_HDA(snd_hda_create_spdif_in_ctls);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002246
Takashi Iwaicb53c622007-08-10 17:21:45 +02002247#ifdef SND_HDA_NEEDS_RESUME
Takashi Iwai82beb8f2007-08-10 17:09:26 +02002248/*
2249 * command cache
2250 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002251
Takashi Iwaib3ac5632007-08-10 17:03:40 +02002252/* build a 32bit cache key with the widget id and the command parameter */
2253#define build_cmd_cache_key(nid, verb) ((verb << 8) | nid)
2254#define get_cmd_cache_nid(key) ((key) & 0xff)
2255#define get_cmd_cache_cmd(key) (((key) >> 8) & 0xffff)
2256
2257/**
2258 * snd_hda_codec_write_cache - send a single command with caching
2259 * @codec: the HDA codec
2260 * @nid: NID to send the command
2261 * @direct: direct flag
2262 * @verb: the verb to send
2263 * @parm: the parameter for the verb
2264 *
2265 * Send a single command without waiting for response.
2266 *
2267 * Returns 0 if successful, or a negative error code.
2268 */
2269int snd_hda_codec_write_cache(struct hda_codec *codec, hda_nid_t nid,
2270 int direct, unsigned int verb, unsigned int parm)
2271{
Takashi Iwai33fa35e2008-11-06 16:50:40 +01002272 struct hda_bus *bus = codec->bus;
2273 unsigned int res;
Takashi Iwaib3ac5632007-08-10 17:03:40 +02002274 int err;
Takashi Iwai33fa35e2008-11-06 16:50:40 +01002275
2276 res = make_codec_cmd(codec, nid, direct, verb, parm);
Takashi Iwaicb53c622007-08-10 17:21:45 +02002277 snd_hda_power_up(codec);
Takashi Iwai33fa35e2008-11-06 16:50:40 +01002278 mutex_lock(&bus->cmd_mutex);
2279 err = bus->ops.command(bus, res);
Takashi Iwaib3ac5632007-08-10 17:03:40 +02002280 if (!err) {
2281 struct hda_cache_head *c;
Takashi Iwaifcad94a2009-04-15 17:48:35 +02002282 u32 key;
2283 /* parm may contain the verb stuff for get/set amp */
2284 verb = verb | (parm >> 8);
2285 parm &= 0xff;
2286 key = build_cmd_cache_key(nid, verb);
Takashi Iwaib3ac5632007-08-10 17:03:40 +02002287 c = get_alloc_hash(&codec->cmd_cache, key);
2288 if (c)
2289 c->val = parm;
2290 }
Takashi Iwai33fa35e2008-11-06 16:50:40 +01002291 mutex_unlock(&bus->cmd_mutex);
Takashi Iwaicb53c622007-08-10 17:21:45 +02002292 snd_hda_power_down(codec);
Takashi Iwaib3ac5632007-08-10 17:03:40 +02002293 return err;
2294}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002295EXPORT_SYMBOL_HDA(snd_hda_codec_write_cache);
Takashi Iwaib3ac5632007-08-10 17:03:40 +02002296
2297/* resume the all commands from the cache */
2298void snd_hda_codec_resume_cache(struct hda_codec *codec)
2299{
Takashi Iwai603c4012008-07-30 15:01:44 +02002300 struct hda_cache_head *buffer = codec->cmd_cache.buf.list;
Takashi Iwaib3ac5632007-08-10 17:03:40 +02002301 int i;
2302
Takashi Iwai603c4012008-07-30 15:01:44 +02002303 for (i = 0; i < codec->cmd_cache.buf.used; i++, buffer++) {
Takashi Iwaib3ac5632007-08-10 17:03:40 +02002304 u32 key = buffer->key;
2305 if (!key)
2306 continue;
2307 snd_hda_codec_write(codec, get_cmd_cache_nid(key), 0,
2308 get_cmd_cache_cmd(key), buffer->val);
2309 }
2310}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002311EXPORT_SYMBOL_HDA(snd_hda_codec_resume_cache);
Takashi Iwaib3ac5632007-08-10 17:03:40 +02002312
2313/**
2314 * snd_hda_sequence_write_cache - sequence writes with caching
2315 * @codec: the HDA codec
2316 * @seq: VERB array to send
2317 *
2318 * Send the commands sequentially from the given array.
2319 * Thte commands are recorded on cache for power-save and resume.
2320 * The array must be terminated with NID=0.
2321 */
2322void snd_hda_sequence_write_cache(struct hda_codec *codec,
2323 const struct hda_verb *seq)
2324{
2325 for (; seq->nid; seq++)
2326 snd_hda_codec_write_cache(codec, seq->nid, 0, seq->verb,
2327 seq->param);
2328}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002329EXPORT_SYMBOL_HDA(snd_hda_sequence_write_cache);
Takashi Iwaicb53c622007-08-10 17:21:45 +02002330#endif /* SND_HDA_NEEDS_RESUME */
Takashi Iwaib3ac5632007-08-10 17:03:40 +02002331
Takashi Iwai54d17402005-11-21 16:33:22 +01002332/*
2333 * set power state of the codec
2334 */
2335static void hda_set_power_state(struct hda_codec *codec, hda_nid_t fg,
2336 unsigned int power_state)
2337{
Takashi Iwaicb53c622007-08-10 17:21:45 +02002338 hda_nid_t nid;
2339 int i;
Takashi Iwai54d17402005-11-21 16:33:22 +01002340
2341 snd_hda_codec_write(codec, fg, 0, AC_VERB_SET_POWER_STATE,
2342 power_state);
Marc Boucherd2595d82008-01-22 15:23:30 +01002343 msleep(10); /* partial workaround for "azx_get_response timeout" */
Takashi Iwai54d17402005-11-21 16:33:22 +01002344
Takashi Iwaicb53c622007-08-10 17:21:45 +02002345 nid = codec->start_nid;
2346 for (i = 0; i < codec->num_nodes; i++, nid++) {
Takashi Iwai7eba5c92007-11-14 14:53:42 +01002347 unsigned int wcaps = get_wcaps(codec, nid);
2348 if (wcaps & AC_WCAP_POWER) {
2349 unsigned int wid_type = (wcaps & AC_WCAP_TYPE) >>
2350 AC_WCAP_TYPE_SHIFT;
Takashi Iwaia3b48c82009-04-21 13:37:29 +02002351 if (power_state == AC_PWRST_D3 &&
2352 wid_type == AC_WID_PIN) {
Takashi Iwai7eba5c92007-11-14 14:53:42 +01002353 unsigned int pincap;
2354 /*
2355 * don't power down the widget if it controls
2356 * eapd and EAPD_BTLENABLE is set.
2357 */
Takashi Iwai14bafe32009-03-23 16:35:39 +01002358 pincap = snd_hda_query_pin_caps(codec, nid);
Takashi Iwai7eba5c92007-11-14 14:53:42 +01002359 if (pincap & AC_PINCAP_EAPD) {
2360 int eapd = snd_hda_codec_read(codec,
2361 nid, 0,
2362 AC_VERB_GET_EAPD_BTLENABLE, 0);
2363 eapd &= 0x02;
Takashi Iwaia3b48c82009-04-21 13:37:29 +02002364 if (eapd)
Takashi Iwai7eba5c92007-11-14 14:53:42 +01002365 continue;
2366 }
Takashi Iwai1194b5b2007-10-10 10:04:26 +02002367 }
Takashi Iwai54d17402005-11-21 16:33:22 +01002368 snd_hda_codec_write(codec, nid, 0,
2369 AC_VERB_SET_POWER_STATE,
2370 power_state);
Takashi Iwai1194b5b2007-10-10 10:04:26 +02002371 }
Takashi Iwai54d17402005-11-21 16:33:22 +01002372 }
2373
Takashi Iwaicb53c622007-08-10 17:21:45 +02002374 if (power_state == AC_PWRST_D0) {
2375 unsigned long end_time;
2376 int state;
Takashi Iwai54d17402005-11-21 16:33:22 +01002377 msleep(10);
Takashi Iwaicb53c622007-08-10 17:21:45 +02002378 /* wait until the codec reachs to D0 */
2379 end_time = jiffies + msecs_to_jiffies(500);
2380 do {
2381 state = snd_hda_codec_read(codec, fg, 0,
2382 AC_VERB_GET_POWER_STATE, 0);
2383 if (state == power_state)
2384 break;
2385 msleep(1);
2386 } while (time_after_eq(end_time, jiffies));
2387 }
Takashi Iwai54d17402005-11-21 16:33:22 +01002388}
2389
Takashi Iwai11aeff02008-07-30 15:01:46 +02002390#ifdef CONFIG_SND_HDA_HWDEP
2391/* execute additional init verbs */
2392static void hda_exec_init_verbs(struct hda_codec *codec)
2393{
2394 if (codec->init_verbs.list)
2395 snd_hda_sequence_write(codec, codec->init_verbs.list);
2396}
2397#else
2398static inline void hda_exec_init_verbs(struct hda_codec *codec) {}
2399#endif
2400
Takashi Iwaicb53c622007-08-10 17:21:45 +02002401#ifdef SND_HDA_NEEDS_RESUME
2402/*
2403 * call suspend and power-down; used both from PM and power-save
2404 */
2405static void hda_call_codec_suspend(struct hda_codec *codec)
2406{
2407 if (codec->patch_ops.suspend)
2408 codec->patch_ops.suspend(codec, PMSG_SUSPEND);
2409 hda_set_power_state(codec,
2410 codec->afg ? codec->afg : codec->mfg,
2411 AC_PWRST_D3);
2412#ifdef CONFIG_SND_HDA_POWER_SAVE
2413 cancel_delayed_work(&codec->power_work);
Takashi Iwai95e99fd2007-08-13 15:29:04 +02002414 codec->power_on = 0;
Takashi Iwaia221e282007-08-16 16:35:33 +02002415 codec->power_transition = 0;
Takashi Iwaicb53c622007-08-10 17:21:45 +02002416#endif
2417}
2418
2419/*
2420 * kick up codec; used both from PM and power-save
2421 */
2422static void hda_call_codec_resume(struct hda_codec *codec)
2423{
2424 hda_set_power_state(codec,
2425 codec->afg ? codec->afg : codec->mfg,
2426 AC_PWRST_D0);
Takashi Iwai3be14142009-02-20 14:11:16 +01002427 restore_pincfgs(codec); /* restore all current pin configs */
Takashi Iwai11aeff02008-07-30 15:01:46 +02002428 hda_exec_init_verbs(codec);
Takashi Iwaicb53c622007-08-10 17:21:45 +02002429 if (codec->patch_ops.resume)
2430 codec->patch_ops.resume(codec);
2431 else {
Takashi Iwai9d99f312007-08-14 15:15:52 +02002432 if (codec->patch_ops.init)
2433 codec->patch_ops.init(codec);
Takashi Iwaicb53c622007-08-10 17:21:45 +02002434 snd_hda_codec_resume_amp(codec);
2435 snd_hda_codec_resume_cache(codec);
2436 }
2437}
2438#endif /* SND_HDA_NEEDS_RESUME */
2439
Takashi Iwai54d17402005-11-21 16:33:22 +01002440
Linus Torvalds1da177e2005-04-16 15:20:36 -07002441/**
2442 * snd_hda_build_controls - build mixer controls
2443 * @bus: the BUS
2444 *
2445 * Creates mixer controls for each codec included in the bus.
2446 *
2447 * Returns 0 if successful, otherwise a negative error code.
2448 */
Takashi Iwai1289e9e2008-11-27 15:47:11 +01002449int /*__devinit*/ snd_hda_build_controls(struct hda_bus *bus)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002450{
Takashi Iwai0ba21762007-04-16 11:29:14 +02002451 struct hda_codec *codec;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002452
Takashi Iwai0ba21762007-04-16 11:29:14 +02002453 list_for_each_entry(codec, &bus->codec_list, list) {
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02002454 int err = snd_hda_codec_build_controls(codec);
Takashi Iwaif93d4612009-03-02 10:44:15 +01002455 if (err < 0) {
2456 printk(KERN_ERR "hda_codec: cannot build controls"
2457 "for #%d (error %d)\n", codec->addr, err);
2458 err = snd_hda_codec_reset(codec);
2459 if (err < 0) {
2460 printk(KERN_ERR
2461 "hda_codec: cannot revert codec\n");
2462 return err;
2463 }
2464 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002465 }
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02002466 return 0;
2467}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002468EXPORT_SYMBOL_HDA(snd_hda_build_controls);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002469
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02002470int snd_hda_codec_build_controls(struct hda_codec *codec)
2471{
2472 int err = 0;
Takashi Iwai11aeff02008-07-30 15:01:46 +02002473 hda_exec_init_verbs(codec);
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02002474 /* continue to initialize... */
2475 if (codec->patch_ops.init)
2476 err = codec->patch_ops.init(codec);
2477 if (!err && codec->patch_ops.build_controls)
2478 err = codec->patch_ops.build_controls(codec);
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02002479 if (err < 0)
2480 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002481 return 0;
2482}
2483
Linus Torvalds1da177e2005-04-16 15:20:36 -07002484/*
2485 * stream formats
2486 */
Takashi Iwaibefdf312005-08-22 13:57:55 +02002487struct hda_rate_tbl {
2488 unsigned int hz;
2489 unsigned int alsa_bits;
2490 unsigned int hda_fmt;
2491};
2492
2493static struct hda_rate_tbl rate_bits[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002494 /* rate in Hz, ALSA rate bitmask, HDA format value */
Nicolas Graziano9d8f53f2005-08-22 13:47:16 +02002495
2496 /* autodetected value used in snd_hda_query_supported_pcm */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002497 { 8000, SNDRV_PCM_RATE_8000, 0x0500 }, /* 1/6 x 48 */
2498 { 11025, SNDRV_PCM_RATE_11025, 0x4300 }, /* 1/4 x 44 */
2499 { 16000, SNDRV_PCM_RATE_16000, 0x0200 }, /* 1/3 x 48 */
2500 { 22050, SNDRV_PCM_RATE_22050, 0x4100 }, /* 1/2 x 44 */
2501 { 32000, SNDRV_PCM_RATE_32000, 0x0a00 }, /* 2/3 x 48 */
2502 { 44100, SNDRV_PCM_RATE_44100, 0x4000 }, /* 44 */
2503 { 48000, SNDRV_PCM_RATE_48000, 0x0000 }, /* 48 */
2504 { 88200, SNDRV_PCM_RATE_88200, 0x4800 }, /* 2 x 44 */
2505 { 96000, SNDRV_PCM_RATE_96000, 0x0800 }, /* 2 x 48 */
2506 { 176400, SNDRV_PCM_RATE_176400, 0x5800 },/* 4 x 44 */
2507 { 192000, SNDRV_PCM_RATE_192000, 0x1800 }, /* 4 x 48 */
Takashi Iwaia961f9f2007-04-12 13:08:09 +02002508#define AC_PAR_PCM_RATE_BITS 11
2509 /* up to bits 10, 384kHZ isn't supported properly */
2510
2511 /* not autodetected value */
2512 { 9600, SNDRV_PCM_RATE_KNOT, 0x0400 }, /* 1/5 x 48 */
Nicolas Graziano9d8f53f2005-08-22 13:47:16 +02002513
Takashi Iwaibefdf312005-08-22 13:57:55 +02002514 { 0 } /* terminator */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002515};
2516
2517/**
2518 * snd_hda_calc_stream_format - calculate format bitset
2519 * @rate: the sample rate
2520 * @channels: the number of channels
2521 * @format: the PCM format (SNDRV_PCM_FORMAT_XXX)
2522 * @maxbps: the max. bps
2523 *
2524 * Calculate the format bitset from the given rate, channels and th PCM format.
2525 *
2526 * Return zero if invalid.
2527 */
2528unsigned int snd_hda_calc_stream_format(unsigned int rate,
2529 unsigned int channels,
2530 unsigned int format,
2531 unsigned int maxbps)
2532{
2533 int i;
2534 unsigned int val = 0;
2535
Takashi Iwaibefdf312005-08-22 13:57:55 +02002536 for (i = 0; rate_bits[i].hz; i++)
2537 if (rate_bits[i].hz == rate) {
2538 val = rate_bits[i].hda_fmt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002539 break;
2540 }
Takashi Iwai0ba21762007-04-16 11:29:14 +02002541 if (!rate_bits[i].hz) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002542 snd_printdd("invalid rate %d\n", rate);
2543 return 0;
2544 }
2545
2546 if (channels == 0 || channels > 8) {
2547 snd_printdd("invalid channels %d\n", channels);
2548 return 0;
2549 }
2550 val |= channels - 1;
2551
2552 switch (snd_pcm_format_width(format)) {
2553 case 8: val |= 0x00; break;
2554 case 16: val |= 0x10; break;
2555 case 20:
2556 case 24:
2557 case 32:
2558 if (maxbps >= 32)
2559 val |= 0x40;
2560 else if (maxbps >= 24)
2561 val |= 0x30;
2562 else
2563 val |= 0x20;
2564 break;
2565 default:
Takashi Iwai0ba21762007-04-16 11:29:14 +02002566 snd_printdd("invalid format width %d\n",
2567 snd_pcm_format_width(format));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002568 return 0;
2569 }
2570
2571 return val;
2572}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002573EXPORT_SYMBOL_HDA(snd_hda_calc_stream_format);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002574
Takashi Iwai92c7c8a2009-03-24 07:32:14 +01002575static unsigned int get_pcm_param(struct hda_codec *codec, hda_nid_t nid)
2576{
2577 unsigned int val = 0;
2578 if (nid != codec->afg &&
2579 (get_wcaps(codec, nid) & AC_WCAP_FORMAT_OVRD))
2580 val = snd_hda_param_read(codec, nid, AC_PAR_PCM);
2581 if (!val || val == -1)
2582 val = snd_hda_param_read(codec, codec->afg, AC_PAR_PCM);
2583 if (!val || val == -1)
2584 return 0;
2585 return val;
2586}
2587
2588static unsigned int query_pcm_param(struct hda_codec *codec, hda_nid_t nid)
2589{
2590 return query_caps_hash(codec, nid, HDA_HASH_PARPCM_KEY(nid),
2591 get_pcm_param);
2592}
2593
2594static unsigned int get_stream_param(struct hda_codec *codec, hda_nid_t nid)
2595{
2596 unsigned int streams = snd_hda_param_read(codec, nid, AC_PAR_STREAM);
2597 if (!streams || streams == -1)
2598 streams = snd_hda_param_read(codec, codec->afg, AC_PAR_STREAM);
2599 if (!streams || streams == -1)
2600 return 0;
2601 return streams;
2602}
2603
2604static unsigned int query_stream_param(struct hda_codec *codec, hda_nid_t nid)
2605{
2606 return query_caps_hash(codec, nid, HDA_HASH_PARSTR_KEY(nid),
2607 get_stream_param);
2608}
2609
Linus Torvalds1da177e2005-04-16 15:20:36 -07002610/**
2611 * snd_hda_query_supported_pcm - query the supported PCM rates and formats
2612 * @codec: the HDA codec
2613 * @nid: NID to query
2614 * @ratesp: the pointer to store the detected rate bitflags
2615 * @formatsp: the pointer to store the detected formats
2616 * @bpsp: the pointer to store the detected format widths
2617 *
2618 * Queries the supported PCM rates and formats. The NULL @ratesp, @formatsp
2619 * or @bsps argument is ignored.
2620 *
2621 * Returns 0 if successful, otherwise a negative error code.
2622 */
Takashi Iwai986862bd2008-11-27 12:40:13 +01002623static int snd_hda_query_supported_pcm(struct hda_codec *codec, hda_nid_t nid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002624 u32 *ratesp, u64 *formatsp, unsigned int *bpsp)
2625{
Jaroslav Kyselaee504712009-03-17 14:30:31 +01002626 unsigned int i, val, wcaps;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002627
Jaroslav Kyselaee504712009-03-17 14:30:31 +01002628 wcaps = get_wcaps(codec, nid);
Takashi Iwai92c7c8a2009-03-24 07:32:14 +01002629 val = query_pcm_param(codec, nid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002630
2631 if (ratesp) {
2632 u32 rates = 0;
Takashi Iwaia961f9f2007-04-12 13:08:09 +02002633 for (i = 0; i < AC_PAR_PCM_RATE_BITS; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002634 if (val & (1 << i))
Takashi Iwaibefdf312005-08-22 13:57:55 +02002635 rates |= rate_bits[i].alsa_bits;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002636 }
Jaroslav Kyselaee504712009-03-17 14:30:31 +01002637 if (rates == 0) {
2638 snd_printk(KERN_ERR "hda_codec: rates == 0 "
2639 "(nid=0x%x, val=0x%x, ovrd=%i)\n",
2640 nid, val,
2641 (wcaps & AC_WCAP_FORMAT_OVRD) ? 1 : 0);
2642 return -EIO;
2643 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002644 *ratesp = rates;
2645 }
2646
2647 if (formatsp || bpsp) {
2648 u64 formats = 0;
Jaroslav Kyselaee504712009-03-17 14:30:31 +01002649 unsigned int streams, bps;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002650
Takashi Iwai92c7c8a2009-03-24 07:32:14 +01002651 streams = query_stream_param(codec, nid);
2652 if (!streams)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002653 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002654
2655 bps = 0;
2656 if (streams & AC_SUPFMT_PCM) {
2657 if (val & AC_SUPPCM_BITS_8) {
2658 formats |= SNDRV_PCM_FMTBIT_U8;
2659 bps = 8;
2660 }
2661 if (val & AC_SUPPCM_BITS_16) {
2662 formats |= SNDRV_PCM_FMTBIT_S16_LE;
2663 bps = 16;
2664 }
2665 if (wcaps & AC_WCAP_DIGITAL) {
2666 if (val & AC_SUPPCM_BITS_32)
2667 formats |= SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_LE;
2668 if (val & (AC_SUPPCM_BITS_20|AC_SUPPCM_BITS_24))
2669 formats |= SNDRV_PCM_FMTBIT_S32_LE;
2670 if (val & AC_SUPPCM_BITS_24)
2671 bps = 24;
2672 else if (val & AC_SUPPCM_BITS_20)
2673 bps = 20;
Takashi Iwai0ba21762007-04-16 11:29:14 +02002674 } else if (val & (AC_SUPPCM_BITS_20|AC_SUPPCM_BITS_24|
2675 AC_SUPPCM_BITS_32)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002676 formats |= SNDRV_PCM_FMTBIT_S32_LE;
2677 if (val & AC_SUPPCM_BITS_32)
2678 bps = 32;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002679 else if (val & AC_SUPPCM_BITS_24)
2680 bps = 24;
Nicolas Graziano33ef76512006-09-19 14:23:14 +02002681 else if (val & AC_SUPPCM_BITS_20)
2682 bps = 20;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002683 }
2684 }
Takashi Iwai0ba21762007-04-16 11:29:14 +02002685 else if (streams == AC_SUPFMT_FLOAT32) {
2686 /* should be exclusive */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002687 formats |= SNDRV_PCM_FMTBIT_FLOAT_LE;
2688 bps = 32;
Takashi Iwai0ba21762007-04-16 11:29:14 +02002689 } else if (streams == AC_SUPFMT_AC3) {
2690 /* should be exclusive */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002691 /* temporary hack: we have still no proper support
2692 * for the direct AC3 stream...
2693 */
2694 formats |= SNDRV_PCM_FMTBIT_U8;
2695 bps = 8;
2696 }
Jaroslav Kyselaee504712009-03-17 14:30:31 +01002697 if (formats == 0) {
2698 snd_printk(KERN_ERR "hda_codec: formats == 0 "
2699 "(nid=0x%x, val=0x%x, ovrd=%i, "
2700 "streams=0x%x)\n",
2701 nid, val,
2702 (wcaps & AC_WCAP_FORMAT_OVRD) ? 1 : 0,
2703 streams);
2704 return -EIO;
2705 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002706 if (formatsp)
2707 *formatsp = formats;
2708 if (bpsp)
2709 *bpsp = bps;
2710 }
2711
2712 return 0;
2713}
2714
2715/**
Takashi Iwai0ba21762007-04-16 11:29:14 +02002716 * snd_hda_is_supported_format - check whether the given node supports
2717 * the format val
Linus Torvalds1da177e2005-04-16 15:20:36 -07002718 *
2719 * Returns 1 if supported, 0 if not.
2720 */
2721int snd_hda_is_supported_format(struct hda_codec *codec, hda_nid_t nid,
2722 unsigned int format)
2723{
2724 int i;
2725 unsigned int val = 0, rate, stream;
2726
Takashi Iwai92c7c8a2009-03-24 07:32:14 +01002727 val = query_pcm_param(codec, nid);
2728 if (!val)
2729 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002730
2731 rate = format & 0xff00;
Takashi Iwaia961f9f2007-04-12 13:08:09 +02002732 for (i = 0; i < AC_PAR_PCM_RATE_BITS; i++)
Takashi Iwaibefdf312005-08-22 13:57:55 +02002733 if (rate_bits[i].hda_fmt == rate) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002734 if (val & (1 << i))
2735 break;
2736 return 0;
2737 }
Takashi Iwaia961f9f2007-04-12 13:08:09 +02002738 if (i >= AC_PAR_PCM_RATE_BITS)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002739 return 0;
2740
Takashi Iwai92c7c8a2009-03-24 07:32:14 +01002741 stream = query_stream_param(codec, nid);
2742 if (!stream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002743 return 0;
2744
2745 if (stream & AC_SUPFMT_PCM) {
2746 switch (format & 0xf0) {
2747 case 0x00:
Takashi Iwai0ba21762007-04-16 11:29:14 +02002748 if (!(val & AC_SUPPCM_BITS_8))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002749 return 0;
2750 break;
2751 case 0x10:
Takashi Iwai0ba21762007-04-16 11:29:14 +02002752 if (!(val & AC_SUPPCM_BITS_16))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002753 return 0;
2754 break;
2755 case 0x20:
Takashi Iwai0ba21762007-04-16 11:29:14 +02002756 if (!(val & AC_SUPPCM_BITS_20))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002757 return 0;
2758 break;
2759 case 0x30:
Takashi Iwai0ba21762007-04-16 11:29:14 +02002760 if (!(val & AC_SUPPCM_BITS_24))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002761 return 0;
2762 break;
2763 case 0x40:
Takashi Iwai0ba21762007-04-16 11:29:14 +02002764 if (!(val & AC_SUPPCM_BITS_32))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002765 return 0;
2766 break;
2767 default:
2768 return 0;
2769 }
2770 } else {
2771 /* FIXME: check for float32 and AC3? */
2772 }
2773
2774 return 1;
2775}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002776EXPORT_SYMBOL_HDA(snd_hda_is_supported_format);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002777
2778/*
2779 * PCM stuff
2780 */
2781static int hda_pcm_default_open_close(struct hda_pcm_stream *hinfo,
2782 struct hda_codec *codec,
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01002783 struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002784{
2785 return 0;
2786}
2787
2788static int hda_pcm_default_prepare(struct hda_pcm_stream *hinfo,
2789 struct hda_codec *codec,
2790 unsigned int stream_tag,
2791 unsigned int format,
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01002792 struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002793{
2794 snd_hda_codec_setup_stream(codec, hinfo->nid, stream_tag, 0, format);
2795 return 0;
2796}
2797
2798static int hda_pcm_default_cleanup(struct hda_pcm_stream *hinfo,
2799 struct hda_codec *codec,
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01002800 struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002801{
Takashi Iwai888afa12008-03-18 09:57:50 +01002802 snd_hda_codec_cleanup_stream(codec, hinfo->nid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002803 return 0;
2804}
2805
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02002806static int set_pcm_default_values(struct hda_codec *codec,
2807 struct hda_pcm_stream *info)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002808{
Jaroslav Kyselaee504712009-03-17 14:30:31 +01002809 int err;
2810
Takashi Iwai0ba21762007-04-16 11:29:14 +02002811 /* query support PCM information from the given NID */
2812 if (info->nid && (!info->rates || !info->formats)) {
Jaroslav Kyselaee504712009-03-17 14:30:31 +01002813 err = snd_hda_query_supported_pcm(codec, info->nid,
Takashi Iwai0ba21762007-04-16 11:29:14 +02002814 info->rates ? NULL : &info->rates,
2815 info->formats ? NULL : &info->formats,
2816 info->maxbps ? NULL : &info->maxbps);
Jaroslav Kyselaee504712009-03-17 14:30:31 +01002817 if (err < 0)
2818 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002819 }
2820 if (info->ops.open == NULL)
2821 info->ops.open = hda_pcm_default_open_close;
2822 if (info->ops.close == NULL)
2823 info->ops.close = hda_pcm_default_open_close;
2824 if (info->ops.prepare == NULL) {
Takashi Iwaida3cec32008-08-08 17:12:14 +02002825 if (snd_BUG_ON(!info->nid))
2826 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002827 info->ops.prepare = hda_pcm_default_prepare;
2828 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002829 if (info->ops.cleanup == NULL) {
Takashi Iwaida3cec32008-08-08 17:12:14 +02002830 if (snd_BUG_ON(!info->nid))
2831 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002832 info->ops.cleanup = hda_pcm_default_cleanup;
2833 }
2834 return 0;
2835}
2836
Takashi Iwai176d5332008-07-30 15:01:44 +02002837/*
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002838 * get the empty PCM device number to assign
2839 */
2840static int get_empty_pcm_device(struct hda_bus *bus, int type)
2841{
2842 static const char *dev_name[HDA_PCM_NTYPES] = {
2843 "Audio", "SPDIF", "HDMI", "Modem"
2844 };
2845 /* starting device index for each PCM type */
2846 static int dev_idx[HDA_PCM_NTYPES] = {
2847 [HDA_PCM_TYPE_AUDIO] = 0,
2848 [HDA_PCM_TYPE_SPDIF] = 1,
2849 [HDA_PCM_TYPE_HDMI] = 3,
2850 [HDA_PCM_TYPE_MODEM] = 6
2851 };
2852 /* normal audio device indices; not linear to keep compatibility */
2853 static int audio_idx[4] = { 0, 2, 4, 5 };
2854 int i, dev;
2855
2856 switch (type) {
2857 case HDA_PCM_TYPE_AUDIO:
2858 for (i = 0; i < ARRAY_SIZE(audio_idx); i++) {
2859 dev = audio_idx[i];
2860 if (!test_bit(dev, bus->pcm_dev_bits))
Takashi Iwai82ad39f2009-03-03 15:00:35 +01002861 goto ok;
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002862 }
Takashi Iwai82ad39f2009-03-03 15:00:35 +01002863 snd_printk(KERN_WARNING "Too many audio devices\n");
2864 return -EAGAIN;
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002865 case HDA_PCM_TYPE_SPDIF:
2866 case HDA_PCM_TYPE_HDMI:
2867 case HDA_PCM_TYPE_MODEM:
2868 dev = dev_idx[type];
2869 if (test_bit(dev, bus->pcm_dev_bits)) {
2870 snd_printk(KERN_WARNING "%s already defined\n",
2871 dev_name[type]);
2872 return -EAGAIN;
2873 }
2874 break;
2875 default:
2876 snd_printk(KERN_WARNING "Invalid PCM type %d\n", type);
2877 return -EINVAL;
2878 }
Takashi Iwai82ad39f2009-03-03 15:00:35 +01002879 ok:
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002880 set_bit(dev, bus->pcm_dev_bits);
2881 return dev;
2882}
2883
2884/*
Takashi Iwai176d5332008-07-30 15:01:44 +02002885 * attach a new PCM stream
2886 */
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002887static int snd_hda_attach_pcm(struct hda_codec *codec, struct hda_pcm *pcm)
Takashi Iwai176d5332008-07-30 15:01:44 +02002888{
Takashi Iwai33fa35e2008-11-06 16:50:40 +01002889 struct hda_bus *bus = codec->bus;
Takashi Iwai176d5332008-07-30 15:01:44 +02002890 struct hda_pcm_stream *info;
2891 int stream, err;
2892
Takashi Iwaib91f0802008-11-04 08:43:08 +01002893 if (snd_BUG_ON(!pcm->name))
Takashi Iwai176d5332008-07-30 15:01:44 +02002894 return -EINVAL;
2895 for (stream = 0; stream < 2; stream++) {
2896 info = &pcm->stream[stream];
2897 if (info->substreams) {
2898 err = set_pcm_default_values(codec, info);
2899 if (err < 0)
2900 return err;
2901 }
2902 }
Takashi Iwai33fa35e2008-11-06 16:50:40 +01002903 return bus->ops.attach_pcm(bus, codec, pcm);
Takashi Iwai176d5332008-07-30 15:01:44 +02002904}
2905
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002906/* assign all PCMs of the given codec */
2907int snd_hda_codec_build_pcms(struct hda_codec *codec)
2908{
2909 unsigned int pcm;
2910 int err;
2911
2912 if (!codec->num_pcms) {
2913 if (!codec->patch_ops.build_pcms)
2914 return 0;
2915 err = codec->patch_ops.build_pcms(codec);
Takashi Iwai6e655bf2009-03-02 10:46:03 +01002916 if (err < 0) {
2917 printk(KERN_ERR "hda_codec: cannot build PCMs"
2918 "for #%d (error %d)\n", codec->addr, err);
2919 err = snd_hda_codec_reset(codec);
2920 if (err < 0) {
2921 printk(KERN_ERR
2922 "hda_codec: cannot revert codec\n");
2923 return err;
2924 }
2925 }
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002926 }
2927 for (pcm = 0; pcm < codec->num_pcms; pcm++) {
2928 struct hda_pcm *cpcm = &codec->pcm_info[pcm];
2929 int dev;
2930
2931 if (!cpcm->stream[0].substreams && !cpcm->stream[1].substreams)
Takashi Iwai41b5b012009-01-20 18:21:23 +01002932 continue; /* no substreams assigned */
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002933
2934 if (!cpcm->pcm) {
2935 dev = get_empty_pcm_device(codec->bus, cpcm->pcm_type);
2936 if (dev < 0)
Takashi Iwai6e655bf2009-03-02 10:46:03 +01002937 continue; /* no fatal error */
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002938 cpcm->device = dev;
2939 err = snd_hda_attach_pcm(codec, cpcm);
Takashi Iwai6e655bf2009-03-02 10:46:03 +01002940 if (err < 0) {
2941 printk(KERN_ERR "hda_codec: cannot attach "
2942 "PCM stream %d for codec #%d\n",
2943 dev, codec->addr);
2944 continue; /* no fatal error */
2945 }
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002946 }
2947 }
2948 return 0;
2949}
2950
Linus Torvalds1da177e2005-04-16 15:20:36 -07002951/**
2952 * snd_hda_build_pcms - build PCM information
2953 * @bus: the BUS
2954 *
2955 * Create PCM information for each codec included in the bus.
2956 *
2957 * The build_pcms codec patch is requested to set up codec->num_pcms and
2958 * codec->pcm_info properly. The array is referred by the top-level driver
2959 * to create its PCM instances.
2960 * The allocated codec->pcm_info should be released in codec->patch_ops.free
2961 * callback.
2962 *
2963 * At least, substreams, channels_min and channels_max must be filled for
2964 * each stream. substreams = 0 indicates that the stream doesn't exist.
2965 * When rates and/or formats are zero, the supported values are queried
2966 * from the given nid. The nid is used also by the default ops.prepare
2967 * and ops.cleanup callbacks.
2968 *
2969 * The driver needs to call ops.open in its open callback. Similarly,
2970 * ops.close is supposed to be called in the close callback.
2971 * ops.prepare should be called in the prepare or hw_params callback
2972 * with the proper parameters for set up.
2973 * ops.cleanup should be called in hw_free for clean up of streams.
2974 *
2975 * This function returns 0 if successfull, or a negative error code.
2976 */
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002977int __devinit snd_hda_build_pcms(struct hda_bus *bus)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002978{
Takashi Iwai0ba21762007-04-16 11:29:14 +02002979 struct hda_codec *codec;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002980
Takashi Iwai0ba21762007-04-16 11:29:14 +02002981 list_for_each_entry(codec, &bus->codec_list, list) {
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002982 int err = snd_hda_codec_build_pcms(codec);
2983 if (err < 0)
2984 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002985 }
2986 return 0;
2987}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002988EXPORT_SYMBOL_HDA(snd_hda_build_pcms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002989
Linus Torvalds1da177e2005-04-16 15:20:36 -07002990/**
2991 * snd_hda_check_board_config - compare the current codec with the config table
2992 * @codec: the HDA codec
Takashi Iwaif5fcc132006-11-24 17:07:44 +01002993 * @num_configs: number of config enums
2994 * @models: array of model name strings
Linus Torvalds1da177e2005-04-16 15:20:36 -07002995 * @tbl: configuration table, terminated by null entries
2996 *
2997 * Compares the modelname or PCI subsystem id of the current codec with the
2998 * given configuration table. If a matching entry is found, returns its
2999 * config value (supposed to be 0 or positive).
3000 *
3001 * If no entries are matching, the function returns a negative value.
3002 */
Takashi Iwai12f288b2007-08-02 15:51:59 +02003003int snd_hda_check_board_config(struct hda_codec *codec,
3004 int num_configs, const char **models,
3005 const struct snd_pci_quirk *tbl)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003006{
Takashi Iwaif44ac832008-07-30 15:01:45 +02003007 if (codec->modelname && models) {
Takashi Iwaif5fcc132006-11-24 17:07:44 +01003008 int i;
3009 for (i = 0; i < num_configs; i++) {
3010 if (models[i] &&
Takashi Iwaif44ac832008-07-30 15:01:45 +02003011 !strcmp(codec->modelname, models[i])) {
Takashi Iwaif5fcc132006-11-24 17:07:44 +01003012 snd_printd(KERN_INFO "hda_codec: model '%s' is "
3013 "selected\n", models[i]);
3014 return i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003015 }
3016 }
3017 }
3018
Takashi Iwaif5fcc132006-11-24 17:07:44 +01003019 if (!codec->bus->pci || !tbl)
3020 return -1;
3021
3022 tbl = snd_pci_quirk_lookup(codec->bus->pci, tbl);
3023 if (!tbl)
3024 return -1;
3025 if (tbl->value >= 0 && tbl->value < num_configs) {
Takashi Iwai62cf8722008-05-20 12:15:15 +02003026#ifdef CONFIG_SND_DEBUG_VERBOSE
Takashi Iwaif5fcc132006-11-24 17:07:44 +01003027 char tmp[10];
3028 const char *model = NULL;
3029 if (models)
3030 model = models[tbl->value];
3031 if (!model) {
3032 sprintf(tmp, "#%d", tbl->value);
3033 model = tmp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003034 }
Takashi Iwaif5fcc132006-11-24 17:07:44 +01003035 snd_printdd(KERN_INFO "hda_codec: model '%s' is selected "
3036 "for config %x:%x (%s)\n",
3037 model, tbl->subvendor, tbl->subdevice,
3038 (tbl->name ? tbl->name : "Unknown device"));
3039#endif
3040 return tbl->value;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003041 }
3042 return -1;
3043}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003044EXPORT_SYMBOL_HDA(snd_hda_check_board_config);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003045
3046/**
Mauro Carvalho Chehab2eda3442008-08-11 10:18:39 +02003047 * snd_hda_check_board_codec_sid_config - compare the current codec
3048 subsystem ID with the
3049 config table
3050
3051 This is important for Gateway notebooks with SB450 HDA Audio
3052 where the vendor ID of the PCI device is:
3053 ATI Technologies Inc SB450 HDA Audio [1002:437b]
3054 and the vendor/subvendor are found only at the codec.
3055
3056 * @codec: the HDA codec
3057 * @num_configs: number of config enums
3058 * @models: array of model name strings
3059 * @tbl: configuration table, terminated by null entries
3060 *
3061 * Compares the modelname or PCI subsystem id of the current codec with the
3062 * given configuration table. If a matching entry is found, returns its
3063 * config value (supposed to be 0 or positive).
3064 *
3065 * If no entries are matching, the function returns a negative value.
3066 */
3067int snd_hda_check_board_codec_sid_config(struct hda_codec *codec,
3068 int num_configs, const char **models,
3069 const struct snd_pci_quirk *tbl)
3070{
3071 const struct snd_pci_quirk *q;
3072
3073 /* Search for codec ID */
3074 for (q = tbl; q->subvendor; q++) {
3075 unsigned long vendorid = (q->subdevice) | (q->subvendor << 16);
3076
3077 if (vendorid == codec->subsystem_id)
3078 break;
3079 }
3080
3081 if (!q->subvendor)
3082 return -1;
3083
3084 tbl = q;
3085
3086 if (tbl->value >= 0 && tbl->value < num_configs) {
3087#ifdef CONFIG_SND_DEBUG_DETECT
3088 char tmp[10];
3089 const char *model = NULL;
3090 if (models)
3091 model = models[tbl->value];
3092 if (!model) {
3093 sprintf(tmp, "#%d", tbl->value);
3094 model = tmp;
3095 }
3096 snd_printdd(KERN_INFO "hda_codec: model '%s' is selected "
3097 "for config %x:%x (%s)\n",
3098 model, tbl->subvendor, tbl->subdevice,
3099 (tbl->name ? tbl->name : "Unknown device"));
3100#endif
3101 return tbl->value;
3102 }
3103 return -1;
3104}
3105EXPORT_SYMBOL_HDA(snd_hda_check_board_codec_sid_config);
3106
3107/**
Linus Torvalds1da177e2005-04-16 15:20:36 -07003108 * snd_hda_add_new_ctls - create controls from the array
3109 * @codec: the HDA codec
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01003110 * @knew: the array of struct snd_kcontrol_new
Linus Torvalds1da177e2005-04-16 15:20:36 -07003111 *
3112 * This helper function creates and add new controls in the given array.
3113 * The array must be terminated with an empty entry as terminator.
3114 *
3115 * Returns 0 if successful, or a negative error code.
3116 */
Takashi Iwai12f288b2007-08-02 15:51:59 +02003117int snd_hda_add_new_ctls(struct hda_codec *codec, struct snd_kcontrol_new *knew)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003118{
Takashi Iwaicb53c622007-08-10 17:21:45 +02003119 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003120
3121 for (; knew->name; knew++) {
Takashi Iwai54d17402005-11-21 16:33:22 +01003122 struct snd_kcontrol *kctl;
3123 kctl = snd_ctl_new1(knew, codec);
Takashi Iwai0ba21762007-04-16 11:29:14 +02003124 if (!kctl)
Takashi Iwai54d17402005-11-21 16:33:22 +01003125 return -ENOMEM;
Takashi Iwaid13bd412008-07-30 15:01:45 +02003126 err = snd_hda_ctl_add(codec, kctl);
Takashi Iwai54d17402005-11-21 16:33:22 +01003127 if (err < 0) {
Takashi Iwai0ba21762007-04-16 11:29:14 +02003128 if (!codec->addr)
Takashi Iwai54d17402005-11-21 16:33:22 +01003129 return err;
3130 kctl = snd_ctl_new1(knew, codec);
Takashi Iwai0ba21762007-04-16 11:29:14 +02003131 if (!kctl)
Takashi Iwai54d17402005-11-21 16:33:22 +01003132 return -ENOMEM;
3133 kctl->id.device = codec->addr;
Takashi Iwaid13bd412008-07-30 15:01:45 +02003134 err = snd_hda_ctl_add(codec, kctl);
Takashi Iwai0ba21762007-04-16 11:29:14 +02003135 if (err < 0)
Takashi Iwai54d17402005-11-21 16:33:22 +01003136 return err;
3137 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003138 }
3139 return 0;
3140}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003141EXPORT_SYMBOL_HDA(snd_hda_add_new_ctls);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003142
Takashi Iwaicb53c622007-08-10 17:21:45 +02003143#ifdef CONFIG_SND_HDA_POWER_SAVE
3144static void hda_set_power_state(struct hda_codec *codec, hda_nid_t fg,
3145 unsigned int power_state);
3146
3147static void hda_power_work(struct work_struct *work)
3148{
3149 struct hda_codec *codec =
3150 container_of(work, struct hda_codec, power_work.work);
Takashi Iwai33fa35e2008-11-06 16:50:40 +01003151 struct hda_bus *bus = codec->bus;
Takashi Iwaicb53c622007-08-10 17:21:45 +02003152
Maxim Levitsky2e492462007-09-03 15:26:57 +02003153 if (!codec->power_on || codec->power_count) {
3154 codec->power_transition = 0;
Takashi Iwaicb53c622007-08-10 17:21:45 +02003155 return;
Maxim Levitsky2e492462007-09-03 15:26:57 +02003156 }
Takashi Iwaicb53c622007-08-10 17:21:45 +02003157
3158 hda_call_codec_suspend(codec);
Takashi Iwai33fa35e2008-11-06 16:50:40 +01003159 if (bus->ops.pm_notify)
3160 bus->ops.pm_notify(bus);
Takashi Iwaicb53c622007-08-10 17:21:45 +02003161}
3162
3163static void hda_keep_power_on(struct hda_codec *codec)
3164{
3165 codec->power_count++;
3166 codec->power_on = 1;
3167}
3168
3169void snd_hda_power_up(struct hda_codec *codec)
3170{
Takashi Iwai33fa35e2008-11-06 16:50:40 +01003171 struct hda_bus *bus = codec->bus;
3172
Takashi Iwaicb53c622007-08-10 17:21:45 +02003173 codec->power_count++;
Takashi Iwaia221e282007-08-16 16:35:33 +02003174 if (codec->power_on || codec->power_transition)
Takashi Iwaicb53c622007-08-10 17:21:45 +02003175 return;
3176
3177 codec->power_on = 1;
Takashi Iwai33fa35e2008-11-06 16:50:40 +01003178 if (bus->ops.pm_notify)
3179 bus->ops.pm_notify(bus);
Takashi Iwaicb53c622007-08-10 17:21:45 +02003180 hda_call_codec_resume(codec);
3181 cancel_delayed_work(&codec->power_work);
Takashi Iwaia221e282007-08-16 16:35:33 +02003182 codec->power_transition = 0;
Takashi Iwaicb53c622007-08-10 17:21:45 +02003183}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003184EXPORT_SYMBOL_HDA(snd_hda_power_up);
Takashi Iwai1289e9e2008-11-27 15:47:11 +01003185
3186#define power_save(codec) \
3187 ((codec)->bus->power_save ? *(codec)->bus->power_save : 0)
Takashi Iwaicb53c622007-08-10 17:21:45 +02003188
Takashi Iwaifee2fba2008-11-27 12:43:28 +01003189#define power_save(codec) \
3190 ((codec)->bus->power_save ? *(codec)->bus->power_save : 0)
3191
Takashi Iwaicb53c622007-08-10 17:21:45 +02003192void snd_hda_power_down(struct hda_codec *codec)
3193{
3194 --codec->power_count;
Takashi Iwaia221e282007-08-16 16:35:33 +02003195 if (!codec->power_on || codec->power_count || codec->power_transition)
Takashi Iwaicb53c622007-08-10 17:21:45 +02003196 return;
Takashi Iwaifee2fba2008-11-27 12:43:28 +01003197 if (power_save(codec)) {
Takashi Iwaia221e282007-08-16 16:35:33 +02003198 codec->power_transition = 1; /* avoid reentrance */
Takashi Iwaic107b412009-01-13 17:46:37 +01003199 queue_delayed_work(codec->bus->workq, &codec->power_work,
Takashi Iwaifee2fba2008-11-27 12:43:28 +01003200 msecs_to_jiffies(power_save(codec) * 1000));
Takashi Iwaia221e282007-08-16 16:35:33 +02003201 }
Takashi Iwaicb53c622007-08-10 17:21:45 +02003202}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003203EXPORT_SYMBOL_HDA(snd_hda_power_down);
Takashi Iwaicb53c622007-08-10 17:21:45 +02003204
3205int snd_hda_check_amp_list_power(struct hda_codec *codec,
3206 struct hda_loopback_check *check,
3207 hda_nid_t nid)
3208{
3209 struct hda_amp_list *p;
3210 int ch, v;
3211
3212 if (!check->amplist)
3213 return 0;
3214 for (p = check->amplist; p->nid; p++) {
3215 if (p->nid == nid)
3216 break;
3217 }
3218 if (!p->nid)
3219 return 0; /* nothing changed */
3220
3221 for (p = check->amplist; p->nid; p++) {
3222 for (ch = 0; ch < 2; ch++) {
3223 v = snd_hda_codec_amp_read(codec, p->nid, ch, p->dir,
3224 p->idx);
3225 if (!(v & HDA_AMP_MUTE) && v > 0) {
3226 if (!check->power_on) {
3227 check->power_on = 1;
3228 snd_hda_power_up(codec);
3229 }
3230 return 1;
3231 }
3232 }
3233 }
3234 if (check->power_on) {
3235 check->power_on = 0;
3236 snd_hda_power_down(codec);
3237 }
3238 return 0;
3239}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003240EXPORT_SYMBOL_HDA(snd_hda_check_amp_list_power);
Takashi Iwaicb53c622007-08-10 17:21:45 +02003241#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07003242
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01003243/*
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01003244 * Channel mode helper
3245 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003246int snd_hda_ch_mode_info(struct hda_codec *codec,
3247 struct snd_ctl_elem_info *uinfo,
3248 const struct hda_channel_mode *chmode,
3249 int num_chmodes)
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01003250{
3251 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
3252 uinfo->count = 1;
3253 uinfo->value.enumerated.items = num_chmodes;
3254 if (uinfo->value.enumerated.item >= num_chmodes)
3255 uinfo->value.enumerated.item = num_chmodes - 1;
3256 sprintf(uinfo->value.enumerated.name, "%dch",
3257 chmode[uinfo->value.enumerated.item].channels);
3258 return 0;
3259}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003260EXPORT_SYMBOL_HDA(snd_hda_ch_mode_info);
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01003261
Takashi Iwai0ba21762007-04-16 11:29:14 +02003262int snd_hda_ch_mode_get(struct hda_codec *codec,
3263 struct snd_ctl_elem_value *ucontrol,
3264 const struct hda_channel_mode *chmode,
3265 int num_chmodes,
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01003266 int max_channels)
3267{
3268 int i;
3269
3270 for (i = 0; i < num_chmodes; i++) {
3271 if (max_channels == chmode[i].channels) {
3272 ucontrol->value.enumerated.item[0] = i;
3273 break;
3274 }
3275 }
3276 return 0;
3277}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003278EXPORT_SYMBOL_HDA(snd_hda_ch_mode_get);
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01003279
Takashi Iwai0ba21762007-04-16 11:29:14 +02003280int snd_hda_ch_mode_put(struct hda_codec *codec,
3281 struct snd_ctl_elem_value *ucontrol,
3282 const struct hda_channel_mode *chmode,
3283 int num_chmodes,
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01003284 int *max_channelsp)
3285{
3286 unsigned int mode;
3287
3288 mode = ucontrol->value.enumerated.item[0];
Takashi Iwai68ea7b22007-11-15 15:54:38 +01003289 if (mode >= num_chmodes)
3290 return -EINVAL;
Takashi Iwai82beb8f2007-08-10 17:09:26 +02003291 if (*max_channelsp == chmode[mode].channels)
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01003292 return 0;
3293 /* change the current channel setting */
3294 *max_channelsp = chmode[mode].channels;
3295 if (chmode[mode].sequence)
Takashi Iwai82beb8f2007-08-10 17:09:26 +02003296 snd_hda_sequence_write_cache(codec, chmode[mode].sequence);
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01003297 return 1;
3298}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003299EXPORT_SYMBOL_HDA(snd_hda_ch_mode_put);
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01003300
Linus Torvalds1da177e2005-04-16 15:20:36 -07003301/*
3302 * input MUX helper
3303 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003304int snd_hda_input_mux_info(const struct hda_input_mux *imux,
3305 struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003306{
3307 unsigned int index;
3308
3309 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
3310 uinfo->count = 1;
3311 uinfo->value.enumerated.items = imux->num_items;
Takashi Iwai5513b0c2007-10-09 11:58:41 +02003312 if (!imux->num_items)
3313 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003314 index = uinfo->value.enumerated.item;
3315 if (index >= imux->num_items)
3316 index = imux->num_items - 1;
3317 strcpy(uinfo->value.enumerated.name, imux->items[index].label);
3318 return 0;
3319}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003320EXPORT_SYMBOL_HDA(snd_hda_input_mux_info);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003321
Takashi Iwai0ba21762007-04-16 11:29:14 +02003322int snd_hda_input_mux_put(struct hda_codec *codec,
3323 const struct hda_input_mux *imux,
3324 struct snd_ctl_elem_value *ucontrol,
3325 hda_nid_t nid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003326 unsigned int *cur_val)
3327{
3328 unsigned int idx;
3329
Takashi Iwai5513b0c2007-10-09 11:58:41 +02003330 if (!imux->num_items)
3331 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003332 idx = ucontrol->value.enumerated.item[0];
3333 if (idx >= imux->num_items)
3334 idx = imux->num_items - 1;
Takashi Iwai82beb8f2007-08-10 17:09:26 +02003335 if (*cur_val == idx)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003336 return 0;
Takashi Iwai82beb8f2007-08-10 17:09:26 +02003337 snd_hda_codec_write_cache(codec, nid, 0, AC_VERB_SET_CONNECT_SEL,
3338 imux->items[idx].index);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003339 *cur_val = idx;
3340 return 1;
3341}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003342EXPORT_SYMBOL_HDA(snd_hda_input_mux_put);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003343
3344
3345/*
3346 * Multi-channel / digital-out PCM helper functions
3347 */
3348
Takashi Iwai6b97eb42007-04-05 14:51:48 +02003349/* setup SPDIF output stream */
3350static void setup_dig_out_stream(struct hda_codec *codec, hda_nid_t nid,
3351 unsigned int stream_tag, unsigned int format)
3352{
3353 /* turn off SPDIF once; otherwise the IEC958 bits won't be updated */
Takashi Iwai2f728532008-09-25 16:32:41 +02003354 if (codec->spdif_status_reset && (codec->spdif_ctls & AC_DIG1_ENABLE))
3355 set_dig_out_convert(codec, nid,
3356 codec->spdif_ctls & ~AC_DIG1_ENABLE & 0xff,
3357 -1);
Takashi Iwai6b97eb42007-04-05 14:51:48 +02003358 snd_hda_codec_setup_stream(codec, nid, stream_tag, 0, format);
Takashi Iwai2f728532008-09-25 16:32:41 +02003359 if (codec->slave_dig_outs) {
3360 hda_nid_t *d;
3361 for (d = codec->slave_dig_outs; *d; d++)
3362 snd_hda_codec_setup_stream(codec, *d, stream_tag, 0,
3363 format);
Matthew Ranostayde51ca12008-09-07 14:31:40 -04003364 }
Takashi Iwai2f728532008-09-25 16:32:41 +02003365 /* turn on again (if needed) */
3366 if (codec->spdif_status_reset && (codec->spdif_ctls & AC_DIG1_ENABLE))
3367 set_dig_out_convert(codec, nid,
3368 codec->spdif_ctls & 0xff, -1);
3369}
Matthew Ranostayde51ca12008-09-07 14:31:40 -04003370
Takashi Iwai2f728532008-09-25 16:32:41 +02003371static void cleanup_dig_out_stream(struct hda_codec *codec, hda_nid_t nid)
3372{
3373 snd_hda_codec_cleanup_stream(codec, nid);
3374 if (codec->slave_dig_outs) {
3375 hda_nid_t *d;
3376 for (d = codec->slave_dig_outs; *d; d++)
3377 snd_hda_codec_cleanup_stream(codec, *d);
3378 }
Takashi Iwai6b97eb42007-04-05 14:51:48 +02003379}
3380
Linus Torvalds1da177e2005-04-16 15:20:36 -07003381/*
3382 * open the digital out in the exclusive mode
3383 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003384int snd_hda_multi_out_dig_open(struct hda_codec *codec,
3385 struct hda_multi_out *mout)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003386{
Ingo Molnar62932df2006-01-16 16:34:20 +01003387 mutex_lock(&codec->spdif_mutex);
Takashi Iwai5930ca42007-04-16 11:23:56 +02003388 if (mout->dig_out_used == HDA_DIG_ANALOG_DUP)
3389 /* already opened as analog dup; reset it once */
Takashi Iwai2f728532008-09-25 16:32:41 +02003390 cleanup_dig_out_stream(codec, mout->dig_out_nid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003391 mout->dig_out_used = HDA_DIG_EXCLUSIVE;
Ingo Molnar62932df2006-01-16 16:34:20 +01003392 mutex_unlock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003393 return 0;
3394}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003395EXPORT_SYMBOL_HDA(snd_hda_multi_out_dig_open);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003396
Takashi Iwai6b97eb42007-04-05 14:51:48 +02003397int snd_hda_multi_out_dig_prepare(struct hda_codec *codec,
3398 struct hda_multi_out *mout,
3399 unsigned int stream_tag,
3400 unsigned int format,
3401 struct snd_pcm_substream *substream)
3402{
3403 mutex_lock(&codec->spdif_mutex);
3404 setup_dig_out_stream(codec, mout->dig_out_nid, stream_tag, format);
3405 mutex_unlock(&codec->spdif_mutex);
3406 return 0;
3407}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003408EXPORT_SYMBOL_HDA(snd_hda_multi_out_dig_prepare);
Takashi Iwai6b97eb42007-04-05 14:51:48 +02003409
Takashi Iwai9411e212009-02-13 11:32:28 +01003410int snd_hda_multi_out_dig_cleanup(struct hda_codec *codec,
3411 struct hda_multi_out *mout)
3412{
3413 mutex_lock(&codec->spdif_mutex);
3414 cleanup_dig_out_stream(codec, mout->dig_out_nid);
3415 mutex_unlock(&codec->spdif_mutex);
3416 return 0;
3417}
3418EXPORT_SYMBOL_HDA(snd_hda_multi_out_dig_cleanup);
3419
Linus Torvalds1da177e2005-04-16 15:20:36 -07003420/*
3421 * release the digital out
3422 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003423int snd_hda_multi_out_dig_close(struct hda_codec *codec,
3424 struct hda_multi_out *mout)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003425{
Ingo Molnar62932df2006-01-16 16:34:20 +01003426 mutex_lock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003427 mout->dig_out_used = 0;
Ingo Molnar62932df2006-01-16 16:34:20 +01003428 mutex_unlock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003429 return 0;
3430}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003431EXPORT_SYMBOL_HDA(snd_hda_multi_out_dig_close);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003432
3433/*
3434 * set up more restrictions for analog out
3435 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003436int snd_hda_multi_out_analog_open(struct hda_codec *codec,
3437 struct hda_multi_out *mout,
Takashi Iwai9a081602008-02-12 18:37:26 +01003438 struct snd_pcm_substream *substream,
3439 struct hda_pcm_stream *hinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003440{
Takashi Iwai9a081602008-02-12 18:37:26 +01003441 struct snd_pcm_runtime *runtime = substream->runtime;
3442 runtime->hw.channels_max = mout->max_channels;
3443 if (mout->dig_out_nid) {
3444 if (!mout->analog_rates) {
3445 mout->analog_rates = hinfo->rates;
3446 mout->analog_formats = hinfo->formats;
3447 mout->analog_maxbps = hinfo->maxbps;
3448 } else {
3449 runtime->hw.rates = mout->analog_rates;
3450 runtime->hw.formats = mout->analog_formats;
3451 hinfo->maxbps = mout->analog_maxbps;
3452 }
3453 if (!mout->spdif_rates) {
3454 snd_hda_query_supported_pcm(codec, mout->dig_out_nid,
3455 &mout->spdif_rates,
3456 &mout->spdif_formats,
3457 &mout->spdif_maxbps);
3458 }
3459 mutex_lock(&codec->spdif_mutex);
3460 if (mout->share_spdif) {
3461 runtime->hw.rates &= mout->spdif_rates;
3462 runtime->hw.formats &= mout->spdif_formats;
3463 if (mout->spdif_maxbps < hinfo->maxbps)
3464 hinfo->maxbps = mout->spdif_maxbps;
3465 }
Frederik Deweerdteaa99852008-04-14 13:11:44 +02003466 mutex_unlock(&codec->spdif_mutex);
Takashi Iwai9a081602008-02-12 18:37:26 +01003467 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003468 return snd_pcm_hw_constraint_step(substream->runtime, 0,
3469 SNDRV_PCM_HW_PARAM_CHANNELS, 2);
3470}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003471EXPORT_SYMBOL_HDA(snd_hda_multi_out_analog_open);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003472
3473/*
3474 * set up the i/o for analog out
3475 * when the digital out is available, copy the front out to digital out, too.
3476 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003477int snd_hda_multi_out_analog_prepare(struct hda_codec *codec,
3478 struct hda_multi_out *mout,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003479 unsigned int stream_tag,
3480 unsigned int format,
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01003481 struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003482{
3483 hda_nid_t *nids = mout->dac_nids;
3484 int chs = substream->runtime->channels;
3485 int i;
3486
Ingo Molnar62932df2006-01-16 16:34:20 +01003487 mutex_lock(&codec->spdif_mutex);
Takashi Iwai9a081602008-02-12 18:37:26 +01003488 if (mout->dig_out_nid && mout->share_spdif &&
3489 mout->dig_out_used != HDA_DIG_EXCLUSIVE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003490 if (chs == 2 &&
Takashi Iwai0ba21762007-04-16 11:29:14 +02003491 snd_hda_is_supported_format(codec, mout->dig_out_nid,
3492 format) &&
3493 !(codec->spdif_status & IEC958_AES0_NONAUDIO)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003494 mout->dig_out_used = HDA_DIG_ANALOG_DUP;
Takashi Iwai6b97eb42007-04-05 14:51:48 +02003495 setup_dig_out_stream(codec, mout->dig_out_nid,
3496 stream_tag, format);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003497 } else {
3498 mout->dig_out_used = 0;
Takashi Iwai2f728532008-09-25 16:32:41 +02003499 cleanup_dig_out_stream(codec, mout->dig_out_nid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003500 }
3501 }
Ingo Molnar62932df2006-01-16 16:34:20 +01003502 mutex_unlock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003503
3504 /* front */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003505 snd_hda_codec_setup_stream(codec, nids[HDA_FRONT], stream_tag,
3506 0, format);
Takashi Iwaid29240c2007-10-26 12:35:56 +02003507 if (!mout->no_share_stream &&
3508 mout->hp_nid && mout->hp_nid != nids[HDA_FRONT])
Linus Torvalds1da177e2005-04-16 15:20:36 -07003509 /* headphone out will just decode front left/right (stereo) */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003510 snd_hda_codec_setup_stream(codec, mout->hp_nid, stream_tag,
3511 0, format);
Takashi Iwai82bc9552006-03-21 11:24:42 +01003512 /* extra outputs copied from front */
3513 for (i = 0; i < ARRAY_SIZE(mout->extra_out_nid); i++)
Takashi Iwaid29240c2007-10-26 12:35:56 +02003514 if (!mout->no_share_stream && mout->extra_out_nid[i])
Takashi Iwai82bc9552006-03-21 11:24:42 +01003515 snd_hda_codec_setup_stream(codec,
3516 mout->extra_out_nid[i],
3517 stream_tag, 0, format);
3518
Linus Torvalds1da177e2005-04-16 15:20:36 -07003519 /* surrounds */
3520 for (i = 1; i < mout->num_dacs; i++) {
Takashi Iwai4b3acaf2005-06-10 19:48:10 +02003521 if (chs >= (i + 1) * 2) /* independent out */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003522 snd_hda_codec_setup_stream(codec, nids[i], stream_tag,
3523 i * 2, format);
Takashi Iwaid29240c2007-10-26 12:35:56 +02003524 else if (!mout->no_share_stream) /* copy front */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003525 snd_hda_codec_setup_stream(codec, nids[i], stream_tag,
3526 0, format);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003527 }
3528 return 0;
3529}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003530EXPORT_SYMBOL_HDA(snd_hda_multi_out_analog_prepare);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003531
3532/*
3533 * clean up the setting for analog out
3534 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003535int snd_hda_multi_out_analog_cleanup(struct hda_codec *codec,
3536 struct hda_multi_out *mout)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003537{
3538 hda_nid_t *nids = mout->dac_nids;
3539 int i;
3540
3541 for (i = 0; i < mout->num_dacs; i++)
Takashi Iwai888afa12008-03-18 09:57:50 +01003542 snd_hda_codec_cleanup_stream(codec, nids[i]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003543 if (mout->hp_nid)
Takashi Iwai888afa12008-03-18 09:57:50 +01003544 snd_hda_codec_cleanup_stream(codec, mout->hp_nid);
Takashi Iwai82bc9552006-03-21 11:24:42 +01003545 for (i = 0; i < ARRAY_SIZE(mout->extra_out_nid); i++)
3546 if (mout->extra_out_nid[i])
Takashi Iwai888afa12008-03-18 09:57:50 +01003547 snd_hda_codec_cleanup_stream(codec,
3548 mout->extra_out_nid[i]);
Ingo Molnar62932df2006-01-16 16:34:20 +01003549 mutex_lock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003550 if (mout->dig_out_nid && mout->dig_out_used == HDA_DIG_ANALOG_DUP) {
Takashi Iwai2f728532008-09-25 16:32:41 +02003551 cleanup_dig_out_stream(codec, mout->dig_out_nid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003552 mout->dig_out_used = 0;
3553 }
Ingo Molnar62932df2006-01-16 16:34:20 +01003554 mutex_unlock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003555 return 0;
3556}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003557EXPORT_SYMBOL_HDA(snd_hda_multi_out_analog_cleanup);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003558
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003559/*
Wu Fengguang6b345002008-10-07 14:21:41 +08003560 * Helper for automatic pin configuration
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003561 */
Kailang Yangdf694da2005-12-05 19:42:22 +01003562
Takashi Iwai12f288b2007-08-02 15:51:59 +02003563static int is_in_nid_list(hda_nid_t nid, hda_nid_t *list)
Kailang Yangdf694da2005-12-05 19:42:22 +01003564{
3565 for (; *list; list++)
3566 if (*list == nid)
3567 return 1;
3568 return 0;
3569}
3570
Steve Longerbeam81937d32007-05-08 15:33:03 +02003571
3572/*
3573 * Sort an associated group of pins according to their sequence numbers.
3574 */
3575static void sort_pins_by_sequence(hda_nid_t * pins, short * sequences,
3576 int num_pins)
3577{
3578 int i, j;
3579 short seq;
3580 hda_nid_t nid;
3581
3582 for (i = 0; i < num_pins; i++) {
3583 for (j = i + 1; j < num_pins; j++) {
3584 if (sequences[i] > sequences[j]) {
3585 seq = sequences[i];
3586 sequences[i] = sequences[j];
3587 sequences[j] = seq;
3588 nid = pins[i];
3589 pins[i] = pins[j];
3590 pins[j] = nid;
3591 }
3592 }
3593 }
3594}
3595
3596
Takashi Iwai82bc9552006-03-21 11:24:42 +01003597/*
3598 * Parse all pin widgets and store the useful pin nids to cfg
3599 *
3600 * The number of line-outs or any primary output is stored in line_outs,
3601 * and the corresponding output pins are assigned to line_out_pins[],
3602 * in the order of front, rear, CLFE, side, ...
3603 *
3604 * If more extra outputs (speaker and headphone) are found, the pins are
Takashi Iwaieb06ed82006-09-20 17:10:27 +02003605 * assisnged to hp_pins[] and speaker_pins[], respectively. If no line-out jack
Takashi Iwai82bc9552006-03-21 11:24:42 +01003606 * is detected, one of speaker of HP pins is assigned as the primary
3607 * output, i.e. to line_out_pins[0]. So, line_outs is always positive
3608 * if any analog output exists.
3609 *
3610 * The analog input pins are assigned to input_pins array.
3611 * The digital input/output pins are assigned to dig_in_pin and dig_out_pin,
3612 * respectively.
3613 */
Takashi Iwai12f288b2007-08-02 15:51:59 +02003614int snd_hda_parse_pin_def_config(struct hda_codec *codec,
3615 struct auto_pin_cfg *cfg,
3616 hda_nid_t *ignore_nids)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003617{
Takashi Iwai0ef6ce72008-01-22 15:35:37 +01003618 hda_nid_t nid, end_nid;
Steve Longerbeam81937d32007-05-08 15:33:03 +02003619 short seq, assoc_line_out, assoc_speaker;
3620 short sequences_line_out[ARRAY_SIZE(cfg->line_out_pins)];
3621 short sequences_speaker[ARRAY_SIZE(cfg->speaker_pins)];
Takashi Iwaif889fa92007-10-31 15:49:32 +01003622 short sequences_hp[ARRAY_SIZE(cfg->hp_pins)];
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003623
3624 memset(cfg, 0, sizeof(*cfg));
3625
Steve Longerbeam81937d32007-05-08 15:33:03 +02003626 memset(sequences_line_out, 0, sizeof(sequences_line_out));
3627 memset(sequences_speaker, 0, sizeof(sequences_speaker));
Takashi Iwaif889fa92007-10-31 15:49:32 +01003628 memset(sequences_hp, 0, sizeof(sequences_hp));
Steve Longerbeam81937d32007-05-08 15:33:03 +02003629 assoc_line_out = assoc_speaker = 0;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003630
Takashi Iwai0ef6ce72008-01-22 15:35:37 +01003631 end_nid = codec->start_nid + codec->num_nodes;
3632 for (nid = codec->start_nid; nid < end_nid; nid++) {
Takashi Iwai54d17402005-11-21 16:33:22 +01003633 unsigned int wid_caps = get_wcaps(codec, nid);
Takashi Iwai0ba21762007-04-16 11:29:14 +02003634 unsigned int wid_type =
3635 (wid_caps & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003636 unsigned int def_conf;
3637 short assoc, loc;
3638
3639 /* read all default configuration for pin complex */
3640 if (wid_type != AC_WID_PIN)
3641 continue;
Kailang Yangdf694da2005-12-05 19:42:22 +01003642 /* ignore the given nids (e.g. pc-beep returns error) */
3643 if (ignore_nids && is_in_nid_list(nid, ignore_nids))
3644 continue;
3645
Takashi Iwaic17a1ab2009-02-23 09:28:12 +01003646 def_conf = snd_hda_codec_get_pincfg(codec, nid);
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003647 if (get_defcfg_connect(def_conf) == AC_JACK_PORT_NONE)
3648 continue;
3649 loc = get_defcfg_location(def_conf);
3650 switch (get_defcfg_device(def_conf)) {
3651 case AC_JACK_LINE_OUT:
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003652 seq = get_defcfg_sequence(def_conf);
3653 assoc = get_defcfg_association(def_conf);
Matthew Ranostay90da78b2008-01-24 11:48:01 +01003654
3655 if (!(wid_caps & AC_WCAP_STEREO))
3656 if (!cfg->mono_out_pin)
3657 cfg->mono_out_pin = nid;
Takashi Iwai0ba21762007-04-16 11:29:14 +02003658 if (!assoc)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003659 continue;
Takashi Iwai0ba21762007-04-16 11:29:14 +02003660 if (!assoc_line_out)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003661 assoc_line_out = assoc;
3662 else if (assoc_line_out != assoc)
3663 continue;
3664 if (cfg->line_outs >= ARRAY_SIZE(cfg->line_out_pins))
3665 continue;
3666 cfg->line_out_pins[cfg->line_outs] = nid;
Steve Longerbeam81937d32007-05-08 15:33:03 +02003667 sequences_line_out[cfg->line_outs] = seq;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003668 cfg->line_outs++;
3669 break;
Takashi Iwai8d88bc32005-11-17 11:09:23 +01003670 case AC_JACK_SPEAKER:
Steve Longerbeam81937d32007-05-08 15:33:03 +02003671 seq = get_defcfg_sequence(def_conf);
3672 assoc = get_defcfg_association(def_conf);
3673 if (! assoc)
3674 continue;
3675 if (! assoc_speaker)
3676 assoc_speaker = assoc;
3677 else if (assoc_speaker != assoc)
3678 continue;
Takashi Iwai82bc9552006-03-21 11:24:42 +01003679 if (cfg->speaker_outs >= ARRAY_SIZE(cfg->speaker_pins))
3680 continue;
3681 cfg->speaker_pins[cfg->speaker_outs] = nid;
Steve Longerbeam81937d32007-05-08 15:33:03 +02003682 sequences_speaker[cfg->speaker_outs] = seq;
Takashi Iwai82bc9552006-03-21 11:24:42 +01003683 cfg->speaker_outs++;
Takashi Iwai8d88bc32005-11-17 11:09:23 +01003684 break;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003685 case AC_JACK_HP_OUT:
Takashi Iwaif889fa92007-10-31 15:49:32 +01003686 seq = get_defcfg_sequence(def_conf);
3687 assoc = get_defcfg_association(def_conf);
Takashi Iwaieb06ed82006-09-20 17:10:27 +02003688 if (cfg->hp_outs >= ARRAY_SIZE(cfg->hp_pins))
3689 continue;
3690 cfg->hp_pins[cfg->hp_outs] = nid;
Takashi Iwaif889fa92007-10-31 15:49:32 +01003691 sequences_hp[cfg->hp_outs] = (assoc << 4) | seq;
Takashi Iwaieb06ed82006-09-20 17:10:27 +02003692 cfg->hp_outs++;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003693 break;
Takashi Iwai314634b2006-09-21 11:56:18 +02003694 case AC_JACK_MIC_IN: {
3695 int preferred, alt;
3696 if (loc == AC_JACK_LOC_FRONT) {
3697 preferred = AUTO_PIN_FRONT_MIC;
3698 alt = AUTO_PIN_MIC;
3699 } else {
3700 preferred = AUTO_PIN_MIC;
3701 alt = AUTO_PIN_FRONT_MIC;
3702 }
3703 if (!cfg->input_pins[preferred])
3704 cfg->input_pins[preferred] = nid;
3705 else if (!cfg->input_pins[alt])
3706 cfg->input_pins[alt] = nid;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003707 break;
Takashi Iwai314634b2006-09-21 11:56:18 +02003708 }
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003709 case AC_JACK_LINE_IN:
3710 if (loc == AC_JACK_LOC_FRONT)
3711 cfg->input_pins[AUTO_PIN_FRONT_LINE] = nid;
3712 else
3713 cfg->input_pins[AUTO_PIN_LINE] = nid;
3714 break;
3715 case AC_JACK_CD:
3716 cfg->input_pins[AUTO_PIN_CD] = nid;
3717 break;
3718 case AC_JACK_AUX:
3719 cfg->input_pins[AUTO_PIN_AUX] = nid;
3720 break;
3721 case AC_JACK_SPDIF_OUT:
Takashi Iwai1b52ae72009-01-20 17:17:29 +01003722 case AC_JACK_DIG_OTHER_OUT:
Takashi Iwai0852d7a2009-02-11 11:35:15 +01003723 if (cfg->dig_outs >= ARRAY_SIZE(cfg->dig_out_pins))
3724 continue;
3725 cfg->dig_out_pins[cfg->dig_outs] = nid;
3726 cfg->dig_out_type[cfg->dig_outs] =
3727 (loc == AC_JACK_LOC_HDMI) ?
3728 HDA_PCM_TYPE_HDMI : HDA_PCM_TYPE_SPDIF;
3729 cfg->dig_outs++;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003730 break;
3731 case AC_JACK_SPDIF_IN:
Takashi Iwai1b52ae72009-01-20 17:17:29 +01003732 case AC_JACK_DIG_OTHER_IN:
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003733 cfg->dig_in_pin = nid;
Takashi Iwai2297bd62009-01-20 18:24:13 +01003734 if (loc == AC_JACK_LOC_HDMI)
3735 cfg->dig_in_type = HDA_PCM_TYPE_HDMI;
3736 else
3737 cfg->dig_in_type = HDA_PCM_TYPE_SPDIF;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003738 break;
3739 }
3740 }
3741
Takashi Iwai5832fcf2008-02-12 18:30:12 +01003742 /* FIX-UP:
3743 * If no line-out is defined but multiple HPs are found,
3744 * some of them might be the real line-outs.
3745 */
3746 if (!cfg->line_outs && cfg->hp_outs > 1) {
3747 int i = 0;
3748 while (i < cfg->hp_outs) {
3749 /* The real HPs should have the sequence 0x0f */
3750 if ((sequences_hp[i] & 0x0f) == 0x0f) {
3751 i++;
3752 continue;
3753 }
3754 /* Move it to the line-out table */
3755 cfg->line_out_pins[cfg->line_outs] = cfg->hp_pins[i];
3756 sequences_line_out[cfg->line_outs] = sequences_hp[i];
3757 cfg->line_outs++;
3758 cfg->hp_outs--;
3759 memmove(cfg->hp_pins + i, cfg->hp_pins + i + 1,
3760 sizeof(cfg->hp_pins[0]) * (cfg->hp_outs - i));
3761 memmove(sequences_hp + i - 1, sequences_hp + i,
3762 sizeof(sequences_hp[0]) * (cfg->hp_outs - i));
3763 }
3764 }
3765
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003766 /* sort by sequence */
Steve Longerbeam81937d32007-05-08 15:33:03 +02003767 sort_pins_by_sequence(cfg->line_out_pins, sequences_line_out,
3768 cfg->line_outs);
3769 sort_pins_by_sequence(cfg->speaker_pins, sequences_speaker,
3770 cfg->speaker_outs);
Takashi Iwaif889fa92007-10-31 15:49:32 +01003771 sort_pins_by_sequence(cfg->hp_pins, sequences_hp,
3772 cfg->hp_outs);
Steve Longerbeam81937d32007-05-08 15:33:03 +02003773
Takashi Iwaif889fa92007-10-31 15:49:32 +01003774 /* if we have only one mic, make it AUTO_PIN_MIC */
3775 if (!cfg->input_pins[AUTO_PIN_MIC] &&
3776 cfg->input_pins[AUTO_PIN_FRONT_MIC]) {
3777 cfg->input_pins[AUTO_PIN_MIC] =
3778 cfg->input_pins[AUTO_PIN_FRONT_MIC];
3779 cfg->input_pins[AUTO_PIN_FRONT_MIC] = 0;
3780 }
3781 /* ditto for line-in */
3782 if (!cfg->input_pins[AUTO_PIN_LINE] &&
3783 cfg->input_pins[AUTO_PIN_FRONT_LINE]) {
3784 cfg->input_pins[AUTO_PIN_LINE] =
3785 cfg->input_pins[AUTO_PIN_FRONT_LINE];
3786 cfg->input_pins[AUTO_PIN_FRONT_LINE] = 0;
3787 }
3788
Steve Longerbeam81937d32007-05-08 15:33:03 +02003789 /*
3790 * FIX-UP: if no line-outs are detected, try to use speaker or HP pin
3791 * as a primary output
3792 */
3793 if (!cfg->line_outs) {
3794 if (cfg->speaker_outs) {
3795 cfg->line_outs = cfg->speaker_outs;
3796 memcpy(cfg->line_out_pins, cfg->speaker_pins,
3797 sizeof(cfg->speaker_pins));
3798 cfg->speaker_outs = 0;
3799 memset(cfg->speaker_pins, 0, sizeof(cfg->speaker_pins));
3800 cfg->line_out_type = AUTO_PIN_SPEAKER_OUT;
3801 } else if (cfg->hp_outs) {
3802 cfg->line_outs = cfg->hp_outs;
3803 memcpy(cfg->line_out_pins, cfg->hp_pins,
3804 sizeof(cfg->hp_pins));
3805 cfg->hp_outs = 0;
3806 memset(cfg->hp_pins, 0, sizeof(cfg->hp_pins));
3807 cfg->line_out_type = AUTO_PIN_HP_OUT;
3808 }
3809 }
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003810
Takashi Iwaicb8e2f82005-07-29 11:54:32 +02003811 /* Reorder the surround channels
3812 * ALSA sequence is front/surr/clfe/side
3813 * HDA sequence is:
3814 * 4-ch: front/surr => OK as it is
3815 * 6-ch: front/clfe/surr
Takashi Iwai9422db42007-04-20 16:11:43 +02003816 * 8-ch: front/clfe/rear/side|fc
Takashi Iwaicb8e2f82005-07-29 11:54:32 +02003817 */
3818 switch (cfg->line_outs) {
3819 case 3:
Takashi Iwaicb8e2f82005-07-29 11:54:32 +02003820 case 4:
3821 nid = cfg->line_out_pins[1];
Takashi Iwai9422db42007-04-20 16:11:43 +02003822 cfg->line_out_pins[1] = cfg->line_out_pins[2];
Takashi Iwaicb8e2f82005-07-29 11:54:32 +02003823 cfg->line_out_pins[2] = nid;
3824 break;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003825 }
3826
Takashi Iwai82bc9552006-03-21 11:24:42 +01003827 /*
3828 * debug prints of the parsed results
3829 */
3830 snd_printd("autoconfig: line_outs=%d (0x%x/0x%x/0x%x/0x%x/0x%x)\n",
3831 cfg->line_outs, cfg->line_out_pins[0], cfg->line_out_pins[1],
3832 cfg->line_out_pins[2], cfg->line_out_pins[3],
3833 cfg->line_out_pins[4]);
3834 snd_printd(" speaker_outs=%d (0x%x/0x%x/0x%x/0x%x/0x%x)\n",
3835 cfg->speaker_outs, cfg->speaker_pins[0],
3836 cfg->speaker_pins[1], cfg->speaker_pins[2],
3837 cfg->speaker_pins[3], cfg->speaker_pins[4]);
Takashi Iwaieb06ed82006-09-20 17:10:27 +02003838 snd_printd(" hp_outs=%d (0x%x/0x%x/0x%x/0x%x/0x%x)\n",
3839 cfg->hp_outs, cfg->hp_pins[0],
3840 cfg->hp_pins[1], cfg->hp_pins[2],
3841 cfg->hp_pins[3], cfg->hp_pins[4]);
Matthew Ranostay90da78b2008-01-24 11:48:01 +01003842 snd_printd(" mono: mono_out=0x%x\n", cfg->mono_out_pin);
Takashi Iwai0852d7a2009-02-11 11:35:15 +01003843 if (cfg->dig_outs)
3844 snd_printd(" dig-out=0x%x/0x%x\n",
3845 cfg->dig_out_pins[0], cfg->dig_out_pins[1]);
Takashi Iwai82bc9552006-03-21 11:24:42 +01003846 snd_printd(" inputs: mic=0x%x, fmic=0x%x, line=0x%x, fline=0x%x,"
3847 " cd=0x%x, aux=0x%x\n",
3848 cfg->input_pins[AUTO_PIN_MIC],
3849 cfg->input_pins[AUTO_PIN_FRONT_MIC],
3850 cfg->input_pins[AUTO_PIN_LINE],
3851 cfg->input_pins[AUTO_PIN_FRONT_LINE],
3852 cfg->input_pins[AUTO_PIN_CD],
3853 cfg->input_pins[AUTO_PIN_AUX]);
Takashi Iwai32d2c7f2009-02-11 11:33:13 +01003854 if (cfg->dig_in_pin)
Takashi Iwai89ce9e82009-01-20 17:15:57 +01003855 snd_printd(" dig-in=0x%x\n", cfg->dig_in_pin);
Takashi Iwai82bc9552006-03-21 11:24:42 +01003856
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003857 return 0;
3858}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003859EXPORT_SYMBOL_HDA(snd_hda_parse_pin_def_config);
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003860
Takashi Iwai4a471b72005-12-07 13:56:29 +01003861/* labels for input pins */
3862const char *auto_pin_cfg_labels[AUTO_PIN_LAST] = {
3863 "Mic", "Front Mic", "Line", "Front Line", "CD", "Aux"
3864};
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003865EXPORT_SYMBOL_HDA(auto_pin_cfg_labels);
Takashi Iwai4a471b72005-12-07 13:56:29 +01003866
3867
Linus Torvalds1da177e2005-04-16 15:20:36 -07003868#ifdef CONFIG_PM
3869/*
3870 * power management
3871 */
3872
3873/**
3874 * snd_hda_suspend - suspend the codecs
3875 * @bus: the HDA bus
3876 * @state: suspsend state
3877 *
3878 * Returns 0 if successful.
3879 */
3880int snd_hda_suspend(struct hda_bus *bus, pm_message_t state)
3881{
Takashi Iwai0ba21762007-04-16 11:29:14 +02003882 struct hda_codec *codec;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003883
Takashi Iwai0ba21762007-04-16 11:29:14 +02003884 list_for_each_entry(codec, &bus->codec_list, list) {
Takashi Iwai0b7a2e92007-08-14 15:18:26 +02003885#ifdef CONFIG_SND_HDA_POWER_SAVE
3886 if (!codec->power_on)
3887 continue;
3888#endif
Takashi Iwaicb53c622007-08-10 17:21:45 +02003889 hda_call_codec_suspend(codec);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003890 }
3891 return 0;
3892}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003893EXPORT_SYMBOL_HDA(snd_hda_suspend);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003894
3895/**
3896 * snd_hda_resume - resume the codecs
3897 * @bus: the HDA bus
Linus Torvalds1da177e2005-04-16 15:20:36 -07003898 *
3899 * Returns 0 if successful.
Takashi Iwaicb53c622007-08-10 17:21:45 +02003900 *
3901 * This fucntion is defined only when POWER_SAVE isn't set.
3902 * In the power-save mode, the codec is resumed dynamically.
Linus Torvalds1da177e2005-04-16 15:20:36 -07003903 */
3904int snd_hda_resume(struct hda_bus *bus)
3905{
Takashi Iwai0ba21762007-04-16 11:29:14 +02003906 struct hda_codec *codec;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003907
Takashi Iwai0ba21762007-04-16 11:29:14 +02003908 list_for_each_entry(codec, &bus->codec_list, list) {
Maxim Levitskyd804ad92007-09-03 15:28:04 +02003909 if (snd_hda_codec_needs_resume(codec))
3910 hda_call_codec_resume(codec);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003911 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003912 return 0;
3913}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003914EXPORT_SYMBOL_HDA(snd_hda_resume);
Takashi Iwai1289e9e2008-11-27 15:47:11 +01003915#endif /* CONFIG_PM */
Takashi Iwaib2e18592008-07-30 15:01:44 +02003916
3917/*
3918 * generic arrays
3919 */
3920
3921/* get a new element from the given array
3922 * if it exceeds the pre-allocated array size, re-allocate the array
3923 */
3924void *snd_array_new(struct snd_array *array)
3925{
3926 if (array->used >= array->alloced) {
3927 int num = array->alloced + array->alloc_align;
Takashi Iwaib910d9a2008-11-07 00:26:52 +01003928 void *nlist;
3929 if (snd_BUG_ON(num >= 4096))
3930 return NULL;
3931 nlist = kcalloc(num + 1, array->elem_size, GFP_KERNEL);
Takashi Iwaib2e18592008-07-30 15:01:44 +02003932 if (!nlist)
3933 return NULL;
3934 if (array->list) {
3935 memcpy(nlist, array->list,
3936 array->elem_size * array->alloced);
3937 kfree(array->list);
3938 }
3939 array->list = nlist;
3940 array->alloced = num;
3941 }
Takashi Iwaif43aa022008-11-10 16:24:26 +01003942 return snd_array_elem(array, array->used++);
Takashi Iwaib2e18592008-07-30 15:01:44 +02003943}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003944EXPORT_SYMBOL_HDA(snd_array_new);
Takashi Iwaib2e18592008-07-30 15:01:44 +02003945
3946/* free the given array elements */
3947void snd_array_free(struct snd_array *array)
3948{
3949 kfree(array->list);
3950 array->used = 0;
3951 array->alloced = 0;
3952 array->list = NULL;
3953}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003954EXPORT_SYMBOL_HDA(snd_array_free);
Takashi Iwaib2022262008-11-21 21:24:03 +01003955
3956/*
3957 * used by hda_proc.c and hda_eld.c
3958 */
3959void snd_print_pcm_rates(int pcm, char *buf, int buflen)
3960{
3961 static unsigned int rates[] = {
3962 8000, 11025, 16000, 22050, 32000, 44100, 48000, 88200,
3963 96000, 176400, 192000, 384000
3964 };
3965 int i, j;
3966
3967 for (i = 0, j = 0; i < ARRAY_SIZE(rates); i++)
3968 if (pcm & (1 << i))
3969 j += snprintf(buf + j, buflen - j, " %d", rates[i]);
3970
3971 buf[j] = '\0'; /* necessary when j == 0 */
3972}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003973EXPORT_SYMBOL_HDA(snd_print_pcm_rates);
Takashi Iwaib2022262008-11-21 21:24:03 +01003974
3975void snd_print_pcm_bits(int pcm, char *buf, int buflen)
3976{
3977 static unsigned int bits[] = { 8, 16, 20, 24, 32 };
3978 int i, j;
3979
3980 for (i = 0, j = 0; i < ARRAY_SIZE(bits); i++)
3981 if (pcm & (AC_SUPPCM_BITS_8 << i))
3982 j += snprintf(buf + j, buflen - j, " %d", bits[i]);
3983
3984 buf[j] = '\0'; /* necessary when j == 0 */
3985}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003986EXPORT_SYMBOL_HDA(snd_print_pcm_bits);
Takashi Iwai1289e9e2008-11-27 15:47:11 +01003987
3988MODULE_DESCRIPTION("HDA codec core");
3989MODULE_LICENSE("GPL");