blob: 8820faf6c9d82cd556c7de92ec55cb11efa56ebd [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * Universal Interface for Intel High Definition Audio Codec
3 *
4 * Copyright (c) 2004 Takashi Iwai <tiwai@suse.de>
5 *
6 *
7 * This driver is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This driver is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21
Linus Torvalds1da177e2005-04-16 15:20:36 -070022#include <linux/init.h>
23#include <linux/delay.h>
24#include <linux/slab.h>
25#include <linux/pci.h>
Ingo Molnar62932df2006-01-16 16:34:20 +010026#include <linux/mutex.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070027#include <sound/core.h>
28#include "hda_codec.h"
29#include <sound/asoundef.h>
Jaroslav Kysela302e9c52006-07-05 17:39:49 +020030#include <sound/tlv.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070031#include <sound/initval.h>
32#include "hda_local.h"
Takashi Iwai28073142007-07-27 18:58:06 +020033#include <sound/hda_hwdep.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070034
Linus Torvalds1da177e2005-04-16 15:20:36 -070035/*
36 * vendor / preset table
37 */
38
39struct hda_vendor_id {
40 unsigned int id;
41 const char *name;
42};
43
44/* codec vendor labels */
45static struct hda_vendor_id hda_vendor_ids[] = {
Takashi Iwaic8cd1282008-02-13 16:59:29 +010046 { 0x1002, "ATI" },
Takashi Iwaia9226252006-09-17 22:05:54 +020047 { 0x1057, "Motorola" },
Takashi Iwaic8cd1282008-02-13 16:59:29 +010048 { 0x1095, "Silicon Image" },
Takashi Iwai31117b72008-12-16 14:43:21 +010049 { 0x10de, "Nvidia" },
Takashi Iwaic8cd1282008-02-13 16:59:29 +010050 { 0x10ec, "Realtek" },
Joseph Chanc577b8a2006-11-29 15:29:40 +010051 { 0x1106, "VIA" },
Matthew Ranostay7f168592007-10-18 17:38:17 +020052 { 0x111d, "IDT" },
Takashi Iwaic8cd1282008-02-13 16:59:29 +010053 { 0x11c1, "LSI" },
Takashi Iwai54b903e2005-05-15 14:30:10 +020054 { 0x11d4, "Analog Devices" },
Linus Torvalds1da177e2005-04-16 15:20:36 -070055 { 0x13f6, "C-Media" },
Takashi Iwaia9226252006-09-17 22:05:54 +020056 { 0x14f1, "Conexant" },
Takashi Iwaic8cd1282008-02-13 16:59:29 +010057 { 0x17e8, "Chrontel" },
58 { 0x1854, "LG" },
Mark Brown8199de32008-10-28 14:50:13 +000059 { 0x1aec, "Wolfson Microelectronics" },
Linus Torvalds1da177e2005-04-16 15:20:36 -070060 { 0x434d, "C-Media" },
Takashi Iwai74c61132008-12-18 09:11:33 +010061 { 0x8086, "Intel" },
Matt2f2f4252005-04-13 14:45:30 +020062 { 0x8384, "SigmaTel" },
Linus Torvalds1da177e2005-04-16 15:20:36 -070063 {} /* terminator */
64};
65
Takashi Iwai1289e9e2008-11-27 15:47:11 +010066static DEFINE_MUTEX(preset_mutex);
67static LIST_HEAD(hda_preset_tables);
68
69int snd_hda_add_codec_preset(struct hda_codec_preset_list *preset)
70{
71 mutex_lock(&preset_mutex);
72 list_add_tail(&preset->list, &hda_preset_tables);
73 mutex_unlock(&preset_mutex);
74 return 0;
75}
Takashi Iwaiff7a3262008-11-28 15:17:06 +010076EXPORT_SYMBOL_HDA(snd_hda_add_codec_preset);
Takashi Iwai1289e9e2008-11-27 15:47:11 +010077
78int snd_hda_delete_codec_preset(struct hda_codec_preset_list *preset)
79{
80 mutex_lock(&preset_mutex);
81 list_del(&preset->list);
82 mutex_unlock(&preset_mutex);
83 return 0;
84}
Takashi Iwaiff7a3262008-11-28 15:17:06 +010085EXPORT_SYMBOL_HDA(snd_hda_delete_codec_preset);
Linus Torvalds1da177e2005-04-16 15:20:36 -070086
Takashi Iwaicb53c622007-08-10 17:21:45 +020087#ifdef CONFIG_SND_HDA_POWER_SAVE
88static void hda_power_work(struct work_struct *work);
89static void hda_keep_power_on(struct hda_codec *codec);
90#else
91static inline void hda_keep_power_on(struct hda_codec *codec) {}
92#endif
93
Matthew Ranostay50a9f792008-10-25 01:05:45 -040094const char *snd_hda_get_jack_location(u32 cfg)
95{
96 static char *bases[7] = {
97 "N/A", "Rear", "Front", "Left", "Right", "Top", "Bottom",
98 };
99 static unsigned char specials_idx[] = {
100 0x07, 0x08,
101 0x17, 0x18, 0x19,
102 0x37, 0x38
103 };
104 static char *specials[] = {
105 "Rear Panel", "Drive Bar",
106 "Riser", "HDMI", "ATAPI",
107 "Mobile-In", "Mobile-Out"
108 };
109 int i;
110 cfg = (cfg & AC_DEFCFG_LOCATION) >> AC_DEFCFG_LOCATION_SHIFT;
111 if ((cfg & 0x0f) < 7)
112 return bases[cfg & 0x0f];
113 for (i = 0; i < ARRAY_SIZE(specials_idx); i++) {
114 if (cfg == specials_idx[i])
115 return specials[i];
116 }
117 return "UNKNOWN";
118}
Takashi Iwaiff7a3262008-11-28 15:17:06 +0100119EXPORT_SYMBOL_HDA(snd_hda_get_jack_location);
Matthew Ranostay50a9f792008-10-25 01:05:45 -0400120
121const char *snd_hda_get_jack_connectivity(u32 cfg)
122{
123 static char *jack_locations[4] = { "Ext", "Int", "Sep", "Oth" };
124
125 return jack_locations[(cfg >> (AC_DEFCFG_LOCATION_SHIFT + 4)) & 3];
126}
Takashi Iwaiff7a3262008-11-28 15:17:06 +0100127EXPORT_SYMBOL_HDA(snd_hda_get_jack_connectivity);
Matthew Ranostay50a9f792008-10-25 01:05:45 -0400128
129const char *snd_hda_get_jack_type(u32 cfg)
130{
131 static char *jack_types[16] = {
132 "Line Out", "Speaker", "HP Out", "CD",
133 "SPDIF Out", "Digital Out", "Modem Line", "Modem Hand",
134 "Line In", "Aux", "Mic", "Telephony",
135 "SPDIF In", "Digitial In", "Reserved", "Other"
136 };
137
138 return jack_types[(cfg & AC_DEFCFG_DEVICE)
139 >> AC_DEFCFG_DEVICE_SHIFT];
140}
Takashi Iwaiff7a3262008-11-28 15:17:06 +0100141EXPORT_SYMBOL_HDA(snd_hda_get_jack_type);
Matthew Ranostay50a9f792008-10-25 01:05:45 -0400142
Takashi Iwai33fa35e2008-11-06 16:50:40 +0100143/*
144 * Compose a 32bit command word to be sent to the HD-audio controller
145 */
146static inline unsigned int
147make_codec_cmd(struct hda_codec *codec, hda_nid_t nid, int direct,
148 unsigned int verb, unsigned int parm)
149{
150 u32 val;
151
152 val = (u32)(codec->addr & 0x0f) << 28;
153 val |= (u32)direct << 27;
154 val |= (u32)nid << 20;
155 val |= verb << 8;
156 val |= parm;
157 return val;
158}
159
Linus Torvalds1da177e2005-04-16 15:20:36 -0700160/**
161 * snd_hda_codec_read - send a command and get the response
162 * @codec: the HDA codec
163 * @nid: NID to send the command
164 * @direct: direct flag
165 * @verb: the verb to send
166 * @parm: the parameter for the verb
167 *
168 * Send a single command and read the corresponding response.
169 *
170 * Returns the obtained response value, or -1 for an error.
171 */
Takashi Iwai0ba21762007-04-16 11:29:14 +0200172unsigned int snd_hda_codec_read(struct hda_codec *codec, hda_nid_t nid,
173 int direct,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700174 unsigned int verb, unsigned int parm)
175{
Takashi Iwai33fa35e2008-11-06 16:50:40 +0100176 struct hda_bus *bus = codec->bus;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700177 unsigned int res;
Takashi Iwai33fa35e2008-11-06 16:50:40 +0100178
179 res = make_codec_cmd(codec, nid, direct, verb, parm);
Takashi Iwaicb53c622007-08-10 17:21:45 +0200180 snd_hda_power_up(codec);
Takashi Iwai33fa35e2008-11-06 16:50:40 +0100181 mutex_lock(&bus->cmd_mutex);
182 if (!bus->ops.command(bus, res))
183 res = bus->ops.get_response(bus);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700184 else
185 res = (unsigned int)-1;
Takashi Iwai33fa35e2008-11-06 16:50:40 +0100186 mutex_unlock(&bus->cmd_mutex);
Takashi Iwaicb53c622007-08-10 17:21:45 +0200187 snd_hda_power_down(codec);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700188 return res;
189}
Takashi Iwaiff7a3262008-11-28 15:17:06 +0100190EXPORT_SYMBOL_HDA(snd_hda_codec_read);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700191
192/**
193 * snd_hda_codec_write - send a single command without waiting for response
194 * @codec: the HDA codec
195 * @nid: NID to send the command
196 * @direct: direct flag
197 * @verb: the verb to send
198 * @parm: the parameter for the verb
199 *
200 * Send a single command without waiting for response.
201 *
202 * Returns 0 if successful, or a negative error code.
203 */
204int snd_hda_codec_write(struct hda_codec *codec, hda_nid_t nid, int direct,
205 unsigned int verb, unsigned int parm)
206{
Takashi Iwai33fa35e2008-11-06 16:50:40 +0100207 struct hda_bus *bus = codec->bus;
208 unsigned int res;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700209 int err;
Takashi Iwai33fa35e2008-11-06 16:50:40 +0100210
211 res = make_codec_cmd(codec, nid, direct, verb, parm);
Takashi Iwaicb53c622007-08-10 17:21:45 +0200212 snd_hda_power_up(codec);
Takashi Iwai33fa35e2008-11-06 16:50:40 +0100213 mutex_lock(&bus->cmd_mutex);
214 err = bus->ops.command(bus, res);
215 mutex_unlock(&bus->cmd_mutex);
Takashi Iwaicb53c622007-08-10 17:21:45 +0200216 snd_hda_power_down(codec);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700217 return err;
218}
Takashi Iwaiff7a3262008-11-28 15:17:06 +0100219EXPORT_SYMBOL_HDA(snd_hda_codec_write);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700220
221/**
222 * snd_hda_sequence_write - sequence writes
223 * @codec: the HDA codec
224 * @seq: VERB array to send
225 *
226 * Send the commands sequentially from the given array.
227 * The array must be terminated with NID=0.
228 */
229void snd_hda_sequence_write(struct hda_codec *codec, const struct hda_verb *seq)
230{
231 for (; seq->nid; seq++)
232 snd_hda_codec_write(codec, seq->nid, 0, seq->verb, seq->param);
233}
Takashi Iwaiff7a3262008-11-28 15:17:06 +0100234EXPORT_SYMBOL_HDA(snd_hda_sequence_write);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700235
236/**
237 * snd_hda_get_sub_nodes - get the range of sub nodes
238 * @codec: the HDA codec
239 * @nid: NID to parse
240 * @start_id: the pointer to store the start NID
241 *
242 * Parse the NID and store the start NID of its sub-nodes.
243 * Returns the number of sub-nodes.
244 */
Takashi Iwai0ba21762007-04-16 11:29:14 +0200245int snd_hda_get_sub_nodes(struct hda_codec *codec, hda_nid_t nid,
246 hda_nid_t *start_id)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700247{
248 unsigned int parm;
249
250 parm = snd_hda_param_read(codec, nid, AC_PAR_NODE_COUNT);
Danny Tholene8a7f132007-09-11 21:41:56 +0200251 if (parm == -1)
252 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700253 *start_id = (parm >> 16) & 0x7fff;
254 return (int)(parm & 0x7fff);
255}
Takashi Iwaiff7a3262008-11-28 15:17:06 +0100256EXPORT_SYMBOL_HDA(snd_hda_get_sub_nodes);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700257
258/**
259 * snd_hda_get_connections - get connection list
260 * @codec: the HDA codec
261 * @nid: NID to parse
262 * @conn_list: connection list array
263 * @max_conns: max. number of connections to store
264 *
265 * Parses the connection list of the given widget and stores the list
266 * of NIDs.
267 *
268 * Returns the number of connections, or a negative error code.
269 */
270int snd_hda_get_connections(struct hda_codec *codec, hda_nid_t nid,
271 hda_nid_t *conn_list, int max_conns)
272{
273 unsigned int parm;
Takashi Iwai54d17402005-11-21 16:33:22 +0100274 int i, conn_len, conns;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700275 unsigned int shift, num_elems, mask;
Takashi Iwai54d17402005-11-21 16:33:22 +0100276 hda_nid_t prev_nid;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700277
Takashi Iwaida3cec32008-08-08 17:12:14 +0200278 if (snd_BUG_ON(!conn_list || max_conns <= 0))
279 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700280
281 parm = snd_hda_param_read(codec, nid, AC_PAR_CONNLIST_LEN);
282 if (parm & AC_CLIST_LONG) {
283 /* long form */
284 shift = 16;
285 num_elems = 2;
286 } else {
287 /* short form */
288 shift = 8;
289 num_elems = 4;
290 }
291 conn_len = parm & AC_CLIST_LENGTH;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700292 mask = (1 << (shift-1)) - 1;
293
Takashi Iwai0ba21762007-04-16 11:29:14 +0200294 if (!conn_len)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700295 return 0; /* no connection */
296
297 if (conn_len == 1) {
298 /* single connection */
Takashi Iwai0ba21762007-04-16 11:29:14 +0200299 parm = snd_hda_codec_read(codec, nid, 0,
300 AC_VERB_GET_CONNECT_LIST, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700301 conn_list[0] = parm & mask;
302 return 1;
303 }
304
305 /* multi connection */
306 conns = 0;
Takashi Iwai54d17402005-11-21 16:33:22 +0100307 prev_nid = 0;
308 for (i = 0; i < conn_len; i++) {
309 int range_val;
310 hda_nid_t val, n;
311
312 if (i % num_elems == 0)
313 parm = snd_hda_codec_read(codec, nid, 0,
314 AC_VERB_GET_CONNECT_LIST, i);
Takashi Iwai0ba21762007-04-16 11:29:14 +0200315 range_val = !!(parm & (1 << (shift-1))); /* ranges */
Takashi Iwai54d17402005-11-21 16:33:22 +0100316 val = parm & mask;
317 parm >>= shift;
318 if (range_val) {
319 /* ranges between the previous and this one */
Takashi Iwai0ba21762007-04-16 11:29:14 +0200320 if (!prev_nid || prev_nid >= val) {
321 snd_printk(KERN_WARNING "hda_codec: "
322 "invalid dep_range_val %x:%x\n",
323 prev_nid, val);
Takashi Iwai54d17402005-11-21 16:33:22 +0100324 continue;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700325 }
Takashi Iwai54d17402005-11-21 16:33:22 +0100326 for (n = prev_nid + 1; n <= val; n++) {
327 if (conns >= max_conns) {
Takashi Iwai0ba21762007-04-16 11:29:14 +0200328 snd_printk(KERN_ERR
329 "Too many connections\n");
Takashi Iwai54d17402005-11-21 16:33:22 +0100330 return -EINVAL;
331 }
332 conn_list[conns++] = n;
333 }
334 } else {
335 if (conns >= max_conns) {
336 snd_printk(KERN_ERR "Too many connections\n");
337 return -EINVAL;
338 }
339 conn_list[conns++] = val;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700340 }
Takashi Iwai54d17402005-11-21 16:33:22 +0100341 prev_nid = val;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700342 }
343 return conns;
344}
Takashi Iwaiff7a3262008-11-28 15:17:06 +0100345EXPORT_SYMBOL_HDA(snd_hda_get_connections);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700346
347
348/**
349 * snd_hda_queue_unsol_event - add an unsolicited event to queue
350 * @bus: the BUS
351 * @res: unsolicited event (lower 32bit of RIRB entry)
352 * @res_ex: codec addr and flags (upper 32bit or RIRB entry)
353 *
354 * Adds the given event to the queue. The events are processed in
355 * the workqueue asynchronously. Call this function in the interrupt
356 * hanlder when RIRB receives an unsolicited event.
357 *
358 * Returns 0 if successful, or a negative error code.
359 */
360int snd_hda_queue_unsol_event(struct hda_bus *bus, u32 res, u32 res_ex)
361{
362 struct hda_bus_unsolicited *unsol;
363 unsigned int wp;
364
Takashi Iwai0ba21762007-04-16 11:29:14 +0200365 unsol = bus->unsol;
366 if (!unsol)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700367 return 0;
368
369 wp = (unsol->wp + 1) % HDA_UNSOL_QUEUE_SIZE;
370 unsol->wp = wp;
371
372 wp <<= 1;
373 unsol->queue[wp] = res;
374 unsol->queue[wp + 1] = res_ex;
375
Takashi Iwai6acaed32009-01-12 10:09:24 +0100376 queue_work(bus->workq, &unsol->work);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700377
378 return 0;
379}
Takashi Iwaiff7a3262008-11-28 15:17:06 +0100380EXPORT_SYMBOL_HDA(snd_hda_queue_unsol_event);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700381
382/*
Wu Fengguang5c1d1a92008-10-07 14:17:53 +0800383 * process queued unsolicited events
Linus Torvalds1da177e2005-04-16 15:20:36 -0700384 */
David Howellsc4028952006-11-22 14:57:56 +0000385static void process_unsol_events(struct work_struct *work)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700386{
David Howellsc4028952006-11-22 14:57:56 +0000387 struct hda_bus_unsolicited *unsol =
388 container_of(work, struct hda_bus_unsolicited, work);
389 struct hda_bus *bus = unsol->bus;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700390 struct hda_codec *codec;
391 unsigned int rp, caddr, res;
392
393 while (unsol->rp != unsol->wp) {
394 rp = (unsol->rp + 1) % HDA_UNSOL_QUEUE_SIZE;
395 unsol->rp = rp;
396 rp <<= 1;
397 res = unsol->queue[rp];
398 caddr = unsol->queue[rp + 1];
Takashi Iwai0ba21762007-04-16 11:29:14 +0200399 if (!(caddr & (1 << 4))) /* no unsolicited event? */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700400 continue;
401 codec = bus->caddr_tbl[caddr & 0x0f];
402 if (codec && codec->patch_ops.unsol_event)
403 codec->patch_ops.unsol_event(codec, res);
404 }
405}
406
407/*
408 * initialize unsolicited queue
409 */
Takashi Iwai6c1f45e2008-07-30 15:01:45 +0200410static int init_unsol_queue(struct hda_bus *bus)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700411{
412 struct hda_bus_unsolicited *unsol;
413
Takashi Iwai9f146bb2005-11-17 11:07:49 +0100414 if (bus->unsol) /* already initialized */
415 return 0;
416
Takashi Iwaie560d8d2005-09-09 14:21:46 +0200417 unsol = kzalloc(sizeof(*unsol), GFP_KERNEL);
Takashi Iwai0ba21762007-04-16 11:29:14 +0200418 if (!unsol) {
419 snd_printk(KERN_ERR "hda_codec: "
420 "can't allocate unsolicited queue\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700421 return -ENOMEM;
422 }
David Howellsc4028952006-11-22 14:57:56 +0000423 INIT_WORK(&unsol->work, process_unsol_events);
424 unsol->bus = bus;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700425 bus->unsol = unsol;
426 return 0;
427}
428
429/*
430 * destructor
431 */
432static void snd_hda_codec_free(struct hda_codec *codec);
433
434static int snd_hda_bus_free(struct hda_bus *bus)
435{
Takashi Iwai0ba21762007-04-16 11:29:14 +0200436 struct hda_codec *codec, *n;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700437
Takashi Iwai0ba21762007-04-16 11:29:14 +0200438 if (!bus)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700439 return 0;
Takashi Iwai6acaed32009-01-12 10:09:24 +0100440 if (bus->workq)
441 flush_workqueue(bus->workq);
442 if (bus->unsol)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700443 kfree(bus->unsol);
Takashi Iwai0ba21762007-04-16 11:29:14 +0200444 list_for_each_entry_safe(codec, n, &bus->codec_list, list) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700445 snd_hda_codec_free(codec);
446 }
447 if (bus->ops.private_free)
448 bus->ops.private_free(bus);
Takashi Iwai6acaed32009-01-12 10:09:24 +0100449 if (bus->workq)
450 destroy_workqueue(bus->workq);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700451 kfree(bus);
452 return 0;
453}
454
Takashi Iwaic8b6bf92005-11-17 14:57:47 +0100455static int snd_hda_bus_dev_free(struct snd_device *device)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700456{
457 struct hda_bus *bus = device->device_data;
Takashi Iwaib94d35392008-11-21 09:08:06 +0100458 bus->shutdown = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700459 return snd_hda_bus_free(bus);
460}
461
Takashi Iwaid7ffba12008-07-30 15:01:46 +0200462#ifdef CONFIG_SND_HDA_HWDEP
463static int snd_hda_bus_dev_register(struct snd_device *device)
464{
465 struct hda_bus *bus = device->device_data;
466 struct hda_codec *codec;
467 list_for_each_entry(codec, &bus->codec_list, list) {
468 snd_hda_hwdep_add_sysfs(codec);
469 }
470 return 0;
471}
472#else
473#define snd_hda_bus_dev_register NULL
474#endif
475
Linus Torvalds1da177e2005-04-16 15:20:36 -0700476/**
477 * snd_hda_bus_new - create a HDA bus
478 * @card: the card entry
479 * @temp: the template for hda_bus information
480 * @busp: the pointer to store the created bus instance
481 *
482 * Returns 0 if successful, or a negative error code.
483 */
Takashi Iwai1289e9e2008-11-27 15:47:11 +0100484int /*__devinit*/ snd_hda_bus_new(struct snd_card *card,
Takashi Iwai756e2b02007-04-16 11:27:07 +0200485 const struct hda_bus_template *temp,
486 struct hda_bus **busp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700487{
488 struct hda_bus *bus;
489 int err;
Takashi Iwaic8b6bf92005-11-17 14:57:47 +0100490 static struct snd_device_ops dev_ops = {
Takashi Iwaid7ffba12008-07-30 15:01:46 +0200491 .dev_register = snd_hda_bus_dev_register,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700492 .dev_free = snd_hda_bus_dev_free,
493 };
494
Takashi Iwaida3cec32008-08-08 17:12:14 +0200495 if (snd_BUG_ON(!temp))
496 return -EINVAL;
497 if (snd_BUG_ON(!temp->ops.command || !temp->ops.get_response))
498 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700499
500 if (busp)
501 *busp = NULL;
502
Takashi Iwaie560d8d2005-09-09 14:21:46 +0200503 bus = kzalloc(sizeof(*bus), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700504 if (bus == NULL) {
505 snd_printk(KERN_ERR "can't allocate struct hda_bus\n");
506 return -ENOMEM;
507 }
508
509 bus->card = card;
510 bus->private_data = temp->private_data;
511 bus->pci = temp->pci;
512 bus->modelname = temp->modelname;
Takashi Iwaifee2fba2008-11-27 12:43:28 +0100513 bus->power_save = temp->power_save;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700514 bus->ops = temp->ops;
515
Ingo Molnar62932df2006-01-16 16:34:20 +0100516 mutex_init(&bus->cmd_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700517 INIT_LIST_HEAD(&bus->codec_list);
518
Takashi Iwaie8c0ee52009-02-05 07:34:28 +0100519 snprintf(bus->workq_name, sizeof(bus->workq_name),
520 "hd-audio%d", card->number);
521 bus->workq = create_singlethread_workqueue(bus->workq_name);
Takashi Iwai6acaed32009-01-12 10:09:24 +0100522 if (!bus->workq) {
Takashi Iwaie8c0ee52009-02-05 07:34:28 +0100523 snd_printk(KERN_ERR "cannot create workqueue %s\n",
524 bus->workq_name);
Takashi Iwai6acaed32009-01-12 10:09:24 +0100525 kfree(bus);
526 return -ENOMEM;
527 }
528
Takashi Iwai0ba21762007-04-16 11:29:14 +0200529 err = snd_device_new(card, SNDRV_DEV_BUS, bus, &dev_ops);
530 if (err < 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700531 snd_hda_bus_free(bus);
532 return err;
533 }
534 if (busp)
535 *busp = bus;
536 return 0;
537}
Takashi Iwaiff7a3262008-11-28 15:17:06 +0100538EXPORT_SYMBOL_HDA(snd_hda_bus_new);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700539
Takashi Iwai82467612007-07-27 19:15:54 +0200540#ifdef CONFIG_SND_HDA_GENERIC
541#define is_generic_config(codec) \
Takashi Iwaif44ac832008-07-30 15:01:45 +0200542 (codec->modelname && !strcmp(codec->modelname, "generic"))
Takashi Iwai82467612007-07-27 19:15:54 +0200543#else
544#define is_generic_config(codec) 0
545#endif
546
Takashi Iwai645f10c2008-11-28 15:07:37 +0100547#ifdef MODULE
Takashi Iwai1289e9e2008-11-27 15:47:11 +0100548#define HDA_MODREQ_MAX_COUNT 2 /* two request_modules()'s */
549#else
Takashi Iwai645f10c2008-11-28 15:07:37 +0100550#define HDA_MODREQ_MAX_COUNT 0 /* all presets are statically linked */
Takashi Iwai1289e9e2008-11-27 15:47:11 +0100551#endif
552
Linus Torvalds1da177e2005-04-16 15:20:36 -0700553/*
554 * find a matching codec preset
555 */
Takashi Iwai6c1f45e2008-07-30 15:01:45 +0200556static const struct hda_codec_preset *
Takashi Iwai756e2b02007-04-16 11:27:07 +0200557find_codec_preset(struct hda_codec *codec)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700558{
Takashi Iwai1289e9e2008-11-27 15:47:11 +0100559 struct hda_codec_preset_list *tbl;
560 const struct hda_codec_preset *preset;
561 int mod_requested = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700562
Takashi Iwai82467612007-07-27 19:15:54 +0200563 if (is_generic_config(codec))
Takashi Iwaid5ad6302007-03-07 15:55:59 +0100564 return NULL; /* use the generic parser */
565
Takashi Iwai1289e9e2008-11-27 15:47:11 +0100566 again:
567 mutex_lock(&preset_mutex);
568 list_for_each_entry(tbl, &hda_preset_tables, list) {
569 if (!try_module_get(tbl->owner)) {
570 snd_printk(KERN_ERR "hda_codec: cannot module_get\n");
571 continue;
572 }
573 for (preset = tbl->preset; preset->id; preset++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700574 u32 mask = preset->mask;
Marc Boucherca7cfae2008-01-22 15:32:25 +0100575 if (preset->afg && preset->afg != codec->afg)
576 continue;
577 if (preset->mfg && preset->mfg != codec->mfg)
578 continue;
Takashi Iwai0ba21762007-04-16 11:29:14 +0200579 if (!mask)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700580 mask = ~0;
Takashi Iwai9c7f8522006-06-28 15:08:22 +0200581 if (preset->id == (codec->vendor_id & mask) &&
Takashi Iwai0ba21762007-04-16 11:29:14 +0200582 (!preset->rev ||
Takashi Iwai1289e9e2008-11-27 15:47:11 +0100583 preset->rev == codec->revision_id)) {
584 mutex_unlock(&preset_mutex);
585 codec->owner = tbl->owner;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700586 return preset;
Takashi Iwai1289e9e2008-11-27 15:47:11 +0100587 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700588 }
Takashi Iwai1289e9e2008-11-27 15:47:11 +0100589 module_put(tbl->owner);
590 }
591 mutex_unlock(&preset_mutex);
592
593 if (mod_requested < HDA_MODREQ_MAX_COUNT) {
594 char name[32];
595 if (!mod_requested)
596 snprintf(name, sizeof(name), "snd-hda-codec-id:%08x",
597 codec->vendor_id);
598 else
599 snprintf(name, sizeof(name), "snd-hda-codec-id:%04x*",
600 (codec->vendor_id >> 16) & 0xffff);
601 request_module(name);
602 mod_requested++;
603 goto again;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700604 }
605 return NULL;
606}
607
608/*
Takashi Iwaif44ac832008-07-30 15:01:45 +0200609 * get_codec_name - store the codec name
Linus Torvalds1da177e2005-04-16 15:20:36 -0700610 */
Takashi Iwaif44ac832008-07-30 15:01:45 +0200611static int get_codec_name(struct hda_codec *codec)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700612{
613 const struct hda_vendor_id *c;
614 const char *vendor = NULL;
615 u16 vendor_id = codec->vendor_id >> 16;
Takashi Iwaif44ac832008-07-30 15:01:45 +0200616 char tmp[16], name[32];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700617
618 for (c = hda_vendor_ids; c->id; c++) {
619 if (c->id == vendor_id) {
620 vendor = c->name;
621 break;
622 }
623 }
Takashi Iwai0ba21762007-04-16 11:29:14 +0200624 if (!vendor) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700625 sprintf(tmp, "Generic %04x", vendor_id);
626 vendor = tmp;
627 }
628 if (codec->preset && codec->preset->name)
Takashi Iwaif44ac832008-07-30 15:01:45 +0200629 snprintf(name, sizeof(name), "%s %s", vendor,
630 codec->preset->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700631 else
Takashi Iwaif44ac832008-07-30 15:01:45 +0200632 snprintf(name, sizeof(name), "%s ID %x", vendor,
Takashi Iwai0ba21762007-04-16 11:29:14 +0200633 codec->vendor_id & 0xffff);
Takashi Iwaif44ac832008-07-30 15:01:45 +0200634 codec->name = kstrdup(name, GFP_KERNEL);
635 if (!codec->name)
636 return -ENOMEM;
637 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700638}
639
640/*
Sasha Khapyorsky673b6832005-08-11 11:00:16 +0200641 * look for an AFG and MFG nodes
Linus Torvalds1da177e2005-04-16 15:20:36 -0700642 */
Takashi Iwai1289e9e2008-11-27 15:47:11 +0100643static void /*__devinit*/ setup_fg_nodes(struct hda_codec *codec)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700644{
Takashi Iwai93e82ae2009-04-17 18:04:41 +0200645 int i, total_nodes, function_id;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700646 hda_nid_t nid;
647
648 total_nodes = snd_hda_get_sub_nodes(codec, AC_NODE_ROOT, &nid);
649 for (i = 0; i < total_nodes; i++, nid++) {
Takashi Iwai93e82ae2009-04-17 18:04:41 +0200650 function_id = snd_hda_param_read(codec, nid,
Pascal de Bruijn234b4342009-03-23 11:15:59 +0100651 AC_PAR_FUNCTION_TYPE) & 0xff;
Takashi Iwai93e82ae2009-04-17 18:04:41 +0200652 switch (function_id) {
Sasha Khapyorsky673b6832005-08-11 11:00:16 +0200653 case AC_GRP_AUDIO_FUNCTION:
654 codec->afg = nid;
Takashi Iwai93e82ae2009-04-17 18:04:41 +0200655 codec->function_id = function_id;
Sasha Khapyorsky673b6832005-08-11 11:00:16 +0200656 break;
657 case AC_GRP_MODEM_FUNCTION:
658 codec->mfg = nid;
Takashi Iwai93e82ae2009-04-17 18:04:41 +0200659 codec->function_id = function_id;
Sasha Khapyorsky673b6832005-08-11 11:00:16 +0200660 break;
661 default:
662 break;
663 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700664 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700665}
666
667/*
Takashi Iwai54d17402005-11-21 16:33:22 +0100668 * read widget caps for each widget and store in cache
669 */
670static int read_widget_caps(struct hda_codec *codec, hda_nid_t fg_node)
671{
672 int i;
673 hda_nid_t nid;
674
675 codec->num_nodes = snd_hda_get_sub_nodes(codec, fg_node,
676 &codec->start_nid);
677 codec->wcaps = kmalloc(codec->num_nodes * 4, GFP_KERNEL);
Takashi Iwai0ba21762007-04-16 11:29:14 +0200678 if (!codec->wcaps)
Takashi Iwai54d17402005-11-21 16:33:22 +0100679 return -ENOMEM;
680 nid = codec->start_nid;
681 for (i = 0; i < codec->num_nodes; i++, nid++)
682 codec->wcaps[i] = snd_hda_param_read(codec, nid,
683 AC_PAR_AUDIO_WIDGET_CAP);
684 return 0;
685}
686
Takashi Iwai3be14142009-02-20 14:11:16 +0100687/* read all pin default configurations and save codec->init_pins */
688static int read_pin_defaults(struct hda_codec *codec)
689{
690 int i;
691 hda_nid_t nid = codec->start_nid;
692
693 for (i = 0; i < codec->num_nodes; i++, nid++) {
694 struct hda_pincfg *pin;
695 unsigned int wcaps = get_wcaps(codec, nid);
696 unsigned int wid_type = (wcaps & AC_WCAP_TYPE) >>
697 AC_WCAP_TYPE_SHIFT;
698 if (wid_type != AC_WID_PIN)
699 continue;
700 pin = snd_array_new(&codec->init_pins);
701 if (!pin)
702 return -ENOMEM;
703 pin->nid = nid;
704 pin->cfg = snd_hda_codec_read(codec, nid, 0,
705 AC_VERB_GET_CONFIG_DEFAULT, 0);
706 }
707 return 0;
708}
709
710/* look up the given pin config list and return the item matching with NID */
711static struct hda_pincfg *look_up_pincfg(struct hda_codec *codec,
712 struct snd_array *array,
713 hda_nid_t nid)
714{
715 int i;
716 for (i = 0; i < array->used; i++) {
717 struct hda_pincfg *pin = snd_array_elem(array, i);
718 if (pin->nid == nid)
719 return pin;
720 }
721 return NULL;
722}
723
724/* write a config value for the given NID */
725static void set_pincfg(struct hda_codec *codec, hda_nid_t nid,
726 unsigned int cfg)
727{
728 int i;
729 for (i = 0; i < 4; i++) {
730 snd_hda_codec_write(codec, nid, 0,
731 AC_VERB_SET_CONFIG_DEFAULT_BYTES_0 + i,
732 cfg & 0xff);
733 cfg >>= 8;
734 }
735}
736
737/* set the current pin config value for the given NID.
738 * the value is cached, and read via snd_hda_codec_get_pincfg()
739 */
740int snd_hda_add_pincfg(struct hda_codec *codec, struct snd_array *list,
741 hda_nid_t nid, unsigned int cfg)
742{
743 struct hda_pincfg *pin;
Takashi Iwai5e7b8e02009-02-23 09:45:59 +0100744 unsigned int oldcfg;
Takashi Iwai3be14142009-02-20 14:11:16 +0100745
Takashi Iwai5e7b8e02009-02-23 09:45:59 +0100746 oldcfg = snd_hda_codec_get_pincfg(codec, nid);
Takashi Iwai3be14142009-02-20 14:11:16 +0100747 pin = look_up_pincfg(codec, list, nid);
748 if (!pin) {
749 pin = snd_array_new(list);
750 if (!pin)
751 return -ENOMEM;
752 pin->nid = nid;
753 }
754 pin->cfg = cfg;
Takashi Iwai5e7b8e02009-02-23 09:45:59 +0100755
756 /* change only when needed; e.g. if the pincfg is already present
757 * in user_pins[], don't write it
758 */
759 cfg = snd_hda_codec_get_pincfg(codec, nid);
760 if (oldcfg != cfg)
761 set_pincfg(codec, nid, cfg);
Takashi Iwai3be14142009-02-20 14:11:16 +0100762 return 0;
763}
764
765int snd_hda_codec_set_pincfg(struct hda_codec *codec,
766 hda_nid_t nid, unsigned int cfg)
767{
Takashi Iwai346ff702009-02-23 09:42:57 +0100768 return snd_hda_add_pincfg(codec, &codec->driver_pins, nid, cfg);
Takashi Iwai3be14142009-02-20 14:11:16 +0100769}
770EXPORT_SYMBOL_HDA(snd_hda_codec_set_pincfg);
771
772/* get the current pin config value of the given pin NID */
773unsigned int snd_hda_codec_get_pincfg(struct hda_codec *codec, hda_nid_t nid)
774{
775 struct hda_pincfg *pin;
776
Takashi Iwai3be14142009-02-20 14:11:16 +0100777#ifdef CONFIG_SND_HDA_HWDEP
Takashi Iwai346ff702009-02-23 09:42:57 +0100778 pin = look_up_pincfg(codec, &codec->user_pins, nid);
Takashi Iwai3be14142009-02-20 14:11:16 +0100779 if (pin)
780 return pin->cfg;
781#endif
Takashi Iwai5e7b8e02009-02-23 09:45:59 +0100782 pin = look_up_pincfg(codec, &codec->driver_pins, nid);
783 if (pin)
784 return pin->cfg;
Takashi Iwai3be14142009-02-20 14:11:16 +0100785 pin = look_up_pincfg(codec, &codec->init_pins, nid);
786 if (pin)
787 return pin->cfg;
788 return 0;
789}
790EXPORT_SYMBOL_HDA(snd_hda_codec_get_pincfg);
791
792/* restore all current pin configs */
793static void restore_pincfgs(struct hda_codec *codec)
794{
795 int i;
796 for (i = 0; i < codec->init_pins.used; i++) {
797 struct hda_pincfg *pin = snd_array_elem(&codec->init_pins, i);
798 set_pincfg(codec, pin->nid,
799 snd_hda_codec_get_pincfg(codec, pin->nid));
800 }
801}
Takashi Iwai54d17402005-11-21 16:33:22 +0100802
Takashi Iwai01751f52007-08-10 16:59:39 +0200803static void init_hda_cache(struct hda_cache_rec *cache,
804 unsigned int record_size);
Takashi Iwai1fcaee62007-08-23 00:01:09 +0200805static void free_hda_cache(struct hda_cache_rec *cache);
Takashi Iwai01751f52007-08-10 16:59:39 +0200806
Takashi Iwai3be14142009-02-20 14:11:16 +0100807/* restore the initial pin cfgs and release all pincfg lists */
808static void restore_init_pincfgs(struct hda_codec *codec)
809{
Takashi Iwai346ff702009-02-23 09:42:57 +0100810 /* first free driver_pins and user_pins, then call restore_pincfg
Takashi Iwai3be14142009-02-20 14:11:16 +0100811 * so that only the values in init_pins are restored
812 */
Takashi Iwai346ff702009-02-23 09:42:57 +0100813 snd_array_free(&codec->driver_pins);
Takashi Iwai3be14142009-02-20 14:11:16 +0100814#ifdef CONFIG_SND_HDA_HWDEP
Takashi Iwai346ff702009-02-23 09:42:57 +0100815 snd_array_free(&codec->user_pins);
Takashi Iwai3be14142009-02-20 14:11:16 +0100816#endif
817 restore_pincfgs(codec);
818 snd_array_free(&codec->init_pins);
819}
820
Takashi Iwai54d17402005-11-21 16:33:22 +0100821/*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700822 * codec destructor
823 */
824static void snd_hda_codec_free(struct hda_codec *codec)
825{
Takashi Iwai0ba21762007-04-16 11:29:14 +0200826 if (!codec)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700827 return;
Takashi Iwai3be14142009-02-20 14:11:16 +0100828 restore_init_pincfgs(codec);
Takashi Iwaicb53c622007-08-10 17:21:45 +0200829#ifdef CONFIG_SND_HDA_POWER_SAVE
830 cancel_delayed_work(&codec->power_work);
Takashi Iwai6acaed32009-01-12 10:09:24 +0100831 flush_workqueue(codec->bus->workq);
Takashi Iwaicb53c622007-08-10 17:21:45 +0200832#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700833 list_del(&codec->list);
Takashi Iwaid13bd412008-07-30 15:01:45 +0200834 snd_array_free(&codec->mixers);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700835 codec->bus->caddr_tbl[codec->addr] = NULL;
836 if (codec->patch_ops.free)
837 codec->patch_ops.free(codec);
Takashi Iwai1289e9e2008-11-27 15:47:11 +0100838 module_put(codec->owner);
Takashi Iwai01751f52007-08-10 16:59:39 +0200839 free_hda_cache(&codec->amp_cache);
Takashi Iwaib3ac5632007-08-10 17:03:40 +0200840 free_hda_cache(&codec->cmd_cache);
Takashi Iwaif44ac832008-07-30 15:01:45 +0200841 kfree(codec->name);
842 kfree(codec->modelname);
Takashi Iwai54d17402005-11-21 16:33:22 +0100843 kfree(codec->wcaps);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700844 kfree(codec);
845}
846
Takashi Iwaibb6ac722009-03-13 09:02:42 +0100847static void hda_set_power_state(struct hda_codec *codec, hda_nid_t fg,
848 unsigned int power_state);
849
Linus Torvalds1da177e2005-04-16 15:20:36 -0700850/**
851 * snd_hda_codec_new - create a HDA codec
852 * @bus: the bus to assign
853 * @codec_addr: the codec address
854 * @codecp: the pointer to store the generated codec
855 *
856 * Returns 0 if successful, or a negative error code.
857 */
Takashi Iwai1289e9e2008-11-27 15:47:11 +0100858int /*__devinit*/ snd_hda_codec_new(struct hda_bus *bus, unsigned int codec_addr,
Takashi Iwaid4d9cd032008-12-19 15:19:11 +0100859 int do_init, struct hda_codec **codecp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700860{
861 struct hda_codec *codec;
Jaroslav Kyselaba443682008-08-13 20:55:32 +0200862 char component[31];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700863 int err;
864
Takashi Iwaida3cec32008-08-08 17:12:14 +0200865 if (snd_BUG_ON(!bus))
866 return -EINVAL;
867 if (snd_BUG_ON(codec_addr > HDA_MAX_CODEC_ADDRESS))
868 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700869
870 if (bus->caddr_tbl[codec_addr]) {
Takashi Iwai0ba21762007-04-16 11:29:14 +0200871 snd_printk(KERN_ERR "hda_codec: "
872 "address 0x%x is already occupied\n", codec_addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700873 return -EBUSY;
874 }
875
Takashi Iwaie560d8d2005-09-09 14:21:46 +0200876 codec = kzalloc(sizeof(*codec), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700877 if (codec == NULL) {
878 snd_printk(KERN_ERR "can't allocate struct hda_codec\n");
879 return -ENOMEM;
880 }
881
882 codec->bus = bus;
883 codec->addr = codec_addr;
Ingo Molnar62932df2006-01-16 16:34:20 +0100884 mutex_init(&codec->spdif_mutex);
Wu Fengguang5a9e02e2009-01-09 16:45:24 +0800885 mutex_init(&codec->control_mutex);
Takashi Iwai01751f52007-08-10 16:59:39 +0200886 init_hda_cache(&codec->amp_cache, sizeof(struct hda_amp_info));
Takashi Iwaib3ac5632007-08-10 17:03:40 +0200887 init_hda_cache(&codec->cmd_cache, sizeof(struct hda_cache_head));
Takashi Iwaid13bd412008-07-30 15:01:45 +0200888 snd_array_init(&codec->mixers, sizeof(struct snd_kcontrol *), 32);
Takashi Iwai3be14142009-02-20 14:11:16 +0100889 snd_array_init(&codec->init_pins, sizeof(struct hda_pincfg), 16);
Takashi Iwai346ff702009-02-23 09:42:57 +0100890 snd_array_init(&codec->driver_pins, sizeof(struct hda_pincfg), 16);
Takashi Iwai6c1f45e2008-07-30 15:01:45 +0200891 if (codec->bus->modelname) {
892 codec->modelname = kstrdup(codec->bus->modelname, GFP_KERNEL);
893 if (!codec->modelname) {
894 snd_hda_codec_free(codec);
895 return -ENODEV;
896 }
897 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700898
Takashi Iwaicb53c622007-08-10 17:21:45 +0200899#ifdef CONFIG_SND_HDA_POWER_SAVE
900 INIT_DELAYED_WORK(&codec->power_work, hda_power_work);
901 /* snd_hda_codec_new() marks the codec as power-up, and leave it as is.
902 * the caller has to power down appropriatley after initialization
903 * phase.
904 */
905 hda_keep_power_on(codec);
906#endif
907
Linus Torvalds1da177e2005-04-16 15:20:36 -0700908 list_add_tail(&codec->list, &bus->codec_list);
909 bus->caddr_tbl[codec_addr] = codec;
910
Takashi Iwai0ba21762007-04-16 11:29:14 +0200911 codec->vendor_id = snd_hda_param_read(codec, AC_NODE_ROOT,
912 AC_PAR_VENDOR_ID);
Takashi Iwai111d3af2006-02-16 18:17:58 +0100913 if (codec->vendor_id == -1)
914 /* read again, hopefully the access method was corrected
915 * in the last read...
916 */
917 codec->vendor_id = snd_hda_param_read(codec, AC_NODE_ROOT,
918 AC_PAR_VENDOR_ID);
Takashi Iwai0ba21762007-04-16 11:29:14 +0200919 codec->subsystem_id = snd_hda_param_read(codec, AC_NODE_ROOT,
920 AC_PAR_SUBSYSTEM_ID);
921 codec->revision_id = snd_hda_param_read(codec, AC_NODE_ROOT,
922 AC_PAR_REV_ID);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700923
Sasha Khapyorsky673b6832005-08-11 11:00:16 +0200924 setup_fg_nodes(codec);
Takashi Iwai0ba21762007-04-16 11:29:14 +0200925 if (!codec->afg && !codec->mfg) {
Sasha Khapyorsky673b6832005-08-11 11:00:16 +0200926 snd_printdd("hda_codec: no AFG or MFG node found\n");
Takashi Iwai3be14142009-02-20 14:11:16 +0100927 err = -ENODEV;
928 goto error;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700929 }
930
Takashi Iwai3be14142009-02-20 14:11:16 +0100931 err = read_widget_caps(codec, codec->afg ? codec->afg : codec->mfg);
932 if (err < 0) {
Takashi Iwai54d17402005-11-21 16:33:22 +0100933 snd_printk(KERN_ERR "hda_codec: cannot malloc\n");
Takashi Iwai3be14142009-02-20 14:11:16 +0100934 goto error;
Takashi Iwai54d17402005-11-21 16:33:22 +0100935 }
Takashi Iwai3be14142009-02-20 14:11:16 +0100936 err = read_pin_defaults(codec);
937 if (err < 0)
938 goto error;
Takashi Iwai54d17402005-11-21 16:33:22 +0100939
Takashi Iwai0ba21762007-04-16 11:29:14 +0200940 if (!codec->subsystem_id) {
Takashi Iwai86284e42005-10-11 15:05:54 +0200941 hda_nid_t nid = codec->afg ? codec->afg : codec->mfg;
Takashi Iwai0ba21762007-04-16 11:29:14 +0200942 codec->subsystem_id =
943 snd_hda_codec_read(codec, nid, 0,
944 AC_VERB_GET_SUBSYSTEM_ID, 0);
Takashi Iwai86284e42005-10-11 15:05:54 +0200945 }
Takashi Iwaif44ac832008-07-30 15:01:45 +0200946 if (bus->modelname)
947 codec->modelname = kstrdup(bus->modelname, GFP_KERNEL);
Takashi Iwai86284e42005-10-11 15:05:54 +0200948
Takashi Iwaibb6ac722009-03-13 09:02:42 +0100949 /* power-up all before initialization */
950 hda_set_power_state(codec,
951 codec->afg ? codec->afg : codec->mfg,
952 AC_PWRST_D0);
953
Takashi Iwaid4d9cd032008-12-19 15:19:11 +0100954 if (do_init) {
955 err = snd_hda_codec_configure(codec);
Takashi Iwai3be14142009-02-20 14:11:16 +0100956 if (err < 0)
957 goto error;
Takashi Iwai6c1f45e2008-07-30 15:01:45 +0200958 }
959 snd_hda_codec_proc_new(codec);
960
Takashi Iwai6c1f45e2008-07-30 15:01:45 +0200961 snd_hda_create_hwdep(codec);
Takashi Iwai6c1f45e2008-07-30 15:01:45 +0200962
963 sprintf(component, "HDA:%08x,%08x,%08x", codec->vendor_id,
964 codec->subsystem_id, codec->revision_id);
965 snd_component_add(codec->bus->card, component);
966
967 if (codecp)
968 *codecp = codec;
969 return 0;
Takashi Iwai3be14142009-02-20 14:11:16 +0100970
971 error:
972 snd_hda_codec_free(codec);
973 return err;
Takashi Iwai6c1f45e2008-07-30 15:01:45 +0200974}
Takashi Iwaiff7a3262008-11-28 15:17:06 +0100975EXPORT_SYMBOL_HDA(snd_hda_codec_new);
Takashi Iwai6c1f45e2008-07-30 15:01:45 +0200976
977int snd_hda_codec_configure(struct hda_codec *codec)
978{
979 int err;
980
Takashi Iwaid5ad6302007-03-07 15:55:59 +0100981 codec->preset = find_codec_preset(codec);
Takashi Iwaif44ac832008-07-30 15:01:45 +0200982 if (!codec->name) {
983 err = get_codec_name(codec);
984 if (err < 0)
985 return err;
986 }
Takashi Iwai43ea1d42007-04-26 19:12:08 +0200987 /* audio codec should override the mixer name */
Takashi Iwaif44ac832008-07-30 15:01:45 +0200988 if (codec->afg || !*codec->bus->card->mixername)
989 strlcpy(codec->bus->card->mixername, codec->name,
990 sizeof(codec->bus->card->mixername));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700991
Takashi Iwai82467612007-07-27 19:15:54 +0200992 if (is_generic_config(codec)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700993 err = snd_hda_parse_generic_codec(codec);
Takashi Iwai82467612007-07-27 19:15:54 +0200994 goto patched;
995 }
Takashi Iwai82467612007-07-27 19:15:54 +0200996 if (codec->preset && codec->preset->patch) {
997 err = codec->preset->patch(codec);
998 goto patched;
999 }
1000
1001 /* call the default parser */
Takashi Iwai82467612007-07-27 19:15:54 +02001002 err = snd_hda_parse_generic_codec(codec);
Takashi Iwai35a1e0c2007-10-19 08:13:40 +02001003 if (err < 0)
1004 printk(KERN_ERR "hda-codec: No codec parser is available\n");
Takashi Iwai82467612007-07-27 19:15:54 +02001005
1006 patched:
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001007 if (!err && codec->patch_ops.unsol_event)
1008 err = init_unsol_queue(codec->bus);
1009 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001010}
1011
1012/**
1013 * snd_hda_codec_setup_stream - set up the codec for streaming
1014 * @codec: the CODEC to set up
1015 * @nid: the NID to set up
1016 * @stream_tag: stream tag to pass, it's between 0x1 and 0xf.
1017 * @channel_id: channel id to pass, zero based.
1018 * @format: stream format.
1019 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02001020void snd_hda_codec_setup_stream(struct hda_codec *codec, hda_nid_t nid,
1021 u32 stream_tag,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001022 int channel_id, int format)
1023{
Takashi Iwai0ba21762007-04-16 11:29:14 +02001024 if (!nid)
Takashi Iwaid21b37e2005-04-20 13:45:55 +02001025 return;
1026
Takashi Iwai0ba21762007-04-16 11:29:14 +02001027 snd_printdd("hda_codec_setup_stream: "
1028 "NID=0x%x, stream=0x%x, channel=%d, format=0x%x\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07001029 nid, stream_tag, channel_id, format);
1030 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CHANNEL_STREAMID,
1031 (stream_tag << 4) | channel_id);
1032 msleep(1);
1033 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_STREAM_FORMAT, format);
1034}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001035EXPORT_SYMBOL_HDA(snd_hda_codec_setup_stream);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001036
Takashi Iwai888afa12008-03-18 09:57:50 +01001037void snd_hda_codec_cleanup_stream(struct hda_codec *codec, hda_nid_t nid)
1038{
1039 if (!nid)
1040 return;
1041
1042 snd_printdd("hda_codec_cleanup_stream: NID=0x%x\n", nid);
1043 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CHANNEL_STREAMID, 0);
1044#if 0 /* keep the format */
1045 msleep(1);
1046 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_STREAM_FORMAT, 0);
1047#endif
1048}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001049EXPORT_SYMBOL_HDA(snd_hda_codec_cleanup_stream);
Takashi Iwai888afa12008-03-18 09:57:50 +01001050
Linus Torvalds1da177e2005-04-16 15:20:36 -07001051/*
1052 * amp access functions
1053 */
1054
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001055/* FIXME: more better hash key? */
1056#define HDA_HASH_KEY(nid,dir,idx) (u32)((nid) + ((idx) << 16) + ((dir) << 24))
Takashi Iwai1327a322009-03-23 13:07:47 +01001057#define HDA_HASH_PINCAP_KEY(nid) (u32)((nid) + (0x02 << 24))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001058#define INFO_AMP_CAPS (1<<0)
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001059#define INFO_AMP_VOL(ch) (1 << (1 + (ch)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001060
1061/* initialize the hash table */
Takashi Iwai1289e9e2008-11-27 15:47:11 +01001062static void /*__devinit*/ init_hda_cache(struct hda_cache_rec *cache,
Takashi Iwai01751f52007-08-10 16:59:39 +02001063 unsigned int record_size)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001064{
Takashi Iwai01751f52007-08-10 16:59:39 +02001065 memset(cache, 0, sizeof(*cache));
1066 memset(cache->hash, 0xff, sizeof(cache->hash));
Takashi Iwai603c4012008-07-30 15:01:44 +02001067 snd_array_init(&cache->buf, record_size, 64);
Takashi Iwai01751f52007-08-10 16:59:39 +02001068}
1069
Takashi Iwai1fcaee62007-08-23 00:01:09 +02001070static void free_hda_cache(struct hda_cache_rec *cache)
Takashi Iwai01751f52007-08-10 16:59:39 +02001071{
Takashi Iwai603c4012008-07-30 15:01:44 +02001072 snd_array_free(&cache->buf);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001073}
1074
1075/* query the hash. allocate an entry if not found. */
Takashi Iwai01751f52007-08-10 16:59:39 +02001076static struct hda_cache_head *get_alloc_hash(struct hda_cache_rec *cache,
1077 u32 key)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001078{
Takashi Iwai01751f52007-08-10 16:59:39 +02001079 u16 idx = key % (u16)ARRAY_SIZE(cache->hash);
1080 u16 cur = cache->hash[idx];
1081 struct hda_cache_head *info;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001082
1083 while (cur != 0xffff) {
Takashi Iwaif43aa022008-11-10 16:24:26 +01001084 info = snd_array_elem(&cache->buf, cur);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001085 if (info->key == key)
1086 return info;
1087 cur = info->next;
1088 }
1089
1090 /* add a new hash entry */
Takashi Iwai603c4012008-07-30 15:01:44 +02001091 info = snd_array_new(&cache->buf);
Takashi Iwaic2174292008-11-07 00:23:30 +01001092 if (!info)
1093 return NULL;
Takashi Iwaif43aa022008-11-10 16:24:26 +01001094 cur = snd_array_index(&cache->buf, info);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001095 info->key = key;
Takashi Iwai01751f52007-08-10 16:59:39 +02001096 info->val = 0;
1097 info->next = cache->hash[idx];
1098 cache->hash[idx] = cur;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001099
1100 return info;
1101}
1102
Takashi Iwai01751f52007-08-10 16:59:39 +02001103/* query and allocate an amp hash entry */
1104static inline struct hda_amp_info *
1105get_alloc_amp_hash(struct hda_codec *codec, u32 key)
1106{
1107 return (struct hda_amp_info *)get_alloc_hash(&codec->amp_cache, key);
1108}
1109
Linus Torvalds1da177e2005-04-16 15:20:36 -07001110/*
1111 * query AMP capabilities for the given widget and direction
1112 */
Matthew Ranostay09a99952008-01-24 11:49:21 +01001113u32 query_amp_caps(struct hda_codec *codec, hda_nid_t nid, int direction)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001114{
Takashi Iwai0ba21762007-04-16 11:29:14 +02001115 struct hda_amp_info *info;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001116
Takashi Iwai0ba21762007-04-16 11:29:14 +02001117 info = get_alloc_amp_hash(codec, HDA_HASH_KEY(nid, direction, 0));
1118 if (!info)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001119 return 0;
Takashi Iwai01751f52007-08-10 16:59:39 +02001120 if (!(info->head.val & INFO_AMP_CAPS)) {
Takashi Iwai0ba21762007-04-16 11:29:14 +02001121 if (!(get_wcaps(codec, nid) & AC_WCAP_AMP_OVRD))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001122 nid = codec->afg;
Takashi Iwai0ba21762007-04-16 11:29:14 +02001123 info->amp_caps = snd_hda_param_read(codec, nid,
1124 direction == HDA_OUTPUT ?
1125 AC_PAR_AMP_OUT_CAP :
1126 AC_PAR_AMP_IN_CAP);
Takashi Iwaib75e53f2007-05-10 16:56:09 +02001127 if (info->amp_caps)
Takashi Iwai01751f52007-08-10 16:59:39 +02001128 info->head.val |= INFO_AMP_CAPS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001129 }
1130 return info->amp_caps;
1131}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001132EXPORT_SYMBOL_HDA(query_amp_caps);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001133
Takashi Iwai897cc182007-05-29 19:01:37 +02001134int snd_hda_override_amp_caps(struct hda_codec *codec, hda_nid_t nid, int dir,
1135 unsigned int caps)
1136{
1137 struct hda_amp_info *info;
1138
1139 info = get_alloc_amp_hash(codec, HDA_HASH_KEY(nid, dir, 0));
1140 if (!info)
1141 return -EINVAL;
1142 info->amp_caps = caps;
Takashi Iwai01751f52007-08-10 16:59:39 +02001143 info->head.val |= INFO_AMP_CAPS;
Takashi Iwai897cc182007-05-29 19:01:37 +02001144 return 0;
1145}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001146EXPORT_SYMBOL_HDA(snd_hda_override_amp_caps);
Takashi Iwai897cc182007-05-29 19:01:37 +02001147
Takashi Iwai1327a322009-03-23 13:07:47 +01001148u32 snd_hda_query_pin_caps(struct hda_codec *codec, hda_nid_t nid)
1149{
1150 struct hda_amp_info *info;
1151
1152 info = get_alloc_amp_hash(codec, HDA_HASH_PINCAP_KEY(nid));
1153 if (!info)
1154 return 0;
1155 if (!info->head.val) {
1156 info->amp_caps = snd_hda_param_read(codec, nid, AC_PAR_PIN_CAP);
1157 info->head.val |= INFO_AMP_CAPS;
1158 }
1159 return info->amp_caps;
1160}
1161EXPORT_SYMBOL_HDA(snd_hda_query_pin_caps);
1162
Linus Torvalds1da177e2005-04-16 15:20:36 -07001163/*
1164 * read the current volume to info
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001165 * if the cache exists, read the cache value.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001166 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02001167static unsigned int get_vol_mute(struct hda_codec *codec,
1168 struct hda_amp_info *info, hda_nid_t nid,
1169 int ch, int direction, int index)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001170{
1171 u32 val, parm;
1172
Takashi Iwai01751f52007-08-10 16:59:39 +02001173 if (info->head.val & INFO_AMP_VOL(ch))
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001174 return info->vol[ch];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001175
1176 parm = ch ? AC_AMP_GET_RIGHT : AC_AMP_GET_LEFT;
1177 parm |= direction == HDA_OUTPUT ? AC_AMP_GET_OUTPUT : AC_AMP_GET_INPUT;
1178 parm |= index;
Takashi Iwai0ba21762007-04-16 11:29:14 +02001179 val = snd_hda_codec_read(codec, nid, 0,
1180 AC_VERB_GET_AMP_GAIN_MUTE, parm);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001181 info->vol[ch] = val & 0xff;
Takashi Iwai01751f52007-08-10 16:59:39 +02001182 info->head.val |= INFO_AMP_VOL(ch);
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001183 return info->vol[ch];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001184}
1185
1186/*
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001187 * write the current volume in info to the h/w and update the cache
Linus Torvalds1da177e2005-04-16 15:20:36 -07001188 */
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001189static void put_vol_mute(struct hda_codec *codec, struct hda_amp_info *info,
Takashi Iwai0ba21762007-04-16 11:29:14 +02001190 hda_nid_t nid, int ch, int direction, int index,
1191 int val)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001192{
1193 u32 parm;
1194
1195 parm = ch ? AC_AMP_SET_RIGHT : AC_AMP_SET_LEFT;
1196 parm |= direction == HDA_OUTPUT ? AC_AMP_SET_OUTPUT : AC_AMP_SET_INPUT;
1197 parm |= index << AC_AMP_SET_INDEX_SHIFT;
1198 parm |= val;
1199 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, parm);
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001200 info->vol[ch] = val;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001201}
1202
1203/*
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001204 * read AMP value. The volume is between 0 to 0x7f, 0x80 = mute bit.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001205 */
Takashi Iwai834be882006-03-01 14:16:17 +01001206int snd_hda_codec_amp_read(struct hda_codec *codec, hda_nid_t nid, int ch,
1207 int direction, int index)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001208{
Takashi Iwai0ba21762007-04-16 11:29:14 +02001209 struct hda_amp_info *info;
1210 info = get_alloc_amp_hash(codec, HDA_HASH_KEY(nid, direction, index));
1211 if (!info)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001212 return 0;
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001213 return get_vol_mute(codec, info, nid, ch, direction, index);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001214}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001215EXPORT_SYMBOL_HDA(snd_hda_codec_amp_read);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001216
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001217/*
1218 * update the AMP value, mask = bit mask to set, val = the value
1219 */
Takashi Iwai834be882006-03-01 14:16:17 +01001220int snd_hda_codec_amp_update(struct hda_codec *codec, hda_nid_t nid, int ch,
1221 int direction, int idx, int mask, int val)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001222{
Takashi Iwai0ba21762007-04-16 11:29:14 +02001223 struct hda_amp_info *info;
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001224
Takashi Iwai0ba21762007-04-16 11:29:14 +02001225 info = get_alloc_amp_hash(codec, HDA_HASH_KEY(nid, direction, idx));
1226 if (!info)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001227 return 0;
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001228 val &= mask;
1229 val |= get_vol_mute(codec, info, nid, ch, direction, idx) & ~mask;
Takashi Iwai82beb8f2007-08-10 17:09:26 +02001230 if (info->vol[ch] == val)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001231 return 0;
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001232 put_vol_mute(codec, info, nid, ch, direction, idx, val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001233 return 1;
1234}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001235EXPORT_SYMBOL_HDA(snd_hda_codec_amp_update);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001236
Takashi Iwai47fd8302007-08-10 17:11:07 +02001237/*
1238 * update the AMP stereo with the same mask and value
1239 */
1240int snd_hda_codec_amp_stereo(struct hda_codec *codec, hda_nid_t nid,
1241 int direction, int idx, int mask, int val)
1242{
1243 int ch, ret = 0;
1244 for (ch = 0; ch < 2; ch++)
1245 ret |= snd_hda_codec_amp_update(codec, nid, ch, direction,
1246 idx, mask, val);
1247 return ret;
1248}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001249EXPORT_SYMBOL_HDA(snd_hda_codec_amp_stereo);
Takashi Iwai47fd8302007-08-10 17:11:07 +02001250
Takashi Iwaicb53c622007-08-10 17:21:45 +02001251#ifdef SND_HDA_NEEDS_RESUME
Takashi Iwaib3ac5632007-08-10 17:03:40 +02001252/* resume the all amp commands from the cache */
1253void snd_hda_codec_resume_amp(struct hda_codec *codec)
1254{
Takashi Iwai603c4012008-07-30 15:01:44 +02001255 struct hda_amp_info *buffer = codec->amp_cache.buf.list;
Takashi Iwaib3ac5632007-08-10 17:03:40 +02001256 int i;
1257
Takashi Iwai603c4012008-07-30 15:01:44 +02001258 for (i = 0; i < codec->amp_cache.buf.used; i++, buffer++) {
Takashi Iwaib3ac5632007-08-10 17:03:40 +02001259 u32 key = buffer->head.key;
1260 hda_nid_t nid;
1261 unsigned int idx, dir, ch;
1262 if (!key)
1263 continue;
1264 nid = key & 0xff;
1265 idx = (key >> 16) & 0xff;
1266 dir = (key >> 24) & 0xff;
1267 for (ch = 0; ch < 2; ch++) {
1268 if (!(buffer->head.val & INFO_AMP_VOL(ch)))
1269 continue;
1270 put_vol_mute(codec, buffer, nid, ch, dir, idx,
1271 buffer->vol[ch]);
1272 }
1273 }
1274}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001275EXPORT_SYMBOL_HDA(snd_hda_codec_resume_amp);
Takashi Iwaicb53c622007-08-10 17:21:45 +02001276#endif /* SND_HDA_NEEDS_RESUME */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001277
Linus Torvalds1da177e2005-04-16 15:20:36 -07001278/* volume */
Takashi Iwai0ba21762007-04-16 11:29:14 +02001279int snd_hda_mixer_amp_volume_info(struct snd_kcontrol *kcontrol,
1280 struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001281{
1282 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1283 u16 nid = get_amp_nid(kcontrol);
1284 u8 chs = get_amp_channels(kcontrol);
1285 int dir = get_amp_direction(kcontrol);
Takashi Iwai29fdbec2009-01-20 13:07:55 +01001286 unsigned int ofs = get_amp_offset(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001287 u32 caps;
1288
1289 caps = query_amp_caps(codec, nid, dir);
Takashi Iwai0ba21762007-04-16 11:29:14 +02001290 /* num steps */
1291 caps = (caps & AC_AMPCAP_NUM_STEPS) >> AC_AMPCAP_NUM_STEPS_SHIFT;
1292 if (!caps) {
1293 printk(KERN_WARNING "hda_codec: "
Takashi Iwai9c8f2ab2008-01-11 16:12:23 +01001294 "num_steps = 0 for NID=0x%x (ctl = %s)\n", nid,
1295 kcontrol->id.name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001296 return -EINVAL;
1297 }
Takashi Iwai29fdbec2009-01-20 13:07:55 +01001298 if (ofs < caps)
1299 caps -= ofs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001300 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
1301 uinfo->count = chs == 3 ? 2 : 1;
1302 uinfo->value.integer.min = 0;
1303 uinfo->value.integer.max = caps;
1304 return 0;
1305}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001306EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_volume_info);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001307
Takashi Iwai29fdbec2009-01-20 13:07:55 +01001308
1309static inline unsigned int
1310read_amp_value(struct hda_codec *codec, hda_nid_t nid,
1311 int ch, int dir, int idx, unsigned int ofs)
1312{
1313 unsigned int val;
1314 val = snd_hda_codec_amp_read(codec, nid, ch, dir, idx);
1315 val &= HDA_AMP_VOLMASK;
1316 if (val >= ofs)
1317 val -= ofs;
1318 else
1319 val = 0;
1320 return val;
1321}
1322
1323static inline int
1324update_amp_value(struct hda_codec *codec, hda_nid_t nid,
1325 int ch, int dir, int idx, unsigned int ofs,
1326 unsigned int val)
1327{
1328 if (val > 0)
1329 val += ofs;
1330 return snd_hda_codec_amp_update(codec, nid, ch, dir, idx,
1331 HDA_AMP_VOLMASK, val);
1332}
1333
Takashi Iwai0ba21762007-04-16 11:29:14 +02001334int snd_hda_mixer_amp_volume_get(struct snd_kcontrol *kcontrol,
1335 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001336{
1337 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1338 hda_nid_t nid = get_amp_nid(kcontrol);
1339 int chs = get_amp_channels(kcontrol);
1340 int dir = get_amp_direction(kcontrol);
1341 int idx = get_amp_index(kcontrol);
Takashi Iwai29fdbec2009-01-20 13:07:55 +01001342 unsigned int ofs = get_amp_offset(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001343 long *valp = ucontrol->value.integer.value;
1344
1345 if (chs & 1)
Takashi Iwai29fdbec2009-01-20 13:07:55 +01001346 *valp++ = read_amp_value(codec, nid, 0, dir, idx, ofs);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001347 if (chs & 2)
Takashi Iwai29fdbec2009-01-20 13:07:55 +01001348 *valp = read_amp_value(codec, nid, 1, dir, idx, ofs);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001349 return 0;
1350}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001351EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_volume_get);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001352
Takashi Iwai0ba21762007-04-16 11:29:14 +02001353int snd_hda_mixer_amp_volume_put(struct snd_kcontrol *kcontrol,
1354 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001355{
1356 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1357 hda_nid_t nid = get_amp_nid(kcontrol);
1358 int chs = get_amp_channels(kcontrol);
1359 int dir = get_amp_direction(kcontrol);
1360 int idx = get_amp_index(kcontrol);
Takashi Iwai29fdbec2009-01-20 13:07:55 +01001361 unsigned int ofs = get_amp_offset(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001362 long *valp = ucontrol->value.integer.value;
1363 int change = 0;
1364
Takashi Iwaicb53c622007-08-10 17:21:45 +02001365 snd_hda_power_up(codec);
Nicolas Grazianob9f5a892005-07-29 12:17:20 +02001366 if (chs & 1) {
Takashi Iwai29fdbec2009-01-20 13:07:55 +01001367 change = update_amp_value(codec, nid, 0, dir, idx, ofs, *valp);
Nicolas Grazianob9f5a892005-07-29 12:17:20 +02001368 valp++;
1369 }
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001370 if (chs & 2)
Takashi Iwai29fdbec2009-01-20 13:07:55 +01001371 change |= update_amp_value(codec, nid, 1, dir, idx, ofs, *valp);
Takashi Iwaicb53c622007-08-10 17:21:45 +02001372 snd_hda_power_down(codec);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001373 return change;
1374}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001375EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_volume_put);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001376
Jaroslav Kysela302e9c52006-07-05 17:39:49 +02001377int snd_hda_mixer_amp_tlv(struct snd_kcontrol *kcontrol, int op_flag,
1378 unsigned int size, unsigned int __user *_tlv)
1379{
1380 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1381 hda_nid_t nid = get_amp_nid(kcontrol);
1382 int dir = get_amp_direction(kcontrol);
Takashi Iwai29fdbec2009-01-20 13:07:55 +01001383 unsigned int ofs = get_amp_offset(kcontrol);
Jaroslav Kysela302e9c52006-07-05 17:39:49 +02001384 u32 caps, val1, val2;
1385
1386 if (size < 4 * sizeof(unsigned int))
1387 return -ENOMEM;
1388 caps = query_amp_caps(codec, nid, dir);
Takashi Iwai0ba21762007-04-16 11:29:14 +02001389 val2 = (caps & AC_AMPCAP_STEP_SIZE) >> AC_AMPCAP_STEP_SIZE_SHIFT;
1390 val2 = (val2 + 1) * 25;
Jaroslav Kysela302e9c52006-07-05 17:39:49 +02001391 val1 = -((caps & AC_AMPCAP_OFFSET) >> AC_AMPCAP_OFFSET_SHIFT);
Takashi Iwai29fdbec2009-01-20 13:07:55 +01001392 val1 += ofs;
Jaroslav Kysela302e9c52006-07-05 17:39:49 +02001393 val1 = ((int)val1) * ((int)val2);
Jaroslav Kysela302e9c52006-07-05 17:39:49 +02001394 if (put_user(SNDRV_CTL_TLVT_DB_SCALE, _tlv))
1395 return -EFAULT;
1396 if (put_user(2 * sizeof(unsigned int), _tlv + 1))
1397 return -EFAULT;
1398 if (put_user(val1, _tlv + 2))
1399 return -EFAULT;
1400 if (put_user(val2, _tlv + 3))
1401 return -EFAULT;
1402 return 0;
1403}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001404EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_tlv);
Jaroslav Kysela302e9c52006-07-05 17:39:49 +02001405
Takashi Iwai2134ea42008-01-10 16:53:55 +01001406/*
1407 * set (static) TLV for virtual master volume; recalculated as max 0dB
1408 */
1409void snd_hda_set_vmaster_tlv(struct hda_codec *codec, hda_nid_t nid, int dir,
1410 unsigned int *tlv)
1411{
1412 u32 caps;
1413 int nums, step;
1414
1415 caps = query_amp_caps(codec, nid, dir);
1416 nums = (caps & AC_AMPCAP_NUM_STEPS) >> AC_AMPCAP_NUM_STEPS_SHIFT;
1417 step = (caps & AC_AMPCAP_STEP_SIZE) >> AC_AMPCAP_STEP_SIZE_SHIFT;
1418 step = (step + 1) * 25;
1419 tlv[0] = SNDRV_CTL_TLVT_DB_SCALE;
1420 tlv[1] = 2 * sizeof(unsigned int);
1421 tlv[2] = -nums * step;
1422 tlv[3] = step;
1423}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001424EXPORT_SYMBOL_HDA(snd_hda_set_vmaster_tlv);
Takashi Iwai2134ea42008-01-10 16:53:55 +01001425
1426/* find a mixer control element with the given name */
Takashi Iwai09f99702008-02-04 12:31:13 +01001427static struct snd_kcontrol *
1428_snd_hda_find_mixer_ctl(struct hda_codec *codec,
1429 const char *name, int idx)
Takashi Iwai2134ea42008-01-10 16:53:55 +01001430{
1431 struct snd_ctl_elem_id id;
1432 memset(&id, 0, sizeof(id));
1433 id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
Takashi Iwai09f99702008-02-04 12:31:13 +01001434 id.index = idx;
Takashi Iwai2134ea42008-01-10 16:53:55 +01001435 strcpy(id.name, name);
1436 return snd_ctl_find_id(codec->bus->card, &id);
1437}
1438
Takashi Iwai09f99702008-02-04 12:31:13 +01001439struct snd_kcontrol *snd_hda_find_mixer_ctl(struct hda_codec *codec,
1440 const char *name)
1441{
1442 return _snd_hda_find_mixer_ctl(codec, name, 0);
1443}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001444EXPORT_SYMBOL_HDA(snd_hda_find_mixer_ctl);
Takashi Iwai09f99702008-02-04 12:31:13 +01001445
Takashi Iwaid13bd412008-07-30 15:01:45 +02001446/* Add a control element and assign to the codec */
1447int snd_hda_ctl_add(struct hda_codec *codec, struct snd_kcontrol *kctl)
1448{
1449 int err;
1450 struct snd_kcontrol **knewp;
1451
1452 err = snd_ctl_add(codec->bus->card, kctl);
1453 if (err < 0)
1454 return err;
1455 knewp = snd_array_new(&codec->mixers);
1456 if (!knewp)
1457 return -ENOMEM;
1458 *knewp = kctl;
1459 return 0;
1460}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001461EXPORT_SYMBOL_HDA(snd_hda_ctl_add);
Takashi Iwaid13bd412008-07-30 15:01:45 +02001462
1463/* Clear all controls assigned to the given codec */
1464void snd_hda_ctls_clear(struct hda_codec *codec)
1465{
1466 int i;
1467 struct snd_kcontrol **kctls = codec->mixers.list;
1468 for (i = 0; i < codec->mixers.used; i++)
1469 snd_ctl_remove(codec->bus->card, kctls[i]);
1470 snd_array_free(&codec->mixers);
1471}
1472
Takashi Iwaia65d6292009-02-23 16:57:04 +01001473/* pseudo device locking
1474 * toggle card->shutdown to allow/disallow the device access (as a hack)
1475 */
1476static int hda_lock_devices(struct snd_card *card)
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001477{
Takashi Iwaia65d6292009-02-23 16:57:04 +01001478 spin_lock(&card->files_lock);
1479 if (card->shutdown) {
1480 spin_unlock(&card->files_lock);
1481 return -EINVAL;
1482 }
1483 card->shutdown = 1;
1484 spin_unlock(&card->files_lock);
1485 return 0;
1486}
1487
1488static void hda_unlock_devices(struct snd_card *card)
1489{
1490 spin_lock(&card->files_lock);
1491 card->shutdown = 0;
1492 spin_unlock(&card->files_lock);
1493}
1494
1495int snd_hda_codec_reset(struct hda_codec *codec)
1496{
1497 struct snd_card *card = codec->bus->card;
1498 int i, pcm;
1499
1500 if (hda_lock_devices(card) < 0)
1501 return -EBUSY;
1502 /* check whether the codec isn't used by any mixer or PCM streams */
1503 if (!list_empty(&card->ctl_files)) {
1504 hda_unlock_devices(card);
1505 return -EBUSY;
1506 }
1507 for (pcm = 0; pcm < codec->num_pcms; pcm++) {
1508 struct hda_pcm *cpcm = &codec->pcm_info[pcm];
1509 if (!cpcm->pcm)
1510 continue;
1511 if (cpcm->pcm->streams[0].substream_opened ||
1512 cpcm->pcm->streams[1].substream_opened) {
1513 hda_unlock_devices(card);
1514 return -EBUSY;
1515 }
1516 }
1517
1518 /* OK, let it free */
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001519
1520#ifdef CONFIG_SND_HDA_POWER_SAVE
1521 cancel_delayed_work(&codec->power_work);
Takashi Iwai6acaed32009-01-12 10:09:24 +01001522 flush_workqueue(codec->bus->workq);
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001523#endif
1524 snd_hda_ctls_clear(codec);
1525 /* relase PCMs */
1526 for (i = 0; i < codec->num_pcms; i++) {
Takashi Iwai529bd6c2008-11-27 14:17:01 +01001527 if (codec->pcm_info[i].pcm) {
Takashi Iwaia65d6292009-02-23 16:57:04 +01001528 snd_device_free(card, codec->pcm_info[i].pcm);
Takashi Iwai529bd6c2008-11-27 14:17:01 +01001529 clear_bit(codec->pcm_info[i].device,
1530 codec->bus->pcm_dev_bits);
1531 }
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001532 }
1533 if (codec->patch_ops.free)
1534 codec->patch_ops.free(codec);
Takashi Iwai56d17712008-11-28 14:36:23 +01001535 codec->proc_widget_hook = NULL;
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001536 codec->spec = NULL;
1537 free_hda_cache(&codec->amp_cache);
1538 free_hda_cache(&codec->cmd_cache);
Takashi Iwai827057f2008-12-19 10:12:02 +01001539 init_hda_cache(&codec->amp_cache, sizeof(struct hda_amp_info));
1540 init_hda_cache(&codec->cmd_cache, sizeof(struct hda_cache_head));
Takashi Iwai346ff702009-02-23 09:42:57 +01001541 /* free only driver_pins so that init_pins + user_pins are restored */
1542 snd_array_free(&codec->driver_pins);
Takashi Iwai3be14142009-02-20 14:11:16 +01001543 restore_pincfgs(codec);
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001544 codec->num_pcms = 0;
1545 codec->pcm_info = NULL;
1546 codec->preset = NULL;
Takashi Iwaid1f1af22009-03-02 10:35:29 +01001547 memset(&codec->patch_ops, 0, sizeof(codec->patch_ops));
1548 codec->slave_dig_outs = NULL;
1549 codec->spdif_status_reset = 0;
Takashi Iwai1289e9e2008-11-27 15:47:11 +01001550 module_put(codec->owner);
1551 codec->owner = NULL;
Takashi Iwaia65d6292009-02-23 16:57:04 +01001552
1553 /* allow device access again */
1554 hda_unlock_devices(card);
1555 return 0;
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001556}
1557
Takashi Iwai2134ea42008-01-10 16:53:55 +01001558/* create a virtual master control and add slaves */
1559int snd_hda_add_vmaster(struct hda_codec *codec, char *name,
1560 unsigned int *tlv, const char **slaves)
1561{
1562 struct snd_kcontrol *kctl;
1563 const char **s;
1564 int err;
1565
Takashi Iwai2f085542008-02-22 18:43:50 +01001566 for (s = slaves; *s && !snd_hda_find_mixer_ctl(codec, *s); s++)
1567 ;
1568 if (!*s) {
1569 snd_printdd("No slave found for %s\n", name);
1570 return 0;
1571 }
Takashi Iwai2134ea42008-01-10 16:53:55 +01001572 kctl = snd_ctl_make_virtual_master(name, tlv);
1573 if (!kctl)
1574 return -ENOMEM;
Takashi Iwaid13bd412008-07-30 15:01:45 +02001575 err = snd_hda_ctl_add(codec, kctl);
Takashi Iwai2134ea42008-01-10 16:53:55 +01001576 if (err < 0)
1577 return err;
1578
1579 for (s = slaves; *s; s++) {
1580 struct snd_kcontrol *sctl;
Takashi Iwai7a411ee2009-03-06 10:08:14 +01001581 int i = 0;
1582 for (;;) {
1583 sctl = _snd_hda_find_mixer_ctl(codec, *s, i);
1584 if (!sctl) {
1585 if (!i)
1586 snd_printdd("Cannot find slave %s, "
1587 "skipped\n", *s);
1588 break;
1589 }
1590 err = snd_ctl_add_slave(kctl, sctl);
1591 if (err < 0)
1592 return err;
1593 i++;
Takashi Iwai2134ea42008-01-10 16:53:55 +01001594 }
Takashi Iwai2134ea42008-01-10 16:53:55 +01001595 }
1596 return 0;
1597}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001598EXPORT_SYMBOL_HDA(snd_hda_add_vmaster);
Takashi Iwai2134ea42008-01-10 16:53:55 +01001599
Linus Torvalds1da177e2005-04-16 15:20:36 -07001600/* switch */
Takashi Iwai0ba21762007-04-16 11:29:14 +02001601int snd_hda_mixer_amp_switch_info(struct snd_kcontrol *kcontrol,
1602 struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001603{
1604 int chs = get_amp_channels(kcontrol);
1605
1606 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
1607 uinfo->count = chs == 3 ? 2 : 1;
1608 uinfo->value.integer.min = 0;
1609 uinfo->value.integer.max = 1;
1610 return 0;
1611}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001612EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_switch_info);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001613
Takashi Iwai0ba21762007-04-16 11:29:14 +02001614int snd_hda_mixer_amp_switch_get(struct snd_kcontrol *kcontrol,
1615 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001616{
1617 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1618 hda_nid_t nid = get_amp_nid(kcontrol);
1619 int chs = get_amp_channels(kcontrol);
1620 int dir = get_amp_direction(kcontrol);
1621 int idx = get_amp_index(kcontrol);
1622 long *valp = ucontrol->value.integer.value;
1623
1624 if (chs & 1)
Takashi Iwai0ba21762007-04-16 11:29:14 +02001625 *valp++ = (snd_hda_codec_amp_read(codec, nid, 0, dir, idx) &
Takashi Iwai47fd8302007-08-10 17:11:07 +02001626 HDA_AMP_MUTE) ? 0 : 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001627 if (chs & 2)
Takashi Iwai0ba21762007-04-16 11:29:14 +02001628 *valp = (snd_hda_codec_amp_read(codec, nid, 1, dir, idx) &
Takashi Iwai47fd8302007-08-10 17:11:07 +02001629 HDA_AMP_MUTE) ? 0 : 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001630 return 0;
1631}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001632EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_switch_get);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001633
Takashi Iwai0ba21762007-04-16 11:29:14 +02001634int snd_hda_mixer_amp_switch_put(struct snd_kcontrol *kcontrol,
1635 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001636{
1637 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1638 hda_nid_t nid = get_amp_nid(kcontrol);
1639 int chs = get_amp_channels(kcontrol);
1640 int dir = get_amp_direction(kcontrol);
1641 int idx = get_amp_index(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001642 long *valp = ucontrol->value.integer.value;
1643 int change = 0;
1644
Takashi Iwaicb53c622007-08-10 17:21:45 +02001645 snd_hda_power_up(codec);
Nicolas Grazianob9f5a892005-07-29 12:17:20 +02001646 if (chs & 1) {
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001647 change = snd_hda_codec_amp_update(codec, nid, 0, dir, idx,
Takashi Iwai47fd8302007-08-10 17:11:07 +02001648 HDA_AMP_MUTE,
1649 *valp ? 0 : HDA_AMP_MUTE);
Nicolas Grazianob9f5a892005-07-29 12:17:20 +02001650 valp++;
1651 }
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001652 if (chs & 2)
1653 change |= snd_hda_codec_amp_update(codec, nid, 1, dir, idx,
Takashi Iwai47fd8302007-08-10 17:11:07 +02001654 HDA_AMP_MUTE,
1655 *valp ? 0 : HDA_AMP_MUTE);
Takashi Iwaicb53c622007-08-10 17:21:45 +02001656#ifdef CONFIG_SND_HDA_POWER_SAVE
1657 if (codec->patch_ops.check_power_status)
1658 codec->patch_ops.check_power_status(codec, nid);
1659#endif
1660 snd_hda_power_down(codec);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001661 return change;
1662}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001663EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_switch_put);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001664
1665/*
Takashi Iwai985be542005-11-02 18:26:49 +01001666 * bound volume controls
1667 *
1668 * bind multiple volumes (# indices, from 0)
1669 */
1670
1671#define AMP_VAL_IDX_SHIFT 19
1672#define AMP_VAL_IDX_MASK (0x0f<<19)
1673
Takashi Iwai0ba21762007-04-16 11:29:14 +02001674int snd_hda_mixer_bind_switch_get(struct snd_kcontrol *kcontrol,
1675 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai985be542005-11-02 18:26:49 +01001676{
1677 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1678 unsigned long pval;
1679 int err;
1680
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001681 mutex_lock(&codec->control_mutex);
Takashi Iwai985be542005-11-02 18:26:49 +01001682 pval = kcontrol->private_value;
1683 kcontrol->private_value = pval & ~AMP_VAL_IDX_MASK; /* index 0 */
1684 err = snd_hda_mixer_amp_switch_get(kcontrol, ucontrol);
1685 kcontrol->private_value = pval;
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001686 mutex_unlock(&codec->control_mutex);
Takashi Iwai985be542005-11-02 18:26:49 +01001687 return err;
1688}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001689EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_switch_get);
Takashi Iwai985be542005-11-02 18:26:49 +01001690
Takashi Iwai0ba21762007-04-16 11:29:14 +02001691int snd_hda_mixer_bind_switch_put(struct snd_kcontrol *kcontrol,
1692 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai985be542005-11-02 18:26:49 +01001693{
1694 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1695 unsigned long pval;
1696 int i, indices, err = 0, change = 0;
1697
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001698 mutex_lock(&codec->control_mutex);
Takashi Iwai985be542005-11-02 18:26:49 +01001699 pval = kcontrol->private_value;
1700 indices = (pval & AMP_VAL_IDX_MASK) >> AMP_VAL_IDX_SHIFT;
1701 for (i = 0; i < indices; i++) {
Takashi Iwai0ba21762007-04-16 11:29:14 +02001702 kcontrol->private_value = (pval & ~AMP_VAL_IDX_MASK) |
1703 (i << AMP_VAL_IDX_SHIFT);
Takashi Iwai985be542005-11-02 18:26:49 +01001704 err = snd_hda_mixer_amp_switch_put(kcontrol, ucontrol);
1705 if (err < 0)
1706 break;
1707 change |= err;
1708 }
1709 kcontrol->private_value = pval;
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001710 mutex_unlock(&codec->control_mutex);
Takashi Iwai985be542005-11-02 18:26:49 +01001711 return err < 0 ? err : change;
1712}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001713EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_switch_put);
Takashi Iwai985be542005-11-02 18:26:49 +01001714
1715/*
Takashi Iwai532d5382007-07-27 19:02:40 +02001716 * generic bound volume/swtich controls
1717 */
1718int snd_hda_mixer_bind_ctls_info(struct snd_kcontrol *kcontrol,
1719 struct snd_ctl_elem_info *uinfo)
1720{
1721 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1722 struct hda_bind_ctls *c;
1723 int err;
1724
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001725 mutex_lock(&codec->control_mutex);
Serge A. Suchkov14c65f92008-02-22 18:43:16 +01001726 c = (struct hda_bind_ctls *)kcontrol->private_value;
Takashi Iwai532d5382007-07-27 19:02:40 +02001727 kcontrol->private_value = *c->values;
1728 err = c->ops->info(kcontrol, uinfo);
1729 kcontrol->private_value = (long)c;
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001730 mutex_unlock(&codec->control_mutex);
Takashi Iwai532d5382007-07-27 19:02:40 +02001731 return err;
1732}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001733EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_ctls_info);
Takashi Iwai532d5382007-07-27 19:02:40 +02001734
1735int snd_hda_mixer_bind_ctls_get(struct snd_kcontrol *kcontrol,
1736 struct snd_ctl_elem_value *ucontrol)
1737{
1738 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1739 struct hda_bind_ctls *c;
1740 int err;
1741
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001742 mutex_lock(&codec->control_mutex);
Serge A. Suchkov14c65f92008-02-22 18:43:16 +01001743 c = (struct hda_bind_ctls *)kcontrol->private_value;
Takashi Iwai532d5382007-07-27 19:02:40 +02001744 kcontrol->private_value = *c->values;
1745 err = c->ops->get(kcontrol, ucontrol);
1746 kcontrol->private_value = (long)c;
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001747 mutex_unlock(&codec->control_mutex);
Takashi Iwai532d5382007-07-27 19:02:40 +02001748 return err;
1749}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001750EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_ctls_get);
Takashi Iwai532d5382007-07-27 19:02:40 +02001751
1752int snd_hda_mixer_bind_ctls_put(struct snd_kcontrol *kcontrol,
1753 struct snd_ctl_elem_value *ucontrol)
1754{
1755 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1756 struct hda_bind_ctls *c;
1757 unsigned long *vals;
1758 int err = 0, change = 0;
1759
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001760 mutex_lock(&codec->control_mutex);
Serge A. Suchkov14c65f92008-02-22 18:43:16 +01001761 c = (struct hda_bind_ctls *)kcontrol->private_value;
Takashi Iwai532d5382007-07-27 19:02:40 +02001762 for (vals = c->values; *vals; vals++) {
1763 kcontrol->private_value = *vals;
1764 err = c->ops->put(kcontrol, ucontrol);
1765 if (err < 0)
1766 break;
1767 change |= err;
1768 }
1769 kcontrol->private_value = (long)c;
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001770 mutex_unlock(&codec->control_mutex);
Takashi Iwai532d5382007-07-27 19:02:40 +02001771 return err < 0 ? err : change;
1772}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001773EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_ctls_put);
Takashi Iwai532d5382007-07-27 19:02:40 +02001774
1775int snd_hda_mixer_bind_tlv(struct snd_kcontrol *kcontrol, int op_flag,
1776 unsigned int size, unsigned int __user *tlv)
1777{
1778 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1779 struct hda_bind_ctls *c;
1780 int err;
1781
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001782 mutex_lock(&codec->control_mutex);
Serge A. Suchkov14c65f92008-02-22 18:43:16 +01001783 c = (struct hda_bind_ctls *)kcontrol->private_value;
Takashi Iwai532d5382007-07-27 19:02:40 +02001784 kcontrol->private_value = *c->values;
1785 err = c->ops->tlv(kcontrol, op_flag, size, tlv);
1786 kcontrol->private_value = (long)c;
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001787 mutex_unlock(&codec->control_mutex);
Takashi Iwai532d5382007-07-27 19:02:40 +02001788 return err;
1789}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001790EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_tlv);
Takashi Iwai532d5382007-07-27 19:02:40 +02001791
1792struct hda_ctl_ops snd_hda_bind_vol = {
1793 .info = snd_hda_mixer_amp_volume_info,
1794 .get = snd_hda_mixer_amp_volume_get,
1795 .put = snd_hda_mixer_amp_volume_put,
1796 .tlv = snd_hda_mixer_amp_tlv
1797};
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001798EXPORT_SYMBOL_HDA(snd_hda_bind_vol);
Takashi Iwai532d5382007-07-27 19:02:40 +02001799
1800struct hda_ctl_ops snd_hda_bind_sw = {
1801 .info = snd_hda_mixer_amp_switch_info,
1802 .get = snd_hda_mixer_amp_switch_get,
1803 .put = snd_hda_mixer_amp_switch_put,
1804 .tlv = snd_hda_mixer_amp_tlv
1805};
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001806EXPORT_SYMBOL_HDA(snd_hda_bind_sw);
Takashi Iwai532d5382007-07-27 19:02:40 +02001807
1808/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07001809 * SPDIF out controls
1810 */
1811
Takashi Iwai0ba21762007-04-16 11:29:14 +02001812static int snd_hda_spdif_mask_info(struct snd_kcontrol *kcontrol,
1813 struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001814{
1815 uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
1816 uinfo->count = 1;
1817 return 0;
1818}
1819
Takashi Iwai0ba21762007-04-16 11:29:14 +02001820static int snd_hda_spdif_cmask_get(struct snd_kcontrol *kcontrol,
1821 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001822{
1823 ucontrol->value.iec958.status[0] = IEC958_AES0_PROFESSIONAL |
1824 IEC958_AES0_NONAUDIO |
1825 IEC958_AES0_CON_EMPHASIS_5015 |
1826 IEC958_AES0_CON_NOT_COPYRIGHT;
1827 ucontrol->value.iec958.status[1] = IEC958_AES1_CON_CATEGORY |
1828 IEC958_AES1_CON_ORIGINAL;
1829 return 0;
1830}
1831
Takashi Iwai0ba21762007-04-16 11:29:14 +02001832static int snd_hda_spdif_pmask_get(struct snd_kcontrol *kcontrol,
1833 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001834{
1835 ucontrol->value.iec958.status[0] = IEC958_AES0_PROFESSIONAL |
1836 IEC958_AES0_NONAUDIO |
1837 IEC958_AES0_PRO_EMPHASIS_5015;
1838 return 0;
1839}
1840
Takashi Iwai0ba21762007-04-16 11:29:14 +02001841static int snd_hda_spdif_default_get(struct snd_kcontrol *kcontrol,
1842 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001843{
1844 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1845
1846 ucontrol->value.iec958.status[0] = codec->spdif_status & 0xff;
1847 ucontrol->value.iec958.status[1] = (codec->spdif_status >> 8) & 0xff;
1848 ucontrol->value.iec958.status[2] = (codec->spdif_status >> 16) & 0xff;
1849 ucontrol->value.iec958.status[3] = (codec->spdif_status >> 24) & 0xff;
1850
1851 return 0;
1852}
1853
1854/* convert from SPDIF status bits to HDA SPDIF bits
1855 * bit 0 (DigEn) is always set zero (to be filled later)
1856 */
1857static unsigned short convert_from_spdif_status(unsigned int sbits)
1858{
1859 unsigned short val = 0;
1860
1861 if (sbits & IEC958_AES0_PROFESSIONAL)
Takashi Iwai0ba21762007-04-16 11:29:14 +02001862 val |= AC_DIG1_PROFESSIONAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001863 if (sbits & IEC958_AES0_NONAUDIO)
Takashi Iwai0ba21762007-04-16 11:29:14 +02001864 val |= AC_DIG1_NONAUDIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001865 if (sbits & IEC958_AES0_PROFESSIONAL) {
Takashi Iwai0ba21762007-04-16 11:29:14 +02001866 if ((sbits & IEC958_AES0_PRO_EMPHASIS) ==
1867 IEC958_AES0_PRO_EMPHASIS_5015)
1868 val |= AC_DIG1_EMPHASIS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001869 } else {
Takashi Iwai0ba21762007-04-16 11:29:14 +02001870 if ((sbits & IEC958_AES0_CON_EMPHASIS) ==
1871 IEC958_AES0_CON_EMPHASIS_5015)
1872 val |= AC_DIG1_EMPHASIS;
1873 if (!(sbits & IEC958_AES0_CON_NOT_COPYRIGHT))
1874 val |= AC_DIG1_COPYRIGHT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001875 if (sbits & (IEC958_AES1_CON_ORIGINAL << 8))
Takashi Iwai0ba21762007-04-16 11:29:14 +02001876 val |= AC_DIG1_LEVEL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001877 val |= sbits & (IEC958_AES1_CON_CATEGORY << 8);
1878 }
1879 return val;
1880}
1881
1882/* convert to SPDIF status bits from HDA SPDIF bits
1883 */
1884static unsigned int convert_to_spdif_status(unsigned short val)
1885{
1886 unsigned int sbits = 0;
1887
Takashi Iwai0ba21762007-04-16 11:29:14 +02001888 if (val & AC_DIG1_NONAUDIO)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001889 sbits |= IEC958_AES0_NONAUDIO;
Takashi Iwai0ba21762007-04-16 11:29:14 +02001890 if (val & AC_DIG1_PROFESSIONAL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001891 sbits |= IEC958_AES0_PROFESSIONAL;
1892 if (sbits & IEC958_AES0_PROFESSIONAL) {
Takashi Iwai0ba21762007-04-16 11:29:14 +02001893 if (sbits & AC_DIG1_EMPHASIS)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001894 sbits |= IEC958_AES0_PRO_EMPHASIS_5015;
1895 } else {
Takashi Iwai0ba21762007-04-16 11:29:14 +02001896 if (val & AC_DIG1_EMPHASIS)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001897 sbits |= IEC958_AES0_CON_EMPHASIS_5015;
Takashi Iwai0ba21762007-04-16 11:29:14 +02001898 if (!(val & AC_DIG1_COPYRIGHT))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001899 sbits |= IEC958_AES0_CON_NOT_COPYRIGHT;
Takashi Iwai0ba21762007-04-16 11:29:14 +02001900 if (val & AC_DIG1_LEVEL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001901 sbits |= (IEC958_AES1_CON_ORIGINAL << 8);
1902 sbits |= val & (0x7f << 8);
1903 }
1904 return sbits;
1905}
1906
Takashi Iwai2f728532008-09-25 16:32:41 +02001907/* set digital convert verbs both for the given NID and its slaves */
1908static void set_dig_out(struct hda_codec *codec, hda_nid_t nid,
1909 int verb, int val)
1910{
1911 hda_nid_t *d;
1912
Takashi Iwai9e976972008-11-25 08:17:20 +01001913 snd_hda_codec_write_cache(codec, nid, 0, verb, val);
Takashi Iwai2f728532008-09-25 16:32:41 +02001914 d = codec->slave_dig_outs;
1915 if (!d)
1916 return;
1917 for (; *d; d++)
Takashi Iwai9e976972008-11-25 08:17:20 +01001918 snd_hda_codec_write_cache(codec, *d, 0, verb, val);
Takashi Iwai2f728532008-09-25 16:32:41 +02001919}
1920
1921static inline void set_dig_out_convert(struct hda_codec *codec, hda_nid_t nid,
1922 int dig1, int dig2)
1923{
1924 if (dig1 != -1)
1925 set_dig_out(codec, nid, AC_VERB_SET_DIGI_CONVERT_1, dig1);
1926 if (dig2 != -1)
1927 set_dig_out(codec, nid, AC_VERB_SET_DIGI_CONVERT_2, dig2);
1928}
1929
Takashi Iwai0ba21762007-04-16 11:29:14 +02001930static int snd_hda_spdif_default_put(struct snd_kcontrol *kcontrol,
1931 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001932{
1933 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1934 hda_nid_t nid = kcontrol->private_value;
1935 unsigned short val;
1936 int change;
1937
Ingo Molnar62932df2006-01-16 16:34:20 +01001938 mutex_lock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001939 codec->spdif_status = ucontrol->value.iec958.status[0] |
1940 ((unsigned int)ucontrol->value.iec958.status[1] << 8) |
1941 ((unsigned int)ucontrol->value.iec958.status[2] << 16) |
1942 ((unsigned int)ucontrol->value.iec958.status[3] << 24);
1943 val = convert_from_spdif_status(codec->spdif_status);
1944 val |= codec->spdif_ctls & 1;
1945 change = codec->spdif_ctls != val;
1946 codec->spdif_ctls = val;
1947
Takashi Iwai2f728532008-09-25 16:32:41 +02001948 if (change)
1949 set_dig_out_convert(codec, nid, val & 0xff, (val >> 8) & 0xff);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001950
Ingo Molnar62932df2006-01-16 16:34:20 +01001951 mutex_unlock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001952 return change;
1953}
1954
Takashi Iwaia5ce8892007-07-23 15:42:26 +02001955#define snd_hda_spdif_out_switch_info snd_ctl_boolean_mono_info
Linus Torvalds1da177e2005-04-16 15:20:36 -07001956
Takashi Iwai0ba21762007-04-16 11:29:14 +02001957static int snd_hda_spdif_out_switch_get(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
Takashi Iwai0ba21762007-04-16 11:29:14 +02001962 ucontrol->value.integer.value[0] = codec->spdif_ctls & AC_DIG1_ENABLE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001963 return 0;
1964}
1965
Takashi Iwai0ba21762007-04-16 11:29:14 +02001966static int snd_hda_spdif_out_switch_put(struct snd_kcontrol *kcontrol,
1967 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001968{
1969 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1970 hda_nid_t nid = kcontrol->private_value;
1971 unsigned short val;
1972 int change;
1973
Ingo Molnar62932df2006-01-16 16:34:20 +01001974 mutex_lock(&codec->spdif_mutex);
Takashi Iwai0ba21762007-04-16 11:29:14 +02001975 val = codec->spdif_ctls & ~AC_DIG1_ENABLE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001976 if (ucontrol->value.integer.value[0])
Takashi Iwai0ba21762007-04-16 11:29:14 +02001977 val |= AC_DIG1_ENABLE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001978 change = codec->spdif_ctls != val;
Takashi Iwai82beb8f2007-08-10 17:09:26 +02001979 if (change) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001980 codec->spdif_ctls = val;
Takashi Iwai2f728532008-09-25 16:32:41 +02001981 set_dig_out_convert(codec, nid, val & 0xff, -1);
Takashi Iwai0ba21762007-04-16 11:29:14 +02001982 /* unmute amp switch (if any) */
1983 if ((get_wcaps(codec, nid) & AC_WCAP_OUT_AMP) &&
Takashi Iwai47fd8302007-08-10 17:11:07 +02001984 (val & AC_DIG1_ENABLE))
1985 snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0,
1986 HDA_AMP_MUTE, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001987 }
Ingo Molnar62932df2006-01-16 16:34:20 +01001988 mutex_unlock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001989 return change;
1990}
1991
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01001992static struct snd_kcontrol_new dig_mixes[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001993 {
1994 .access = SNDRV_CTL_ELEM_ACCESS_READ,
1995 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1996 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,CON_MASK),
1997 .info = snd_hda_spdif_mask_info,
1998 .get = snd_hda_spdif_cmask_get,
1999 },
2000 {
2001 .access = SNDRV_CTL_ELEM_ACCESS_READ,
2002 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2003 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,PRO_MASK),
2004 .info = snd_hda_spdif_mask_info,
2005 .get = snd_hda_spdif_pmask_get,
2006 },
2007 {
2008 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2009 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT),
2010 .info = snd_hda_spdif_mask_info,
2011 .get = snd_hda_spdif_default_get,
2012 .put = snd_hda_spdif_default_put,
2013 },
2014 {
2015 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2016 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,SWITCH),
2017 .info = snd_hda_spdif_out_switch_info,
2018 .get = snd_hda_spdif_out_switch_get,
2019 .put = snd_hda_spdif_out_switch_put,
2020 },
2021 { } /* end */
2022};
2023
Takashi Iwai09f99702008-02-04 12:31:13 +01002024#define SPDIF_MAX_IDX 4 /* 4 instances should be enough to probe */
2025
Linus Torvalds1da177e2005-04-16 15:20:36 -07002026/**
2027 * snd_hda_create_spdif_out_ctls - create Output SPDIF-related controls
2028 * @codec: the HDA codec
2029 * @nid: audio out widget NID
2030 *
2031 * Creates controls related with the SPDIF output.
2032 * Called from each patch supporting the SPDIF out.
2033 *
2034 * Returns 0 if successful, or a negative error code.
2035 */
Takashi Iwai12f288b2007-08-02 15:51:59 +02002036int snd_hda_create_spdif_out_ctls(struct hda_codec *codec, hda_nid_t nid)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002037{
2038 int err;
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01002039 struct snd_kcontrol *kctl;
2040 struct snd_kcontrol_new *dig_mix;
Takashi Iwai09f99702008-02-04 12:31:13 +01002041 int idx;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002042
Takashi Iwai09f99702008-02-04 12:31:13 +01002043 for (idx = 0; idx < SPDIF_MAX_IDX; idx++) {
2044 if (!_snd_hda_find_mixer_ctl(codec, "IEC958 Playback Switch",
2045 idx))
2046 break;
2047 }
2048 if (idx >= SPDIF_MAX_IDX) {
2049 printk(KERN_ERR "hda_codec: too many IEC958 outputs\n");
2050 return -EBUSY;
2051 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002052 for (dig_mix = dig_mixes; dig_mix->name; dig_mix++) {
2053 kctl = snd_ctl_new1(dig_mix, codec);
Takashi Iwaib91f0802008-11-04 08:43:08 +01002054 if (!kctl)
2055 return -ENOMEM;
Takashi Iwai09f99702008-02-04 12:31:13 +01002056 kctl->id.index = idx;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002057 kctl->private_value = nid;
Takashi Iwaid13bd412008-07-30 15:01:45 +02002058 err = snd_hda_ctl_add(codec, kctl);
Takashi Iwai0ba21762007-04-16 11:29:14 +02002059 if (err < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002060 return err;
2061 }
Takashi Iwai0ba21762007-04-16 11:29:14 +02002062 codec->spdif_ctls =
Andrew Paprocki3982d172007-12-19 12:13:44 +01002063 snd_hda_codec_read(codec, nid, 0,
2064 AC_VERB_GET_DIGI_CONVERT_1, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002065 codec->spdif_status = convert_to_spdif_status(codec->spdif_ctls);
2066 return 0;
2067}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002068EXPORT_SYMBOL_HDA(snd_hda_create_spdif_out_ctls);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002069
2070/*
Takashi Iwai9a081602008-02-12 18:37:26 +01002071 * SPDIF sharing with analog output
2072 */
2073static int spdif_share_sw_get(struct snd_kcontrol *kcontrol,
2074 struct snd_ctl_elem_value *ucontrol)
2075{
2076 struct hda_multi_out *mout = snd_kcontrol_chip(kcontrol);
2077 ucontrol->value.integer.value[0] = mout->share_spdif;
2078 return 0;
2079}
2080
2081static int spdif_share_sw_put(struct snd_kcontrol *kcontrol,
2082 struct snd_ctl_elem_value *ucontrol)
2083{
2084 struct hda_multi_out *mout = snd_kcontrol_chip(kcontrol);
2085 mout->share_spdif = !!ucontrol->value.integer.value[0];
2086 return 0;
2087}
2088
2089static struct snd_kcontrol_new spdif_share_sw = {
2090 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2091 .name = "IEC958 Default PCM Playback Switch",
2092 .info = snd_ctl_boolean_mono_info,
2093 .get = spdif_share_sw_get,
2094 .put = spdif_share_sw_put,
2095};
2096
2097int snd_hda_create_spdif_share_sw(struct hda_codec *codec,
2098 struct hda_multi_out *mout)
2099{
2100 if (!mout->dig_out_nid)
2101 return 0;
2102 /* ATTENTION: here mout is passed as private_data, instead of codec */
Takashi Iwaid13bd412008-07-30 15:01:45 +02002103 return snd_hda_ctl_add(codec,
Takashi Iwai9a081602008-02-12 18:37:26 +01002104 snd_ctl_new1(&spdif_share_sw, mout));
2105}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002106EXPORT_SYMBOL_HDA(snd_hda_create_spdif_share_sw);
Takashi Iwai9a081602008-02-12 18:37:26 +01002107
2108/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002109 * SPDIF input
2110 */
2111
2112#define snd_hda_spdif_in_switch_info snd_hda_spdif_out_switch_info
2113
Takashi Iwai0ba21762007-04-16 11:29:14 +02002114static int snd_hda_spdif_in_switch_get(struct snd_kcontrol *kcontrol,
2115 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002116{
2117 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2118
2119 ucontrol->value.integer.value[0] = codec->spdif_in_enable;
2120 return 0;
2121}
2122
Takashi Iwai0ba21762007-04-16 11:29:14 +02002123static int snd_hda_spdif_in_switch_put(struct snd_kcontrol *kcontrol,
2124 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002125{
2126 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2127 hda_nid_t nid = kcontrol->private_value;
2128 unsigned int val = !!ucontrol->value.integer.value[0];
2129 int change;
2130
Ingo Molnar62932df2006-01-16 16:34:20 +01002131 mutex_lock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002132 change = codec->spdif_in_enable != val;
Takashi Iwai82beb8f2007-08-10 17:09:26 +02002133 if (change) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002134 codec->spdif_in_enable = val;
Takashi Iwai82beb8f2007-08-10 17:09:26 +02002135 snd_hda_codec_write_cache(codec, nid, 0,
2136 AC_VERB_SET_DIGI_CONVERT_1, val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002137 }
Ingo Molnar62932df2006-01-16 16:34:20 +01002138 mutex_unlock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002139 return change;
2140}
2141
Takashi Iwai0ba21762007-04-16 11:29:14 +02002142static int snd_hda_spdif_in_status_get(struct snd_kcontrol *kcontrol,
2143 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002144{
2145 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2146 hda_nid_t nid = kcontrol->private_value;
2147 unsigned short val;
2148 unsigned int sbits;
2149
Andrew Paprocki3982d172007-12-19 12:13:44 +01002150 val = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_DIGI_CONVERT_1, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002151 sbits = convert_to_spdif_status(val);
2152 ucontrol->value.iec958.status[0] = sbits;
2153 ucontrol->value.iec958.status[1] = sbits >> 8;
2154 ucontrol->value.iec958.status[2] = sbits >> 16;
2155 ucontrol->value.iec958.status[3] = sbits >> 24;
2156 return 0;
2157}
2158
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01002159static struct snd_kcontrol_new dig_in_ctls[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002160 {
2161 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2162 .name = SNDRV_CTL_NAME_IEC958("",CAPTURE,SWITCH),
2163 .info = snd_hda_spdif_in_switch_info,
2164 .get = snd_hda_spdif_in_switch_get,
2165 .put = snd_hda_spdif_in_switch_put,
2166 },
2167 {
2168 .access = SNDRV_CTL_ELEM_ACCESS_READ,
2169 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2170 .name = SNDRV_CTL_NAME_IEC958("",CAPTURE,DEFAULT),
2171 .info = snd_hda_spdif_mask_info,
2172 .get = snd_hda_spdif_in_status_get,
2173 },
2174 { } /* end */
2175};
2176
2177/**
2178 * snd_hda_create_spdif_in_ctls - create Input SPDIF-related controls
2179 * @codec: the HDA codec
2180 * @nid: audio in widget NID
2181 *
2182 * Creates controls related with the SPDIF input.
2183 * Called from each patch supporting the SPDIF in.
2184 *
2185 * Returns 0 if successful, or a negative error code.
2186 */
Takashi Iwai12f288b2007-08-02 15:51:59 +02002187int snd_hda_create_spdif_in_ctls(struct hda_codec *codec, hda_nid_t nid)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002188{
2189 int err;
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01002190 struct snd_kcontrol *kctl;
2191 struct snd_kcontrol_new *dig_mix;
Takashi Iwai09f99702008-02-04 12:31:13 +01002192 int idx;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002193
Takashi Iwai09f99702008-02-04 12:31:13 +01002194 for (idx = 0; idx < SPDIF_MAX_IDX; idx++) {
2195 if (!_snd_hda_find_mixer_ctl(codec, "IEC958 Capture Switch",
2196 idx))
2197 break;
2198 }
2199 if (idx >= SPDIF_MAX_IDX) {
2200 printk(KERN_ERR "hda_codec: too many IEC958 inputs\n");
2201 return -EBUSY;
2202 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002203 for (dig_mix = dig_in_ctls; dig_mix->name; dig_mix++) {
2204 kctl = snd_ctl_new1(dig_mix, codec);
Takashi Iwaic8dcdf82009-02-06 16:21:20 +01002205 if (!kctl)
2206 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002207 kctl->private_value = nid;
Takashi Iwaid13bd412008-07-30 15:01:45 +02002208 err = snd_hda_ctl_add(codec, kctl);
Takashi Iwai0ba21762007-04-16 11:29:14 +02002209 if (err < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002210 return err;
2211 }
Takashi Iwai0ba21762007-04-16 11:29:14 +02002212 codec->spdif_in_enable =
Andrew Paprocki3982d172007-12-19 12:13:44 +01002213 snd_hda_codec_read(codec, nid, 0,
2214 AC_VERB_GET_DIGI_CONVERT_1, 0) &
Takashi Iwai0ba21762007-04-16 11:29:14 +02002215 AC_DIG1_ENABLE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002216 return 0;
2217}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002218EXPORT_SYMBOL_HDA(snd_hda_create_spdif_in_ctls);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002219
Takashi Iwaicb53c622007-08-10 17:21:45 +02002220#ifdef SND_HDA_NEEDS_RESUME
Takashi Iwai82beb8f2007-08-10 17:09:26 +02002221/*
2222 * command cache
2223 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002224
Takashi Iwaib3ac5632007-08-10 17:03:40 +02002225/* build a 32bit cache key with the widget id and the command parameter */
2226#define build_cmd_cache_key(nid, verb) ((verb << 8) | nid)
2227#define get_cmd_cache_nid(key) ((key) & 0xff)
2228#define get_cmd_cache_cmd(key) (((key) >> 8) & 0xffff)
2229
2230/**
2231 * snd_hda_codec_write_cache - send a single command with caching
2232 * @codec: the HDA codec
2233 * @nid: NID to send the command
2234 * @direct: direct flag
2235 * @verb: the verb to send
2236 * @parm: the parameter for the verb
2237 *
2238 * Send a single command without waiting for response.
2239 *
2240 * Returns 0 if successful, or a negative error code.
2241 */
2242int snd_hda_codec_write_cache(struct hda_codec *codec, hda_nid_t nid,
2243 int direct, unsigned int verb, unsigned int parm)
2244{
Takashi Iwai33fa35e2008-11-06 16:50:40 +01002245 struct hda_bus *bus = codec->bus;
2246 unsigned int res;
Takashi Iwaib3ac5632007-08-10 17:03:40 +02002247 int err;
Takashi Iwai33fa35e2008-11-06 16:50:40 +01002248
2249 res = make_codec_cmd(codec, nid, direct, verb, parm);
Takashi Iwaicb53c622007-08-10 17:21:45 +02002250 snd_hda_power_up(codec);
Takashi Iwai33fa35e2008-11-06 16:50:40 +01002251 mutex_lock(&bus->cmd_mutex);
2252 err = bus->ops.command(bus, res);
Takashi Iwaib3ac5632007-08-10 17:03:40 +02002253 if (!err) {
2254 struct hda_cache_head *c;
Takashi Iwaifcad94a2009-04-15 17:48:35 +02002255 u32 key;
2256 /* parm may contain the verb stuff for get/set amp */
2257 verb = verb | (parm >> 8);
2258 parm &= 0xff;
2259 key = build_cmd_cache_key(nid, verb);
Takashi Iwaib3ac5632007-08-10 17:03:40 +02002260 c = get_alloc_hash(&codec->cmd_cache, key);
2261 if (c)
2262 c->val = parm;
2263 }
Takashi Iwai33fa35e2008-11-06 16:50:40 +01002264 mutex_unlock(&bus->cmd_mutex);
Takashi Iwaicb53c622007-08-10 17:21:45 +02002265 snd_hda_power_down(codec);
Takashi Iwaib3ac5632007-08-10 17:03:40 +02002266 return err;
2267}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002268EXPORT_SYMBOL_HDA(snd_hda_codec_write_cache);
Takashi Iwaib3ac5632007-08-10 17:03:40 +02002269
2270/* resume the all commands from the cache */
2271void snd_hda_codec_resume_cache(struct hda_codec *codec)
2272{
Takashi Iwai603c4012008-07-30 15:01:44 +02002273 struct hda_cache_head *buffer = codec->cmd_cache.buf.list;
Takashi Iwaib3ac5632007-08-10 17:03:40 +02002274 int i;
2275
Takashi Iwai603c4012008-07-30 15:01:44 +02002276 for (i = 0; i < codec->cmd_cache.buf.used; i++, buffer++) {
Takashi Iwaib3ac5632007-08-10 17:03:40 +02002277 u32 key = buffer->key;
2278 if (!key)
2279 continue;
2280 snd_hda_codec_write(codec, get_cmd_cache_nid(key), 0,
2281 get_cmd_cache_cmd(key), buffer->val);
2282 }
2283}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002284EXPORT_SYMBOL_HDA(snd_hda_codec_resume_cache);
Takashi Iwaib3ac5632007-08-10 17:03:40 +02002285
2286/**
2287 * snd_hda_sequence_write_cache - sequence writes with caching
2288 * @codec: the HDA codec
2289 * @seq: VERB array to send
2290 *
2291 * Send the commands sequentially from the given array.
2292 * Thte commands are recorded on cache for power-save and resume.
2293 * The array must be terminated with NID=0.
2294 */
2295void snd_hda_sequence_write_cache(struct hda_codec *codec,
2296 const struct hda_verb *seq)
2297{
2298 for (; seq->nid; seq++)
2299 snd_hda_codec_write_cache(codec, seq->nid, 0, seq->verb,
2300 seq->param);
2301}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002302EXPORT_SYMBOL_HDA(snd_hda_sequence_write_cache);
Takashi Iwaicb53c622007-08-10 17:21:45 +02002303#endif /* SND_HDA_NEEDS_RESUME */
Takashi Iwaib3ac5632007-08-10 17:03:40 +02002304
Takashi Iwai54d17402005-11-21 16:33:22 +01002305/*
2306 * set power state of the codec
2307 */
2308static void hda_set_power_state(struct hda_codec *codec, hda_nid_t fg,
2309 unsigned int power_state)
2310{
Takashi Iwaicb53c622007-08-10 17:21:45 +02002311 hda_nid_t nid;
2312 int i;
Takashi Iwai54d17402005-11-21 16:33:22 +01002313
2314 snd_hda_codec_write(codec, fg, 0, AC_VERB_SET_POWER_STATE,
2315 power_state);
Marc Boucherd2595d82008-01-22 15:23:30 +01002316 msleep(10); /* partial workaround for "azx_get_response timeout" */
Takashi Iwai54d17402005-11-21 16:33:22 +01002317
Takashi Iwaicb53c622007-08-10 17:21:45 +02002318 nid = codec->start_nid;
2319 for (i = 0; i < codec->num_nodes; i++, nid++) {
Takashi Iwai7eba5c92007-11-14 14:53:42 +01002320 unsigned int wcaps = get_wcaps(codec, nid);
2321 if (wcaps & AC_WCAP_POWER) {
2322 unsigned int wid_type = (wcaps & AC_WCAP_TYPE) >>
2323 AC_WCAP_TYPE_SHIFT;
2324 if (wid_type == AC_WID_PIN) {
2325 unsigned int pincap;
2326 /*
2327 * don't power down the widget if it controls
2328 * eapd and EAPD_BTLENABLE is set.
2329 */
Takashi Iwai14bafe32009-03-23 16:35:39 +01002330 pincap = snd_hda_query_pin_caps(codec, nid);
Takashi Iwai7eba5c92007-11-14 14:53:42 +01002331 if (pincap & AC_PINCAP_EAPD) {
2332 int eapd = snd_hda_codec_read(codec,
2333 nid, 0,
2334 AC_VERB_GET_EAPD_BTLENABLE, 0);
2335 eapd &= 0x02;
2336 if (power_state == AC_PWRST_D3 && eapd)
2337 continue;
2338 }
Takashi Iwai1194b5b2007-10-10 10:04:26 +02002339 }
Takashi Iwai54d17402005-11-21 16:33:22 +01002340 snd_hda_codec_write(codec, nid, 0,
2341 AC_VERB_SET_POWER_STATE,
2342 power_state);
Takashi Iwai1194b5b2007-10-10 10:04:26 +02002343 }
Takashi Iwai54d17402005-11-21 16:33:22 +01002344 }
2345
Takashi Iwaicb53c622007-08-10 17:21:45 +02002346 if (power_state == AC_PWRST_D0) {
2347 unsigned long end_time;
2348 int state;
Takashi Iwai54d17402005-11-21 16:33:22 +01002349 msleep(10);
Takashi Iwaicb53c622007-08-10 17:21:45 +02002350 /* wait until the codec reachs to D0 */
2351 end_time = jiffies + msecs_to_jiffies(500);
2352 do {
2353 state = snd_hda_codec_read(codec, fg, 0,
2354 AC_VERB_GET_POWER_STATE, 0);
2355 if (state == power_state)
2356 break;
2357 msleep(1);
2358 } while (time_after_eq(end_time, jiffies));
2359 }
Takashi Iwai54d17402005-11-21 16:33:22 +01002360}
2361
Takashi Iwai11aeff02008-07-30 15:01:46 +02002362#ifdef CONFIG_SND_HDA_HWDEP
2363/* execute additional init verbs */
2364static void hda_exec_init_verbs(struct hda_codec *codec)
2365{
2366 if (codec->init_verbs.list)
2367 snd_hda_sequence_write(codec, codec->init_verbs.list);
2368}
2369#else
2370static inline void hda_exec_init_verbs(struct hda_codec *codec) {}
2371#endif
2372
Takashi Iwaicb53c622007-08-10 17:21:45 +02002373#ifdef SND_HDA_NEEDS_RESUME
2374/*
2375 * call suspend and power-down; used both from PM and power-save
2376 */
2377static void hda_call_codec_suspend(struct hda_codec *codec)
2378{
2379 if (codec->patch_ops.suspend)
2380 codec->patch_ops.suspend(codec, PMSG_SUSPEND);
2381 hda_set_power_state(codec,
2382 codec->afg ? codec->afg : codec->mfg,
2383 AC_PWRST_D3);
2384#ifdef CONFIG_SND_HDA_POWER_SAVE
2385 cancel_delayed_work(&codec->power_work);
Takashi Iwai95e99fd2007-08-13 15:29:04 +02002386 codec->power_on = 0;
Takashi Iwaia221e282007-08-16 16:35:33 +02002387 codec->power_transition = 0;
Takashi Iwaicb53c622007-08-10 17:21:45 +02002388#endif
2389}
2390
2391/*
2392 * kick up codec; used both from PM and power-save
2393 */
2394static void hda_call_codec_resume(struct hda_codec *codec)
2395{
2396 hda_set_power_state(codec,
2397 codec->afg ? codec->afg : codec->mfg,
2398 AC_PWRST_D0);
Takashi Iwai3be14142009-02-20 14:11:16 +01002399 restore_pincfgs(codec); /* restore all current pin configs */
Takashi Iwai11aeff02008-07-30 15:01:46 +02002400 hda_exec_init_verbs(codec);
Takashi Iwaicb53c622007-08-10 17:21:45 +02002401 if (codec->patch_ops.resume)
2402 codec->patch_ops.resume(codec);
2403 else {
Takashi Iwai9d99f312007-08-14 15:15:52 +02002404 if (codec->patch_ops.init)
2405 codec->patch_ops.init(codec);
Takashi Iwaicb53c622007-08-10 17:21:45 +02002406 snd_hda_codec_resume_amp(codec);
2407 snd_hda_codec_resume_cache(codec);
2408 }
2409}
2410#endif /* SND_HDA_NEEDS_RESUME */
2411
Takashi Iwai54d17402005-11-21 16:33:22 +01002412
Linus Torvalds1da177e2005-04-16 15:20:36 -07002413/**
2414 * snd_hda_build_controls - build mixer controls
2415 * @bus: the BUS
2416 *
2417 * Creates mixer controls for each codec included in the bus.
2418 *
2419 * Returns 0 if successful, otherwise a negative error code.
2420 */
Takashi Iwai1289e9e2008-11-27 15:47:11 +01002421int /*__devinit*/ snd_hda_build_controls(struct hda_bus *bus)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002422{
Takashi Iwai0ba21762007-04-16 11:29:14 +02002423 struct hda_codec *codec;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002424
Takashi Iwai0ba21762007-04-16 11:29:14 +02002425 list_for_each_entry(codec, &bus->codec_list, list) {
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02002426 int err = snd_hda_codec_build_controls(codec);
Takashi Iwaif93d4612009-03-02 10:44:15 +01002427 if (err < 0) {
2428 printk(KERN_ERR "hda_codec: cannot build controls"
2429 "for #%d (error %d)\n", codec->addr, err);
2430 err = snd_hda_codec_reset(codec);
2431 if (err < 0) {
2432 printk(KERN_ERR
2433 "hda_codec: cannot revert codec\n");
2434 return err;
2435 }
2436 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002437 }
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02002438 return 0;
2439}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002440EXPORT_SYMBOL_HDA(snd_hda_build_controls);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002441
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02002442int snd_hda_codec_build_controls(struct hda_codec *codec)
2443{
2444 int err = 0;
Takashi Iwai11aeff02008-07-30 15:01:46 +02002445 hda_exec_init_verbs(codec);
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02002446 /* continue to initialize... */
2447 if (codec->patch_ops.init)
2448 err = codec->patch_ops.init(codec);
2449 if (!err && codec->patch_ops.build_controls)
2450 err = codec->patch_ops.build_controls(codec);
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02002451 if (err < 0)
2452 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002453 return 0;
2454}
2455
Linus Torvalds1da177e2005-04-16 15:20:36 -07002456/*
2457 * stream formats
2458 */
Takashi Iwaibefdf312005-08-22 13:57:55 +02002459struct hda_rate_tbl {
2460 unsigned int hz;
2461 unsigned int alsa_bits;
2462 unsigned int hda_fmt;
2463};
2464
2465static struct hda_rate_tbl rate_bits[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002466 /* rate in Hz, ALSA rate bitmask, HDA format value */
Nicolas Graziano9d8f53f2005-08-22 13:47:16 +02002467
2468 /* autodetected value used in snd_hda_query_supported_pcm */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002469 { 8000, SNDRV_PCM_RATE_8000, 0x0500 }, /* 1/6 x 48 */
2470 { 11025, SNDRV_PCM_RATE_11025, 0x4300 }, /* 1/4 x 44 */
2471 { 16000, SNDRV_PCM_RATE_16000, 0x0200 }, /* 1/3 x 48 */
2472 { 22050, SNDRV_PCM_RATE_22050, 0x4100 }, /* 1/2 x 44 */
2473 { 32000, SNDRV_PCM_RATE_32000, 0x0a00 }, /* 2/3 x 48 */
2474 { 44100, SNDRV_PCM_RATE_44100, 0x4000 }, /* 44 */
2475 { 48000, SNDRV_PCM_RATE_48000, 0x0000 }, /* 48 */
2476 { 88200, SNDRV_PCM_RATE_88200, 0x4800 }, /* 2 x 44 */
2477 { 96000, SNDRV_PCM_RATE_96000, 0x0800 }, /* 2 x 48 */
2478 { 176400, SNDRV_PCM_RATE_176400, 0x5800 },/* 4 x 44 */
2479 { 192000, SNDRV_PCM_RATE_192000, 0x1800 }, /* 4 x 48 */
Takashi Iwaia961f9f2007-04-12 13:08:09 +02002480#define AC_PAR_PCM_RATE_BITS 11
2481 /* up to bits 10, 384kHZ isn't supported properly */
2482
2483 /* not autodetected value */
2484 { 9600, SNDRV_PCM_RATE_KNOT, 0x0400 }, /* 1/5 x 48 */
Nicolas Graziano9d8f53f2005-08-22 13:47:16 +02002485
Takashi Iwaibefdf312005-08-22 13:57:55 +02002486 { 0 } /* terminator */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002487};
2488
2489/**
2490 * snd_hda_calc_stream_format - calculate format bitset
2491 * @rate: the sample rate
2492 * @channels: the number of channels
2493 * @format: the PCM format (SNDRV_PCM_FORMAT_XXX)
2494 * @maxbps: the max. bps
2495 *
2496 * Calculate the format bitset from the given rate, channels and th PCM format.
2497 *
2498 * Return zero if invalid.
2499 */
2500unsigned int snd_hda_calc_stream_format(unsigned int rate,
2501 unsigned int channels,
2502 unsigned int format,
2503 unsigned int maxbps)
2504{
2505 int i;
2506 unsigned int val = 0;
2507
Takashi Iwaibefdf312005-08-22 13:57:55 +02002508 for (i = 0; rate_bits[i].hz; i++)
2509 if (rate_bits[i].hz == rate) {
2510 val = rate_bits[i].hda_fmt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002511 break;
2512 }
Takashi Iwai0ba21762007-04-16 11:29:14 +02002513 if (!rate_bits[i].hz) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002514 snd_printdd("invalid rate %d\n", rate);
2515 return 0;
2516 }
2517
2518 if (channels == 0 || channels > 8) {
2519 snd_printdd("invalid channels %d\n", channels);
2520 return 0;
2521 }
2522 val |= channels - 1;
2523
2524 switch (snd_pcm_format_width(format)) {
2525 case 8: val |= 0x00; break;
2526 case 16: val |= 0x10; break;
2527 case 20:
2528 case 24:
2529 case 32:
2530 if (maxbps >= 32)
2531 val |= 0x40;
2532 else if (maxbps >= 24)
2533 val |= 0x30;
2534 else
2535 val |= 0x20;
2536 break;
2537 default:
Takashi Iwai0ba21762007-04-16 11:29:14 +02002538 snd_printdd("invalid format width %d\n",
2539 snd_pcm_format_width(format));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002540 return 0;
2541 }
2542
2543 return val;
2544}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002545EXPORT_SYMBOL_HDA(snd_hda_calc_stream_format);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002546
2547/**
2548 * snd_hda_query_supported_pcm - query the supported PCM rates and formats
2549 * @codec: the HDA codec
2550 * @nid: NID to query
2551 * @ratesp: the pointer to store the detected rate bitflags
2552 * @formatsp: the pointer to store the detected formats
2553 * @bpsp: the pointer to store the detected format widths
2554 *
2555 * Queries the supported PCM rates and formats. The NULL @ratesp, @formatsp
2556 * or @bsps argument is ignored.
2557 *
2558 * Returns 0 if successful, otherwise a negative error code.
2559 */
Takashi Iwai986862bd2008-11-27 12:40:13 +01002560static int snd_hda_query_supported_pcm(struct hda_codec *codec, hda_nid_t nid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002561 u32 *ratesp, u64 *formatsp, unsigned int *bpsp)
2562{
Jaroslav Kyselaee504712009-03-17 14:30:31 +01002563 unsigned int i, val, wcaps;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002564
2565 val = 0;
Jaroslav Kyselaee504712009-03-17 14:30:31 +01002566 wcaps = get_wcaps(codec, nid);
2567 if (nid != codec->afg && (wcaps & AC_WCAP_FORMAT_OVRD)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002568 val = snd_hda_param_read(codec, nid, AC_PAR_PCM);
2569 if (val == -1)
2570 return -EIO;
2571 }
Takashi Iwai0ba21762007-04-16 11:29:14 +02002572 if (!val)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002573 val = snd_hda_param_read(codec, codec->afg, AC_PAR_PCM);
2574
2575 if (ratesp) {
2576 u32 rates = 0;
Takashi Iwaia961f9f2007-04-12 13:08:09 +02002577 for (i = 0; i < AC_PAR_PCM_RATE_BITS; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002578 if (val & (1 << i))
Takashi Iwaibefdf312005-08-22 13:57:55 +02002579 rates |= rate_bits[i].alsa_bits;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002580 }
Jaroslav Kyselaee504712009-03-17 14:30:31 +01002581 if (rates == 0) {
2582 snd_printk(KERN_ERR "hda_codec: rates == 0 "
2583 "(nid=0x%x, val=0x%x, ovrd=%i)\n",
2584 nid, val,
2585 (wcaps & AC_WCAP_FORMAT_OVRD) ? 1 : 0);
2586 return -EIO;
2587 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002588 *ratesp = rates;
2589 }
2590
2591 if (formatsp || bpsp) {
2592 u64 formats = 0;
Jaroslav Kyselaee504712009-03-17 14:30:31 +01002593 unsigned int streams, bps;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002594
Linus Torvalds1da177e2005-04-16 15:20:36 -07002595 streams = snd_hda_param_read(codec, nid, AC_PAR_STREAM);
2596 if (streams == -1)
2597 return -EIO;
Takashi Iwai0ba21762007-04-16 11:29:14 +02002598 if (!streams) {
2599 streams = snd_hda_param_read(codec, codec->afg,
2600 AC_PAR_STREAM);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002601 if (streams == -1)
2602 return -EIO;
2603 }
2604
2605 bps = 0;
2606 if (streams & AC_SUPFMT_PCM) {
2607 if (val & AC_SUPPCM_BITS_8) {
2608 formats |= SNDRV_PCM_FMTBIT_U8;
2609 bps = 8;
2610 }
2611 if (val & AC_SUPPCM_BITS_16) {
2612 formats |= SNDRV_PCM_FMTBIT_S16_LE;
2613 bps = 16;
2614 }
2615 if (wcaps & AC_WCAP_DIGITAL) {
2616 if (val & AC_SUPPCM_BITS_32)
2617 formats |= SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_LE;
2618 if (val & (AC_SUPPCM_BITS_20|AC_SUPPCM_BITS_24))
2619 formats |= SNDRV_PCM_FMTBIT_S32_LE;
2620 if (val & AC_SUPPCM_BITS_24)
2621 bps = 24;
2622 else if (val & AC_SUPPCM_BITS_20)
2623 bps = 20;
Takashi Iwai0ba21762007-04-16 11:29:14 +02002624 } else if (val & (AC_SUPPCM_BITS_20|AC_SUPPCM_BITS_24|
2625 AC_SUPPCM_BITS_32)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002626 formats |= SNDRV_PCM_FMTBIT_S32_LE;
2627 if (val & AC_SUPPCM_BITS_32)
2628 bps = 32;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002629 else if (val & AC_SUPPCM_BITS_24)
2630 bps = 24;
Nicolas Graziano33ef76512006-09-19 14:23:14 +02002631 else if (val & AC_SUPPCM_BITS_20)
2632 bps = 20;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002633 }
2634 }
Takashi Iwai0ba21762007-04-16 11:29:14 +02002635 else if (streams == AC_SUPFMT_FLOAT32) {
2636 /* should be exclusive */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002637 formats |= SNDRV_PCM_FMTBIT_FLOAT_LE;
2638 bps = 32;
Takashi Iwai0ba21762007-04-16 11:29:14 +02002639 } else if (streams == AC_SUPFMT_AC3) {
2640 /* should be exclusive */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002641 /* temporary hack: we have still no proper support
2642 * for the direct AC3 stream...
2643 */
2644 formats |= SNDRV_PCM_FMTBIT_U8;
2645 bps = 8;
2646 }
Jaroslav Kyselaee504712009-03-17 14:30:31 +01002647 if (formats == 0) {
2648 snd_printk(KERN_ERR "hda_codec: formats == 0 "
2649 "(nid=0x%x, val=0x%x, ovrd=%i, "
2650 "streams=0x%x)\n",
2651 nid, val,
2652 (wcaps & AC_WCAP_FORMAT_OVRD) ? 1 : 0,
2653 streams);
2654 return -EIO;
2655 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002656 if (formatsp)
2657 *formatsp = formats;
2658 if (bpsp)
2659 *bpsp = bps;
2660 }
2661
2662 return 0;
2663}
2664
2665/**
Takashi Iwai0ba21762007-04-16 11:29:14 +02002666 * snd_hda_is_supported_format - check whether the given node supports
2667 * the format val
Linus Torvalds1da177e2005-04-16 15:20:36 -07002668 *
2669 * Returns 1 if supported, 0 if not.
2670 */
2671int snd_hda_is_supported_format(struct hda_codec *codec, hda_nid_t nid,
2672 unsigned int format)
2673{
2674 int i;
2675 unsigned int val = 0, rate, stream;
2676
2677 if (nid != codec->afg &&
Takashi Iwai54d17402005-11-21 16:33:22 +01002678 (get_wcaps(codec, nid) & AC_WCAP_FORMAT_OVRD)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002679 val = snd_hda_param_read(codec, nid, AC_PAR_PCM);
2680 if (val == -1)
2681 return 0;
2682 }
Takashi Iwai0ba21762007-04-16 11:29:14 +02002683 if (!val) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002684 val = snd_hda_param_read(codec, codec->afg, AC_PAR_PCM);
2685 if (val == -1)
2686 return 0;
2687 }
2688
2689 rate = format & 0xff00;
Takashi Iwaia961f9f2007-04-12 13:08:09 +02002690 for (i = 0; i < AC_PAR_PCM_RATE_BITS; i++)
Takashi Iwaibefdf312005-08-22 13:57:55 +02002691 if (rate_bits[i].hda_fmt == rate) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002692 if (val & (1 << i))
2693 break;
2694 return 0;
2695 }
Takashi Iwaia961f9f2007-04-12 13:08:09 +02002696 if (i >= AC_PAR_PCM_RATE_BITS)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002697 return 0;
2698
2699 stream = snd_hda_param_read(codec, nid, AC_PAR_STREAM);
2700 if (stream == -1)
2701 return 0;
Takashi Iwai0ba21762007-04-16 11:29:14 +02002702 if (!stream && nid != codec->afg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002703 stream = snd_hda_param_read(codec, codec->afg, AC_PAR_STREAM);
Takashi Iwai0ba21762007-04-16 11:29:14 +02002704 if (!stream || stream == -1)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002705 return 0;
2706
2707 if (stream & AC_SUPFMT_PCM) {
2708 switch (format & 0xf0) {
2709 case 0x00:
Takashi Iwai0ba21762007-04-16 11:29:14 +02002710 if (!(val & AC_SUPPCM_BITS_8))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002711 return 0;
2712 break;
2713 case 0x10:
Takashi Iwai0ba21762007-04-16 11:29:14 +02002714 if (!(val & AC_SUPPCM_BITS_16))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002715 return 0;
2716 break;
2717 case 0x20:
Takashi Iwai0ba21762007-04-16 11:29:14 +02002718 if (!(val & AC_SUPPCM_BITS_20))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002719 return 0;
2720 break;
2721 case 0x30:
Takashi Iwai0ba21762007-04-16 11:29:14 +02002722 if (!(val & AC_SUPPCM_BITS_24))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002723 return 0;
2724 break;
2725 case 0x40:
Takashi Iwai0ba21762007-04-16 11:29:14 +02002726 if (!(val & AC_SUPPCM_BITS_32))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002727 return 0;
2728 break;
2729 default:
2730 return 0;
2731 }
2732 } else {
2733 /* FIXME: check for float32 and AC3? */
2734 }
2735
2736 return 1;
2737}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002738EXPORT_SYMBOL_HDA(snd_hda_is_supported_format);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002739
2740/*
2741 * PCM stuff
2742 */
2743static int hda_pcm_default_open_close(struct hda_pcm_stream *hinfo,
2744 struct hda_codec *codec,
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01002745 struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002746{
2747 return 0;
2748}
2749
2750static int hda_pcm_default_prepare(struct hda_pcm_stream *hinfo,
2751 struct hda_codec *codec,
2752 unsigned int stream_tag,
2753 unsigned int format,
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01002754 struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002755{
2756 snd_hda_codec_setup_stream(codec, hinfo->nid, stream_tag, 0, format);
2757 return 0;
2758}
2759
2760static int hda_pcm_default_cleanup(struct hda_pcm_stream *hinfo,
2761 struct hda_codec *codec,
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01002762 struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002763{
Takashi Iwai888afa12008-03-18 09:57:50 +01002764 snd_hda_codec_cleanup_stream(codec, hinfo->nid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002765 return 0;
2766}
2767
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02002768static int set_pcm_default_values(struct hda_codec *codec,
2769 struct hda_pcm_stream *info)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002770{
Jaroslav Kyselaee504712009-03-17 14:30:31 +01002771 int err;
2772
Takashi Iwai0ba21762007-04-16 11:29:14 +02002773 /* query support PCM information from the given NID */
2774 if (info->nid && (!info->rates || !info->formats)) {
Jaroslav Kyselaee504712009-03-17 14:30:31 +01002775 err = snd_hda_query_supported_pcm(codec, info->nid,
Takashi Iwai0ba21762007-04-16 11:29:14 +02002776 info->rates ? NULL : &info->rates,
2777 info->formats ? NULL : &info->formats,
2778 info->maxbps ? NULL : &info->maxbps);
Jaroslav Kyselaee504712009-03-17 14:30:31 +01002779 if (err < 0)
2780 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002781 }
2782 if (info->ops.open == NULL)
2783 info->ops.open = hda_pcm_default_open_close;
2784 if (info->ops.close == NULL)
2785 info->ops.close = hda_pcm_default_open_close;
2786 if (info->ops.prepare == NULL) {
Takashi Iwaida3cec32008-08-08 17:12:14 +02002787 if (snd_BUG_ON(!info->nid))
2788 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002789 info->ops.prepare = hda_pcm_default_prepare;
2790 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002791 if (info->ops.cleanup == NULL) {
Takashi Iwaida3cec32008-08-08 17:12:14 +02002792 if (snd_BUG_ON(!info->nid))
2793 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002794 info->ops.cleanup = hda_pcm_default_cleanup;
2795 }
2796 return 0;
2797}
2798
Takashi Iwai176d5332008-07-30 15:01:44 +02002799/*
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002800 * get the empty PCM device number to assign
2801 */
2802static int get_empty_pcm_device(struct hda_bus *bus, int type)
2803{
2804 static const char *dev_name[HDA_PCM_NTYPES] = {
2805 "Audio", "SPDIF", "HDMI", "Modem"
2806 };
2807 /* starting device index for each PCM type */
2808 static int dev_idx[HDA_PCM_NTYPES] = {
2809 [HDA_PCM_TYPE_AUDIO] = 0,
2810 [HDA_PCM_TYPE_SPDIF] = 1,
2811 [HDA_PCM_TYPE_HDMI] = 3,
2812 [HDA_PCM_TYPE_MODEM] = 6
2813 };
2814 /* normal audio device indices; not linear to keep compatibility */
2815 static int audio_idx[4] = { 0, 2, 4, 5 };
2816 int i, dev;
2817
2818 switch (type) {
2819 case HDA_PCM_TYPE_AUDIO:
2820 for (i = 0; i < ARRAY_SIZE(audio_idx); i++) {
2821 dev = audio_idx[i];
2822 if (!test_bit(dev, bus->pcm_dev_bits))
Takashi Iwai82ad39f2009-03-03 15:00:35 +01002823 goto ok;
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002824 }
Takashi Iwai82ad39f2009-03-03 15:00:35 +01002825 snd_printk(KERN_WARNING "Too many audio devices\n");
2826 return -EAGAIN;
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002827 case HDA_PCM_TYPE_SPDIF:
2828 case HDA_PCM_TYPE_HDMI:
2829 case HDA_PCM_TYPE_MODEM:
2830 dev = dev_idx[type];
2831 if (test_bit(dev, bus->pcm_dev_bits)) {
2832 snd_printk(KERN_WARNING "%s already defined\n",
2833 dev_name[type]);
2834 return -EAGAIN;
2835 }
2836 break;
2837 default:
2838 snd_printk(KERN_WARNING "Invalid PCM type %d\n", type);
2839 return -EINVAL;
2840 }
Takashi Iwai82ad39f2009-03-03 15:00:35 +01002841 ok:
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002842 set_bit(dev, bus->pcm_dev_bits);
2843 return dev;
2844}
2845
2846/*
Takashi Iwai176d5332008-07-30 15:01:44 +02002847 * attach a new PCM stream
2848 */
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002849static int snd_hda_attach_pcm(struct hda_codec *codec, struct hda_pcm *pcm)
Takashi Iwai176d5332008-07-30 15:01:44 +02002850{
Takashi Iwai33fa35e2008-11-06 16:50:40 +01002851 struct hda_bus *bus = codec->bus;
Takashi Iwai176d5332008-07-30 15:01:44 +02002852 struct hda_pcm_stream *info;
2853 int stream, err;
2854
Takashi Iwaib91f0802008-11-04 08:43:08 +01002855 if (snd_BUG_ON(!pcm->name))
Takashi Iwai176d5332008-07-30 15:01:44 +02002856 return -EINVAL;
2857 for (stream = 0; stream < 2; stream++) {
2858 info = &pcm->stream[stream];
2859 if (info->substreams) {
2860 err = set_pcm_default_values(codec, info);
2861 if (err < 0)
2862 return err;
2863 }
2864 }
Takashi Iwai33fa35e2008-11-06 16:50:40 +01002865 return bus->ops.attach_pcm(bus, codec, pcm);
Takashi Iwai176d5332008-07-30 15:01:44 +02002866}
2867
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002868/* assign all PCMs of the given codec */
2869int snd_hda_codec_build_pcms(struct hda_codec *codec)
2870{
2871 unsigned int pcm;
2872 int err;
2873
2874 if (!codec->num_pcms) {
2875 if (!codec->patch_ops.build_pcms)
2876 return 0;
2877 err = codec->patch_ops.build_pcms(codec);
Takashi Iwai6e655bf2009-03-02 10:46:03 +01002878 if (err < 0) {
2879 printk(KERN_ERR "hda_codec: cannot build PCMs"
2880 "for #%d (error %d)\n", codec->addr, err);
2881 err = snd_hda_codec_reset(codec);
2882 if (err < 0) {
2883 printk(KERN_ERR
2884 "hda_codec: cannot revert codec\n");
2885 return err;
2886 }
2887 }
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002888 }
2889 for (pcm = 0; pcm < codec->num_pcms; pcm++) {
2890 struct hda_pcm *cpcm = &codec->pcm_info[pcm];
2891 int dev;
2892
2893 if (!cpcm->stream[0].substreams && !cpcm->stream[1].substreams)
Takashi Iwai41b5b012009-01-20 18:21:23 +01002894 continue; /* no substreams assigned */
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002895
2896 if (!cpcm->pcm) {
2897 dev = get_empty_pcm_device(codec->bus, cpcm->pcm_type);
2898 if (dev < 0)
Takashi Iwai6e655bf2009-03-02 10:46:03 +01002899 continue; /* no fatal error */
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002900 cpcm->device = dev;
2901 err = snd_hda_attach_pcm(codec, cpcm);
Takashi Iwai6e655bf2009-03-02 10:46:03 +01002902 if (err < 0) {
2903 printk(KERN_ERR "hda_codec: cannot attach "
2904 "PCM stream %d for codec #%d\n",
2905 dev, codec->addr);
2906 continue; /* no fatal error */
2907 }
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002908 }
2909 }
2910 return 0;
2911}
2912
Linus Torvalds1da177e2005-04-16 15:20:36 -07002913/**
2914 * snd_hda_build_pcms - build PCM information
2915 * @bus: the BUS
2916 *
2917 * Create PCM information for each codec included in the bus.
2918 *
2919 * The build_pcms codec patch is requested to set up codec->num_pcms and
2920 * codec->pcm_info properly. The array is referred by the top-level driver
2921 * to create its PCM instances.
2922 * The allocated codec->pcm_info should be released in codec->patch_ops.free
2923 * callback.
2924 *
2925 * At least, substreams, channels_min and channels_max must be filled for
2926 * each stream. substreams = 0 indicates that the stream doesn't exist.
2927 * When rates and/or formats are zero, the supported values are queried
2928 * from the given nid. The nid is used also by the default ops.prepare
2929 * and ops.cleanup callbacks.
2930 *
2931 * The driver needs to call ops.open in its open callback. Similarly,
2932 * ops.close is supposed to be called in the close callback.
2933 * ops.prepare should be called in the prepare or hw_params callback
2934 * with the proper parameters for set up.
2935 * ops.cleanup should be called in hw_free for clean up of streams.
2936 *
2937 * This function returns 0 if successfull, or a negative error code.
2938 */
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002939int __devinit snd_hda_build_pcms(struct hda_bus *bus)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002940{
Takashi Iwai0ba21762007-04-16 11:29:14 +02002941 struct hda_codec *codec;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002942
Takashi Iwai0ba21762007-04-16 11:29:14 +02002943 list_for_each_entry(codec, &bus->codec_list, list) {
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002944 int err = snd_hda_codec_build_pcms(codec);
2945 if (err < 0)
2946 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002947 }
2948 return 0;
2949}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002950EXPORT_SYMBOL_HDA(snd_hda_build_pcms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002951
Linus Torvalds1da177e2005-04-16 15:20:36 -07002952/**
2953 * snd_hda_check_board_config - compare the current codec with the config table
2954 * @codec: the HDA codec
Takashi Iwaif5fcc132006-11-24 17:07:44 +01002955 * @num_configs: number of config enums
2956 * @models: array of model name strings
Linus Torvalds1da177e2005-04-16 15:20:36 -07002957 * @tbl: configuration table, terminated by null entries
2958 *
2959 * Compares the modelname or PCI subsystem id of the current codec with the
2960 * given configuration table. If a matching entry is found, returns its
2961 * config value (supposed to be 0 or positive).
2962 *
2963 * If no entries are matching, the function returns a negative value.
2964 */
Takashi Iwai12f288b2007-08-02 15:51:59 +02002965int snd_hda_check_board_config(struct hda_codec *codec,
2966 int num_configs, const char **models,
2967 const struct snd_pci_quirk *tbl)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002968{
Takashi Iwaif44ac832008-07-30 15:01:45 +02002969 if (codec->modelname && models) {
Takashi Iwaif5fcc132006-11-24 17:07:44 +01002970 int i;
2971 for (i = 0; i < num_configs; i++) {
2972 if (models[i] &&
Takashi Iwaif44ac832008-07-30 15:01:45 +02002973 !strcmp(codec->modelname, models[i])) {
Takashi Iwaif5fcc132006-11-24 17:07:44 +01002974 snd_printd(KERN_INFO "hda_codec: model '%s' is "
2975 "selected\n", models[i]);
2976 return i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002977 }
2978 }
2979 }
2980
Takashi Iwaif5fcc132006-11-24 17:07:44 +01002981 if (!codec->bus->pci || !tbl)
2982 return -1;
2983
2984 tbl = snd_pci_quirk_lookup(codec->bus->pci, tbl);
2985 if (!tbl)
2986 return -1;
2987 if (tbl->value >= 0 && tbl->value < num_configs) {
Takashi Iwai62cf8722008-05-20 12:15:15 +02002988#ifdef CONFIG_SND_DEBUG_VERBOSE
Takashi Iwaif5fcc132006-11-24 17:07:44 +01002989 char tmp[10];
2990 const char *model = NULL;
2991 if (models)
2992 model = models[tbl->value];
2993 if (!model) {
2994 sprintf(tmp, "#%d", tbl->value);
2995 model = tmp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002996 }
Takashi Iwaif5fcc132006-11-24 17:07:44 +01002997 snd_printdd(KERN_INFO "hda_codec: model '%s' is selected "
2998 "for config %x:%x (%s)\n",
2999 model, tbl->subvendor, tbl->subdevice,
3000 (tbl->name ? tbl->name : "Unknown device"));
3001#endif
3002 return tbl->value;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003003 }
3004 return -1;
3005}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003006EXPORT_SYMBOL_HDA(snd_hda_check_board_config);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003007
3008/**
Mauro Carvalho Chehab2eda3442008-08-11 10:18:39 +02003009 * snd_hda_check_board_codec_sid_config - compare the current codec
3010 subsystem ID with the
3011 config table
3012
3013 This is important for Gateway notebooks with SB450 HDA Audio
3014 where the vendor ID of the PCI device is:
3015 ATI Technologies Inc SB450 HDA Audio [1002:437b]
3016 and the vendor/subvendor are found only at the codec.
3017
3018 * @codec: the HDA codec
3019 * @num_configs: number of config enums
3020 * @models: array of model name strings
3021 * @tbl: configuration table, terminated by null entries
3022 *
3023 * Compares the modelname or PCI subsystem id of the current codec with the
3024 * given configuration table. If a matching entry is found, returns its
3025 * config value (supposed to be 0 or positive).
3026 *
3027 * If no entries are matching, the function returns a negative value.
3028 */
3029int snd_hda_check_board_codec_sid_config(struct hda_codec *codec,
3030 int num_configs, const char **models,
3031 const struct snd_pci_quirk *tbl)
3032{
3033 const struct snd_pci_quirk *q;
3034
3035 /* Search for codec ID */
3036 for (q = tbl; q->subvendor; q++) {
3037 unsigned long vendorid = (q->subdevice) | (q->subvendor << 16);
3038
3039 if (vendorid == codec->subsystem_id)
3040 break;
3041 }
3042
3043 if (!q->subvendor)
3044 return -1;
3045
3046 tbl = q;
3047
3048 if (tbl->value >= 0 && tbl->value < num_configs) {
3049#ifdef CONFIG_SND_DEBUG_DETECT
3050 char tmp[10];
3051 const char *model = NULL;
3052 if (models)
3053 model = models[tbl->value];
3054 if (!model) {
3055 sprintf(tmp, "#%d", tbl->value);
3056 model = tmp;
3057 }
3058 snd_printdd(KERN_INFO "hda_codec: model '%s' is selected "
3059 "for config %x:%x (%s)\n",
3060 model, tbl->subvendor, tbl->subdevice,
3061 (tbl->name ? tbl->name : "Unknown device"));
3062#endif
3063 return tbl->value;
3064 }
3065 return -1;
3066}
3067EXPORT_SYMBOL_HDA(snd_hda_check_board_codec_sid_config);
3068
3069/**
Linus Torvalds1da177e2005-04-16 15:20:36 -07003070 * snd_hda_add_new_ctls - create controls from the array
3071 * @codec: the HDA codec
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01003072 * @knew: the array of struct snd_kcontrol_new
Linus Torvalds1da177e2005-04-16 15:20:36 -07003073 *
3074 * This helper function creates and add new controls in the given array.
3075 * The array must be terminated with an empty entry as terminator.
3076 *
3077 * Returns 0 if successful, or a negative error code.
3078 */
Takashi Iwai12f288b2007-08-02 15:51:59 +02003079int snd_hda_add_new_ctls(struct hda_codec *codec, struct snd_kcontrol_new *knew)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003080{
Takashi Iwaicb53c622007-08-10 17:21:45 +02003081 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003082
3083 for (; knew->name; knew++) {
Takashi Iwai54d17402005-11-21 16:33:22 +01003084 struct snd_kcontrol *kctl;
3085 kctl = snd_ctl_new1(knew, codec);
Takashi Iwai0ba21762007-04-16 11:29:14 +02003086 if (!kctl)
Takashi Iwai54d17402005-11-21 16:33:22 +01003087 return -ENOMEM;
Takashi Iwaid13bd412008-07-30 15:01:45 +02003088 err = snd_hda_ctl_add(codec, kctl);
Takashi Iwai54d17402005-11-21 16:33:22 +01003089 if (err < 0) {
Takashi Iwai0ba21762007-04-16 11:29:14 +02003090 if (!codec->addr)
Takashi Iwai54d17402005-11-21 16:33:22 +01003091 return err;
3092 kctl = snd_ctl_new1(knew, codec);
Takashi Iwai0ba21762007-04-16 11:29:14 +02003093 if (!kctl)
Takashi Iwai54d17402005-11-21 16:33:22 +01003094 return -ENOMEM;
3095 kctl->id.device = codec->addr;
Takashi Iwaid13bd412008-07-30 15:01:45 +02003096 err = snd_hda_ctl_add(codec, kctl);
Takashi Iwai0ba21762007-04-16 11:29:14 +02003097 if (err < 0)
Takashi Iwai54d17402005-11-21 16:33:22 +01003098 return err;
3099 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003100 }
3101 return 0;
3102}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003103EXPORT_SYMBOL_HDA(snd_hda_add_new_ctls);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003104
Takashi Iwaicb53c622007-08-10 17:21:45 +02003105#ifdef CONFIG_SND_HDA_POWER_SAVE
3106static void hda_set_power_state(struct hda_codec *codec, hda_nid_t fg,
3107 unsigned int power_state);
3108
3109static void hda_power_work(struct work_struct *work)
3110{
3111 struct hda_codec *codec =
3112 container_of(work, struct hda_codec, power_work.work);
Takashi Iwai33fa35e2008-11-06 16:50:40 +01003113 struct hda_bus *bus = codec->bus;
Takashi Iwaicb53c622007-08-10 17:21:45 +02003114
Maxim Levitsky2e492462007-09-03 15:26:57 +02003115 if (!codec->power_on || codec->power_count) {
3116 codec->power_transition = 0;
Takashi Iwaicb53c622007-08-10 17:21:45 +02003117 return;
Maxim Levitsky2e492462007-09-03 15:26:57 +02003118 }
Takashi Iwaicb53c622007-08-10 17:21:45 +02003119
3120 hda_call_codec_suspend(codec);
Takashi Iwai33fa35e2008-11-06 16:50:40 +01003121 if (bus->ops.pm_notify)
3122 bus->ops.pm_notify(bus);
Takashi Iwaicb53c622007-08-10 17:21:45 +02003123}
3124
3125static void hda_keep_power_on(struct hda_codec *codec)
3126{
3127 codec->power_count++;
3128 codec->power_on = 1;
3129}
3130
3131void snd_hda_power_up(struct hda_codec *codec)
3132{
Takashi Iwai33fa35e2008-11-06 16:50:40 +01003133 struct hda_bus *bus = codec->bus;
3134
Takashi Iwaicb53c622007-08-10 17:21:45 +02003135 codec->power_count++;
Takashi Iwaia221e282007-08-16 16:35:33 +02003136 if (codec->power_on || codec->power_transition)
Takashi Iwaicb53c622007-08-10 17:21:45 +02003137 return;
3138
3139 codec->power_on = 1;
Takashi Iwai33fa35e2008-11-06 16:50:40 +01003140 if (bus->ops.pm_notify)
3141 bus->ops.pm_notify(bus);
Takashi Iwaicb53c622007-08-10 17:21:45 +02003142 hda_call_codec_resume(codec);
3143 cancel_delayed_work(&codec->power_work);
Takashi Iwaia221e282007-08-16 16:35:33 +02003144 codec->power_transition = 0;
Takashi Iwaicb53c622007-08-10 17:21:45 +02003145}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003146EXPORT_SYMBOL_HDA(snd_hda_power_up);
Takashi Iwai1289e9e2008-11-27 15:47:11 +01003147
3148#define power_save(codec) \
3149 ((codec)->bus->power_save ? *(codec)->bus->power_save : 0)
Takashi Iwaicb53c622007-08-10 17:21:45 +02003150
Takashi Iwaifee2fba2008-11-27 12:43:28 +01003151#define power_save(codec) \
3152 ((codec)->bus->power_save ? *(codec)->bus->power_save : 0)
3153
Takashi Iwaicb53c622007-08-10 17:21:45 +02003154void snd_hda_power_down(struct hda_codec *codec)
3155{
3156 --codec->power_count;
Takashi Iwaia221e282007-08-16 16:35:33 +02003157 if (!codec->power_on || codec->power_count || codec->power_transition)
Takashi Iwaicb53c622007-08-10 17:21:45 +02003158 return;
Takashi Iwaifee2fba2008-11-27 12:43:28 +01003159 if (power_save(codec)) {
Takashi Iwaia221e282007-08-16 16:35:33 +02003160 codec->power_transition = 1; /* avoid reentrance */
Takashi Iwaic107b412009-01-13 17:46:37 +01003161 queue_delayed_work(codec->bus->workq, &codec->power_work,
Takashi Iwaifee2fba2008-11-27 12:43:28 +01003162 msecs_to_jiffies(power_save(codec) * 1000));
Takashi Iwaia221e282007-08-16 16:35:33 +02003163 }
Takashi Iwaicb53c622007-08-10 17:21:45 +02003164}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003165EXPORT_SYMBOL_HDA(snd_hda_power_down);
Takashi Iwaicb53c622007-08-10 17:21:45 +02003166
3167int snd_hda_check_amp_list_power(struct hda_codec *codec,
3168 struct hda_loopback_check *check,
3169 hda_nid_t nid)
3170{
3171 struct hda_amp_list *p;
3172 int ch, v;
3173
3174 if (!check->amplist)
3175 return 0;
3176 for (p = check->amplist; p->nid; p++) {
3177 if (p->nid == nid)
3178 break;
3179 }
3180 if (!p->nid)
3181 return 0; /* nothing changed */
3182
3183 for (p = check->amplist; p->nid; p++) {
3184 for (ch = 0; ch < 2; ch++) {
3185 v = snd_hda_codec_amp_read(codec, p->nid, ch, p->dir,
3186 p->idx);
3187 if (!(v & HDA_AMP_MUTE) && v > 0) {
3188 if (!check->power_on) {
3189 check->power_on = 1;
3190 snd_hda_power_up(codec);
3191 }
3192 return 1;
3193 }
3194 }
3195 }
3196 if (check->power_on) {
3197 check->power_on = 0;
3198 snd_hda_power_down(codec);
3199 }
3200 return 0;
3201}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003202EXPORT_SYMBOL_HDA(snd_hda_check_amp_list_power);
Takashi Iwaicb53c622007-08-10 17:21:45 +02003203#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07003204
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01003205/*
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01003206 * Channel mode helper
3207 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003208int snd_hda_ch_mode_info(struct hda_codec *codec,
3209 struct snd_ctl_elem_info *uinfo,
3210 const struct hda_channel_mode *chmode,
3211 int num_chmodes)
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01003212{
3213 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
3214 uinfo->count = 1;
3215 uinfo->value.enumerated.items = num_chmodes;
3216 if (uinfo->value.enumerated.item >= num_chmodes)
3217 uinfo->value.enumerated.item = num_chmodes - 1;
3218 sprintf(uinfo->value.enumerated.name, "%dch",
3219 chmode[uinfo->value.enumerated.item].channels);
3220 return 0;
3221}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003222EXPORT_SYMBOL_HDA(snd_hda_ch_mode_info);
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01003223
Takashi Iwai0ba21762007-04-16 11:29:14 +02003224int snd_hda_ch_mode_get(struct hda_codec *codec,
3225 struct snd_ctl_elem_value *ucontrol,
3226 const struct hda_channel_mode *chmode,
3227 int num_chmodes,
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01003228 int max_channels)
3229{
3230 int i;
3231
3232 for (i = 0; i < num_chmodes; i++) {
3233 if (max_channels == chmode[i].channels) {
3234 ucontrol->value.enumerated.item[0] = i;
3235 break;
3236 }
3237 }
3238 return 0;
3239}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003240EXPORT_SYMBOL_HDA(snd_hda_ch_mode_get);
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01003241
Takashi Iwai0ba21762007-04-16 11:29:14 +02003242int snd_hda_ch_mode_put(struct hda_codec *codec,
3243 struct snd_ctl_elem_value *ucontrol,
3244 const struct hda_channel_mode *chmode,
3245 int num_chmodes,
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01003246 int *max_channelsp)
3247{
3248 unsigned int mode;
3249
3250 mode = ucontrol->value.enumerated.item[0];
Takashi Iwai68ea7b22007-11-15 15:54:38 +01003251 if (mode >= num_chmodes)
3252 return -EINVAL;
Takashi Iwai82beb8f2007-08-10 17:09:26 +02003253 if (*max_channelsp == chmode[mode].channels)
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01003254 return 0;
3255 /* change the current channel setting */
3256 *max_channelsp = chmode[mode].channels;
3257 if (chmode[mode].sequence)
Takashi Iwai82beb8f2007-08-10 17:09:26 +02003258 snd_hda_sequence_write_cache(codec, chmode[mode].sequence);
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01003259 return 1;
3260}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003261EXPORT_SYMBOL_HDA(snd_hda_ch_mode_put);
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01003262
Linus Torvalds1da177e2005-04-16 15:20:36 -07003263/*
3264 * input MUX helper
3265 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003266int snd_hda_input_mux_info(const struct hda_input_mux *imux,
3267 struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003268{
3269 unsigned int index;
3270
3271 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
3272 uinfo->count = 1;
3273 uinfo->value.enumerated.items = imux->num_items;
Takashi Iwai5513b0c2007-10-09 11:58:41 +02003274 if (!imux->num_items)
3275 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003276 index = uinfo->value.enumerated.item;
3277 if (index >= imux->num_items)
3278 index = imux->num_items - 1;
3279 strcpy(uinfo->value.enumerated.name, imux->items[index].label);
3280 return 0;
3281}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003282EXPORT_SYMBOL_HDA(snd_hda_input_mux_info);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003283
Takashi Iwai0ba21762007-04-16 11:29:14 +02003284int snd_hda_input_mux_put(struct hda_codec *codec,
3285 const struct hda_input_mux *imux,
3286 struct snd_ctl_elem_value *ucontrol,
3287 hda_nid_t nid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003288 unsigned int *cur_val)
3289{
3290 unsigned int idx;
3291
Takashi Iwai5513b0c2007-10-09 11:58:41 +02003292 if (!imux->num_items)
3293 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003294 idx = ucontrol->value.enumerated.item[0];
3295 if (idx >= imux->num_items)
3296 idx = imux->num_items - 1;
Takashi Iwai82beb8f2007-08-10 17:09:26 +02003297 if (*cur_val == idx)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003298 return 0;
Takashi Iwai82beb8f2007-08-10 17:09:26 +02003299 snd_hda_codec_write_cache(codec, nid, 0, AC_VERB_SET_CONNECT_SEL,
3300 imux->items[idx].index);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003301 *cur_val = idx;
3302 return 1;
3303}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003304EXPORT_SYMBOL_HDA(snd_hda_input_mux_put);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003305
3306
3307/*
3308 * Multi-channel / digital-out PCM helper functions
3309 */
3310
Takashi Iwai6b97eb42007-04-05 14:51:48 +02003311/* setup SPDIF output stream */
3312static void setup_dig_out_stream(struct hda_codec *codec, hda_nid_t nid,
3313 unsigned int stream_tag, unsigned int format)
3314{
3315 /* turn off SPDIF once; otherwise the IEC958 bits won't be updated */
Takashi Iwai2f728532008-09-25 16:32:41 +02003316 if (codec->spdif_status_reset && (codec->spdif_ctls & AC_DIG1_ENABLE))
3317 set_dig_out_convert(codec, nid,
3318 codec->spdif_ctls & ~AC_DIG1_ENABLE & 0xff,
3319 -1);
Takashi Iwai6b97eb42007-04-05 14:51:48 +02003320 snd_hda_codec_setup_stream(codec, nid, stream_tag, 0, format);
Takashi Iwai2f728532008-09-25 16:32:41 +02003321 if (codec->slave_dig_outs) {
3322 hda_nid_t *d;
3323 for (d = codec->slave_dig_outs; *d; d++)
3324 snd_hda_codec_setup_stream(codec, *d, stream_tag, 0,
3325 format);
Matthew Ranostayde51ca12008-09-07 14:31:40 -04003326 }
Takashi Iwai2f728532008-09-25 16:32:41 +02003327 /* turn on again (if needed) */
3328 if (codec->spdif_status_reset && (codec->spdif_ctls & AC_DIG1_ENABLE))
3329 set_dig_out_convert(codec, nid,
3330 codec->spdif_ctls & 0xff, -1);
3331}
Matthew Ranostayde51ca12008-09-07 14:31:40 -04003332
Takashi Iwai2f728532008-09-25 16:32:41 +02003333static void cleanup_dig_out_stream(struct hda_codec *codec, hda_nid_t nid)
3334{
3335 snd_hda_codec_cleanup_stream(codec, nid);
3336 if (codec->slave_dig_outs) {
3337 hda_nid_t *d;
3338 for (d = codec->slave_dig_outs; *d; d++)
3339 snd_hda_codec_cleanup_stream(codec, *d);
3340 }
Takashi Iwai6b97eb42007-04-05 14:51:48 +02003341}
3342
Linus Torvalds1da177e2005-04-16 15:20:36 -07003343/*
3344 * open the digital out in the exclusive mode
3345 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003346int snd_hda_multi_out_dig_open(struct hda_codec *codec,
3347 struct hda_multi_out *mout)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003348{
Ingo Molnar62932df2006-01-16 16:34:20 +01003349 mutex_lock(&codec->spdif_mutex);
Takashi Iwai5930ca42007-04-16 11:23:56 +02003350 if (mout->dig_out_used == HDA_DIG_ANALOG_DUP)
3351 /* already opened as analog dup; reset it once */
Takashi Iwai2f728532008-09-25 16:32:41 +02003352 cleanup_dig_out_stream(codec, mout->dig_out_nid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003353 mout->dig_out_used = HDA_DIG_EXCLUSIVE;
Ingo Molnar62932df2006-01-16 16:34:20 +01003354 mutex_unlock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003355 return 0;
3356}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003357EXPORT_SYMBOL_HDA(snd_hda_multi_out_dig_open);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003358
Takashi Iwai6b97eb42007-04-05 14:51:48 +02003359int snd_hda_multi_out_dig_prepare(struct hda_codec *codec,
3360 struct hda_multi_out *mout,
3361 unsigned int stream_tag,
3362 unsigned int format,
3363 struct snd_pcm_substream *substream)
3364{
3365 mutex_lock(&codec->spdif_mutex);
3366 setup_dig_out_stream(codec, mout->dig_out_nid, stream_tag, format);
3367 mutex_unlock(&codec->spdif_mutex);
3368 return 0;
3369}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003370EXPORT_SYMBOL_HDA(snd_hda_multi_out_dig_prepare);
Takashi Iwai6b97eb42007-04-05 14:51:48 +02003371
Takashi Iwai9411e212009-02-13 11:32:28 +01003372int snd_hda_multi_out_dig_cleanup(struct hda_codec *codec,
3373 struct hda_multi_out *mout)
3374{
3375 mutex_lock(&codec->spdif_mutex);
3376 cleanup_dig_out_stream(codec, mout->dig_out_nid);
3377 mutex_unlock(&codec->spdif_mutex);
3378 return 0;
3379}
3380EXPORT_SYMBOL_HDA(snd_hda_multi_out_dig_cleanup);
3381
Linus Torvalds1da177e2005-04-16 15:20:36 -07003382/*
3383 * release the digital out
3384 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003385int snd_hda_multi_out_dig_close(struct hda_codec *codec,
3386 struct hda_multi_out *mout)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003387{
Ingo Molnar62932df2006-01-16 16:34:20 +01003388 mutex_lock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003389 mout->dig_out_used = 0;
Ingo Molnar62932df2006-01-16 16:34:20 +01003390 mutex_unlock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003391 return 0;
3392}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003393EXPORT_SYMBOL_HDA(snd_hda_multi_out_dig_close);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003394
3395/*
3396 * set up more restrictions for analog out
3397 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003398int snd_hda_multi_out_analog_open(struct hda_codec *codec,
3399 struct hda_multi_out *mout,
Takashi Iwai9a081602008-02-12 18:37:26 +01003400 struct snd_pcm_substream *substream,
3401 struct hda_pcm_stream *hinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003402{
Takashi Iwai9a081602008-02-12 18:37:26 +01003403 struct snd_pcm_runtime *runtime = substream->runtime;
3404 runtime->hw.channels_max = mout->max_channels;
3405 if (mout->dig_out_nid) {
3406 if (!mout->analog_rates) {
3407 mout->analog_rates = hinfo->rates;
3408 mout->analog_formats = hinfo->formats;
3409 mout->analog_maxbps = hinfo->maxbps;
3410 } else {
3411 runtime->hw.rates = mout->analog_rates;
3412 runtime->hw.formats = mout->analog_formats;
3413 hinfo->maxbps = mout->analog_maxbps;
3414 }
3415 if (!mout->spdif_rates) {
3416 snd_hda_query_supported_pcm(codec, mout->dig_out_nid,
3417 &mout->spdif_rates,
3418 &mout->spdif_formats,
3419 &mout->spdif_maxbps);
3420 }
3421 mutex_lock(&codec->spdif_mutex);
3422 if (mout->share_spdif) {
3423 runtime->hw.rates &= mout->spdif_rates;
3424 runtime->hw.formats &= mout->spdif_formats;
3425 if (mout->spdif_maxbps < hinfo->maxbps)
3426 hinfo->maxbps = mout->spdif_maxbps;
3427 }
Frederik Deweerdteaa99852008-04-14 13:11:44 +02003428 mutex_unlock(&codec->spdif_mutex);
Takashi Iwai9a081602008-02-12 18:37:26 +01003429 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003430 return snd_pcm_hw_constraint_step(substream->runtime, 0,
3431 SNDRV_PCM_HW_PARAM_CHANNELS, 2);
3432}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003433EXPORT_SYMBOL_HDA(snd_hda_multi_out_analog_open);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003434
3435/*
3436 * set up the i/o for analog out
3437 * when the digital out is available, copy the front out to digital out, too.
3438 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003439int snd_hda_multi_out_analog_prepare(struct hda_codec *codec,
3440 struct hda_multi_out *mout,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003441 unsigned int stream_tag,
3442 unsigned int format,
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01003443 struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003444{
3445 hda_nid_t *nids = mout->dac_nids;
3446 int chs = substream->runtime->channels;
3447 int i;
3448
Ingo Molnar62932df2006-01-16 16:34:20 +01003449 mutex_lock(&codec->spdif_mutex);
Takashi Iwai9a081602008-02-12 18:37:26 +01003450 if (mout->dig_out_nid && mout->share_spdif &&
3451 mout->dig_out_used != HDA_DIG_EXCLUSIVE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003452 if (chs == 2 &&
Takashi Iwai0ba21762007-04-16 11:29:14 +02003453 snd_hda_is_supported_format(codec, mout->dig_out_nid,
3454 format) &&
3455 !(codec->spdif_status & IEC958_AES0_NONAUDIO)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003456 mout->dig_out_used = HDA_DIG_ANALOG_DUP;
Takashi Iwai6b97eb42007-04-05 14:51:48 +02003457 setup_dig_out_stream(codec, mout->dig_out_nid,
3458 stream_tag, format);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003459 } else {
3460 mout->dig_out_used = 0;
Takashi Iwai2f728532008-09-25 16:32:41 +02003461 cleanup_dig_out_stream(codec, mout->dig_out_nid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003462 }
3463 }
Ingo Molnar62932df2006-01-16 16:34:20 +01003464 mutex_unlock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003465
3466 /* front */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003467 snd_hda_codec_setup_stream(codec, nids[HDA_FRONT], stream_tag,
3468 0, format);
Takashi Iwaid29240c2007-10-26 12:35:56 +02003469 if (!mout->no_share_stream &&
3470 mout->hp_nid && mout->hp_nid != nids[HDA_FRONT])
Linus Torvalds1da177e2005-04-16 15:20:36 -07003471 /* headphone out will just decode front left/right (stereo) */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003472 snd_hda_codec_setup_stream(codec, mout->hp_nid, stream_tag,
3473 0, format);
Takashi Iwai82bc9552006-03-21 11:24:42 +01003474 /* extra outputs copied from front */
3475 for (i = 0; i < ARRAY_SIZE(mout->extra_out_nid); i++)
Takashi Iwaid29240c2007-10-26 12:35:56 +02003476 if (!mout->no_share_stream && mout->extra_out_nid[i])
Takashi Iwai82bc9552006-03-21 11:24:42 +01003477 snd_hda_codec_setup_stream(codec,
3478 mout->extra_out_nid[i],
3479 stream_tag, 0, format);
3480
Linus Torvalds1da177e2005-04-16 15:20:36 -07003481 /* surrounds */
3482 for (i = 1; i < mout->num_dacs; i++) {
Takashi Iwai4b3acaf2005-06-10 19:48:10 +02003483 if (chs >= (i + 1) * 2) /* independent out */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003484 snd_hda_codec_setup_stream(codec, nids[i], stream_tag,
3485 i * 2, format);
Takashi Iwaid29240c2007-10-26 12:35:56 +02003486 else if (!mout->no_share_stream) /* copy front */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003487 snd_hda_codec_setup_stream(codec, nids[i], stream_tag,
3488 0, format);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003489 }
3490 return 0;
3491}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003492EXPORT_SYMBOL_HDA(snd_hda_multi_out_analog_prepare);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003493
3494/*
3495 * clean up the setting for analog out
3496 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003497int snd_hda_multi_out_analog_cleanup(struct hda_codec *codec,
3498 struct hda_multi_out *mout)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003499{
3500 hda_nid_t *nids = mout->dac_nids;
3501 int i;
3502
3503 for (i = 0; i < mout->num_dacs; i++)
Takashi Iwai888afa12008-03-18 09:57:50 +01003504 snd_hda_codec_cleanup_stream(codec, nids[i]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003505 if (mout->hp_nid)
Takashi Iwai888afa12008-03-18 09:57:50 +01003506 snd_hda_codec_cleanup_stream(codec, mout->hp_nid);
Takashi Iwai82bc9552006-03-21 11:24:42 +01003507 for (i = 0; i < ARRAY_SIZE(mout->extra_out_nid); i++)
3508 if (mout->extra_out_nid[i])
Takashi Iwai888afa12008-03-18 09:57:50 +01003509 snd_hda_codec_cleanup_stream(codec,
3510 mout->extra_out_nid[i]);
Ingo Molnar62932df2006-01-16 16:34:20 +01003511 mutex_lock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003512 if (mout->dig_out_nid && mout->dig_out_used == HDA_DIG_ANALOG_DUP) {
Takashi Iwai2f728532008-09-25 16:32:41 +02003513 cleanup_dig_out_stream(codec, mout->dig_out_nid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003514 mout->dig_out_used = 0;
3515 }
Ingo Molnar62932df2006-01-16 16:34:20 +01003516 mutex_unlock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003517 return 0;
3518}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003519EXPORT_SYMBOL_HDA(snd_hda_multi_out_analog_cleanup);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003520
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003521/*
Wu Fengguang6b345002008-10-07 14:21:41 +08003522 * Helper for automatic pin configuration
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003523 */
Kailang Yangdf694da2005-12-05 19:42:22 +01003524
Takashi Iwai12f288b2007-08-02 15:51:59 +02003525static int is_in_nid_list(hda_nid_t nid, hda_nid_t *list)
Kailang Yangdf694da2005-12-05 19:42:22 +01003526{
3527 for (; *list; list++)
3528 if (*list == nid)
3529 return 1;
3530 return 0;
3531}
3532
Steve Longerbeam81937d32007-05-08 15:33:03 +02003533
3534/*
3535 * Sort an associated group of pins according to their sequence numbers.
3536 */
3537static void sort_pins_by_sequence(hda_nid_t * pins, short * sequences,
3538 int num_pins)
3539{
3540 int i, j;
3541 short seq;
3542 hda_nid_t nid;
3543
3544 for (i = 0; i < num_pins; i++) {
3545 for (j = i + 1; j < num_pins; j++) {
3546 if (sequences[i] > sequences[j]) {
3547 seq = sequences[i];
3548 sequences[i] = sequences[j];
3549 sequences[j] = seq;
3550 nid = pins[i];
3551 pins[i] = pins[j];
3552 pins[j] = nid;
3553 }
3554 }
3555 }
3556}
3557
3558
Takashi Iwai82bc9552006-03-21 11:24:42 +01003559/*
3560 * Parse all pin widgets and store the useful pin nids to cfg
3561 *
3562 * The number of line-outs or any primary output is stored in line_outs,
3563 * and the corresponding output pins are assigned to line_out_pins[],
3564 * in the order of front, rear, CLFE, side, ...
3565 *
3566 * If more extra outputs (speaker and headphone) are found, the pins are
Takashi Iwaieb06ed82006-09-20 17:10:27 +02003567 * assisnged to hp_pins[] and speaker_pins[], respectively. If no line-out jack
Takashi Iwai82bc9552006-03-21 11:24:42 +01003568 * is detected, one of speaker of HP pins is assigned as the primary
3569 * output, i.e. to line_out_pins[0]. So, line_outs is always positive
3570 * if any analog output exists.
3571 *
3572 * The analog input pins are assigned to input_pins array.
3573 * The digital input/output pins are assigned to dig_in_pin and dig_out_pin,
3574 * respectively.
3575 */
Takashi Iwai12f288b2007-08-02 15:51:59 +02003576int snd_hda_parse_pin_def_config(struct hda_codec *codec,
3577 struct auto_pin_cfg *cfg,
3578 hda_nid_t *ignore_nids)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003579{
Takashi Iwai0ef6ce72008-01-22 15:35:37 +01003580 hda_nid_t nid, end_nid;
Steve Longerbeam81937d32007-05-08 15:33:03 +02003581 short seq, assoc_line_out, assoc_speaker;
3582 short sequences_line_out[ARRAY_SIZE(cfg->line_out_pins)];
3583 short sequences_speaker[ARRAY_SIZE(cfg->speaker_pins)];
Takashi Iwaif889fa92007-10-31 15:49:32 +01003584 short sequences_hp[ARRAY_SIZE(cfg->hp_pins)];
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003585
3586 memset(cfg, 0, sizeof(*cfg));
3587
Steve Longerbeam81937d32007-05-08 15:33:03 +02003588 memset(sequences_line_out, 0, sizeof(sequences_line_out));
3589 memset(sequences_speaker, 0, sizeof(sequences_speaker));
Takashi Iwaif889fa92007-10-31 15:49:32 +01003590 memset(sequences_hp, 0, sizeof(sequences_hp));
Steve Longerbeam81937d32007-05-08 15:33:03 +02003591 assoc_line_out = assoc_speaker = 0;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003592
Takashi Iwai0ef6ce72008-01-22 15:35:37 +01003593 end_nid = codec->start_nid + codec->num_nodes;
3594 for (nid = codec->start_nid; nid < end_nid; nid++) {
Takashi Iwai54d17402005-11-21 16:33:22 +01003595 unsigned int wid_caps = get_wcaps(codec, nid);
Takashi Iwai0ba21762007-04-16 11:29:14 +02003596 unsigned int wid_type =
3597 (wid_caps & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003598 unsigned int def_conf;
3599 short assoc, loc;
3600
3601 /* read all default configuration for pin complex */
3602 if (wid_type != AC_WID_PIN)
3603 continue;
Kailang Yangdf694da2005-12-05 19:42:22 +01003604 /* ignore the given nids (e.g. pc-beep returns error) */
3605 if (ignore_nids && is_in_nid_list(nid, ignore_nids))
3606 continue;
3607
Takashi Iwaic17a1ab2009-02-23 09:28:12 +01003608 def_conf = snd_hda_codec_get_pincfg(codec, nid);
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003609 if (get_defcfg_connect(def_conf) == AC_JACK_PORT_NONE)
3610 continue;
3611 loc = get_defcfg_location(def_conf);
3612 switch (get_defcfg_device(def_conf)) {
3613 case AC_JACK_LINE_OUT:
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003614 seq = get_defcfg_sequence(def_conf);
3615 assoc = get_defcfg_association(def_conf);
Matthew Ranostay90da78b2008-01-24 11:48:01 +01003616
3617 if (!(wid_caps & AC_WCAP_STEREO))
3618 if (!cfg->mono_out_pin)
3619 cfg->mono_out_pin = nid;
Takashi Iwai0ba21762007-04-16 11:29:14 +02003620 if (!assoc)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003621 continue;
Takashi Iwai0ba21762007-04-16 11:29:14 +02003622 if (!assoc_line_out)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003623 assoc_line_out = assoc;
3624 else if (assoc_line_out != assoc)
3625 continue;
3626 if (cfg->line_outs >= ARRAY_SIZE(cfg->line_out_pins))
3627 continue;
3628 cfg->line_out_pins[cfg->line_outs] = nid;
Steve Longerbeam81937d32007-05-08 15:33:03 +02003629 sequences_line_out[cfg->line_outs] = seq;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003630 cfg->line_outs++;
3631 break;
Takashi Iwai8d88bc32005-11-17 11:09:23 +01003632 case AC_JACK_SPEAKER:
Steve Longerbeam81937d32007-05-08 15:33:03 +02003633 seq = get_defcfg_sequence(def_conf);
3634 assoc = get_defcfg_association(def_conf);
3635 if (! assoc)
3636 continue;
3637 if (! assoc_speaker)
3638 assoc_speaker = assoc;
3639 else if (assoc_speaker != assoc)
3640 continue;
Takashi Iwai82bc9552006-03-21 11:24:42 +01003641 if (cfg->speaker_outs >= ARRAY_SIZE(cfg->speaker_pins))
3642 continue;
3643 cfg->speaker_pins[cfg->speaker_outs] = nid;
Steve Longerbeam81937d32007-05-08 15:33:03 +02003644 sequences_speaker[cfg->speaker_outs] = seq;
Takashi Iwai82bc9552006-03-21 11:24:42 +01003645 cfg->speaker_outs++;
Takashi Iwai8d88bc32005-11-17 11:09:23 +01003646 break;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003647 case AC_JACK_HP_OUT:
Takashi Iwaif889fa92007-10-31 15:49:32 +01003648 seq = get_defcfg_sequence(def_conf);
3649 assoc = get_defcfg_association(def_conf);
Takashi Iwaieb06ed82006-09-20 17:10:27 +02003650 if (cfg->hp_outs >= ARRAY_SIZE(cfg->hp_pins))
3651 continue;
3652 cfg->hp_pins[cfg->hp_outs] = nid;
Takashi Iwaif889fa92007-10-31 15:49:32 +01003653 sequences_hp[cfg->hp_outs] = (assoc << 4) | seq;
Takashi Iwaieb06ed82006-09-20 17:10:27 +02003654 cfg->hp_outs++;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003655 break;
Takashi Iwai314634b2006-09-21 11:56:18 +02003656 case AC_JACK_MIC_IN: {
3657 int preferred, alt;
3658 if (loc == AC_JACK_LOC_FRONT) {
3659 preferred = AUTO_PIN_FRONT_MIC;
3660 alt = AUTO_PIN_MIC;
3661 } else {
3662 preferred = AUTO_PIN_MIC;
3663 alt = AUTO_PIN_FRONT_MIC;
3664 }
3665 if (!cfg->input_pins[preferred])
3666 cfg->input_pins[preferred] = nid;
3667 else if (!cfg->input_pins[alt])
3668 cfg->input_pins[alt] = nid;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003669 break;
Takashi Iwai314634b2006-09-21 11:56:18 +02003670 }
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003671 case AC_JACK_LINE_IN:
3672 if (loc == AC_JACK_LOC_FRONT)
3673 cfg->input_pins[AUTO_PIN_FRONT_LINE] = nid;
3674 else
3675 cfg->input_pins[AUTO_PIN_LINE] = nid;
3676 break;
3677 case AC_JACK_CD:
3678 cfg->input_pins[AUTO_PIN_CD] = nid;
3679 break;
3680 case AC_JACK_AUX:
3681 cfg->input_pins[AUTO_PIN_AUX] = nid;
3682 break;
3683 case AC_JACK_SPDIF_OUT:
Takashi Iwai1b52ae72009-01-20 17:17:29 +01003684 case AC_JACK_DIG_OTHER_OUT:
Takashi Iwai0852d7a2009-02-11 11:35:15 +01003685 if (cfg->dig_outs >= ARRAY_SIZE(cfg->dig_out_pins))
3686 continue;
3687 cfg->dig_out_pins[cfg->dig_outs] = nid;
3688 cfg->dig_out_type[cfg->dig_outs] =
3689 (loc == AC_JACK_LOC_HDMI) ?
3690 HDA_PCM_TYPE_HDMI : HDA_PCM_TYPE_SPDIF;
3691 cfg->dig_outs++;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003692 break;
3693 case AC_JACK_SPDIF_IN:
Takashi Iwai1b52ae72009-01-20 17:17:29 +01003694 case AC_JACK_DIG_OTHER_IN:
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003695 cfg->dig_in_pin = nid;
Takashi Iwai2297bd62009-01-20 18:24:13 +01003696 if (loc == AC_JACK_LOC_HDMI)
3697 cfg->dig_in_type = HDA_PCM_TYPE_HDMI;
3698 else
3699 cfg->dig_in_type = HDA_PCM_TYPE_SPDIF;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003700 break;
3701 }
3702 }
3703
Takashi Iwai5832fcf2008-02-12 18:30:12 +01003704 /* FIX-UP:
3705 * If no line-out is defined but multiple HPs are found,
3706 * some of them might be the real line-outs.
3707 */
3708 if (!cfg->line_outs && cfg->hp_outs > 1) {
3709 int i = 0;
3710 while (i < cfg->hp_outs) {
3711 /* The real HPs should have the sequence 0x0f */
3712 if ((sequences_hp[i] & 0x0f) == 0x0f) {
3713 i++;
3714 continue;
3715 }
3716 /* Move it to the line-out table */
3717 cfg->line_out_pins[cfg->line_outs] = cfg->hp_pins[i];
3718 sequences_line_out[cfg->line_outs] = sequences_hp[i];
3719 cfg->line_outs++;
3720 cfg->hp_outs--;
3721 memmove(cfg->hp_pins + i, cfg->hp_pins + i + 1,
3722 sizeof(cfg->hp_pins[0]) * (cfg->hp_outs - i));
3723 memmove(sequences_hp + i - 1, sequences_hp + i,
3724 sizeof(sequences_hp[0]) * (cfg->hp_outs - i));
3725 }
3726 }
3727
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003728 /* sort by sequence */
Steve Longerbeam81937d32007-05-08 15:33:03 +02003729 sort_pins_by_sequence(cfg->line_out_pins, sequences_line_out,
3730 cfg->line_outs);
3731 sort_pins_by_sequence(cfg->speaker_pins, sequences_speaker,
3732 cfg->speaker_outs);
Takashi Iwaif889fa92007-10-31 15:49:32 +01003733 sort_pins_by_sequence(cfg->hp_pins, sequences_hp,
3734 cfg->hp_outs);
Steve Longerbeam81937d32007-05-08 15:33:03 +02003735
Takashi Iwaif889fa92007-10-31 15:49:32 +01003736 /* if we have only one mic, make it AUTO_PIN_MIC */
3737 if (!cfg->input_pins[AUTO_PIN_MIC] &&
3738 cfg->input_pins[AUTO_PIN_FRONT_MIC]) {
3739 cfg->input_pins[AUTO_PIN_MIC] =
3740 cfg->input_pins[AUTO_PIN_FRONT_MIC];
3741 cfg->input_pins[AUTO_PIN_FRONT_MIC] = 0;
3742 }
3743 /* ditto for line-in */
3744 if (!cfg->input_pins[AUTO_PIN_LINE] &&
3745 cfg->input_pins[AUTO_PIN_FRONT_LINE]) {
3746 cfg->input_pins[AUTO_PIN_LINE] =
3747 cfg->input_pins[AUTO_PIN_FRONT_LINE];
3748 cfg->input_pins[AUTO_PIN_FRONT_LINE] = 0;
3749 }
3750
Steve Longerbeam81937d32007-05-08 15:33:03 +02003751 /*
3752 * FIX-UP: if no line-outs are detected, try to use speaker or HP pin
3753 * as a primary output
3754 */
3755 if (!cfg->line_outs) {
3756 if (cfg->speaker_outs) {
3757 cfg->line_outs = cfg->speaker_outs;
3758 memcpy(cfg->line_out_pins, cfg->speaker_pins,
3759 sizeof(cfg->speaker_pins));
3760 cfg->speaker_outs = 0;
3761 memset(cfg->speaker_pins, 0, sizeof(cfg->speaker_pins));
3762 cfg->line_out_type = AUTO_PIN_SPEAKER_OUT;
3763 } else if (cfg->hp_outs) {
3764 cfg->line_outs = cfg->hp_outs;
3765 memcpy(cfg->line_out_pins, cfg->hp_pins,
3766 sizeof(cfg->hp_pins));
3767 cfg->hp_outs = 0;
3768 memset(cfg->hp_pins, 0, sizeof(cfg->hp_pins));
3769 cfg->line_out_type = AUTO_PIN_HP_OUT;
3770 }
3771 }
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003772
Takashi Iwaicb8e2f82005-07-29 11:54:32 +02003773 /* Reorder the surround channels
3774 * ALSA sequence is front/surr/clfe/side
3775 * HDA sequence is:
3776 * 4-ch: front/surr => OK as it is
3777 * 6-ch: front/clfe/surr
Takashi Iwai9422db42007-04-20 16:11:43 +02003778 * 8-ch: front/clfe/rear/side|fc
Takashi Iwaicb8e2f82005-07-29 11:54:32 +02003779 */
3780 switch (cfg->line_outs) {
3781 case 3:
Takashi Iwaicb8e2f82005-07-29 11:54:32 +02003782 case 4:
3783 nid = cfg->line_out_pins[1];
Takashi Iwai9422db42007-04-20 16:11:43 +02003784 cfg->line_out_pins[1] = cfg->line_out_pins[2];
Takashi Iwaicb8e2f82005-07-29 11:54:32 +02003785 cfg->line_out_pins[2] = nid;
3786 break;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003787 }
3788
Takashi Iwai82bc9552006-03-21 11:24:42 +01003789 /*
3790 * debug prints of the parsed results
3791 */
3792 snd_printd("autoconfig: line_outs=%d (0x%x/0x%x/0x%x/0x%x/0x%x)\n",
3793 cfg->line_outs, cfg->line_out_pins[0], cfg->line_out_pins[1],
3794 cfg->line_out_pins[2], cfg->line_out_pins[3],
3795 cfg->line_out_pins[4]);
3796 snd_printd(" speaker_outs=%d (0x%x/0x%x/0x%x/0x%x/0x%x)\n",
3797 cfg->speaker_outs, cfg->speaker_pins[0],
3798 cfg->speaker_pins[1], cfg->speaker_pins[2],
3799 cfg->speaker_pins[3], cfg->speaker_pins[4]);
Takashi Iwaieb06ed82006-09-20 17:10:27 +02003800 snd_printd(" hp_outs=%d (0x%x/0x%x/0x%x/0x%x/0x%x)\n",
3801 cfg->hp_outs, cfg->hp_pins[0],
3802 cfg->hp_pins[1], cfg->hp_pins[2],
3803 cfg->hp_pins[3], cfg->hp_pins[4]);
Matthew Ranostay90da78b2008-01-24 11:48:01 +01003804 snd_printd(" mono: mono_out=0x%x\n", cfg->mono_out_pin);
Takashi Iwai0852d7a2009-02-11 11:35:15 +01003805 if (cfg->dig_outs)
3806 snd_printd(" dig-out=0x%x/0x%x\n",
3807 cfg->dig_out_pins[0], cfg->dig_out_pins[1]);
Takashi Iwai82bc9552006-03-21 11:24:42 +01003808 snd_printd(" inputs: mic=0x%x, fmic=0x%x, line=0x%x, fline=0x%x,"
3809 " cd=0x%x, aux=0x%x\n",
3810 cfg->input_pins[AUTO_PIN_MIC],
3811 cfg->input_pins[AUTO_PIN_FRONT_MIC],
3812 cfg->input_pins[AUTO_PIN_LINE],
3813 cfg->input_pins[AUTO_PIN_FRONT_LINE],
3814 cfg->input_pins[AUTO_PIN_CD],
3815 cfg->input_pins[AUTO_PIN_AUX]);
Takashi Iwai32d2c7f2009-02-11 11:33:13 +01003816 if (cfg->dig_in_pin)
Takashi Iwai89ce9e82009-01-20 17:15:57 +01003817 snd_printd(" dig-in=0x%x\n", cfg->dig_in_pin);
Takashi Iwai82bc9552006-03-21 11:24:42 +01003818
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003819 return 0;
3820}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003821EXPORT_SYMBOL_HDA(snd_hda_parse_pin_def_config);
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003822
Takashi Iwai4a471b72005-12-07 13:56:29 +01003823/* labels for input pins */
3824const char *auto_pin_cfg_labels[AUTO_PIN_LAST] = {
3825 "Mic", "Front Mic", "Line", "Front Line", "CD", "Aux"
3826};
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003827EXPORT_SYMBOL_HDA(auto_pin_cfg_labels);
Takashi Iwai4a471b72005-12-07 13:56:29 +01003828
3829
Linus Torvalds1da177e2005-04-16 15:20:36 -07003830#ifdef CONFIG_PM
3831/*
3832 * power management
3833 */
3834
3835/**
3836 * snd_hda_suspend - suspend the codecs
3837 * @bus: the HDA bus
3838 * @state: suspsend state
3839 *
3840 * Returns 0 if successful.
3841 */
3842int snd_hda_suspend(struct hda_bus *bus, pm_message_t state)
3843{
Takashi Iwai0ba21762007-04-16 11:29:14 +02003844 struct hda_codec *codec;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003845
Takashi Iwai0ba21762007-04-16 11:29:14 +02003846 list_for_each_entry(codec, &bus->codec_list, list) {
Takashi Iwai0b7a2e92007-08-14 15:18:26 +02003847#ifdef CONFIG_SND_HDA_POWER_SAVE
3848 if (!codec->power_on)
3849 continue;
3850#endif
Takashi Iwaicb53c622007-08-10 17:21:45 +02003851 hda_call_codec_suspend(codec);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003852 }
3853 return 0;
3854}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003855EXPORT_SYMBOL_HDA(snd_hda_suspend);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003856
3857/**
3858 * snd_hda_resume - resume the codecs
3859 * @bus: the HDA bus
Linus Torvalds1da177e2005-04-16 15:20:36 -07003860 *
3861 * Returns 0 if successful.
Takashi Iwaicb53c622007-08-10 17:21:45 +02003862 *
3863 * This fucntion is defined only when POWER_SAVE isn't set.
3864 * In the power-save mode, the codec is resumed dynamically.
Linus Torvalds1da177e2005-04-16 15:20:36 -07003865 */
3866int snd_hda_resume(struct hda_bus *bus)
3867{
Takashi Iwai0ba21762007-04-16 11:29:14 +02003868 struct hda_codec *codec;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003869
Takashi Iwai0ba21762007-04-16 11:29:14 +02003870 list_for_each_entry(codec, &bus->codec_list, list) {
Maxim Levitskyd804ad92007-09-03 15:28:04 +02003871 if (snd_hda_codec_needs_resume(codec))
3872 hda_call_codec_resume(codec);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003873 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003874 return 0;
3875}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003876EXPORT_SYMBOL_HDA(snd_hda_resume);
Takashi Iwai1289e9e2008-11-27 15:47:11 +01003877#endif /* CONFIG_PM */
Takashi Iwaib2e18592008-07-30 15:01:44 +02003878
3879/*
3880 * generic arrays
3881 */
3882
3883/* get a new element from the given array
3884 * if it exceeds the pre-allocated array size, re-allocate the array
3885 */
3886void *snd_array_new(struct snd_array *array)
3887{
3888 if (array->used >= array->alloced) {
3889 int num = array->alloced + array->alloc_align;
Takashi Iwaib910d9a2008-11-07 00:26:52 +01003890 void *nlist;
3891 if (snd_BUG_ON(num >= 4096))
3892 return NULL;
3893 nlist = kcalloc(num + 1, array->elem_size, GFP_KERNEL);
Takashi Iwaib2e18592008-07-30 15:01:44 +02003894 if (!nlist)
3895 return NULL;
3896 if (array->list) {
3897 memcpy(nlist, array->list,
3898 array->elem_size * array->alloced);
3899 kfree(array->list);
3900 }
3901 array->list = nlist;
3902 array->alloced = num;
3903 }
Takashi Iwaif43aa022008-11-10 16:24:26 +01003904 return snd_array_elem(array, array->used++);
Takashi Iwaib2e18592008-07-30 15:01:44 +02003905}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003906EXPORT_SYMBOL_HDA(snd_array_new);
Takashi Iwaib2e18592008-07-30 15:01:44 +02003907
3908/* free the given array elements */
3909void snd_array_free(struct snd_array *array)
3910{
3911 kfree(array->list);
3912 array->used = 0;
3913 array->alloced = 0;
3914 array->list = NULL;
3915}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003916EXPORT_SYMBOL_HDA(snd_array_free);
Takashi Iwaib2022262008-11-21 21:24:03 +01003917
3918/*
3919 * used by hda_proc.c and hda_eld.c
3920 */
3921void snd_print_pcm_rates(int pcm, char *buf, int buflen)
3922{
3923 static unsigned int rates[] = {
3924 8000, 11025, 16000, 22050, 32000, 44100, 48000, 88200,
3925 96000, 176400, 192000, 384000
3926 };
3927 int i, j;
3928
3929 for (i = 0, j = 0; i < ARRAY_SIZE(rates); i++)
3930 if (pcm & (1 << i))
3931 j += snprintf(buf + j, buflen - j, " %d", rates[i]);
3932
3933 buf[j] = '\0'; /* necessary when j == 0 */
3934}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003935EXPORT_SYMBOL_HDA(snd_print_pcm_rates);
Takashi Iwaib2022262008-11-21 21:24:03 +01003936
3937void snd_print_pcm_bits(int pcm, char *buf, int buflen)
3938{
3939 static unsigned int bits[] = { 8, 16, 20, 24, 32 };
3940 int i, j;
3941
3942 for (i = 0, j = 0; i < ARRAY_SIZE(bits); i++)
3943 if (pcm & (AC_SUPPCM_BITS_8 << i))
3944 j += snprintf(buf + j, buflen - j, " %d", bits[i]);
3945
3946 buf[j] = '\0'; /* necessary when j == 0 */
3947}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003948EXPORT_SYMBOL_HDA(snd_print_pcm_bits);
Takashi Iwai1289e9e2008-11-27 15:47:11 +01003949
3950MODULE_DESCRIPTION("HDA codec core");
3951MODULE_LICENSE("GPL");