blob: c7df01b72cacf089a78201872c9b5e3b39fb1921 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * Universal Interface for Intel High Definition Audio Codec
3 *
4 * Copyright (c) 2004 Takashi Iwai <tiwai@suse.de>
5 *
6 *
7 * This driver is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This driver is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21
Linus Torvalds1da177e2005-04-16 15:20:36 -070022#include <linux/init.h>
23#include <linux/delay.h>
24#include <linux/slab.h>
25#include <linux/pci.h>
Ingo Molnar62932df2006-01-16 16:34:20 +010026#include <linux/mutex.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070027#include <sound/core.h>
28#include "hda_codec.h"
29#include <sound/asoundef.h>
Jaroslav Kysela302e9c52006-07-05 17:39:49 +020030#include <sound/tlv.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070031#include <sound/initval.h>
32#include "hda_local.h"
Takashi Iwai28073142007-07-27 18:58:06 +020033#include <sound/hda_hwdep.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070034
Linus Torvalds1da177e2005-04-16 15:20:36 -070035/*
36 * vendor / preset table
37 */
38
39struct hda_vendor_id {
40 unsigned int id;
41 const char *name;
42};
43
44/* codec vendor labels */
45static struct hda_vendor_id hda_vendor_ids[] = {
Takashi Iwaic8cd1282008-02-13 16:59:29 +010046 { 0x1002, "ATI" },
Takashi Iwaia9226252006-09-17 22:05:54 +020047 { 0x1057, "Motorola" },
Takashi Iwaic8cd1282008-02-13 16:59:29 +010048 { 0x1095, "Silicon Image" },
Takashi Iwai31117b72008-12-16 14:43:21 +010049 { 0x10de, "Nvidia" },
Takashi Iwaic8cd1282008-02-13 16:59:29 +010050 { 0x10ec, "Realtek" },
Takashi Iwai4e01f542009-04-16 08:53:34 +020051 { 0x1102, "Creative" },
Joseph Chanc577b8a2006-11-29 15:29:40 +010052 { 0x1106, "VIA" },
Matthew Ranostay7f168592007-10-18 17:38:17 +020053 { 0x111d, "IDT" },
Takashi Iwaic8cd1282008-02-13 16:59:29 +010054 { 0x11c1, "LSI" },
Takashi Iwai54b903e2005-05-15 14:30:10 +020055 { 0x11d4, "Analog Devices" },
Linus Torvalds1da177e2005-04-16 15:20:36 -070056 { 0x13f6, "C-Media" },
Takashi Iwaia9226252006-09-17 22:05:54 +020057 { 0x14f1, "Conexant" },
Takashi Iwaic8cd1282008-02-13 16:59:29 +010058 { 0x17e8, "Chrontel" },
59 { 0x1854, "LG" },
Mark Brown8199de32008-10-28 14:50:13 +000060 { 0x1aec, "Wolfson Microelectronics" },
Linus Torvalds1da177e2005-04-16 15:20:36 -070061 { 0x434d, "C-Media" },
Takashi Iwai74c61132008-12-18 09:11:33 +010062 { 0x8086, "Intel" },
Matt2f2f4252005-04-13 14:45:30 +020063 { 0x8384, "SigmaTel" },
Linus Torvalds1da177e2005-04-16 15:20:36 -070064 {} /* terminator */
65};
66
Takashi Iwai1289e9e2008-11-27 15:47:11 +010067static DEFINE_MUTEX(preset_mutex);
68static LIST_HEAD(hda_preset_tables);
69
70int snd_hda_add_codec_preset(struct hda_codec_preset_list *preset)
71{
72 mutex_lock(&preset_mutex);
73 list_add_tail(&preset->list, &hda_preset_tables);
74 mutex_unlock(&preset_mutex);
75 return 0;
76}
Takashi Iwaiff7a3262008-11-28 15:17:06 +010077EXPORT_SYMBOL_HDA(snd_hda_add_codec_preset);
Takashi Iwai1289e9e2008-11-27 15:47:11 +010078
79int snd_hda_delete_codec_preset(struct hda_codec_preset_list *preset)
80{
81 mutex_lock(&preset_mutex);
82 list_del(&preset->list);
83 mutex_unlock(&preset_mutex);
84 return 0;
85}
Takashi Iwaiff7a3262008-11-28 15:17:06 +010086EXPORT_SYMBOL_HDA(snd_hda_delete_codec_preset);
Linus Torvalds1da177e2005-04-16 15:20:36 -070087
Takashi Iwaicb53c622007-08-10 17:21:45 +020088#ifdef CONFIG_SND_HDA_POWER_SAVE
89static void hda_power_work(struct work_struct *work);
90static void hda_keep_power_on(struct hda_codec *codec);
91#else
92static inline void hda_keep_power_on(struct hda_codec *codec) {}
93#endif
94
Matthew Ranostay50a9f792008-10-25 01:05:45 -040095const char *snd_hda_get_jack_location(u32 cfg)
96{
97 static char *bases[7] = {
98 "N/A", "Rear", "Front", "Left", "Right", "Top", "Bottom",
99 };
100 static unsigned char specials_idx[] = {
101 0x07, 0x08,
102 0x17, 0x18, 0x19,
103 0x37, 0x38
104 };
105 static char *specials[] = {
106 "Rear Panel", "Drive Bar",
107 "Riser", "HDMI", "ATAPI",
108 "Mobile-In", "Mobile-Out"
109 };
110 int i;
111 cfg = (cfg & AC_DEFCFG_LOCATION) >> AC_DEFCFG_LOCATION_SHIFT;
112 if ((cfg & 0x0f) < 7)
113 return bases[cfg & 0x0f];
114 for (i = 0; i < ARRAY_SIZE(specials_idx); i++) {
115 if (cfg == specials_idx[i])
116 return specials[i];
117 }
118 return "UNKNOWN";
119}
Takashi Iwaiff7a3262008-11-28 15:17:06 +0100120EXPORT_SYMBOL_HDA(snd_hda_get_jack_location);
Matthew Ranostay50a9f792008-10-25 01:05:45 -0400121
122const char *snd_hda_get_jack_connectivity(u32 cfg)
123{
124 static char *jack_locations[4] = { "Ext", "Int", "Sep", "Oth" };
125
126 return jack_locations[(cfg >> (AC_DEFCFG_LOCATION_SHIFT + 4)) & 3];
127}
Takashi Iwaiff7a3262008-11-28 15:17:06 +0100128EXPORT_SYMBOL_HDA(snd_hda_get_jack_connectivity);
Matthew Ranostay50a9f792008-10-25 01:05:45 -0400129
130const char *snd_hda_get_jack_type(u32 cfg)
131{
132 static char *jack_types[16] = {
133 "Line Out", "Speaker", "HP Out", "CD",
134 "SPDIF Out", "Digital Out", "Modem Line", "Modem Hand",
135 "Line In", "Aux", "Mic", "Telephony",
136 "SPDIF In", "Digitial In", "Reserved", "Other"
137 };
138
139 return jack_types[(cfg & AC_DEFCFG_DEVICE)
140 >> AC_DEFCFG_DEVICE_SHIFT];
141}
Takashi Iwaiff7a3262008-11-28 15:17:06 +0100142EXPORT_SYMBOL_HDA(snd_hda_get_jack_type);
Matthew Ranostay50a9f792008-10-25 01:05:45 -0400143
Takashi Iwai33fa35e2008-11-06 16:50:40 +0100144/*
145 * Compose a 32bit command word to be sent to the HD-audio controller
146 */
147static inline unsigned int
148make_codec_cmd(struct hda_codec *codec, hda_nid_t nid, int direct,
149 unsigned int verb, unsigned int parm)
150{
151 u32 val;
152
153 val = (u32)(codec->addr & 0x0f) << 28;
154 val |= (u32)direct << 27;
155 val |= (u32)nid << 20;
156 val |= verb << 8;
157 val |= parm;
158 return val;
159}
160
Takashi Iwaiaa2936f2009-05-26 16:07:57 +0200161/*
162 * Send and receive a verb
163 */
164static int codec_exec_verb(struct hda_codec *codec, unsigned int cmd,
165 unsigned int *res)
166{
167 struct hda_bus *bus = codec->bus;
Takashi Iwai8dd78332009-06-02 01:16:07 +0200168 int err;
Takashi Iwaiaa2936f2009-05-26 16:07:57 +0200169
170 if (res)
171 *res = -1;
Takashi Iwai8dd78332009-06-02 01:16:07 +0200172 again:
Takashi Iwaiaa2936f2009-05-26 16:07:57 +0200173 snd_hda_power_up(codec);
174 mutex_lock(&bus->cmd_mutex);
Takashi Iwaiaa2936f2009-05-26 16:07:57 +0200175 err = bus->ops.command(bus, cmd);
Takashi Iwai8dd78332009-06-02 01:16:07 +0200176 if (!err && res)
Wu Fengguangdeadff12009-08-01 18:45:16 +0800177 *res = bus->ops.get_response(bus, codec->addr);
Takashi Iwaiaa2936f2009-05-26 16:07:57 +0200178 mutex_unlock(&bus->cmd_mutex);
179 snd_hda_power_down(codec);
Takashi Iwai8dd78332009-06-02 01:16:07 +0200180 if (res && *res == -1 && bus->rirb_error) {
181 if (bus->response_reset) {
182 snd_printd("hda_codec: resetting BUS due to "
183 "fatal communication error\n");
184 bus->ops.bus_reset(bus);
185 }
186 goto again;
187 }
188 /* clear reset-flag when the communication gets recovered */
189 if (!err)
190 bus->response_reset = 0;
Takashi Iwaiaa2936f2009-05-26 16:07:57 +0200191 return err;
192}
193
Linus Torvalds1da177e2005-04-16 15:20:36 -0700194/**
195 * snd_hda_codec_read - send a command and get the response
196 * @codec: the HDA codec
197 * @nid: NID to send the command
198 * @direct: direct flag
199 * @verb: the verb to send
200 * @parm: the parameter for the verb
201 *
202 * Send a single command and read the corresponding response.
203 *
204 * Returns the obtained response value, or -1 for an error.
205 */
Takashi Iwai0ba21762007-04-16 11:29:14 +0200206unsigned int snd_hda_codec_read(struct hda_codec *codec, hda_nid_t nid,
207 int direct,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700208 unsigned int verb, unsigned int parm)
209{
Takashi Iwaiaa2936f2009-05-26 16:07:57 +0200210 unsigned cmd = make_codec_cmd(codec, nid, direct, verb, parm);
211 unsigned int res;
212 codec_exec_verb(codec, cmd, &res);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700213 return res;
214}
Takashi Iwaiff7a3262008-11-28 15:17:06 +0100215EXPORT_SYMBOL_HDA(snd_hda_codec_read);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700216
217/**
218 * snd_hda_codec_write - send a single command without waiting for response
219 * @codec: the HDA codec
220 * @nid: NID to send the command
221 * @direct: direct flag
222 * @verb: the verb to send
223 * @parm: the parameter for the verb
224 *
225 * Send a single command without waiting for response.
226 *
227 * Returns 0 if successful, or a negative error code.
228 */
229int snd_hda_codec_write(struct hda_codec *codec, hda_nid_t nid, int direct,
230 unsigned int verb, unsigned int parm)
231{
Takashi Iwaiaa2936f2009-05-26 16:07:57 +0200232 unsigned int cmd = make_codec_cmd(codec, nid, direct, verb, parm);
Takashi Iwai33fa35e2008-11-06 16:50:40 +0100233 unsigned int res;
Takashi Iwaib20f3b82009-06-02 01:20:22 +0200234 return codec_exec_verb(codec, cmd,
235 codec->bus->sync_write ? &res : NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700236}
Takashi Iwaiff7a3262008-11-28 15:17:06 +0100237EXPORT_SYMBOL_HDA(snd_hda_codec_write);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700238
239/**
240 * snd_hda_sequence_write - sequence writes
241 * @codec: the HDA codec
242 * @seq: VERB array to send
243 *
244 * Send the commands sequentially from the given array.
245 * The array must be terminated with NID=0.
246 */
247void snd_hda_sequence_write(struct hda_codec *codec, const struct hda_verb *seq)
248{
249 for (; seq->nid; seq++)
250 snd_hda_codec_write(codec, seq->nid, 0, seq->verb, seq->param);
251}
Takashi Iwaiff7a3262008-11-28 15:17:06 +0100252EXPORT_SYMBOL_HDA(snd_hda_sequence_write);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700253
254/**
255 * snd_hda_get_sub_nodes - get the range of sub nodes
256 * @codec: the HDA codec
257 * @nid: NID to parse
258 * @start_id: the pointer to store the start NID
259 *
260 * Parse the NID and store the start NID of its sub-nodes.
261 * Returns the number of sub-nodes.
262 */
Takashi Iwai0ba21762007-04-16 11:29:14 +0200263int snd_hda_get_sub_nodes(struct hda_codec *codec, hda_nid_t nid,
264 hda_nid_t *start_id)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700265{
266 unsigned int parm;
267
268 parm = snd_hda_param_read(codec, nid, AC_PAR_NODE_COUNT);
Danny Tholene8a7f132007-09-11 21:41:56 +0200269 if (parm == -1)
270 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700271 *start_id = (parm >> 16) & 0x7fff;
272 return (int)(parm & 0x7fff);
273}
Takashi Iwaiff7a3262008-11-28 15:17:06 +0100274EXPORT_SYMBOL_HDA(snd_hda_get_sub_nodes);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700275
276/**
277 * snd_hda_get_connections - get connection list
278 * @codec: the HDA codec
279 * @nid: NID to parse
280 * @conn_list: connection list array
281 * @max_conns: max. number of connections to store
282 *
283 * Parses the connection list of the given widget and stores the list
284 * of NIDs.
285 *
286 * Returns the number of connections, or a negative error code.
287 */
288int snd_hda_get_connections(struct hda_codec *codec, hda_nid_t nid,
289 hda_nid_t *conn_list, int max_conns)
290{
291 unsigned int parm;
Takashi Iwai54d17402005-11-21 16:33:22 +0100292 int i, conn_len, conns;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700293 unsigned int shift, num_elems, mask;
Takashi Iwai54d17402005-11-21 16:33:22 +0100294 hda_nid_t prev_nid;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700295
Takashi Iwaida3cec32008-08-08 17:12:14 +0200296 if (snd_BUG_ON(!conn_list || max_conns <= 0))
297 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700298
299 parm = snd_hda_param_read(codec, nid, AC_PAR_CONNLIST_LEN);
300 if (parm & AC_CLIST_LONG) {
301 /* long form */
302 shift = 16;
303 num_elems = 2;
304 } else {
305 /* short form */
306 shift = 8;
307 num_elems = 4;
308 }
309 conn_len = parm & AC_CLIST_LENGTH;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700310 mask = (1 << (shift-1)) - 1;
311
Takashi Iwai0ba21762007-04-16 11:29:14 +0200312 if (!conn_len)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700313 return 0; /* no connection */
314
315 if (conn_len == 1) {
316 /* single connection */
Takashi Iwai0ba21762007-04-16 11:29:14 +0200317 parm = snd_hda_codec_read(codec, nid, 0,
318 AC_VERB_GET_CONNECT_LIST, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700319 conn_list[0] = parm & mask;
320 return 1;
321 }
322
323 /* multi connection */
324 conns = 0;
Takashi Iwai54d17402005-11-21 16:33:22 +0100325 prev_nid = 0;
326 for (i = 0; i < conn_len; i++) {
327 int range_val;
328 hda_nid_t val, n;
329
330 if (i % num_elems == 0)
331 parm = snd_hda_codec_read(codec, nid, 0,
332 AC_VERB_GET_CONNECT_LIST, i);
Takashi Iwai0ba21762007-04-16 11:29:14 +0200333 range_val = !!(parm & (1 << (shift-1))); /* ranges */
Takashi Iwai54d17402005-11-21 16:33:22 +0100334 val = parm & mask;
Jaroslav Kysela2e9bf242009-07-18 11:48:19 +0200335 if (val == 0) {
336 snd_printk(KERN_WARNING "hda_codec: "
337 "invalid CONNECT_LIST verb %x[%i]:%x\n",
338 nid, i, parm);
339 return 0;
340 }
Takashi Iwai54d17402005-11-21 16:33:22 +0100341 parm >>= shift;
342 if (range_val) {
343 /* ranges between the previous and this one */
Takashi Iwai0ba21762007-04-16 11:29:14 +0200344 if (!prev_nid || prev_nid >= val) {
345 snd_printk(KERN_WARNING "hda_codec: "
346 "invalid dep_range_val %x:%x\n",
347 prev_nid, val);
Takashi Iwai54d17402005-11-21 16:33:22 +0100348 continue;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700349 }
Takashi Iwai54d17402005-11-21 16:33:22 +0100350 for (n = prev_nid + 1; n <= val; n++) {
351 if (conns >= max_conns) {
Takashi Iwai0ba21762007-04-16 11:29:14 +0200352 snd_printk(KERN_ERR
353 "Too many connections\n");
Takashi Iwai54d17402005-11-21 16:33:22 +0100354 return -EINVAL;
355 }
356 conn_list[conns++] = n;
357 }
358 } else {
359 if (conns >= max_conns) {
360 snd_printk(KERN_ERR "Too many connections\n");
361 return -EINVAL;
362 }
363 conn_list[conns++] = val;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700364 }
Takashi Iwai54d17402005-11-21 16:33:22 +0100365 prev_nid = val;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700366 }
367 return conns;
368}
Takashi Iwaiff7a3262008-11-28 15:17:06 +0100369EXPORT_SYMBOL_HDA(snd_hda_get_connections);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700370
371
372/**
373 * snd_hda_queue_unsol_event - add an unsolicited event to queue
374 * @bus: the BUS
375 * @res: unsolicited event (lower 32bit of RIRB entry)
376 * @res_ex: codec addr and flags (upper 32bit or RIRB entry)
377 *
378 * Adds the given event to the queue. The events are processed in
379 * the workqueue asynchronously. Call this function in the interrupt
380 * hanlder when RIRB receives an unsolicited event.
381 *
382 * Returns 0 if successful, or a negative error code.
383 */
384int snd_hda_queue_unsol_event(struct hda_bus *bus, u32 res, u32 res_ex)
385{
386 struct hda_bus_unsolicited *unsol;
387 unsigned int wp;
388
Takashi Iwai0ba21762007-04-16 11:29:14 +0200389 unsol = bus->unsol;
390 if (!unsol)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700391 return 0;
392
393 wp = (unsol->wp + 1) % HDA_UNSOL_QUEUE_SIZE;
394 unsol->wp = wp;
395
396 wp <<= 1;
397 unsol->queue[wp] = res;
398 unsol->queue[wp + 1] = res_ex;
399
Takashi Iwai6acaed32009-01-12 10:09:24 +0100400 queue_work(bus->workq, &unsol->work);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700401
402 return 0;
403}
Takashi Iwaiff7a3262008-11-28 15:17:06 +0100404EXPORT_SYMBOL_HDA(snd_hda_queue_unsol_event);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700405
406/*
Wu Fengguang5c1d1a92008-10-07 14:17:53 +0800407 * process queued unsolicited events
Linus Torvalds1da177e2005-04-16 15:20:36 -0700408 */
David Howellsc4028952006-11-22 14:57:56 +0000409static void process_unsol_events(struct work_struct *work)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700410{
David Howellsc4028952006-11-22 14:57:56 +0000411 struct hda_bus_unsolicited *unsol =
412 container_of(work, struct hda_bus_unsolicited, work);
413 struct hda_bus *bus = unsol->bus;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700414 struct hda_codec *codec;
415 unsigned int rp, caddr, res;
416
417 while (unsol->rp != unsol->wp) {
418 rp = (unsol->rp + 1) % HDA_UNSOL_QUEUE_SIZE;
419 unsol->rp = rp;
420 rp <<= 1;
421 res = unsol->queue[rp];
422 caddr = unsol->queue[rp + 1];
Takashi Iwai0ba21762007-04-16 11:29:14 +0200423 if (!(caddr & (1 << 4))) /* no unsolicited event? */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700424 continue;
425 codec = bus->caddr_tbl[caddr & 0x0f];
426 if (codec && codec->patch_ops.unsol_event)
427 codec->patch_ops.unsol_event(codec, res);
428 }
429}
430
431/*
432 * initialize unsolicited queue
433 */
Takashi Iwai6c1f45e2008-07-30 15:01:45 +0200434static int init_unsol_queue(struct hda_bus *bus)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700435{
436 struct hda_bus_unsolicited *unsol;
437
Takashi Iwai9f146bb2005-11-17 11:07:49 +0100438 if (bus->unsol) /* already initialized */
439 return 0;
440
Takashi Iwaie560d8d2005-09-09 14:21:46 +0200441 unsol = kzalloc(sizeof(*unsol), GFP_KERNEL);
Takashi Iwai0ba21762007-04-16 11:29:14 +0200442 if (!unsol) {
443 snd_printk(KERN_ERR "hda_codec: "
444 "can't allocate unsolicited queue\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700445 return -ENOMEM;
446 }
David Howellsc4028952006-11-22 14:57:56 +0000447 INIT_WORK(&unsol->work, process_unsol_events);
448 unsol->bus = bus;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700449 bus->unsol = unsol;
450 return 0;
451}
452
453/*
454 * destructor
455 */
456static void snd_hda_codec_free(struct hda_codec *codec);
457
458static int snd_hda_bus_free(struct hda_bus *bus)
459{
Takashi Iwai0ba21762007-04-16 11:29:14 +0200460 struct hda_codec *codec, *n;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700461
Takashi Iwai0ba21762007-04-16 11:29:14 +0200462 if (!bus)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700463 return 0;
Takashi Iwai6acaed32009-01-12 10:09:24 +0100464 if (bus->workq)
465 flush_workqueue(bus->workq);
466 if (bus->unsol)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700467 kfree(bus->unsol);
Takashi Iwai0ba21762007-04-16 11:29:14 +0200468 list_for_each_entry_safe(codec, n, &bus->codec_list, list) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700469 snd_hda_codec_free(codec);
470 }
471 if (bus->ops.private_free)
472 bus->ops.private_free(bus);
Takashi Iwai6acaed32009-01-12 10:09:24 +0100473 if (bus->workq)
474 destroy_workqueue(bus->workq);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700475 kfree(bus);
476 return 0;
477}
478
Takashi Iwaic8b6bf92005-11-17 14:57:47 +0100479static int snd_hda_bus_dev_free(struct snd_device *device)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700480{
481 struct hda_bus *bus = device->device_data;
Takashi Iwaib94d35392008-11-21 09:08:06 +0100482 bus->shutdown = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700483 return snd_hda_bus_free(bus);
484}
485
Takashi Iwaid7ffba12008-07-30 15:01:46 +0200486#ifdef CONFIG_SND_HDA_HWDEP
487static int snd_hda_bus_dev_register(struct snd_device *device)
488{
489 struct hda_bus *bus = device->device_data;
490 struct hda_codec *codec;
491 list_for_each_entry(codec, &bus->codec_list, list) {
492 snd_hda_hwdep_add_sysfs(codec);
493 }
494 return 0;
495}
496#else
497#define snd_hda_bus_dev_register NULL
498#endif
499
Linus Torvalds1da177e2005-04-16 15:20:36 -0700500/**
501 * snd_hda_bus_new - create a HDA bus
502 * @card: the card entry
503 * @temp: the template for hda_bus information
504 * @busp: the pointer to store the created bus instance
505 *
506 * Returns 0 if successful, or a negative error code.
507 */
Takashi Iwai1289e9e2008-11-27 15:47:11 +0100508int /*__devinit*/ snd_hda_bus_new(struct snd_card *card,
Takashi Iwai756e2b02007-04-16 11:27:07 +0200509 const struct hda_bus_template *temp,
510 struct hda_bus **busp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700511{
512 struct hda_bus *bus;
513 int err;
Takashi Iwaic8b6bf92005-11-17 14:57:47 +0100514 static struct snd_device_ops dev_ops = {
Takashi Iwaid7ffba12008-07-30 15:01:46 +0200515 .dev_register = snd_hda_bus_dev_register,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700516 .dev_free = snd_hda_bus_dev_free,
517 };
518
Takashi Iwaida3cec32008-08-08 17:12:14 +0200519 if (snd_BUG_ON(!temp))
520 return -EINVAL;
521 if (snd_BUG_ON(!temp->ops.command || !temp->ops.get_response))
522 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700523
524 if (busp)
525 *busp = NULL;
526
Takashi Iwaie560d8d2005-09-09 14:21:46 +0200527 bus = kzalloc(sizeof(*bus), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700528 if (bus == NULL) {
529 snd_printk(KERN_ERR "can't allocate struct hda_bus\n");
530 return -ENOMEM;
531 }
532
533 bus->card = card;
534 bus->private_data = temp->private_data;
535 bus->pci = temp->pci;
536 bus->modelname = temp->modelname;
Takashi Iwaifee2fba2008-11-27 12:43:28 +0100537 bus->power_save = temp->power_save;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700538 bus->ops = temp->ops;
539
Ingo Molnar62932df2006-01-16 16:34:20 +0100540 mutex_init(&bus->cmd_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700541 INIT_LIST_HEAD(&bus->codec_list);
542
Takashi Iwaie8c0ee52009-02-05 07:34:28 +0100543 snprintf(bus->workq_name, sizeof(bus->workq_name),
544 "hd-audio%d", card->number);
545 bus->workq = create_singlethread_workqueue(bus->workq_name);
Takashi Iwai6acaed32009-01-12 10:09:24 +0100546 if (!bus->workq) {
Takashi Iwaie8c0ee52009-02-05 07:34:28 +0100547 snd_printk(KERN_ERR "cannot create workqueue %s\n",
548 bus->workq_name);
Takashi Iwai6acaed32009-01-12 10:09:24 +0100549 kfree(bus);
550 return -ENOMEM;
551 }
552
Takashi Iwai0ba21762007-04-16 11:29:14 +0200553 err = snd_device_new(card, SNDRV_DEV_BUS, bus, &dev_ops);
554 if (err < 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700555 snd_hda_bus_free(bus);
556 return err;
557 }
558 if (busp)
559 *busp = bus;
560 return 0;
561}
Takashi Iwaiff7a3262008-11-28 15:17:06 +0100562EXPORT_SYMBOL_HDA(snd_hda_bus_new);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700563
Takashi Iwai82467612007-07-27 19:15:54 +0200564#ifdef CONFIG_SND_HDA_GENERIC
565#define is_generic_config(codec) \
Takashi Iwaif44ac832008-07-30 15:01:45 +0200566 (codec->modelname && !strcmp(codec->modelname, "generic"))
Takashi Iwai82467612007-07-27 19:15:54 +0200567#else
568#define is_generic_config(codec) 0
569#endif
570
Takashi Iwai645f10c2008-11-28 15:07:37 +0100571#ifdef MODULE
Takashi Iwai1289e9e2008-11-27 15:47:11 +0100572#define HDA_MODREQ_MAX_COUNT 2 /* two request_modules()'s */
573#else
Takashi Iwai645f10c2008-11-28 15:07:37 +0100574#define HDA_MODREQ_MAX_COUNT 0 /* all presets are statically linked */
Takashi Iwai1289e9e2008-11-27 15:47:11 +0100575#endif
576
Linus Torvalds1da177e2005-04-16 15:20:36 -0700577/*
578 * find a matching codec preset
579 */
Takashi Iwai6c1f45e2008-07-30 15:01:45 +0200580static const struct hda_codec_preset *
Takashi Iwai756e2b02007-04-16 11:27:07 +0200581find_codec_preset(struct hda_codec *codec)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700582{
Takashi Iwai1289e9e2008-11-27 15:47:11 +0100583 struct hda_codec_preset_list *tbl;
584 const struct hda_codec_preset *preset;
585 int mod_requested = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700586
Takashi Iwai82467612007-07-27 19:15:54 +0200587 if (is_generic_config(codec))
Takashi Iwaid5ad6302007-03-07 15:55:59 +0100588 return NULL; /* use the generic parser */
589
Takashi Iwai1289e9e2008-11-27 15:47:11 +0100590 again:
591 mutex_lock(&preset_mutex);
592 list_for_each_entry(tbl, &hda_preset_tables, list) {
593 if (!try_module_get(tbl->owner)) {
594 snd_printk(KERN_ERR "hda_codec: cannot module_get\n");
595 continue;
596 }
597 for (preset = tbl->preset; preset->id; preset++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700598 u32 mask = preset->mask;
Marc Boucherca7cfae2008-01-22 15:32:25 +0100599 if (preset->afg && preset->afg != codec->afg)
600 continue;
601 if (preset->mfg && preset->mfg != codec->mfg)
602 continue;
Takashi Iwai0ba21762007-04-16 11:29:14 +0200603 if (!mask)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700604 mask = ~0;
Takashi Iwai9c7f8522006-06-28 15:08:22 +0200605 if (preset->id == (codec->vendor_id & mask) &&
Takashi Iwai0ba21762007-04-16 11:29:14 +0200606 (!preset->rev ||
Takashi Iwai1289e9e2008-11-27 15:47:11 +0100607 preset->rev == codec->revision_id)) {
608 mutex_unlock(&preset_mutex);
609 codec->owner = tbl->owner;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700610 return preset;
Takashi Iwai1289e9e2008-11-27 15:47:11 +0100611 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700612 }
Takashi Iwai1289e9e2008-11-27 15:47:11 +0100613 module_put(tbl->owner);
614 }
615 mutex_unlock(&preset_mutex);
616
617 if (mod_requested < HDA_MODREQ_MAX_COUNT) {
618 char name[32];
619 if (!mod_requested)
620 snprintf(name, sizeof(name), "snd-hda-codec-id:%08x",
621 codec->vendor_id);
622 else
623 snprintf(name, sizeof(name), "snd-hda-codec-id:%04x*",
624 (codec->vendor_id >> 16) & 0xffff);
625 request_module(name);
626 mod_requested++;
627 goto again;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700628 }
629 return NULL;
630}
631
632/*
Takashi Iwaif44ac832008-07-30 15:01:45 +0200633 * get_codec_name - store the codec name
Linus Torvalds1da177e2005-04-16 15:20:36 -0700634 */
Takashi Iwaif44ac832008-07-30 15:01:45 +0200635static int get_codec_name(struct hda_codec *codec)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700636{
637 const struct hda_vendor_id *c;
638 const char *vendor = NULL;
639 u16 vendor_id = codec->vendor_id >> 16;
Takashi Iwai812a2cc2009-05-16 10:00:49 +0200640 char tmp[16];
641
642 if (codec->vendor_name)
643 goto get_chip_name;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700644
645 for (c = hda_vendor_ids; c->id; c++) {
646 if (c->id == vendor_id) {
647 vendor = c->name;
648 break;
649 }
650 }
Takashi Iwai0ba21762007-04-16 11:29:14 +0200651 if (!vendor) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700652 sprintf(tmp, "Generic %04x", vendor_id);
653 vendor = tmp;
654 }
Takashi Iwai812a2cc2009-05-16 10:00:49 +0200655 codec->vendor_name = kstrdup(vendor, GFP_KERNEL);
656 if (!codec->vendor_name)
657 return -ENOMEM;
658
659 get_chip_name:
660 if (codec->chip_name)
661 return 0;
662
Linus Torvalds1da177e2005-04-16 15:20:36 -0700663 if (codec->preset && codec->preset->name)
Takashi Iwai812a2cc2009-05-16 10:00:49 +0200664 codec->chip_name = kstrdup(codec->preset->name, GFP_KERNEL);
665 else {
666 sprintf(tmp, "ID %x", codec->vendor_id & 0xffff);
667 codec->chip_name = kstrdup(tmp, GFP_KERNEL);
668 }
669 if (!codec->chip_name)
Takashi Iwaif44ac832008-07-30 15:01:45 +0200670 return -ENOMEM;
671 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700672}
673
674/*
Sasha Khapyorsky673b6832005-08-11 11:00:16 +0200675 * look for an AFG and MFG nodes
Linus Torvalds1da177e2005-04-16 15:20:36 -0700676 */
Takashi Iwai1289e9e2008-11-27 15:47:11 +0100677static void /*__devinit*/ setup_fg_nodes(struct hda_codec *codec)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700678{
Takashi Iwai93e82ae2009-04-17 18:04:41 +0200679 int i, total_nodes, function_id;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700680 hda_nid_t nid;
681
682 total_nodes = snd_hda_get_sub_nodes(codec, AC_NODE_ROOT, &nid);
683 for (i = 0; i < total_nodes; i++, nid++) {
Takashi Iwai93e82ae2009-04-17 18:04:41 +0200684 function_id = snd_hda_param_read(codec, nid,
Pascal de Bruijn234b4342009-03-23 11:15:59 +0100685 AC_PAR_FUNCTION_TYPE) & 0xff;
Takashi Iwai93e82ae2009-04-17 18:04:41 +0200686 switch (function_id) {
Sasha Khapyorsky673b6832005-08-11 11:00:16 +0200687 case AC_GRP_AUDIO_FUNCTION:
688 codec->afg = nid;
Takashi Iwai93e82ae2009-04-17 18:04:41 +0200689 codec->function_id = function_id;
Sasha Khapyorsky673b6832005-08-11 11:00:16 +0200690 break;
691 case AC_GRP_MODEM_FUNCTION:
692 codec->mfg = nid;
Takashi Iwai93e82ae2009-04-17 18:04:41 +0200693 codec->function_id = function_id;
Sasha Khapyorsky673b6832005-08-11 11:00:16 +0200694 break;
695 default:
696 break;
697 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700698 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700699}
700
701/*
Takashi Iwai54d17402005-11-21 16:33:22 +0100702 * read widget caps for each widget and store in cache
703 */
704static int read_widget_caps(struct hda_codec *codec, hda_nid_t fg_node)
705{
706 int i;
707 hda_nid_t nid;
708
709 codec->num_nodes = snd_hda_get_sub_nodes(codec, fg_node,
710 &codec->start_nid);
711 codec->wcaps = kmalloc(codec->num_nodes * 4, GFP_KERNEL);
Takashi Iwai0ba21762007-04-16 11:29:14 +0200712 if (!codec->wcaps)
Takashi Iwai54d17402005-11-21 16:33:22 +0100713 return -ENOMEM;
714 nid = codec->start_nid;
715 for (i = 0; i < codec->num_nodes; i++, nid++)
716 codec->wcaps[i] = snd_hda_param_read(codec, nid,
717 AC_PAR_AUDIO_WIDGET_CAP);
718 return 0;
719}
720
Takashi Iwai3be14142009-02-20 14:11:16 +0100721/* read all pin default configurations and save codec->init_pins */
722static int read_pin_defaults(struct hda_codec *codec)
723{
724 int i;
725 hda_nid_t nid = codec->start_nid;
726
727 for (i = 0; i < codec->num_nodes; i++, nid++) {
728 struct hda_pincfg *pin;
729 unsigned int wcaps = get_wcaps(codec, nid);
730 unsigned int wid_type = (wcaps & AC_WCAP_TYPE) >>
731 AC_WCAP_TYPE_SHIFT;
732 if (wid_type != AC_WID_PIN)
733 continue;
734 pin = snd_array_new(&codec->init_pins);
735 if (!pin)
736 return -ENOMEM;
737 pin->nid = nid;
738 pin->cfg = snd_hda_codec_read(codec, nid, 0,
739 AC_VERB_GET_CONFIG_DEFAULT, 0);
740 }
741 return 0;
742}
743
744/* look up the given pin config list and return the item matching with NID */
745static struct hda_pincfg *look_up_pincfg(struct hda_codec *codec,
746 struct snd_array *array,
747 hda_nid_t nid)
748{
749 int i;
750 for (i = 0; i < array->used; i++) {
751 struct hda_pincfg *pin = snd_array_elem(array, i);
752 if (pin->nid == nid)
753 return pin;
754 }
755 return NULL;
756}
757
758/* write a config value for the given NID */
759static void set_pincfg(struct hda_codec *codec, hda_nid_t nid,
760 unsigned int cfg)
761{
762 int i;
763 for (i = 0; i < 4; i++) {
764 snd_hda_codec_write(codec, nid, 0,
765 AC_VERB_SET_CONFIG_DEFAULT_BYTES_0 + i,
766 cfg & 0xff);
767 cfg >>= 8;
768 }
769}
770
771/* set the current pin config value for the given NID.
772 * the value is cached, and read via snd_hda_codec_get_pincfg()
773 */
774int snd_hda_add_pincfg(struct hda_codec *codec, struct snd_array *list,
775 hda_nid_t nid, unsigned int cfg)
776{
777 struct hda_pincfg *pin;
Takashi Iwai5e7b8e02009-02-23 09:45:59 +0100778 unsigned int oldcfg;
Takashi Iwai3be14142009-02-20 14:11:16 +0100779
Takashi Iwai5e7b8e02009-02-23 09:45:59 +0100780 oldcfg = snd_hda_codec_get_pincfg(codec, nid);
Takashi Iwai3be14142009-02-20 14:11:16 +0100781 pin = look_up_pincfg(codec, list, nid);
782 if (!pin) {
783 pin = snd_array_new(list);
784 if (!pin)
785 return -ENOMEM;
786 pin->nid = nid;
787 }
788 pin->cfg = cfg;
Takashi Iwai5e7b8e02009-02-23 09:45:59 +0100789
790 /* change only when needed; e.g. if the pincfg is already present
791 * in user_pins[], don't write it
792 */
793 cfg = snd_hda_codec_get_pincfg(codec, nid);
794 if (oldcfg != cfg)
795 set_pincfg(codec, nid, cfg);
Takashi Iwai3be14142009-02-20 14:11:16 +0100796 return 0;
797}
798
799int snd_hda_codec_set_pincfg(struct hda_codec *codec,
800 hda_nid_t nid, unsigned int cfg)
801{
Takashi Iwai346ff702009-02-23 09:42:57 +0100802 return snd_hda_add_pincfg(codec, &codec->driver_pins, nid, cfg);
Takashi Iwai3be14142009-02-20 14:11:16 +0100803}
804EXPORT_SYMBOL_HDA(snd_hda_codec_set_pincfg);
805
806/* get the current pin config value of the given pin NID */
807unsigned int snd_hda_codec_get_pincfg(struct hda_codec *codec, hda_nid_t nid)
808{
809 struct hda_pincfg *pin;
810
Takashi Iwai3be14142009-02-20 14:11:16 +0100811#ifdef CONFIG_SND_HDA_HWDEP
Takashi Iwai346ff702009-02-23 09:42:57 +0100812 pin = look_up_pincfg(codec, &codec->user_pins, nid);
Takashi Iwai3be14142009-02-20 14:11:16 +0100813 if (pin)
814 return pin->cfg;
815#endif
Takashi Iwai5e7b8e02009-02-23 09:45:59 +0100816 pin = look_up_pincfg(codec, &codec->driver_pins, nid);
817 if (pin)
818 return pin->cfg;
Takashi Iwai3be14142009-02-20 14:11:16 +0100819 pin = look_up_pincfg(codec, &codec->init_pins, nid);
820 if (pin)
821 return pin->cfg;
822 return 0;
823}
824EXPORT_SYMBOL_HDA(snd_hda_codec_get_pincfg);
825
826/* restore all current pin configs */
827static void restore_pincfgs(struct hda_codec *codec)
828{
829 int i;
830 for (i = 0; i < codec->init_pins.used; i++) {
831 struct hda_pincfg *pin = snd_array_elem(&codec->init_pins, i);
832 set_pincfg(codec, pin->nid,
833 snd_hda_codec_get_pincfg(codec, pin->nid));
834 }
835}
Takashi Iwai54d17402005-11-21 16:33:22 +0100836
Takashi Iwai01751f52007-08-10 16:59:39 +0200837static void init_hda_cache(struct hda_cache_rec *cache,
838 unsigned int record_size);
Takashi Iwai1fcaee62007-08-23 00:01:09 +0200839static void free_hda_cache(struct hda_cache_rec *cache);
Takashi Iwai01751f52007-08-10 16:59:39 +0200840
Takashi Iwai3be14142009-02-20 14:11:16 +0100841/* restore the initial pin cfgs and release all pincfg lists */
842static void restore_init_pincfgs(struct hda_codec *codec)
843{
Takashi Iwai346ff702009-02-23 09:42:57 +0100844 /* first free driver_pins and user_pins, then call restore_pincfg
Takashi Iwai3be14142009-02-20 14:11:16 +0100845 * so that only the values in init_pins are restored
846 */
Takashi Iwai346ff702009-02-23 09:42:57 +0100847 snd_array_free(&codec->driver_pins);
Takashi Iwai3be14142009-02-20 14:11:16 +0100848#ifdef CONFIG_SND_HDA_HWDEP
Takashi Iwai346ff702009-02-23 09:42:57 +0100849 snd_array_free(&codec->user_pins);
Takashi Iwai3be14142009-02-20 14:11:16 +0100850#endif
851 restore_pincfgs(codec);
852 snd_array_free(&codec->init_pins);
853}
854
Takashi Iwai54d17402005-11-21 16:33:22 +0100855/*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700856 * codec destructor
857 */
858static void snd_hda_codec_free(struct hda_codec *codec)
859{
Takashi Iwai0ba21762007-04-16 11:29:14 +0200860 if (!codec)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700861 return;
Takashi Iwai3be14142009-02-20 14:11:16 +0100862 restore_init_pincfgs(codec);
Takashi Iwaicb53c622007-08-10 17:21:45 +0200863#ifdef CONFIG_SND_HDA_POWER_SAVE
864 cancel_delayed_work(&codec->power_work);
Takashi Iwai6acaed32009-01-12 10:09:24 +0100865 flush_workqueue(codec->bus->workq);
Takashi Iwaicb53c622007-08-10 17:21:45 +0200866#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700867 list_del(&codec->list);
Takashi Iwaid13bd412008-07-30 15:01:45 +0200868 snd_array_free(&codec->mixers);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700869 codec->bus->caddr_tbl[codec->addr] = NULL;
870 if (codec->patch_ops.free)
871 codec->patch_ops.free(codec);
Takashi Iwai1289e9e2008-11-27 15:47:11 +0100872 module_put(codec->owner);
Takashi Iwai01751f52007-08-10 16:59:39 +0200873 free_hda_cache(&codec->amp_cache);
Takashi Iwaib3ac5632007-08-10 17:03:40 +0200874 free_hda_cache(&codec->cmd_cache);
Takashi Iwai812a2cc2009-05-16 10:00:49 +0200875 kfree(codec->vendor_name);
876 kfree(codec->chip_name);
Takashi Iwaif44ac832008-07-30 15:01:45 +0200877 kfree(codec->modelname);
Takashi Iwai54d17402005-11-21 16:33:22 +0100878 kfree(codec->wcaps);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700879 kfree(codec);
880}
881
Takashi Iwaibb6ac722009-03-13 09:02:42 +0100882static void hda_set_power_state(struct hda_codec *codec, hda_nid_t fg,
883 unsigned int power_state);
884
Linus Torvalds1da177e2005-04-16 15:20:36 -0700885/**
886 * snd_hda_codec_new - create a HDA codec
887 * @bus: the bus to assign
888 * @codec_addr: the codec address
889 * @codecp: the pointer to store the generated codec
890 *
891 * Returns 0 if successful, or a negative error code.
892 */
Takashi Iwai1289e9e2008-11-27 15:47:11 +0100893int /*__devinit*/ snd_hda_codec_new(struct hda_bus *bus, unsigned int codec_addr,
Takashi Iwaid4d9cd032008-12-19 15:19:11 +0100894 int do_init, struct hda_codec **codecp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700895{
896 struct hda_codec *codec;
Jaroslav Kyselaba443682008-08-13 20:55:32 +0200897 char component[31];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700898 int err;
899
Takashi Iwaida3cec32008-08-08 17:12:14 +0200900 if (snd_BUG_ON(!bus))
901 return -EINVAL;
902 if (snd_BUG_ON(codec_addr > HDA_MAX_CODEC_ADDRESS))
903 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700904
905 if (bus->caddr_tbl[codec_addr]) {
Takashi Iwai0ba21762007-04-16 11:29:14 +0200906 snd_printk(KERN_ERR "hda_codec: "
907 "address 0x%x is already occupied\n", codec_addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700908 return -EBUSY;
909 }
910
Takashi Iwaie560d8d2005-09-09 14:21:46 +0200911 codec = kzalloc(sizeof(*codec), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700912 if (codec == NULL) {
913 snd_printk(KERN_ERR "can't allocate struct hda_codec\n");
914 return -ENOMEM;
915 }
916
917 codec->bus = bus;
918 codec->addr = codec_addr;
Ingo Molnar62932df2006-01-16 16:34:20 +0100919 mutex_init(&codec->spdif_mutex);
Wu Fengguang5a9e02e2009-01-09 16:45:24 +0800920 mutex_init(&codec->control_mutex);
Takashi Iwai01751f52007-08-10 16:59:39 +0200921 init_hda_cache(&codec->amp_cache, sizeof(struct hda_amp_info));
Takashi Iwaib3ac5632007-08-10 17:03:40 +0200922 init_hda_cache(&codec->cmd_cache, sizeof(struct hda_cache_head));
Takashi Iwaid13bd412008-07-30 15:01:45 +0200923 snd_array_init(&codec->mixers, sizeof(struct snd_kcontrol *), 32);
Takashi Iwai3be14142009-02-20 14:11:16 +0100924 snd_array_init(&codec->init_pins, sizeof(struct hda_pincfg), 16);
Takashi Iwai346ff702009-02-23 09:42:57 +0100925 snd_array_init(&codec->driver_pins, sizeof(struct hda_pincfg), 16);
Takashi Iwai6c1f45e2008-07-30 15:01:45 +0200926 if (codec->bus->modelname) {
927 codec->modelname = kstrdup(codec->bus->modelname, GFP_KERNEL);
928 if (!codec->modelname) {
929 snd_hda_codec_free(codec);
930 return -ENODEV;
931 }
932 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700933
Takashi Iwaicb53c622007-08-10 17:21:45 +0200934#ifdef CONFIG_SND_HDA_POWER_SAVE
935 INIT_DELAYED_WORK(&codec->power_work, hda_power_work);
936 /* snd_hda_codec_new() marks the codec as power-up, and leave it as is.
937 * the caller has to power down appropriatley after initialization
938 * phase.
939 */
940 hda_keep_power_on(codec);
941#endif
942
Linus Torvalds1da177e2005-04-16 15:20:36 -0700943 list_add_tail(&codec->list, &bus->codec_list);
944 bus->caddr_tbl[codec_addr] = codec;
945
Takashi Iwai0ba21762007-04-16 11:29:14 +0200946 codec->vendor_id = snd_hda_param_read(codec, AC_NODE_ROOT,
947 AC_PAR_VENDOR_ID);
Takashi Iwai111d3af2006-02-16 18:17:58 +0100948 if (codec->vendor_id == -1)
949 /* read again, hopefully the access method was corrected
950 * in the last read...
951 */
952 codec->vendor_id = snd_hda_param_read(codec, AC_NODE_ROOT,
953 AC_PAR_VENDOR_ID);
Takashi Iwai0ba21762007-04-16 11:29:14 +0200954 codec->subsystem_id = snd_hda_param_read(codec, AC_NODE_ROOT,
955 AC_PAR_SUBSYSTEM_ID);
956 codec->revision_id = snd_hda_param_read(codec, AC_NODE_ROOT,
957 AC_PAR_REV_ID);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700958
Sasha Khapyorsky673b6832005-08-11 11:00:16 +0200959 setup_fg_nodes(codec);
Takashi Iwai0ba21762007-04-16 11:29:14 +0200960 if (!codec->afg && !codec->mfg) {
Sasha Khapyorsky673b6832005-08-11 11:00:16 +0200961 snd_printdd("hda_codec: no AFG or MFG node found\n");
Takashi Iwai3be14142009-02-20 14:11:16 +0100962 err = -ENODEV;
963 goto error;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700964 }
965
Takashi Iwai3be14142009-02-20 14:11:16 +0100966 err = read_widget_caps(codec, codec->afg ? codec->afg : codec->mfg);
967 if (err < 0) {
Takashi Iwai54d17402005-11-21 16:33:22 +0100968 snd_printk(KERN_ERR "hda_codec: cannot malloc\n");
Takashi Iwai3be14142009-02-20 14:11:16 +0100969 goto error;
Takashi Iwai54d17402005-11-21 16:33:22 +0100970 }
Takashi Iwai3be14142009-02-20 14:11:16 +0100971 err = read_pin_defaults(codec);
972 if (err < 0)
973 goto error;
Takashi Iwai54d17402005-11-21 16:33:22 +0100974
Takashi Iwai0ba21762007-04-16 11:29:14 +0200975 if (!codec->subsystem_id) {
Takashi Iwai86284e42005-10-11 15:05:54 +0200976 hda_nid_t nid = codec->afg ? codec->afg : codec->mfg;
Takashi Iwai0ba21762007-04-16 11:29:14 +0200977 codec->subsystem_id =
978 snd_hda_codec_read(codec, nid, 0,
979 AC_VERB_GET_SUBSYSTEM_ID, 0);
Takashi Iwai86284e42005-10-11 15:05:54 +0200980 }
981
Takashi Iwaibb6ac722009-03-13 09:02:42 +0100982 /* power-up all before initialization */
983 hda_set_power_state(codec,
984 codec->afg ? codec->afg : codec->mfg,
985 AC_PWRST_D0);
986
Takashi Iwaid4d9cd032008-12-19 15:19:11 +0100987 if (do_init) {
988 err = snd_hda_codec_configure(codec);
Takashi Iwai3be14142009-02-20 14:11:16 +0100989 if (err < 0)
990 goto error;
Takashi Iwai6c1f45e2008-07-30 15:01:45 +0200991 }
992 snd_hda_codec_proc_new(codec);
993
Takashi Iwai6c1f45e2008-07-30 15:01:45 +0200994 snd_hda_create_hwdep(codec);
Takashi Iwai6c1f45e2008-07-30 15:01:45 +0200995
996 sprintf(component, "HDA:%08x,%08x,%08x", codec->vendor_id,
997 codec->subsystem_id, codec->revision_id);
998 snd_component_add(codec->bus->card, component);
999
1000 if (codecp)
1001 *codecp = codec;
1002 return 0;
Takashi Iwai3be14142009-02-20 14:11:16 +01001003
1004 error:
1005 snd_hda_codec_free(codec);
1006 return err;
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001007}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001008EXPORT_SYMBOL_HDA(snd_hda_codec_new);
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001009
1010int snd_hda_codec_configure(struct hda_codec *codec)
1011{
1012 int err;
1013
Takashi Iwaid5ad6302007-03-07 15:55:59 +01001014 codec->preset = find_codec_preset(codec);
Takashi Iwai812a2cc2009-05-16 10:00:49 +02001015 if (!codec->vendor_name || !codec->chip_name) {
Takashi Iwaif44ac832008-07-30 15:01:45 +02001016 err = get_codec_name(codec);
1017 if (err < 0)
1018 return err;
1019 }
Takashi Iwai43ea1d42007-04-26 19:12:08 +02001020 /* audio codec should override the mixer name */
Takashi Iwaif44ac832008-07-30 15:01:45 +02001021 if (codec->afg || !*codec->bus->card->mixername)
Takashi Iwai812a2cc2009-05-16 10:00:49 +02001022 snprintf(codec->bus->card->mixername,
1023 sizeof(codec->bus->card->mixername),
1024 "%s %s", codec->vendor_name, codec->chip_name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001025
Takashi Iwai82467612007-07-27 19:15:54 +02001026 if (is_generic_config(codec)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001027 err = snd_hda_parse_generic_codec(codec);
Takashi Iwai82467612007-07-27 19:15:54 +02001028 goto patched;
1029 }
Takashi Iwai82467612007-07-27 19:15:54 +02001030 if (codec->preset && codec->preset->patch) {
1031 err = codec->preset->patch(codec);
1032 goto patched;
1033 }
1034
1035 /* call the default parser */
Takashi Iwai82467612007-07-27 19:15:54 +02001036 err = snd_hda_parse_generic_codec(codec);
Takashi Iwai35a1e0c2007-10-19 08:13:40 +02001037 if (err < 0)
1038 printk(KERN_ERR "hda-codec: No codec parser is available\n");
Takashi Iwai82467612007-07-27 19:15:54 +02001039
1040 patched:
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001041 if (!err && codec->patch_ops.unsol_event)
1042 err = init_unsol_queue(codec->bus);
1043 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001044}
1045
1046/**
1047 * snd_hda_codec_setup_stream - set up the codec for streaming
1048 * @codec: the CODEC to set up
1049 * @nid: the NID to set up
1050 * @stream_tag: stream tag to pass, it's between 0x1 and 0xf.
1051 * @channel_id: channel id to pass, zero based.
1052 * @format: stream format.
1053 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02001054void snd_hda_codec_setup_stream(struct hda_codec *codec, hda_nid_t nid,
1055 u32 stream_tag,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001056 int channel_id, int format)
1057{
Takashi Iwai0ba21762007-04-16 11:29:14 +02001058 if (!nid)
Takashi Iwaid21b37e2005-04-20 13:45:55 +02001059 return;
1060
Takashi Iwai0ba21762007-04-16 11:29:14 +02001061 snd_printdd("hda_codec_setup_stream: "
1062 "NID=0x%x, stream=0x%x, channel=%d, format=0x%x\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07001063 nid, stream_tag, channel_id, format);
1064 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CHANNEL_STREAMID,
1065 (stream_tag << 4) | channel_id);
1066 msleep(1);
1067 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_STREAM_FORMAT, format);
1068}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001069EXPORT_SYMBOL_HDA(snd_hda_codec_setup_stream);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001070
Takashi Iwai888afa12008-03-18 09:57:50 +01001071void snd_hda_codec_cleanup_stream(struct hda_codec *codec, hda_nid_t nid)
1072{
1073 if (!nid)
1074 return;
1075
1076 snd_printdd("hda_codec_cleanup_stream: NID=0x%x\n", nid);
1077 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CHANNEL_STREAMID, 0);
1078#if 0 /* keep the format */
1079 msleep(1);
1080 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_STREAM_FORMAT, 0);
1081#endif
1082}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001083EXPORT_SYMBOL_HDA(snd_hda_codec_cleanup_stream);
Takashi Iwai888afa12008-03-18 09:57:50 +01001084
Linus Torvalds1da177e2005-04-16 15:20:36 -07001085/*
1086 * amp access functions
1087 */
1088
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001089/* FIXME: more better hash key? */
1090#define HDA_HASH_KEY(nid,dir,idx) (u32)((nid) + ((idx) << 16) + ((dir) << 24))
Takashi Iwai1327a322009-03-23 13:07:47 +01001091#define HDA_HASH_PINCAP_KEY(nid) (u32)((nid) + (0x02 << 24))
Takashi Iwai92c7c8a2009-03-24 07:32:14 +01001092#define HDA_HASH_PARPCM_KEY(nid) (u32)((nid) + (0x03 << 24))
1093#define HDA_HASH_PARSTR_KEY(nid) (u32)((nid) + (0x04 << 24))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001094#define INFO_AMP_CAPS (1<<0)
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001095#define INFO_AMP_VOL(ch) (1 << (1 + (ch)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001096
1097/* initialize the hash table */
Takashi Iwai1289e9e2008-11-27 15:47:11 +01001098static void /*__devinit*/ init_hda_cache(struct hda_cache_rec *cache,
Takashi Iwai01751f52007-08-10 16:59:39 +02001099 unsigned int record_size)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001100{
Takashi Iwai01751f52007-08-10 16:59:39 +02001101 memset(cache, 0, sizeof(*cache));
1102 memset(cache->hash, 0xff, sizeof(cache->hash));
Takashi Iwai603c4012008-07-30 15:01:44 +02001103 snd_array_init(&cache->buf, record_size, 64);
Takashi Iwai01751f52007-08-10 16:59:39 +02001104}
1105
Takashi Iwai1fcaee62007-08-23 00:01:09 +02001106static void free_hda_cache(struct hda_cache_rec *cache)
Takashi Iwai01751f52007-08-10 16:59:39 +02001107{
Takashi Iwai603c4012008-07-30 15:01:44 +02001108 snd_array_free(&cache->buf);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001109}
1110
1111/* query the hash. allocate an entry if not found. */
Takashi Iwai01751f52007-08-10 16:59:39 +02001112static struct hda_cache_head *get_alloc_hash(struct hda_cache_rec *cache,
1113 u32 key)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001114{
Takashi Iwai01751f52007-08-10 16:59:39 +02001115 u16 idx = key % (u16)ARRAY_SIZE(cache->hash);
1116 u16 cur = cache->hash[idx];
1117 struct hda_cache_head *info;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001118
1119 while (cur != 0xffff) {
Takashi Iwaif43aa022008-11-10 16:24:26 +01001120 info = snd_array_elem(&cache->buf, cur);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001121 if (info->key == key)
1122 return info;
1123 cur = info->next;
1124 }
1125
1126 /* add a new hash entry */
Takashi Iwai603c4012008-07-30 15:01:44 +02001127 info = snd_array_new(&cache->buf);
Takashi Iwaic2174292008-11-07 00:23:30 +01001128 if (!info)
1129 return NULL;
Takashi Iwaif43aa022008-11-10 16:24:26 +01001130 cur = snd_array_index(&cache->buf, info);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001131 info->key = key;
Takashi Iwai01751f52007-08-10 16:59:39 +02001132 info->val = 0;
1133 info->next = cache->hash[idx];
1134 cache->hash[idx] = cur;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001135
1136 return info;
1137}
1138
Takashi Iwai01751f52007-08-10 16:59:39 +02001139/* query and allocate an amp hash entry */
1140static inline struct hda_amp_info *
1141get_alloc_amp_hash(struct hda_codec *codec, u32 key)
1142{
1143 return (struct hda_amp_info *)get_alloc_hash(&codec->amp_cache, key);
1144}
1145
Linus Torvalds1da177e2005-04-16 15:20:36 -07001146/*
1147 * query AMP capabilities for the given widget and direction
1148 */
Matthew Ranostay09a99952008-01-24 11:49:21 +01001149u32 query_amp_caps(struct hda_codec *codec, hda_nid_t nid, int direction)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001150{
Takashi Iwai0ba21762007-04-16 11:29:14 +02001151 struct hda_amp_info *info;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001152
Takashi Iwai0ba21762007-04-16 11:29:14 +02001153 info = get_alloc_amp_hash(codec, HDA_HASH_KEY(nid, direction, 0));
1154 if (!info)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001155 return 0;
Takashi Iwai01751f52007-08-10 16:59:39 +02001156 if (!(info->head.val & INFO_AMP_CAPS)) {
Takashi Iwai0ba21762007-04-16 11:29:14 +02001157 if (!(get_wcaps(codec, nid) & AC_WCAP_AMP_OVRD))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001158 nid = codec->afg;
Takashi Iwai0ba21762007-04-16 11:29:14 +02001159 info->amp_caps = snd_hda_param_read(codec, nid,
1160 direction == HDA_OUTPUT ?
1161 AC_PAR_AMP_OUT_CAP :
1162 AC_PAR_AMP_IN_CAP);
Takashi Iwaib75e53f2007-05-10 16:56:09 +02001163 if (info->amp_caps)
Takashi Iwai01751f52007-08-10 16:59:39 +02001164 info->head.val |= INFO_AMP_CAPS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001165 }
1166 return info->amp_caps;
1167}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001168EXPORT_SYMBOL_HDA(query_amp_caps);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001169
Takashi Iwai897cc182007-05-29 19:01:37 +02001170int snd_hda_override_amp_caps(struct hda_codec *codec, hda_nid_t nid, int dir,
1171 unsigned int caps)
1172{
1173 struct hda_amp_info *info;
1174
1175 info = get_alloc_amp_hash(codec, HDA_HASH_KEY(nid, dir, 0));
1176 if (!info)
1177 return -EINVAL;
1178 info->amp_caps = caps;
Takashi Iwai01751f52007-08-10 16:59:39 +02001179 info->head.val |= INFO_AMP_CAPS;
Takashi Iwai897cc182007-05-29 19:01:37 +02001180 return 0;
1181}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001182EXPORT_SYMBOL_HDA(snd_hda_override_amp_caps);
Takashi Iwai897cc182007-05-29 19:01:37 +02001183
Takashi Iwai92c7c8a2009-03-24 07:32:14 +01001184static unsigned int
1185query_caps_hash(struct hda_codec *codec, hda_nid_t nid, u32 key,
1186 unsigned int (*func)(struct hda_codec *, hda_nid_t))
Takashi Iwai1327a322009-03-23 13:07:47 +01001187{
1188 struct hda_amp_info *info;
1189
Takashi Iwai92c7c8a2009-03-24 07:32:14 +01001190 info = get_alloc_amp_hash(codec, key);
Takashi Iwai1327a322009-03-23 13:07:47 +01001191 if (!info)
1192 return 0;
1193 if (!info->head.val) {
Takashi Iwai1327a322009-03-23 13:07:47 +01001194 info->head.val |= INFO_AMP_CAPS;
Takashi Iwai92c7c8a2009-03-24 07:32:14 +01001195 info->amp_caps = func(codec, nid);
Takashi Iwai1327a322009-03-23 13:07:47 +01001196 }
1197 return info->amp_caps;
1198}
Takashi Iwai92c7c8a2009-03-24 07:32:14 +01001199
1200static unsigned int read_pin_cap(struct hda_codec *codec, hda_nid_t nid)
1201{
1202 return snd_hda_param_read(codec, nid, AC_PAR_PIN_CAP);
1203}
1204
1205u32 snd_hda_query_pin_caps(struct hda_codec *codec, hda_nid_t nid)
1206{
1207 return query_caps_hash(codec, nid, HDA_HASH_PINCAP_KEY(nid),
1208 read_pin_cap);
1209}
Takashi Iwai1327a322009-03-23 13:07:47 +01001210EXPORT_SYMBOL_HDA(snd_hda_query_pin_caps);
1211
Linus Torvalds1da177e2005-04-16 15:20:36 -07001212/*
1213 * read the current volume to info
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001214 * if the cache exists, read the cache value.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001215 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02001216static unsigned int get_vol_mute(struct hda_codec *codec,
1217 struct hda_amp_info *info, hda_nid_t nid,
1218 int ch, int direction, int index)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001219{
1220 u32 val, parm;
1221
Takashi Iwai01751f52007-08-10 16:59:39 +02001222 if (info->head.val & INFO_AMP_VOL(ch))
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001223 return info->vol[ch];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001224
1225 parm = ch ? AC_AMP_GET_RIGHT : AC_AMP_GET_LEFT;
1226 parm |= direction == HDA_OUTPUT ? AC_AMP_GET_OUTPUT : AC_AMP_GET_INPUT;
1227 parm |= index;
Takashi Iwai0ba21762007-04-16 11:29:14 +02001228 val = snd_hda_codec_read(codec, nid, 0,
1229 AC_VERB_GET_AMP_GAIN_MUTE, parm);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001230 info->vol[ch] = val & 0xff;
Takashi Iwai01751f52007-08-10 16:59:39 +02001231 info->head.val |= INFO_AMP_VOL(ch);
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001232 return info->vol[ch];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001233}
1234
1235/*
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001236 * write the current volume in info to the h/w and update the cache
Linus Torvalds1da177e2005-04-16 15:20:36 -07001237 */
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001238static void put_vol_mute(struct hda_codec *codec, struct hda_amp_info *info,
Takashi Iwai0ba21762007-04-16 11:29:14 +02001239 hda_nid_t nid, int ch, int direction, int index,
1240 int val)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001241{
1242 u32 parm;
1243
1244 parm = ch ? AC_AMP_SET_RIGHT : AC_AMP_SET_LEFT;
1245 parm |= direction == HDA_OUTPUT ? AC_AMP_SET_OUTPUT : AC_AMP_SET_INPUT;
1246 parm |= index << AC_AMP_SET_INDEX_SHIFT;
1247 parm |= val;
1248 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, parm);
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001249 info->vol[ch] = val;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001250}
1251
1252/*
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001253 * read AMP value. The volume is between 0 to 0x7f, 0x80 = mute bit.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001254 */
Takashi Iwai834be882006-03-01 14:16:17 +01001255int snd_hda_codec_amp_read(struct hda_codec *codec, hda_nid_t nid, int ch,
1256 int direction, int index)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001257{
Takashi Iwai0ba21762007-04-16 11:29:14 +02001258 struct hda_amp_info *info;
1259 info = get_alloc_amp_hash(codec, HDA_HASH_KEY(nid, direction, index));
1260 if (!info)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001261 return 0;
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001262 return get_vol_mute(codec, info, nid, ch, direction, index);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001263}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001264EXPORT_SYMBOL_HDA(snd_hda_codec_amp_read);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001265
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001266/*
1267 * update the AMP value, mask = bit mask to set, val = the value
1268 */
Takashi Iwai834be882006-03-01 14:16:17 +01001269int snd_hda_codec_amp_update(struct hda_codec *codec, hda_nid_t nid, int ch,
1270 int direction, int idx, int mask, int val)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001271{
Takashi Iwai0ba21762007-04-16 11:29:14 +02001272 struct hda_amp_info *info;
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001273
Takashi Iwai0ba21762007-04-16 11:29:14 +02001274 info = get_alloc_amp_hash(codec, HDA_HASH_KEY(nid, direction, idx));
1275 if (!info)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001276 return 0;
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001277 val &= mask;
1278 val |= get_vol_mute(codec, info, nid, ch, direction, idx) & ~mask;
Takashi Iwai82beb8f2007-08-10 17:09:26 +02001279 if (info->vol[ch] == val)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001280 return 0;
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001281 put_vol_mute(codec, info, nid, ch, direction, idx, val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001282 return 1;
1283}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001284EXPORT_SYMBOL_HDA(snd_hda_codec_amp_update);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001285
Takashi Iwai47fd8302007-08-10 17:11:07 +02001286/*
1287 * update the AMP stereo with the same mask and value
1288 */
1289int snd_hda_codec_amp_stereo(struct hda_codec *codec, hda_nid_t nid,
1290 int direction, int idx, int mask, int val)
1291{
1292 int ch, ret = 0;
1293 for (ch = 0; ch < 2; ch++)
1294 ret |= snd_hda_codec_amp_update(codec, nid, ch, direction,
1295 idx, mask, val);
1296 return ret;
1297}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001298EXPORT_SYMBOL_HDA(snd_hda_codec_amp_stereo);
Takashi Iwai47fd8302007-08-10 17:11:07 +02001299
Takashi Iwaicb53c622007-08-10 17:21:45 +02001300#ifdef SND_HDA_NEEDS_RESUME
Takashi Iwaib3ac5632007-08-10 17:03:40 +02001301/* resume the all amp commands from the cache */
1302void snd_hda_codec_resume_amp(struct hda_codec *codec)
1303{
Takashi Iwai603c4012008-07-30 15:01:44 +02001304 struct hda_amp_info *buffer = codec->amp_cache.buf.list;
Takashi Iwaib3ac5632007-08-10 17:03:40 +02001305 int i;
1306
Takashi Iwai603c4012008-07-30 15:01:44 +02001307 for (i = 0; i < codec->amp_cache.buf.used; i++, buffer++) {
Takashi Iwaib3ac5632007-08-10 17:03:40 +02001308 u32 key = buffer->head.key;
1309 hda_nid_t nid;
1310 unsigned int idx, dir, ch;
1311 if (!key)
1312 continue;
1313 nid = key & 0xff;
1314 idx = (key >> 16) & 0xff;
1315 dir = (key >> 24) & 0xff;
1316 for (ch = 0; ch < 2; ch++) {
1317 if (!(buffer->head.val & INFO_AMP_VOL(ch)))
1318 continue;
1319 put_vol_mute(codec, buffer, nid, ch, dir, idx,
1320 buffer->vol[ch]);
1321 }
1322 }
1323}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001324EXPORT_SYMBOL_HDA(snd_hda_codec_resume_amp);
Takashi Iwaicb53c622007-08-10 17:21:45 +02001325#endif /* SND_HDA_NEEDS_RESUME */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001326
Linus Torvalds1da177e2005-04-16 15:20:36 -07001327/* volume */
Takashi Iwai0ba21762007-04-16 11:29:14 +02001328int snd_hda_mixer_amp_volume_info(struct snd_kcontrol *kcontrol,
1329 struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001330{
1331 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1332 u16 nid = get_amp_nid(kcontrol);
1333 u8 chs = get_amp_channels(kcontrol);
1334 int dir = get_amp_direction(kcontrol);
Takashi Iwai29fdbec2009-01-20 13:07:55 +01001335 unsigned int ofs = get_amp_offset(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001336 u32 caps;
1337
1338 caps = query_amp_caps(codec, nid, dir);
Takashi Iwai0ba21762007-04-16 11:29:14 +02001339 /* num steps */
1340 caps = (caps & AC_AMPCAP_NUM_STEPS) >> AC_AMPCAP_NUM_STEPS_SHIFT;
1341 if (!caps) {
1342 printk(KERN_WARNING "hda_codec: "
Takashi Iwai9c8f2ab2008-01-11 16:12:23 +01001343 "num_steps = 0 for NID=0x%x (ctl = %s)\n", nid,
1344 kcontrol->id.name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001345 return -EINVAL;
1346 }
Takashi Iwai29fdbec2009-01-20 13:07:55 +01001347 if (ofs < caps)
1348 caps -= ofs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001349 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
1350 uinfo->count = chs == 3 ? 2 : 1;
1351 uinfo->value.integer.min = 0;
1352 uinfo->value.integer.max = caps;
1353 return 0;
1354}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001355EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_volume_info);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001356
Takashi Iwai29fdbec2009-01-20 13:07:55 +01001357
1358static inline unsigned int
1359read_amp_value(struct hda_codec *codec, hda_nid_t nid,
1360 int ch, int dir, int idx, unsigned int ofs)
1361{
1362 unsigned int val;
1363 val = snd_hda_codec_amp_read(codec, nid, ch, dir, idx);
1364 val &= HDA_AMP_VOLMASK;
1365 if (val >= ofs)
1366 val -= ofs;
1367 else
1368 val = 0;
1369 return val;
1370}
1371
1372static inline int
1373update_amp_value(struct hda_codec *codec, hda_nid_t nid,
1374 int ch, int dir, int idx, unsigned int ofs,
1375 unsigned int val)
1376{
1377 if (val > 0)
1378 val += ofs;
1379 return snd_hda_codec_amp_update(codec, nid, ch, dir, idx,
1380 HDA_AMP_VOLMASK, val);
1381}
1382
Takashi Iwai0ba21762007-04-16 11:29:14 +02001383int snd_hda_mixer_amp_volume_get(struct snd_kcontrol *kcontrol,
1384 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001385{
1386 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1387 hda_nid_t nid = get_amp_nid(kcontrol);
1388 int chs = get_amp_channels(kcontrol);
1389 int dir = get_amp_direction(kcontrol);
1390 int idx = get_amp_index(kcontrol);
Takashi Iwai29fdbec2009-01-20 13:07:55 +01001391 unsigned int ofs = get_amp_offset(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001392 long *valp = ucontrol->value.integer.value;
1393
1394 if (chs & 1)
Takashi Iwai29fdbec2009-01-20 13:07:55 +01001395 *valp++ = read_amp_value(codec, nid, 0, dir, idx, ofs);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001396 if (chs & 2)
Takashi Iwai29fdbec2009-01-20 13:07:55 +01001397 *valp = read_amp_value(codec, nid, 1, dir, idx, ofs);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001398 return 0;
1399}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001400EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_volume_get);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001401
Takashi Iwai0ba21762007-04-16 11:29:14 +02001402int snd_hda_mixer_amp_volume_put(struct snd_kcontrol *kcontrol,
1403 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001404{
1405 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1406 hda_nid_t nid = get_amp_nid(kcontrol);
1407 int chs = get_amp_channels(kcontrol);
1408 int dir = get_amp_direction(kcontrol);
1409 int idx = get_amp_index(kcontrol);
Takashi Iwai29fdbec2009-01-20 13:07:55 +01001410 unsigned int ofs = get_amp_offset(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001411 long *valp = ucontrol->value.integer.value;
1412 int change = 0;
1413
Takashi Iwaicb53c622007-08-10 17:21:45 +02001414 snd_hda_power_up(codec);
Nicolas Grazianob9f5a892005-07-29 12:17:20 +02001415 if (chs & 1) {
Takashi Iwai29fdbec2009-01-20 13:07:55 +01001416 change = update_amp_value(codec, nid, 0, dir, idx, ofs, *valp);
Nicolas Grazianob9f5a892005-07-29 12:17:20 +02001417 valp++;
1418 }
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001419 if (chs & 2)
Takashi Iwai29fdbec2009-01-20 13:07:55 +01001420 change |= update_amp_value(codec, nid, 1, dir, idx, ofs, *valp);
Takashi Iwaicb53c622007-08-10 17:21:45 +02001421 snd_hda_power_down(codec);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001422 return change;
1423}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001424EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_volume_put);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001425
Jaroslav Kysela302e9c52006-07-05 17:39:49 +02001426int snd_hda_mixer_amp_tlv(struct snd_kcontrol *kcontrol, int op_flag,
1427 unsigned int size, unsigned int __user *_tlv)
1428{
1429 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1430 hda_nid_t nid = get_amp_nid(kcontrol);
1431 int dir = get_amp_direction(kcontrol);
Takashi Iwai29fdbec2009-01-20 13:07:55 +01001432 unsigned int ofs = get_amp_offset(kcontrol);
Jaroslav Kysela302e9c52006-07-05 17:39:49 +02001433 u32 caps, val1, val2;
1434
1435 if (size < 4 * sizeof(unsigned int))
1436 return -ENOMEM;
1437 caps = query_amp_caps(codec, nid, dir);
Takashi Iwai0ba21762007-04-16 11:29:14 +02001438 val2 = (caps & AC_AMPCAP_STEP_SIZE) >> AC_AMPCAP_STEP_SIZE_SHIFT;
1439 val2 = (val2 + 1) * 25;
Jaroslav Kysela302e9c52006-07-05 17:39:49 +02001440 val1 = -((caps & AC_AMPCAP_OFFSET) >> AC_AMPCAP_OFFSET_SHIFT);
Takashi Iwai29fdbec2009-01-20 13:07:55 +01001441 val1 += ofs;
Jaroslav Kysela302e9c52006-07-05 17:39:49 +02001442 val1 = ((int)val1) * ((int)val2);
Jaroslav Kysela302e9c52006-07-05 17:39:49 +02001443 if (put_user(SNDRV_CTL_TLVT_DB_SCALE, _tlv))
1444 return -EFAULT;
1445 if (put_user(2 * sizeof(unsigned int), _tlv + 1))
1446 return -EFAULT;
1447 if (put_user(val1, _tlv + 2))
1448 return -EFAULT;
1449 if (put_user(val2, _tlv + 3))
1450 return -EFAULT;
1451 return 0;
1452}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001453EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_tlv);
Jaroslav Kysela302e9c52006-07-05 17:39:49 +02001454
Takashi Iwai2134ea42008-01-10 16:53:55 +01001455/*
1456 * set (static) TLV for virtual master volume; recalculated as max 0dB
1457 */
1458void snd_hda_set_vmaster_tlv(struct hda_codec *codec, hda_nid_t nid, int dir,
1459 unsigned int *tlv)
1460{
1461 u32 caps;
1462 int nums, step;
1463
1464 caps = query_amp_caps(codec, nid, dir);
1465 nums = (caps & AC_AMPCAP_NUM_STEPS) >> AC_AMPCAP_NUM_STEPS_SHIFT;
1466 step = (caps & AC_AMPCAP_STEP_SIZE) >> AC_AMPCAP_STEP_SIZE_SHIFT;
1467 step = (step + 1) * 25;
1468 tlv[0] = SNDRV_CTL_TLVT_DB_SCALE;
1469 tlv[1] = 2 * sizeof(unsigned int);
1470 tlv[2] = -nums * step;
1471 tlv[3] = step;
1472}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001473EXPORT_SYMBOL_HDA(snd_hda_set_vmaster_tlv);
Takashi Iwai2134ea42008-01-10 16:53:55 +01001474
1475/* find a mixer control element with the given name */
Takashi Iwai09f99702008-02-04 12:31:13 +01001476static struct snd_kcontrol *
1477_snd_hda_find_mixer_ctl(struct hda_codec *codec,
1478 const char *name, int idx)
Takashi Iwai2134ea42008-01-10 16:53:55 +01001479{
1480 struct snd_ctl_elem_id id;
1481 memset(&id, 0, sizeof(id));
1482 id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
Takashi Iwai09f99702008-02-04 12:31:13 +01001483 id.index = idx;
Takashi Iwai18cb7102009-04-16 10:22:24 +02001484 if (snd_BUG_ON(strlen(name) >= sizeof(id.name)))
1485 return NULL;
Takashi Iwai2134ea42008-01-10 16:53:55 +01001486 strcpy(id.name, name);
1487 return snd_ctl_find_id(codec->bus->card, &id);
1488}
1489
Takashi Iwai09f99702008-02-04 12:31:13 +01001490struct snd_kcontrol *snd_hda_find_mixer_ctl(struct hda_codec *codec,
1491 const char *name)
1492{
1493 return _snd_hda_find_mixer_ctl(codec, name, 0);
1494}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001495EXPORT_SYMBOL_HDA(snd_hda_find_mixer_ctl);
Takashi Iwai09f99702008-02-04 12:31:13 +01001496
Takashi Iwaid13bd412008-07-30 15:01:45 +02001497/* Add a control element and assign to the codec */
1498int snd_hda_ctl_add(struct hda_codec *codec, struct snd_kcontrol *kctl)
1499{
1500 int err;
1501 struct snd_kcontrol **knewp;
1502
1503 err = snd_ctl_add(codec->bus->card, kctl);
1504 if (err < 0)
1505 return err;
1506 knewp = snd_array_new(&codec->mixers);
1507 if (!knewp)
1508 return -ENOMEM;
1509 *knewp = kctl;
1510 return 0;
1511}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001512EXPORT_SYMBOL_HDA(snd_hda_ctl_add);
Takashi Iwaid13bd412008-07-30 15:01:45 +02001513
1514/* Clear all controls assigned to the given codec */
1515void snd_hda_ctls_clear(struct hda_codec *codec)
1516{
1517 int i;
1518 struct snd_kcontrol **kctls = codec->mixers.list;
1519 for (i = 0; i < codec->mixers.used; i++)
1520 snd_ctl_remove(codec->bus->card, kctls[i]);
1521 snd_array_free(&codec->mixers);
1522}
1523
Takashi Iwaia65d6292009-02-23 16:57:04 +01001524/* pseudo device locking
1525 * toggle card->shutdown to allow/disallow the device access (as a hack)
1526 */
1527static int hda_lock_devices(struct snd_card *card)
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001528{
Takashi Iwaia65d6292009-02-23 16:57:04 +01001529 spin_lock(&card->files_lock);
1530 if (card->shutdown) {
1531 spin_unlock(&card->files_lock);
1532 return -EINVAL;
1533 }
1534 card->shutdown = 1;
1535 spin_unlock(&card->files_lock);
1536 return 0;
1537}
1538
1539static void hda_unlock_devices(struct snd_card *card)
1540{
1541 spin_lock(&card->files_lock);
1542 card->shutdown = 0;
1543 spin_unlock(&card->files_lock);
1544}
1545
1546int snd_hda_codec_reset(struct hda_codec *codec)
1547{
1548 struct snd_card *card = codec->bus->card;
1549 int i, pcm;
1550
1551 if (hda_lock_devices(card) < 0)
1552 return -EBUSY;
1553 /* check whether the codec isn't used by any mixer or PCM streams */
1554 if (!list_empty(&card->ctl_files)) {
1555 hda_unlock_devices(card);
1556 return -EBUSY;
1557 }
1558 for (pcm = 0; pcm < codec->num_pcms; pcm++) {
1559 struct hda_pcm *cpcm = &codec->pcm_info[pcm];
1560 if (!cpcm->pcm)
1561 continue;
1562 if (cpcm->pcm->streams[0].substream_opened ||
1563 cpcm->pcm->streams[1].substream_opened) {
1564 hda_unlock_devices(card);
1565 return -EBUSY;
1566 }
1567 }
1568
1569 /* OK, let it free */
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001570
1571#ifdef CONFIG_SND_HDA_POWER_SAVE
1572 cancel_delayed_work(&codec->power_work);
Takashi Iwai6acaed32009-01-12 10:09:24 +01001573 flush_workqueue(codec->bus->workq);
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001574#endif
1575 snd_hda_ctls_clear(codec);
1576 /* relase PCMs */
1577 for (i = 0; i < codec->num_pcms; i++) {
Takashi Iwai529bd6c2008-11-27 14:17:01 +01001578 if (codec->pcm_info[i].pcm) {
Takashi Iwaia65d6292009-02-23 16:57:04 +01001579 snd_device_free(card, codec->pcm_info[i].pcm);
Takashi Iwai529bd6c2008-11-27 14:17:01 +01001580 clear_bit(codec->pcm_info[i].device,
1581 codec->bus->pcm_dev_bits);
1582 }
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001583 }
1584 if (codec->patch_ops.free)
1585 codec->patch_ops.free(codec);
Takashi Iwai56d17712008-11-28 14:36:23 +01001586 codec->proc_widget_hook = NULL;
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001587 codec->spec = NULL;
1588 free_hda_cache(&codec->amp_cache);
1589 free_hda_cache(&codec->cmd_cache);
Takashi Iwai827057f2008-12-19 10:12:02 +01001590 init_hda_cache(&codec->amp_cache, sizeof(struct hda_amp_info));
1591 init_hda_cache(&codec->cmd_cache, sizeof(struct hda_cache_head));
Takashi Iwai346ff702009-02-23 09:42:57 +01001592 /* free only driver_pins so that init_pins + user_pins are restored */
1593 snd_array_free(&codec->driver_pins);
Takashi Iwai3be14142009-02-20 14:11:16 +01001594 restore_pincfgs(codec);
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001595 codec->num_pcms = 0;
1596 codec->pcm_info = NULL;
1597 codec->preset = NULL;
Takashi Iwaid1f1af22009-03-02 10:35:29 +01001598 memset(&codec->patch_ops, 0, sizeof(codec->patch_ops));
1599 codec->slave_dig_outs = NULL;
1600 codec->spdif_status_reset = 0;
Takashi Iwai1289e9e2008-11-27 15:47:11 +01001601 module_put(codec->owner);
1602 codec->owner = NULL;
Takashi Iwaia65d6292009-02-23 16:57:04 +01001603
1604 /* allow device access again */
1605 hda_unlock_devices(card);
1606 return 0;
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001607}
1608
Takashi Iwai2134ea42008-01-10 16:53:55 +01001609/* create a virtual master control and add slaves */
1610int snd_hda_add_vmaster(struct hda_codec *codec, char *name,
1611 unsigned int *tlv, const char **slaves)
1612{
1613 struct snd_kcontrol *kctl;
1614 const char **s;
1615 int err;
1616
Takashi Iwai2f085542008-02-22 18:43:50 +01001617 for (s = slaves; *s && !snd_hda_find_mixer_ctl(codec, *s); s++)
1618 ;
1619 if (!*s) {
1620 snd_printdd("No slave found for %s\n", name);
1621 return 0;
1622 }
Takashi Iwai2134ea42008-01-10 16:53:55 +01001623 kctl = snd_ctl_make_virtual_master(name, tlv);
1624 if (!kctl)
1625 return -ENOMEM;
Takashi Iwaid13bd412008-07-30 15:01:45 +02001626 err = snd_hda_ctl_add(codec, kctl);
Takashi Iwai2134ea42008-01-10 16:53:55 +01001627 if (err < 0)
1628 return err;
1629
1630 for (s = slaves; *s; s++) {
1631 struct snd_kcontrol *sctl;
Takashi Iwai7a411ee2009-03-06 10:08:14 +01001632 int i = 0;
1633 for (;;) {
1634 sctl = _snd_hda_find_mixer_ctl(codec, *s, i);
1635 if (!sctl) {
1636 if (!i)
1637 snd_printdd("Cannot find slave %s, "
1638 "skipped\n", *s);
1639 break;
1640 }
1641 err = snd_ctl_add_slave(kctl, sctl);
1642 if (err < 0)
1643 return err;
1644 i++;
Takashi Iwai2134ea42008-01-10 16:53:55 +01001645 }
Takashi Iwai2134ea42008-01-10 16:53:55 +01001646 }
1647 return 0;
1648}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001649EXPORT_SYMBOL_HDA(snd_hda_add_vmaster);
Takashi Iwai2134ea42008-01-10 16:53:55 +01001650
Linus Torvalds1da177e2005-04-16 15:20:36 -07001651/* switch */
Takashi Iwai0ba21762007-04-16 11:29:14 +02001652int snd_hda_mixer_amp_switch_info(struct snd_kcontrol *kcontrol,
1653 struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001654{
1655 int chs = get_amp_channels(kcontrol);
1656
1657 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
1658 uinfo->count = chs == 3 ? 2 : 1;
1659 uinfo->value.integer.min = 0;
1660 uinfo->value.integer.max = 1;
1661 return 0;
1662}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001663EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_switch_info);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001664
Takashi Iwai0ba21762007-04-16 11:29:14 +02001665int snd_hda_mixer_amp_switch_get(struct snd_kcontrol *kcontrol,
1666 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001667{
1668 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1669 hda_nid_t nid = get_amp_nid(kcontrol);
1670 int chs = get_amp_channels(kcontrol);
1671 int dir = get_amp_direction(kcontrol);
1672 int idx = get_amp_index(kcontrol);
1673 long *valp = ucontrol->value.integer.value;
1674
1675 if (chs & 1)
Takashi Iwai0ba21762007-04-16 11:29:14 +02001676 *valp++ = (snd_hda_codec_amp_read(codec, nid, 0, dir, idx) &
Takashi Iwai47fd8302007-08-10 17:11:07 +02001677 HDA_AMP_MUTE) ? 0 : 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001678 if (chs & 2)
Takashi Iwai0ba21762007-04-16 11:29:14 +02001679 *valp = (snd_hda_codec_amp_read(codec, nid, 1, dir, idx) &
Takashi Iwai47fd8302007-08-10 17:11:07 +02001680 HDA_AMP_MUTE) ? 0 : 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001681 return 0;
1682}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001683EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_switch_get);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001684
Takashi Iwai0ba21762007-04-16 11:29:14 +02001685int snd_hda_mixer_amp_switch_put(struct snd_kcontrol *kcontrol,
1686 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001687{
1688 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1689 hda_nid_t nid = get_amp_nid(kcontrol);
1690 int chs = get_amp_channels(kcontrol);
1691 int dir = get_amp_direction(kcontrol);
1692 int idx = get_amp_index(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001693 long *valp = ucontrol->value.integer.value;
1694 int change = 0;
1695
Takashi Iwaicb53c622007-08-10 17:21:45 +02001696 snd_hda_power_up(codec);
Nicolas Grazianob9f5a892005-07-29 12:17:20 +02001697 if (chs & 1) {
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001698 change = snd_hda_codec_amp_update(codec, nid, 0, dir, idx,
Takashi Iwai47fd8302007-08-10 17:11:07 +02001699 HDA_AMP_MUTE,
1700 *valp ? 0 : HDA_AMP_MUTE);
Nicolas Grazianob9f5a892005-07-29 12:17:20 +02001701 valp++;
1702 }
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001703 if (chs & 2)
1704 change |= snd_hda_codec_amp_update(codec, nid, 1, dir, idx,
Takashi Iwai47fd8302007-08-10 17:11:07 +02001705 HDA_AMP_MUTE,
1706 *valp ? 0 : HDA_AMP_MUTE);
Takashi Iwaicb53c622007-08-10 17:21:45 +02001707#ifdef CONFIG_SND_HDA_POWER_SAVE
1708 if (codec->patch_ops.check_power_status)
1709 codec->patch_ops.check_power_status(codec, nid);
1710#endif
1711 snd_hda_power_down(codec);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001712 return change;
1713}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001714EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_switch_put);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001715
1716/*
Takashi Iwai985be542005-11-02 18:26:49 +01001717 * bound volume controls
1718 *
1719 * bind multiple volumes (# indices, from 0)
1720 */
1721
1722#define AMP_VAL_IDX_SHIFT 19
1723#define AMP_VAL_IDX_MASK (0x0f<<19)
1724
Takashi Iwai0ba21762007-04-16 11:29:14 +02001725int snd_hda_mixer_bind_switch_get(struct snd_kcontrol *kcontrol,
1726 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai985be542005-11-02 18:26:49 +01001727{
1728 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1729 unsigned long pval;
1730 int err;
1731
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001732 mutex_lock(&codec->control_mutex);
Takashi Iwai985be542005-11-02 18:26:49 +01001733 pval = kcontrol->private_value;
1734 kcontrol->private_value = pval & ~AMP_VAL_IDX_MASK; /* index 0 */
1735 err = snd_hda_mixer_amp_switch_get(kcontrol, ucontrol);
1736 kcontrol->private_value = pval;
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001737 mutex_unlock(&codec->control_mutex);
Takashi Iwai985be542005-11-02 18:26:49 +01001738 return err;
1739}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001740EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_switch_get);
Takashi Iwai985be542005-11-02 18:26:49 +01001741
Takashi Iwai0ba21762007-04-16 11:29:14 +02001742int snd_hda_mixer_bind_switch_put(struct snd_kcontrol *kcontrol,
1743 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai985be542005-11-02 18:26:49 +01001744{
1745 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1746 unsigned long pval;
1747 int i, indices, err = 0, change = 0;
1748
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001749 mutex_lock(&codec->control_mutex);
Takashi Iwai985be542005-11-02 18:26:49 +01001750 pval = kcontrol->private_value;
1751 indices = (pval & AMP_VAL_IDX_MASK) >> AMP_VAL_IDX_SHIFT;
1752 for (i = 0; i < indices; i++) {
Takashi Iwai0ba21762007-04-16 11:29:14 +02001753 kcontrol->private_value = (pval & ~AMP_VAL_IDX_MASK) |
1754 (i << AMP_VAL_IDX_SHIFT);
Takashi Iwai985be542005-11-02 18:26:49 +01001755 err = snd_hda_mixer_amp_switch_put(kcontrol, ucontrol);
1756 if (err < 0)
1757 break;
1758 change |= err;
1759 }
1760 kcontrol->private_value = pval;
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001761 mutex_unlock(&codec->control_mutex);
Takashi Iwai985be542005-11-02 18:26:49 +01001762 return err < 0 ? err : change;
1763}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001764EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_switch_put);
Takashi Iwai985be542005-11-02 18:26:49 +01001765
1766/*
Takashi Iwai532d5382007-07-27 19:02:40 +02001767 * generic bound volume/swtich controls
1768 */
1769int snd_hda_mixer_bind_ctls_info(struct snd_kcontrol *kcontrol,
1770 struct snd_ctl_elem_info *uinfo)
1771{
1772 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1773 struct hda_bind_ctls *c;
1774 int err;
1775
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001776 mutex_lock(&codec->control_mutex);
Serge A. Suchkov14c65f92008-02-22 18:43:16 +01001777 c = (struct hda_bind_ctls *)kcontrol->private_value;
Takashi Iwai532d5382007-07-27 19:02:40 +02001778 kcontrol->private_value = *c->values;
1779 err = c->ops->info(kcontrol, uinfo);
1780 kcontrol->private_value = (long)c;
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001781 mutex_unlock(&codec->control_mutex);
Takashi Iwai532d5382007-07-27 19:02:40 +02001782 return err;
1783}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001784EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_ctls_info);
Takashi Iwai532d5382007-07-27 19:02:40 +02001785
1786int snd_hda_mixer_bind_ctls_get(struct snd_kcontrol *kcontrol,
1787 struct snd_ctl_elem_value *ucontrol)
1788{
1789 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1790 struct hda_bind_ctls *c;
1791 int err;
1792
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001793 mutex_lock(&codec->control_mutex);
Serge A. Suchkov14c65f92008-02-22 18:43:16 +01001794 c = (struct hda_bind_ctls *)kcontrol->private_value;
Takashi Iwai532d5382007-07-27 19:02:40 +02001795 kcontrol->private_value = *c->values;
1796 err = c->ops->get(kcontrol, ucontrol);
1797 kcontrol->private_value = (long)c;
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001798 mutex_unlock(&codec->control_mutex);
Takashi Iwai532d5382007-07-27 19:02:40 +02001799 return err;
1800}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001801EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_ctls_get);
Takashi Iwai532d5382007-07-27 19:02:40 +02001802
1803int snd_hda_mixer_bind_ctls_put(struct snd_kcontrol *kcontrol,
1804 struct snd_ctl_elem_value *ucontrol)
1805{
1806 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1807 struct hda_bind_ctls *c;
1808 unsigned long *vals;
1809 int err = 0, change = 0;
1810
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001811 mutex_lock(&codec->control_mutex);
Serge A. Suchkov14c65f92008-02-22 18:43:16 +01001812 c = (struct hda_bind_ctls *)kcontrol->private_value;
Takashi Iwai532d5382007-07-27 19:02:40 +02001813 for (vals = c->values; *vals; vals++) {
1814 kcontrol->private_value = *vals;
1815 err = c->ops->put(kcontrol, ucontrol);
1816 if (err < 0)
1817 break;
1818 change |= err;
1819 }
1820 kcontrol->private_value = (long)c;
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001821 mutex_unlock(&codec->control_mutex);
Takashi Iwai532d5382007-07-27 19:02:40 +02001822 return err < 0 ? err : change;
1823}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001824EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_ctls_put);
Takashi Iwai532d5382007-07-27 19:02:40 +02001825
1826int snd_hda_mixer_bind_tlv(struct snd_kcontrol *kcontrol, int op_flag,
1827 unsigned int size, unsigned int __user *tlv)
1828{
1829 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1830 struct hda_bind_ctls *c;
1831 int err;
1832
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001833 mutex_lock(&codec->control_mutex);
Serge A. Suchkov14c65f92008-02-22 18:43:16 +01001834 c = (struct hda_bind_ctls *)kcontrol->private_value;
Takashi Iwai532d5382007-07-27 19:02:40 +02001835 kcontrol->private_value = *c->values;
1836 err = c->ops->tlv(kcontrol, op_flag, size, tlv);
1837 kcontrol->private_value = (long)c;
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001838 mutex_unlock(&codec->control_mutex);
Takashi Iwai532d5382007-07-27 19:02:40 +02001839 return err;
1840}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001841EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_tlv);
Takashi Iwai532d5382007-07-27 19:02:40 +02001842
1843struct hda_ctl_ops snd_hda_bind_vol = {
1844 .info = snd_hda_mixer_amp_volume_info,
1845 .get = snd_hda_mixer_amp_volume_get,
1846 .put = snd_hda_mixer_amp_volume_put,
1847 .tlv = snd_hda_mixer_amp_tlv
1848};
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001849EXPORT_SYMBOL_HDA(snd_hda_bind_vol);
Takashi Iwai532d5382007-07-27 19:02:40 +02001850
1851struct hda_ctl_ops snd_hda_bind_sw = {
1852 .info = snd_hda_mixer_amp_switch_info,
1853 .get = snd_hda_mixer_amp_switch_get,
1854 .put = snd_hda_mixer_amp_switch_put,
1855 .tlv = snd_hda_mixer_amp_tlv
1856};
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001857EXPORT_SYMBOL_HDA(snd_hda_bind_sw);
Takashi Iwai532d5382007-07-27 19:02:40 +02001858
1859/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07001860 * SPDIF out controls
1861 */
1862
Takashi Iwai0ba21762007-04-16 11:29:14 +02001863static int snd_hda_spdif_mask_info(struct snd_kcontrol *kcontrol,
1864 struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001865{
1866 uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
1867 uinfo->count = 1;
1868 return 0;
1869}
1870
Takashi Iwai0ba21762007-04-16 11:29:14 +02001871static int snd_hda_spdif_cmask_get(struct snd_kcontrol *kcontrol,
1872 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001873{
1874 ucontrol->value.iec958.status[0] = IEC958_AES0_PROFESSIONAL |
1875 IEC958_AES0_NONAUDIO |
1876 IEC958_AES0_CON_EMPHASIS_5015 |
1877 IEC958_AES0_CON_NOT_COPYRIGHT;
1878 ucontrol->value.iec958.status[1] = IEC958_AES1_CON_CATEGORY |
1879 IEC958_AES1_CON_ORIGINAL;
1880 return 0;
1881}
1882
Takashi Iwai0ba21762007-04-16 11:29:14 +02001883static int snd_hda_spdif_pmask_get(struct snd_kcontrol *kcontrol,
1884 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001885{
1886 ucontrol->value.iec958.status[0] = IEC958_AES0_PROFESSIONAL |
1887 IEC958_AES0_NONAUDIO |
1888 IEC958_AES0_PRO_EMPHASIS_5015;
1889 return 0;
1890}
1891
Takashi Iwai0ba21762007-04-16 11:29:14 +02001892static int snd_hda_spdif_default_get(struct snd_kcontrol *kcontrol,
1893 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001894{
1895 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1896
1897 ucontrol->value.iec958.status[0] = codec->spdif_status & 0xff;
1898 ucontrol->value.iec958.status[1] = (codec->spdif_status >> 8) & 0xff;
1899 ucontrol->value.iec958.status[2] = (codec->spdif_status >> 16) & 0xff;
1900 ucontrol->value.iec958.status[3] = (codec->spdif_status >> 24) & 0xff;
1901
1902 return 0;
1903}
1904
1905/* convert from SPDIF status bits to HDA SPDIF bits
1906 * bit 0 (DigEn) is always set zero (to be filled later)
1907 */
1908static unsigned short convert_from_spdif_status(unsigned int sbits)
1909{
1910 unsigned short val = 0;
1911
1912 if (sbits & IEC958_AES0_PROFESSIONAL)
Takashi Iwai0ba21762007-04-16 11:29:14 +02001913 val |= AC_DIG1_PROFESSIONAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001914 if (sbits & IEC958_AES0_NONAUDIO)
Takashi Iwai0ba21762007-04-16 11:29:14 +02001915 val |= AC_DIG1_NONAUDIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001916 if (sbits & IEC958_AES0_PROFESSIONAL) {
Takashi Iwai0ba21762007-04-16 11:29:14 +02001917 if ((sbits & IEC958_AES0_PRO_EMPHASIS) ==
1918 IEC958_AES0_PRO_EMPHASIS_5015)
1919 val |= AC_DIG1_EMPHASIS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001920 } else {
Takashi Iwai0ba21762007-04-16 11:29:14 +02001921 if ((sbits & IEC958_AES0_CON_EMPHASIS) ==
1922 IEC958_AES0_CON_EMPHASIS_5015)
1923 val |= AC_DIG1_EMPHASIS;
1924 if (!(sbits & IEC958_AES0_CON_NOT_COPYRIGHT))
1925 val |= AC_DIG1_COPYRIGHT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001926 if (sbits & (IEC958_AES1_CON_ORIGINAL << 8))
Takashi Iwai0ba21762007-04-16 11:29:14 +02001927 val |= AC_DIG1_LEVEL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001928 val |= sbits & (IEC958_AES1_CON_CATEGORY << 8);
1929 }
1930 return val;
1931}
1932
1933/* convert to SPDIF status bits from HDA SPDIF bits
1934 */
1935static unsigned int convert_to_spdif_status(unsigned short val)
1936{
1937 unsigned int sbits = 0;
1938
Takashi Iwai0ba21762007-04-16 11:29:14 +02001939 if (val & AC_DIG1_NONAUDIO)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001940 sbits |= IEC958_AES0_NONAUDIO;
Takashi Iwai0ba21762007-04-16 11:29:14 +02001941 if (val & AC_DIG1_PROFESSIONAL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001942 sbits |= IEC958_AES0_PROFESSIONAL;
1943 if (sbits & IEC958_AES0_PROFESSIONAL) {
Takashi Iwai0ba21762007-04-16 11:29:14 +02001944 if (sbits & AC_DIG1_EMPHASIS)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001945 sbits |= IEC958_AES0_PRO_EMPHASIS_5015;
1946 } else {
Takashi Iwai0ba21762007-04-16 11:29:14 +02001947 if (val & AC_DIG1_EMPHASIS)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001948 sbits |= IEC958_AES0_CON_EMPHASIS_5015;
Takashi Iwai0ba21762007-04-16 11:29:14 +02001949 if (!(val & AC_DIG1_COPYRIGHT))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001950 sbits |= IEC958_AES0_CON_NOT_COPYRIGHT;
Takashi Iwai0ba21762007-04-16 11:29:14 +02001951 if (val & AC_DIG1_LEVEL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001952 sbits |= (IEC958_AES1_CON_ORIGINAL << 8);
1953 sbits |= val & (0x7f << 8);
1954 }
1955 return sbits;
1956}
1957
Takashi Iwai2f728532008-09-25 16:32:41 +02001958/* set digital convert verbs both for the given NID and its slaves */
1959static void set_dig_out(struct hda_codec *codec, hda_nid_t nid,
1960 int verb, int val)
1961{
1962 hda_nid_t *d;
1963
Takashi Iwai9e976972008-11-25 08:17:20 +01001964 snd_hda_codec_write_cache(codec, nid, 0, verb, val);
Takashi Iwai2f728532008-09-25 16:32:41 +02001965 d = codec->slave_dig_outs;
1966 if (!d)
1967 return;
1968 for (; *d; d++)
Takashi Iwai9e976972008-11-25 08:17:20 +01001969 snd_hda_codec_write_cache(codec, *d, 0, verb, val);
Takashi Iwai2f728532008-09-25 16:32:41 +02001970}
1971
1972static inline void set_dig_out_convert(struct hda_codec *codec, hda_nid_t nid,
1973 int dig1, int dig2)
1974{
1975 if (dig1 != -1)
1976 set_dig_out(codec, nid, AC_VERB_SET_DIGI_CONVERT_1, dig1);
1977 if (dig2 != -1)
1978 set_dig_out(codec, nid, AC_VERB_SET_DIGI_CONVERT_2, dig2);
1979}
1980
Takashi Iwai0ba21762007-04-16 11:29:14 +02001981static int snd_hda_spdif_default_put(struct snd_kcontrol *kcontrol,
1982 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001983{
1984 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1985 hda_nid_t nid = kcontrol->private_value;
1986 unsigned short val;
1987 int change;
1988
Ingo Molnar62932df2006-01-16 16:34:20 +01001989 mutex_lock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001990 codec->spdif_status = ucontrol->value.iec958.status[0] |
1991 ((unsigned int)ucontrol->value.iec958.status[1] << 8) |
1992 ((unsigned int)ucontrol->value.iec958.status[2] << 16) |
1993 ((unsigned int)ucontrol->value.iec958.status[3] << 24);
1994 val = convert_from_spdif_status(codec->spdif_status);
1995 val |= codec->spdif_ctls & 1;
1996 change = codec->spdif_ctls != val;
1997 codec->spdif_ctls = val;
1998
Takashi Iwai2f728532008-09-25 16:32:41 +02001999 if (change)
2000 set_dig_out_convert(codec, nid, val & 0xff, (val >> 8) & 0xff);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002001
Ingo Molnar62932df2006-01-16 16:34:20 +01002002 mutex_unlock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002003 return change;
2004}
2005
Takashi Iwaia5ce8892007-07-23 15:42:26 +02002006#define snd_hda_spdif_out_switch_info snd_ctl_boolean_mono_info
Linus Torvalds1da177e2005-04-16 15:20:36 -07002007
Takashi Iwai0ba21762007-04-16 11:29:14 +02002008static int snd_hda_spdif_out_switch_get(struct snd_kcontrol *kcontrol,
2009 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002010{
2011 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2012
Takashi Iwai0ba21762007-04-16 11:29:14 +02002013 ucontrol->value.integer.value[0] = codec->spdif_ctls & AC_DIG1_ENABLE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002014 return 0;
2015}
2016
Takashi Iwai0ba21762007-04-16 11:29:14 +02002017static int snd_hda_spdif_out_switch_put(struct snd_kcontrol *kcontrol,
2018 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002019{
2020 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2021 hda_nid_t nid = kcontrol->private_value;
2022 unsigned short val;
2023 int change;
2024
Ingo Molnar62932df2006-01-16 16:34:20 +01002025 mutex_lock(&codec->spdif_mutex);
Takashi Iwai0ba21762007-04-16 11:29:14 +02002026 val = codec->spdif_ctls & ~AC_DIG1_ENABLE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002027 if (ucontrol->value.integer.value[0])
Takashi Iwai0ba21762007-04-16 11:29:14 +02002028 val |= AC_DIG1_ENABLE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002029 change = codec->spdif_ctls != val;
Takashi Iwai82beb8f2007-08-10 17:09:26 +02002030 if (change) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002031 codec->spdif_ctls = val;
Takashi Iwai2f728532008-09-25 16:32:41 +02002032 set_dig_out_convert(codec, nid, val & 0xff, -1);
Takashi Iwai0ba21762007-04-16 11:29:14 +02002033 /* unmute amp switch (if any) */
2034 if ((get_wcaps(codec, nid) & AC_WCAP_OUT_AMP) &&
Takashi Iwai47fd8302007-08-10 17:11:07 +02002035 (val & AC_DIG1_ENABLE))
2036 snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0,
2037 HDA_AMP_MUTE, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002038 }
Ingo Molnar62932df2006-01-16 16:34:20 +01002039 mutex_unlock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002040 return change;
2041}
2042
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01002043static struct snd_kcontrol_new dig_mixes[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002044 {
2045 .access = SNDRV_CTL_ELEM_ACCESS_READ,
2046 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2047 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,CON_MASK),
2048 .info = snd_hda_spdif_mask_info,
2049 .get = snd_hda_spdif_cmask_get,
2050 },
2051 {
2052 .access = SNDRV_CTL_ELEM_ACCESS_READ,
2053 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2054 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,PRO_MASK),
2055 .info = snd_hda_spdif_mask_info,
2056 .get = snd_hda_spdif_pmask_get,
2057 },
2058 {
2059 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2060 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT),
2061 .info = snd_hda_spdif_mask_info,
2062 .get = snd_hda_spdif_default_get,
2063 .put = snd_hda_spdif_default_put,
2064 },
2065 {
2066 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2067 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,SWITCH),
2068 .info = snd_hda_spdif_out_switch_info,
2069 .get = snd_hda_spdif_out_switch_get,
2070 .put = snd_hda_spdif_out_switch_put,
2071 },
2072 { } /* end */
2073};
2074
Takashi Iwai09f99702008-02-04 12:31:13 +01002075#define SPDIF_MAX_IDX 4 /* 4 instances should be enough to probe */
2076
Linus Torvalds1da177e2005-04-16 15:20:36 -07002077/**
2078 * snd_hda_create_spdif_out_ctls - create Output SPDIF-related controls
2079 * @codec: the HDA codec
2080 * @nid: audio out widget NID
2081 *
2082 * Creates controls related with the SPDIF output.
2083 * Called from each patch supporting the SPDIF out.
2084 *
2085 * Returns 0 if successful, or a negative error code.
2086 */
Takashi Iwai12f288b2007-08-02 15:51:59 +02002087int snd_hda_create_spdif_out_ctls(struct hda_codec *codec, hda_nid_t nid)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002088{
2089 int err;
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01002090 struct snd_kcontrol *kctl;
2091 struct snd_kcontrol_new *dig_mix;
Takashi Iwai09f99702008-02-04 12:31:13 +01002092 int idx;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002093
Takashi Iwai09f99702008-02-04 12:31:13 +01002094 for (idx = 0; idx < SPDIF_MAX_IDX; idx++) {
2095 if (!_snd_hda_find_mixer_ctl(codec, "IEC958 Playback Switch",
2096 idx))
2097 break;
2098 }
2099 if (idx >= SPDIF_MAX_IDX) {
2100 printk(KERN_ERR "hda_codec: too many IEC958 outputs\n");
2101 return -EBUSY;
2102 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002103 for (dig_mix = dig_mixes; dig_mix->name; dig_mix++) {
2104 kctl = snd_ctl_new1(dig_mix, codec);
Takashi Iwaib91f0802008-11-04 08:43:08 +01002105 if (!kctl)
2106 return -ENOMEM;
Takashi Iwai09f99702008-02-04 12:31:13 +01002107 kctl->id.index = idx;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002108 kctl->private_value = nid;
Takashi Iwaid13bd412008-07-30 15:01:45 +02002109 err = snd_hda_ctl_add(codec, kctl);
Takashi Iwai0ba21762007-04-16 11:29:14 +02002110 if (err < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002111 return err;
2112 }
Takashi Iwai0ba21762007-04-16 11:29:14 +02002113 codec->spdif_ctls =
Andrew Paprocki3982d172007-12-19 12:13:44 +01002114 snd_hda_codec_read(codec, nid, 0,
2115 AC_VERB_GET_DIGI_CONVERT_1, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002116 codec->spdif_status = convert_to_spdif_status(codec->spdif_ctls);
2117 return 0;
2118}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002119EXPORT_SYMBOL_HDA(snd_hda_create_spdif_out_ctls);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002120
2121/*
Takashi Iwai9a081602008-02-12 18:37:26 +01002122 * SPDIF sharing with analog output
2123 */
2124static int spdif_share_sw_get(struct snd_kcontrol *kcontrol,
2125 struct snd_ctl_elem_value *ucontrol)
2126{
2127 struct hda_multi_out *mout = snd_kcontrol_chip(kcontrol);
2128 ucontrol->value.integer.value[0] = mout->share_spdif;
2129 return 0;
2130}
2131
2132static int spdif_share_sw_put(struct snd_kcontrol *kcontrol,
2133 struct snd_ctl_elem_value *ucontrol)
2134{
2135 struct hda_multi_out *mout = snd_kcontrol_chip(kcontrol);
2136 mout->share_spdif = !!ucontrol->value.integer.value[0];
2137 return 0;
2138}
2139
2140static struct snd_kcontrol_new spdif_share_sw = {
2141 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2142 .name = "IEC958 Default PCM Playback Switch",
2143 .info = snd_ctl_boolean_mono_info,
2144 .get = spdif_share_sw_get,
2145 .put = spdif_share_sw_put,
2146};
2147
2148int snd_hda_create_spdif_share_sw(struct hda_codec *codec,
2149 struct hda_multi_out *mout)
2150{
2151 if (!mout->dig_out_nid)
2152 return 0;
2153 /* ATTENTION: here mout is passed as private_data, instead of codec */
Takashi Iwaid13bd412008-07-30 15:01:45 +02002154 return snd_hda_ctl_add(codec,
Takashi Iwai9a081602008-02-12 18:37:26 +01002155 snd_ctl_new1(&spdif_share_sw, mout));
2156}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002157EXPORT_SYMBOL_HDA(snd_hda_create_spdif_share_sw);
Takashi Iwai9a081602008-02-12 18:37:26 +01002158
2159/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002160 * SPDIF input
2161 */
2162
2163#define snd_hda_spdif_in_switch_info snd_hda_spdif_out_switch_info
2164
Takashi Iwai0ba21762007-04-16 11:29:14 +02002165static int snd_hda_spdif_in_switch_get(struct snd_kcontrol *kcontrol,
2166 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002167{
2168 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2169
2170 ucontrol->value.integer.value[0] = codec->spdif_in_enable;
2171 return 0;
2172}
2173
Takashi Iwai0ba21762007-04-16 11:29:14 +02002174static int snd_hda_spdif_in_switch_put(struct snd_kcontrol *kcontrol,
2175 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002176{
2177 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2178 hda_nid_t nid = kcontrol->private_value;
2179 unsigned int val = !!ucontrol->value.integer.value[0];
2180 int change;
2181
Ingo Molnar62932df2006-01-16 16:34:20 +01002182 mutex_lock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002183 change = codec->spdif_in_enable != val;
Takashi Iwai82beb8f2007-08-10 17:09:26 +02002184 if (change) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002185 codec->spdif_in_enable = val;
Takashi Iwai82beb8f2007-08-10 17:09:26 +02002186 snd_hda_codec_write_cache(codec, nid, 0,
2187 AC_VERB_SET_DIGI_CONVERT_1, val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002188 }
Ingo Molnar62932df2006-01-16 16:34:20 +01002189 mutex_unlock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002190 return change;
2191}
2192
Takashi Iwai0ba21762007-04-16 11:29:14 +02002193static int snd_hda_spdif_in_status_get(struct snd_kcontrol *kcontrol,
2194 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002195{
2196 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2197 hda_nid_t nid = kcontrol->private_value;
2198 unsigned short val;
2199 unsigned int sbits;
2200
Andrew Paprocki3982d172007-12-19 12:13:44 +01002201 val = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_DIGI_CONVERT_1, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002202 sbits = convert_to_spdif_status(val);
2203 ucontrol->value.iec958.status[0] = sbits;
2204 ucontrol->value.iec958.status[1] = sbits >> 8;
2205 ucontrol->value.iec958.status[2] = sbits >> 16;
2206 ucontrol->value.iec958.status[3] = sbits >> 24;
2207 return 0;
2208}
2209
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01002210static struct snd_kcontrol_new dig_in_ctls[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002211 {
2212 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2213 .name = SNDRV_CTL_NAME_IEC958("",CAPTURE,SWITCH),
2214 .info = snd_hda_spdif_in_switch_info,
2215 .get = snd_hda_spdif_in_switch_get,
2216 .put = snd_hda_spdif_in_switch_put,
2217 },
2218 {
2219 .access = SNDRV_CTL_ELEM_ACCESS_READ,
2220 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2221 .name = SNDRV_CTL_NAME_IEC958("",CAPTURE,DEFAULT),
2222 .info = snd_hda_spdif_mask_info,
2223 .get = snd_hda_spdif_in_status_get,
2224 },
2225 { } /* end */
2226};
2227
2228/**
2229 * snd_hda_create_spdif_in_ctls - create Input SPDIF-related controls
2230 * @codec: the HDA codec
2231 * @nid: audio in widget NID
2232 *
2233 * Creates controls related with the SPDIF input.
2234 * Called from each patch supporting the SPDIF in.
2235 *
2236 * Returns 0 if successful, or a negative error code.
2237 */
Takashi Iwai12f288b2007-08-02 15:51:59 +02002238int snd_hda_create_spdif_in_ctls(struct hda_codec *codec, hda_nid_t nid)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002239{
2240 int err;
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01002241 struct snd_kcontrol *kctl;
2242 struct snd_kcontrol_new *dig_mix;
Takashi Iwai09f99702008-02-04 12:31:13 +01002243 int idx;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002244
Takashi Iwai09f99702008-02-04 12:31:13 +01002245 for (idx = 0; idx < SPDIF_MAX_IDX; idx++) {
2246 if (!_snd_hda_find_mixer_ctl(codec, "IEC958 Capture Switch",
2247 idx))
2248 break;
2249 }
2250 if (idx >= SPDIF_MAX_IDX) {
2251 printk(KERN_ERR "hda_codec: too many IEC958 inputs\n");
2252 return -EBUSY;
2253 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002254 for (dig_mix = dig_in_ctls; dig_mix->name; dig_mix++) {
2255 kctl = snd_ctl_new1(dig_mix, codec);
Takashi Iwaic8dcdf82009-02-06 16:21:20 +01002256 if (!kctl)
2257 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002258 kctl->private_value = nid;
Takashi Iwaid13bd412008-07-30 15:01:45 +02002259 err = snd_hda_ctl_add(codec, kctl);
Takashi Iwai0ba21762007-04-16 11:29:14 +02002260 if (err < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002261 return err;
2262 }
Takashi Iwai0ba21762007-04-16 11:29:14 +02002263 codec->spdif_in_enable =
Andrew Paprocki3982d172007-12-19 12:13:44 +01002264 snd_hda_codec_read(codec, nid, 0,
2265 AC_VERB_GET_DIGI_CONVERT_1, 0) &
Takashi Iwai0ba21762007-04-16 11:29:14 +02002266 AC_DIG1_ENABLE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002267 return 0;
2268}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002269EXPORT_SYMBOL_HDA(snd_hda_create_spdif_in_ctls);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002270
Takashi Iwaicb53c622007-08-10 17:21:45 +02002271#ifdef SND_HDA_NEEDS_RESUME
Takashi Iwai82beb8f2007-08-10 17:09:26 +02002272/*
2273 * command cache
2274 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002275
Takashi Iwaib3ac5632007-08-10 17:03:40 +02002276/* build a 32bit cache key with the widget id and the command parameter */
2277#define build_cmd_cache_key(nid, verb) ((verb << 8) | nid)
2278#define get_cmd_cache_nid(key) ((key) & 0xff)
2279#define get_cmd_cache_cmd(key) (((key) >> 8) & 0xffff)
2280
2281/**
2282 * snd_hda_codec_write_cache - send a single command with caching
2283 * @codec: the HDA codec
2284 * @nid: NID to send the command
2285 * @direct: direct flag
2286 * @verb: the verb to send
2287 * @parm: the parameter for the verb
2288 *
2289 * Send a single command without waiting for response.
2290 *
2291 * Returns 0 if successful, or a negative error code.
2292 */
2293int snd_hda_codec_write_cache(struct hda_codec *codec, hda_nid_t nid,
2294 int direct, unsigned int verb, unsigned int parm)
2295{
Takashi Iwaiaa2936f2009-05-26 16:07:57 +02002296 int err = snd_hda_codec_write(codec, nid, direct, verb, parm);
2297 struct hda_cache_head *c;
2298 u32 key;
Takashi Iwai33fa35e2008-11-06 16:50:40 +01002299
Takashi Iwaiaa2936f2009-05-26 16:07:57 +02002300 if (err < 0)
2301 return err;
2302 /* parm may contain the verb stuff for get/set amp */
2303 verb = verb | (parm >> 8);
2304 parm &= 0xff;
2305 key = build_cmd_cache_key(nid, verb);
2306 mutex_lock(&codec->bus->cmd_mutex);
2307 c = get_alloc_hash(&codec->cmd_cache, key);
2308 if (c)
2309 c->val = parm;
2310 mutex_unlock(&codec->bus->cmd_mutex);
2311 return 0;
Takashi Iwaib3ac5632007-08-10 17:03:40 +02002312}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002313EXPORT_SYMBOL_HDA(snd_hda_codec_write_cache);
Takashi Iwaib3ac5632007-08-10 17:03:40 +02002314
2315/* resume the all commands from the cache */
2316void snd_hda_codec_resume_cache(struct hda_codec *codec)
2317{
Takashi Iwai603c4012008-07-30 15:01:44 +02002318 struct hda_cache_head *buffer = codec->cmd_cache.buf.list;
Takashi Iwaib3ac5632007-08-10 17:03:40 +02002319 int i;
2320
Takashi Iwai603c4012008-07-30 15:01:44 +02002321 for (i = 0; i < codec->cmd_cache.buf.used; i++, buffer++) {
Takashi Iwaib3ac5632007-08-10 17:03:40 +02002322 u32 key = buffer->key;
2323 if (!key)
2324 continue;
2325 snd_hda_codec_write(codec, get_cmd_cache_nid(key), 0,
2326 get_cmd_cache_cmd(key), buffer->val);
2327 }
2328}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002329EXPORT_SYMBOL_HDA(snd_hda_codec_resume_cache);
Takashi Iwaib3ac5632007-08-10 17:03:40 +02002330
2331/**
2332 * snd_hda_sequence_write_cache - sequence writes with caching
2333 * @codec: the HDA codec
2334 * @seq: VERB array to send
2335 *
2336 * Send the commands sequentially from the given array.
2337 * Thte commands are recorded on cache for power-save and resume.
2338 * The array must be terminated with NID=0.
2339 */
2340void snd_hda_sequence_write_cache(struct hda_codec *codec,
2341 const struct hda_verb *seq)
2342{
2343 for (; seq->nid; seq++)
2344 snd_hda_codec_write_cache(codec, seq->nid, 0, seq->verb,
2345 seq->param);
2346}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002347EXPORT_SYMBOL_HDA(snd_hda_sequence_write_cache);
Takashi Iwaicb53c622007-08-10 17:21:45 +02002348#endif /* SND_HDA_NEEDS_RESUME */
Takashi Iwaib3ac5632007-08-10 17:03:40 +02002349
Takashi Iwai54d17402005-11-21 16:33:22 +01002350/*
2351 * set power state of the codec
2352 */
2353static void hda_set_power_state(struct hda_codec *codec, hda_nid_t fg,
2354 unsigned int power_state)
2355{
Takashi Iwaicb53c622007-08-10 17:21:45 +02002356 hda_nid_t nid;
2357 int i;
Takashi Iwai54d17402005-11-21 16:33:22 +01002358
2359 snd_hda_codec_write(codec, fg, 0, AC_VERB_SET_POWER_STATE,
2360 power_state);
Marc Boucherd2595d82008-01-22 15:23:30 +01002361 msleep(10); /* partial workaround for "azx_get_response timeout" */
Takashi Iwai54d17402005-11-21 16:33:22 +01002362
Takashi Iwaicb53c622007-08-10 17:21:45 +02002363 nid = codec->start_nid;
2364 for (i = 0; i < codec->num_nodes; i++, nid++) {
Takashi Iwai7eba5c92007-11-14 14:53:42 +01002365 unsigned int wcaps = get_wcaps(codec, nid);
2366 if (wcaps & AC_WCAP_POWER) {
2367 unsigned int wid_type = (wcaps & AC_WCAP_TYPE) >>
2368 AC_WCAP_TYPE_SHIFT;
Takashi Iwaia3b48c82009-04-21 13:37:29 +02002369 if (power_state == AC_PWRST_D3 &&
2370 wid_type == AC_WID_PIN) {
Takashi Iwai7eba5c92007-11-14 14:53:42 +01002371 unsigned int pincap;
2372 /*
2373 * don't power down the widget if it controls
2374 * eapd and EAPD_BTLENABLE is set.
2375 */
Takashi Iwai14bafe32009-03-23 16:35:39 +01002376 pincap = snd_hda_query_pin_caps(codec, nid);
Takashi Iwai7eba5c92007-11-14 14:53:42 +01002377 if (pincap & AC_PINCAP_EAPD) {
2378 int eapd = snd_hda_codec_read(codec,
2379 nid, 0,
2380 AC_VERB_GET_EAPD_BTLENABLE, 0);
2381 eapd &= 0x02;
Takashi Iwaia3b48c82009-04-21 13:37:29 +02002382 if (eapd)
Takashi Iwai7eba5c92007-11-14 14:53:42 +01002383 continue;
2384 }
Takashi Iwai1194b5b2007-10-10 10:04:26 +02002385 }
Takashi Iwai54d17402005-11-21 16:33:22 +01002386 snd_hda_codec_write(codec, nid, 0,
2387 AC_VERB_SET_POWER_STATE,
2388 power_state);
Takashi Iwai1194b5b2007-10-10 10:04:26 +02002389 }
Takashi Iwai54d17402005-11-21 16:33:22 +01002390 }
2391
Takashi Iwaicb53c622007-08-10 17:21:45 +02002392 if (power_state == AC_PWRST_D0) {
2393 unsigned long end_time;
2394 int state;
Takashi Iwai54d17402005-11-21 16:33:22 +01002395 msleep(10);
Takashi Iwaicb53c622007-08-10 17:21:45 +02002396 /* wait until the codec reachs to D0 */
2397 end_time = jiffies + msecs_to_jiffies(500);
2398 do {
2399 state = snd_hda_codec_read(codec, fg, 0,
2400 AC_VERB_GET_POWER_STATE, 0);
2401 if (state == power_state)
2402 break;
2403 msleep(1);
2404 } while (time_after_eq(end_time, jiffies));
2405 }
Takashi Iwai54d17402005-11-21 16:33:22 +01002406}
2407
Takashi Iwai11aeff02008-07-30 15:01:46 +02002408#ifdef CONFIG_SND_HDA_HWDEP
2409/* execute additional init verbs */
2410static void hda_exec_init_verbs(struct hda_codec *codec)
2411{
2412 if (codec->init_verbs.list)
2413 snd_hda_sequence_write(codec, codec->init_verbs.list);
2414}
2415#else
2416static inline void hda_exec_init_verbs(struct hda_codec *codec) {}
2417#endif
2418
Takashi Iwaicb53c622007-08-10 17:21:45 +02002419#ifdef SND_HDA_NEEDS_RESUME
2420/*
2421 * call suspend and power-down; used both from PM and power-save
2422 */
2423static void hda_call_codec_suspend(struct hda_codec *codec)
2424{
2425 if (codec->patch_ops.suspend)
2426 codec->patch_ops.suspend(codec, PMSG_SUSPEND);
2427 hda_set_power_state(codec,
2428 codec->afg ? codec->afg : codec->mfg,
2429 AC_PWRST_D3);
2430#ifdef CONFIG_SND_HDA_POWER_SAVE
2431 cancel_delayed_work(&codec->power_work);
Takashi Iwai95e99fd2007-08-13 15:29:04 +02002432 codec->power_on = 0;
Takashi Iwaia221e282007-08-16 16:35:33 +02002433 codec->power_transition = 0;
Takashi Iwaicb53c622007-08-10 17:21:45 +02002434#endif
2435}
2436
2437/*
2438 * kick up codec; used both from PM and power-save
2439 */
2440static void hda_call_codec_resume(struct hda_codec *codec)
2441{
2442 hda_set_power_state(codec,
2443 codec->afg ? codec->afg : codec->mfg,
2444 AC_PWRST_D0);
Takashi Iwai3be14142009-02-20 14:11:16 +01002445 restore_pincfgs(codec); /* restore all current pin configs */
Takashi Iwai11aeff02008-07-30 15:01:46 +02002446 hda_exec_init_verbs(codec);
Takashi Iwaicb53c622007-08-10 17:21:45 +02002447 if (codec->patch_ops.resume)
2448 codec->patch_ops.resume(codec);
2449 else {
Takashi Iwai9d99f312007-08-14 15:15:52 +02002450 if (codec->patch_ops.init)
2451 codec->patch_ops.init(codec);
Takashi Iwaicb53c622007-08-10 17:21:45 +02002452 snd_hda_codec_resume_amp(codec);
2453 snd_hda_codec_resume_cache(codec);
2454 }
2455}
2456#endif /* SND_HDA_NEEDS_RESUME */
2457
Takashi Iwai54d17402005-11-21 16:33:22 +01002458
Linus Torvalds1da177e2005-04-16 15:20:36 -07002459/**
2460 * snd_hda_build_controls - build mixer controls
2461 * @bus: the BUS
2462 *
2463 * Creates mixer controls for each codec included in the bus.
2464 *
2465 * Returns 0 if successful, otherwise a negative error code.
2466 */
Takashi Iwai1289e9e2008-11-27 15:47:11 +01002467int /*__devinit*/ snd_hda_build_controls(struct hda_bus *bus)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002468{
Takashi Iwai0ba21762007-04-16 11:29:14 +02002469 struct hda_codec *codec;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002470
Takashi Iwai0ba21762007-04-16 11:29:14 +02002471 list_for_each_entry(codec, &bus->codec_list, list) {
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02002472 int err = snd_hda_codec_build_controls(codec);
Takashi Iwaif93d4612009-03-02 10:44:15 +01002473 if (err < 0) {
2474 printk(KERN_ERR "hda_codec: cannot build controls"
2475 "for #%d (error %d)\n", codec->addr, err);
2476 err = snd_hda_codec_reset(codec);
2477 if (err < 0) {
2478 printk(KERN_ERR
2479 "hda_codec: cannot revert codec\n");
2480 return err;
2481 }
2482 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002483 }
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02002484 return 0;
2485}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002486EXPORT_SYMBOL_HDA(snd_hda_build_controls);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002487
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02002488int snd_hda_codec_build_controls(struct hda_codec *codec)
2489{
2490 int err = 0;
Takashi Iwai11aeff02008-07-30 15:01:46 +02002491 hda_exec_init_verbs(codec);
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02002492 /* continue to initialize... */
2493 if (codec->patch_ops.init)
2494 err = codec->patch_ops.init(codec);
2495 if (!err && codec->patch_ops.build_controls)
2496 err = codec->patch_ops.build_controls(codec);
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02002497 if (err < 0)
2498 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002499 return 0;
2500}
2501
Linus Torvalds1da177e2005-04-16 15:20:36 -07002502/*
2503 * stream formats
2504 */
Takashi Iwaibefdf312005-08-22 13:57:55 +02002505struct hda_rate_tbl {
2506 unsigned int hz;
2507 unsigned int alsa_bits;
2508 unsigned int hda_fmt;
2509};
2510
2511static struct hda_rate_tbl rate_bits[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002512 /* rate in Hz, ALSA rate bitmask, HDA format value */
Nicolas Graziano9d8f53f2005-08-22 13:47:16 +02002513
2514 /* autodetected value used in snd_hda_query_supported_pcm */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002515 { 8000, SNDRV_PCM_RATE_8000, 0x0500 }, /* 1/6 x 48 */
2516 { 11025, SNDRV_PCM_RATE_11025, 0x4300 }, /* 1/4 x 44 */
2517 { 16000, SNDRV_PCM_RATE_16000, 0x0200 }, /* 1/3 x 48 */
2518 { 22050, SNDRV_PCM_RATE_22050, 0x4100 }, /* 1/2 x 44 */
2519 { 32000, SNDRV_PCM_RATE_32000, 0x0a00 }, /* 2/3 x 48 */
2520 { 44100, SNDRV_PCM_RATE_44100, 0x4000 }, /* 44 */
2521 { 48000, SNDRV_PCM_RATE_48000, 0x0000 }, /* 48 */
2522 { 88200, SNDRV_PCM_RATE_88200, 0x4800 }, /* 2 x 44 */
2523 { 96000, SNDRV_PCM_RATE_96000, 0x0800 }, /* 2 x 48 */
2524 { 176400, SNDRV_PCM_RATE_176400, 0x5800 },/* 4 x 44 */
2525 { 192000, SNDRV_PCM_RATE_192000, 0x1800 }, /* 4 x 48 */
Takashi Iwaia961f9f2007-04-12 13:08:09 +02002526#define AC_PAR_PCM_RATE_BITS 11
2527 /* up to bits 10, 384kHZ isn't supported properly */
2528
2529 /* not autodetected value */
2530 { 9600, SNDRV_PCM_RATE_KNOT, 0x0400 }, /* 1/5 x 48 */
Nicolas Graziano9d8f53f2005-08-22 13:47:16 +02002531
Takashi Iwaibefdf312005-08-22 13:57:55 +02002532 { 0 } /* terminator */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002533};
2534
2535/**
2536 * snd_hda_calc_stream_format - calculate format bitset
2537 * @rate: the sample rate
2538 * @channels: the number of channels
2539 * @format: the PCM format (SNDRV_PCM_FORMAT_XXX)
2540 * @maxbps: the max. bps
2541 *
2542 * Calculate the format bitset from the given rate, channels and th PCM format.
2543 *
2544 * Return zero if invalid.
2545 */
2546unsigned int snd_hda_calc_stream_format(unsigned int rate,
2547 unsigned int channels,
2548 unsigned int format,
2549 unsigned int maxbps)
2550{
2551 int i;
2552 unsigned int val = 0;
2553
Takashi Iwaibefdf312005-08-22 13:57:55 +02002554 for (i = 0; rate_bits[i].hz; i++)
2555 if (rate_bits[i].hz == rate) {
2556 val = rate_bits[i].hda_fmt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002557 break;
2558 }
Takashi Iwai0ba21762007-04-16 11:29:14 +02002559 if (!rate_bits[i].hz) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002560 snd_printdd("invalid rate %d\n", rate);
2561 return 0;
2562 }
2563
2564 if (channels == 0 || channels > 8) {
2565 snd_printdd("invalid channels %d\n", channels);
2566 return 0;
2567 }
2568 val |= channels - 1;
2569
2570 switch (snd_pcm_format_width(format)) {
2571 case 8: val |= 0x00; break;
2572 case 16: val |= 0x10; break;
2573 case 20:
2574 case 24:
2575 case 32:
2576 if (maxbps >= 32)
2577 val |= 0x40;
2578 else if (maxbps >= 24)
2579 val |= 0x30;
2580 else
2581 val |= 0x20;
2582 break;
2583 default:
Takashi Iwai0ba21762007-04-16 11:29:14 +02002584 snd_printdd("invalid format width %d\n",
2585 snd_pcm_format_width(format));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002586 return 0;
2587 }
2588
2589 return val;
2590}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002591EXPORT_SYMBOL_HDA(snd_hda_calc_stream_format);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002592
Takashi Iwai92c7c8a2009-03-24 07:32:14 +01002593static unsigned int get_pcm_param(struct hda_codec *codec, hda_nid_t nid)
2594{
2595 unsigned int val = 0;
2596 if (nid != codec->afg &&
2597 (get_wcaps(codec, nid) & AC_WCAP_FORMAT_OVRD))
2598 val = snd_hda_param_read(codec, nid, AC_PAR_PCM);
2599 if (!val || val == -1)
2600 val = snd_hda_param_read(codec, codec->afg, AC_PAR_PCM);
2601 if (!val || val == -1)
2602 return 0;
2603 return val;
2604}
2605
2606static unsigned int query_pcm_param(struct hda_codec *codec, hda_nid_t nid)
2607{
2608 return query_caps_hash(codec, nid, HDA_HASH_PARPCM_KEY(nid),
2609 get_pcm_param);
2610}
2611
2612static unsigned int get_stream_param(struct hda_codec *codec, hda_nid_t nid)
2613{
2614 unsigned int streams = snd_hda_param_read(codec, nid, AC_PAR_STREAM);
2615 if (!streams || streams == -1)
2616 streams = snd_hda_param_read(codec, codec->afg, AC_PAR_STREAM);
2617 if (!streams || streams == -1)
2618 return 0;
2619 return streams;
2620}
2621
2622static unsigned int query_stream_param(struct hda_codec *codec, hda_nid_t nid)
2623{
2624 return query_caps_hash(codec, nid, HDA_HASH_PARSTR_KEY(nid),
2625 get_stream_param);
2626}
2627
Linus Torvalds1da177e2005-04-16 15:20:36 -07002628/**
2629 * snd_hda_query_supported_pcm - query the supported PCM rates and formats
2630 * @codec: the HDA codec
2631 * @nid: NID to query
2632 * @ratesp: the pointer to store the detected rate bitflags
2633 * @formatsp: the pointer to store the detected formats
2634 * @bpsp: the pointer to store the detected format widths
2635 *
2636 * Queries the supported PCM rates and formats. The NULL @ratesp, @formatsp
2637 * or @bsps argument is ignored.
2638 *
2639 * Returns 0 if successful, otherwise a negative error code.
2640 */
Takashi Iwai986862bd2008-11-27 12:40:13 +01002641static int snd_hda_query_supported_pcm(struct hda_codec *codec, hda_nid_t nid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002642 u32 *ratesp, u64 *formatsp, unsigned int *bpsp)
2643{
Jaroslav Kyselaee504712009-03-17 14:30:31 +01002644 unsigned int i, val, wcaps;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002645
Jaroslav Kyselaee504712009-03-17 14:30:31 +01002646 wcaps = get_wcaps(codec, nid);
Takashi Iwai92c7c8a2009-03-24 07:32:14 +01002647 val = query_pcm_param(codec, nid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002648
2649 if (ratesp) {
2650 u32 rates = 0;
Takashi Iwaia961f9f2007-04-12 13:08:09 +02002651 for (i = 0; i < AC_PAR_PCM_RATE_BITS; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002652 if (val & (1 << i))
Takashi Iwaibefdf312005-08-22 13:57:55 +02002653 rates |= rate_bits[i].alsa_bits;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002654 }
Jaroslav Kyselaee504712009-03-17 14:30:31 +01002655 if (rates == 0) {
2656 snd_printk(KERN_ERR "hda_codec: rates == 0 "
2657 "(nid=0x%x, val=0x%x, ovrd=%i)\n",
2658 nid, val,
2659 (wcaps & AC_WCAP_FORMAT_OVRD) ? 1 : 0);
2660 return -EIO;
2661 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002662 *ratesp = rates;
2663 }
2664
2665 if (formatsp || bpsp) {
2666 u64 formats = 0;
Jaroslav Kyselaee504712009-03-17 14:30:31 +01002667 unsigned int streams, bps;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002668
Takashi Iwai92c7c8a2009-03-24 07:32:14 +01002669 streams = query_stream_param(codec, nid);
2670 if (!streams)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002671 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002672
2673 bps = 0;
2674 if (streams & AC_SUPFMT_PCM) {
2675 if (val & AC_SUPPCM_BITS_8) {
2676 formats |= SNDRV_PCM_FMTBIT_U8;
2677 bps = 8;
2678 }
2679 if (val & AC_SUPPCM_BITS_16) {
2680 formats |= SNDRV_PCM_FMTBIT_S16_LE;
2681 bps = 16;
2682 }
2683 if (wcaps & AC_WCAP_DIGITAL) {
2684 if (val & AC_SUPPCM_BITS_32)
2685 formats |= SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_LE;
2686 if (val & (AC_SUPPCM_BITS_20|AC_SUPPCM_BITS_24))
2687 formats |= SNDRV_PCM_FMTBIT_S32_LE;
2688 if (val & AC_SUPPCM_BITS_24)
2689 bps = 24;
2690 else if (val & AC_SUPPCM_BITS_20)
2691 bps = 20;
Takashi Iwai0ba21762007-04-16 11:29:14 +02002692 } else if (val & (AC_SUPPCM_BITS_20|AC_SUPPCM_BITS_24|
2693 AC_SUPPCM_BITS_32)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002694 formats |= SNDRV_PCM_FMTBIT_S32_LE;
2695 if (val & AC_SUPPCM_BITS_32)
2696 bps = 32;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002697 else if (val & AC_SUPPCM_BITS_24)
2698 bps = 24;
Nicolas Graziano33ef76512006-09-19 14:23:14 +02002699 else if (val & AC_SUPPCM_BITS_20)
2700 bps = 20;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002701 }
2702 }
Takashi Iwai0ba21762007-04-16 11:29:14 +02002703 else if (streams == AC_SUPFMT_FLOAT32) {
2704 /* should be exclusive */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002705 formats |= SNDRV_PCM_FMTBIT_FLOAT_LE;
2706 bps = 32;
Takashi Iwai0ba21762007-04-16 11:29:14 +02002707 } else if (streams == AC_SUPFMT_AC3) {
2708 /* should be exclusive */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002709 /* temporary hack: we have still no proper support
2710 * for the direct AC3 stream...
2711 */
2712 formats |= SNDRV_PCM_FMTBIT_U8;
2713 bps = 8;
2714 }
Jaroslav Kyselaee504712009-03-17 14:30:31 +01002715 if (formats == 0) {
2716 snd_printk(KERN_ERR "hda_codec: formats == 0 "
2717 "(nid=0x%x, val=0x%x, ovrd=%i, "
2718 "streams=0x%x)\n",
2719 nid, val,
2720 (wcaps & AC_WCAP_FORMAT_OVRD) ? 1 : 0,
2721 streams);
2722 return -EIO;
2723 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002724 if (formatsp)
2725 *formatsp = formats;
2726 if (bpsp)
2727 *bpsp = bps;
2728 }
2729
2730 return 0;
2731}
2732
2733/**
Takashi Iwai0ba21762007-04-16 11:29:14 +02002734 * snd_hda_is_supported_format - check whether the given node supports
2735 * the format val
Linus Torvalds1da177e2005-04-16 15:20:36 -07002736 *
2737 * Returns 1 if supported, 0 if not.
2738 */
2739int snd_hda_is_supported_format(struct hda_codec *codec, hda_nid_t nid,
2740 unsigned int format)
2741{
2742 int i;
2743 unsigned int val = 0, rate, stream;
2744
Takashi Iwai92c7c8a2009-03-24 07:32:14 +01002745 val = query_pcm_param(codec, nid);
2746 if (!val)
2747 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002748
2749 rate = format & 0xff00;
Takashi Iwaia961f9f2007-04-12 13:08:09 +02002750 for (i = 0; i < AC_PAR_PCM_RATE_BITS; i++)
Takashi Iwaibefdf312005-08-22 13:57:55 +02002751 if (rate_bits[i].hda_fmt == rate) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002752 if (val & (1 << i))
2753 break;
2754 return 0;
2755 }
Takashi Iwaia961f9f2007-04-12 13:08:09 +02002756 if (i >= AC_PAR_PCM_RATE_BITS)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002757 return 0;
2758
Takashi Iwai92c7c8a2009-03-24 07:32:14 +01002759 stream = query_stream_param(codec, nid);
2760 if (!stream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002761 return 0;
2762
2763 if (stream & AC_SUPFMT_PCM) {
2764 switch (format & 0xf0) {
2765 case 0x00:
Takashi Iwai0ba21762007-04-16 11:29:14 +02002766 if (!(val & AC_SUPPCM_BITS_8))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002767 return 0;
2768 break;
2769 case 0x10:
Takashi Iwai0ba21762007-04-16 11:29:14 +02002770 if (!(val & AC_SUPPCM_BITS_16))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002771 return 0;
2772 break;
2773 case 0x20:
Takashi Iwai0ba21762007-04-16 11:29:14 +02002774 if (!(val & AC_SUPPCM_BITS_20))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002775 return 0;
2776 break;
2777 case 0x30:
Takashi Iwai0ba21762007-04-16 11:29:14 +02002778 if (!(val & AC_SUPPCM_BITS_24))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002779 return 0;
2780 break;
2781 case 0x40:
Takashi Iwai0ba21762007-04-16 11:29:14 +02002782 if (!(val & AC_SUPPCM_BITS_32))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002783 return 0;
2784 break;
2785 default:
2786 return 0;
2787 }
2788 } else {
2789 /* FIXME: check for float32 and AC3? */
2790 }
2791
2792 return 1;
2793}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002794EXPORT_SYMBOL_HDA(snd_hda_is_supported_format);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002795
2796/*
2797 * PCM stuff
2798 */
2799static int hda_pcm_default_open_close(struct hda_pcm_stream *hinfo,
2800 struct hda_codec *codec,
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01002801 struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002802{
2803 return 0;
2804}
2805
2806static int hda_pcm_default_prepare(struct hda_pcm_stream *hinfo,
2807 struct hda_codec *codec,
2808 unsigned int stream_tag,
2809 unsigned int format,
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01002810 struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002811{
2812 snd_hda_codec_setup_stream(codec, hinfo->nid, stream_tag, 0, format);
2813 return 0;
2814}
2815
2816static int hda_pcm_default_cleanup(struct hda_pcm_stream *hinfo,
2817 struct hda_codec *codec,
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01002818 struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002819{
Takashi Iwai888afa12008-03-18 09:57:50 +01002820 snd_hda_codec_cleanup_stream(codec, hinfo->nid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002821 return 0;
2822}
2823
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02002824static int set_pcm_default_values(struct hda_codec *codec,
2825 struct hda_pcm_stream *info)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002826{
Jaroslav Kyselaee504712009-03-17 14:30:31 +01002827 int err;
2828
Takashi Iwai0ba21762007-04-16 11:29:14 +02002829 /* query support PCM information from the given NID */
2830 if (info->nid && (!info->rates || !info->formats)) {
Jaroslav Kyselaee504712009-03-17 14:30:31 +01002831 err = snd_hda_query_supported_pcm(codec, info->nid,
Takashi Iwai0ba21762007-04-16 11:29:14 +02002832 info->rates ? NULL : &info->rates,
2833 info->formats ? NULL : &info->formats,
2834 info->maxbps ? NULL : &info->maxbps);
Jaroslav Kyselaee504712009-03-17 14:30:31 +01002835 if (err < 0)
2836 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002837 }
2838 if (info->ops.open == NULL)
2839 info->ops.open = hda_pcm_default_open_close;
2840 if (info->ops.close == NULL)
2841 info->ops.close = hda_pcm_default_open_close;
2842 if (info->ops.prepare == NULL) {
Takashi Iwaida3cec32008-08-08 17:12:14 +02002843 if (snd_BUG_ON(!info->nid))
2844 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002845 info->ops.prepare = hda_pcm_default_prepare;
2846 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002847 if (info->ops.cleanup == NULL) {
Takashi Iwaida3cec32008-08-08 17:12:14 +02002848 if (snd_BUG_ON(!info->nid))
2849 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002850 info->ops.cleanup = hda_pcm_default_cleanup;
2851 }
2852 return 0;
2853}
2854
Takashi Iwai176d5332008-07-30 15:01:44 +02002855/*
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002856 * get the empty PCM device number to assign
2857 */
2858static int get_empty_pcm_device(struct hda_bus *bus, int type)
2859{
2860 static const char *dev_name[HDA_PCM_NTYPES] = {
2861 "Audio", "SPDIF", "HDMI", "Modem"
2862 };
2863 /* starting device index for each PCM type */
2864 static int dev_idx[HDA_PCM_NTYPES] = {
2865 [HDA_PCM_TYPE_AUDIO] = 0,
2866 [HDA_PCM_TYPE_SPDIF] = 1,
2867 [HDA_PCM_TYPE_HDMI] = 3,
2868 [HDA_PCM_TYPE_MODEM] = 6
2869 };
2870 /* normal audio device indices; not linear to keep compatibility */
2871 static int audio_idx[4] = { 0, 2, 4, 5 };
2872 int i, dev;
2873
2874 switch (type) {
2875 case HDA_PCM_TYPE_AUDIO:
2876 for (i = 0; i < ARRAY_SIZE(audio_idx); i++) {
2877 dev = audio_idx[i];
2878 if (!test_bit(dev, bus->pcm_dev_bits))
Takashi Iwai82ad39f2009-03-03 15:00:35 +01002879 goto ok;
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002880 }
Takashi Iwai82ad39f2009-03-03 15:00:35 +01002881 snd_printk(KERN_WARNING "Too many audio devices\n");
2882 return -EAGAIN;
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002883 case HDA_PCM_TYPE_SPDIF:
2884 case HDA_PCM_TYPE_HDMI:
2885 case HDA_PCM_TYPE_MODEM:
2886 dev = dev_idx[type];
2887 if (test_bit(dev, bus->pcm_dev_bits)) {
2888 snd_printk(KERN_WARNING "%s already defined\n",
2889 dev_name[type]);
2890 return -EAGAIN;
2891 }
2892 break;
2893 default:
2894 snd_printk(KERN_WARNING "Invalid PCM type %d\n", type);
2895 return -EINVAL;
2896 }
Takashi Iwai82ad39f2009-03-03 15:00:35 +01002897 ok:
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002898 set_bit(dev, bus->pcm_dev_bits);
2899 return dev;
2900}
2901
2902/*
Takashi Iwai176d5332008-07-30 15:01:44 +02002903 * attach a new PCM stream
2904 */
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002905static int snd_hda_attach_pcm(struct hda_codec *codec, struct hda_pcm *pcm)
Takashi Iwai176d5332008-07-30 15:01:44 +02002906{
Takashi Iwai33fa35e2008-11-06 16:50:40 +01002907 struct hda_bus *bus = codec->bus;
Takashi Iwai176d5332008-07-30 15:01:44 +02002908 struct hda_pcm_stream *info;
2909 int stream, err;
2910
Takashi Iwaib91f0802008-11-04 08:43:08 +01002911 if (snd_BUG_ON(!pcm->name))
Takashi Iwai176d5332008-07-30 15:01:44 +02002912 return -EINVAL;
2913 for (stream = 0; stream < 2; stream++) {
2914 info = &pcm->stream[stream];
2915 if (info->substreams) {
2916 err = set_pcm_default_values(codec, info);
2917 if (err < 0)
2918 return err;
2919 }
2920 }
Takashi Iwai33fa35e2008-11-06 16:50:40 +01002921 return bus->ops.attach_pcm(bus, codec, pcm);
Takashi Iwai176d5332008-07-30 15:01:44 +02002922}
2923
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002924/* assign all PCMs of the given codec */
2925int snd_hda_codec_build_pcms(struct hda_codec *codec)
2926{
2927 unsigned int pcm;
2928 int err;
2929
2930 if (!codec->num_pcms) {
2931 if (!codec->patch_ops.build_pcms)
2932 return 0;
2933 err = codec->patch_ops.build_pcms(codec);
Takashi Iwai6e655bf2009-03-02 10:46:03 +01002934 if (err < 0) {
2935 printk(KERN_ERR "hda_codec: cannot build PCMs"
2936 "for #%d (error %d)\n", codec->addr, err);
2937 err = snd_hda_codec_reset(codec);
2938 if (err < 0) {
2939 printk(KERN_ERR
2940 "hda_codec: cannot revert codec\n");
2941 return err;
2942 }
2943 }
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002944 }
2945 for (pcm = 0; pcm < codec->num_pcms; pcm++) {
2946 struct hda_pcm *cpcm = &codec->pcm_info[pcm];
2947 int dev;
2948
2949 if (!cpcm->stream[0].substreams && !cpcm->stream[1].substreams)
Takashi Iwai41b5b012009-01-20 18:21:23 +01002950 continue; /* no substreams assigned */
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002951
2952 if (!cpcm->pcm) {
2953 dev = get_empty_pcm_device(codec->bus, cpcm->pcm_type);
2954 if (dev < 0)
Takashi Iwai6e655bf2009-03-02 10:46:03 +01002955 continue; /* no fatal error */
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002956 cpcm->device = dev;
2957 err = snd_hda_attach_pcm(codec, cpcm);
Takashi Iwai6e655bf2009-03-02 10:46:03 +01002958 if (err < 0) {
2959 printk(KERN_ERR "hda_codec: cannot attach "
2960 "PCM stream %d for codec #%d\n",
2961 dev, codec->addr);
2962 continue; /* no fatal error */
2963 }
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002964 }
2965 }
2966 return 0;
2967}
2968
Linus Torvalds1da177e2005-04-16 15:20:36 -07002969/**
2970 * snd_hda_build_pcms - build PCM information
2971 * @bus: the BUS
2972 *
2973 * Create PCM information for each codec included in the bus.
2974 *
2975 * The build_pcms codec patch is requested to set up codec->num_pcms and
2976 * codec->pcm_info properly. The array is referred by the top-level driver
2977 * to create its PCM instances.
2978 * The allocated codec->pcm_info should be released in codec->patch_ops.free
2979 * callback.
2980 *
2981 * At least, substreams, channels_min and channels_max must be filled for
2982 * each stream. substreams = 0 indicates that the stream doesn't exist.
2983 * When rates and/or formats are zero, the supported values are queried
2984 * from the given nid. The nid is used also by the default ops.prepare
2985 * and ops.cleanup callbacks.
2986 *
2987 * The driver needs to call ops.open in its open callback. Similarly,
2988 * ops.close is supposed to be called in the close callback.
2989 * ops.prepare should be called in the prepare or hw_params callback
2990 * with the proper parameters for set up.
2991 * ops.cleanup should be called in hw_free for clean up of streams.
2992 *
2993 * This function returns 0 if successfull, or a negative error code.
2994 */
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002995int __devinit snd_hda_build_pcms(struct hda_bus *bus)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002996{
Takashi Iwai0ba21762007-04-16 11:29:14 +02002997 struct hda_codec *codec;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002998
Takashi Iwai0ba21762007-04-16 11:29:14 +02002999 list_for_each_entry(codec, &bus->codec_list, list) {
Takashi Iwai529bd6c2008-11-27 14:17:01 +01003000 int err = snd_hda_codec_build_pcms(codec);
3001 if (err < 0)
3002 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003003 }
3004 return 0;
3005}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003006EXPORT_SYMBOL_HDA(snd_hda_build_pcms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003007
Linus Torvalds1da177e2005-04-16 15:20:36 -07003008/**
3009 * snd_hda_check_board_config - compare the current codec with the config table
3010 * @codec: the HDA codec
Takashi Iwaif5fcc132006-11-24 17:07:44 +01003011 * @num_configs: number of config enums
3012 * @models: array of model name strings
Linus Torvalds1da177e2005-04-16 15:20:36 -07003013 * @tbl: configuration table, terminated by null entries
3014 *
3015 * Compares the modelname or PCI subsystem id of the current codec with the
3016 * given configuration table. If a matching entry is found, returns its
3017 * config value (supposed to be 0 or positive).
3018 *
3019 * If no entries are matching, the function returns a negative value.
3020 */
Takashi Iwai12f288b2007-08-02 15:51:59 +02003021int snd_hda_check_board_config(struct hda_codec *codec,
3022 int num_configs, const char **models,
3023 const struct snd_pci_quirk *tbl)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003024{
Takashi Iwaif44ac832008-07-30 15:01:45 +02003025 if (codec->modelname && models) {
Takashi Iwaif5fcc132006-11-24 17:07:44 +01003026 int i;
3027 for (i = 0; i < num_configs; i++) {
3028 if (models[i] &&
Takashi Iwaif44ac832008-07-30 15:01:45 +02003029 !strcmp(codec->modelname, models[i])) {
Takashi Iwaif5fcc132006-11-24 17:07:44 +01003030 snd_printd(KERN_INFO "hda_codec: model '%s' is "
3031 "selected\n", models[i]);
3032 return i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003033 }
3034 }
3035 }
3036
Takashi Iwaif5fcc132006-11-24 17:07:44 +01003037 if (!codec->bus->pci || !tbl)
3038 return -1;
3039
3040 tbl = snd_pci_quirk_lookup(codec->bus->pci, tbl);
3041 if (!tbl)
3042 return -1;
3043 if (tbl->value >= 0 && tbl->value < num_configs) {
Takashi Iwai62cf8722008-05-20 12:15:15 +02003044#ifdef CONFIG_SND_DEBUG_VERBOSE
Takashi Iwaif5fcc132006-11-24 17:07:44 +01003045 char tmp[10];
3046 const char *model = NULL;
3047 if (models)
3048 model = models[tbl->value];
3049 if (!model) {
3050 sprintf(tmp, "#%d", tbl->value);
3051 model = tmp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003052 }
Takashi Iwaif5fcc132006-11-24 17:07:44 +01003053 snd_printdd(KERN_INFO "hda_codec: model '%s' is selected "
3054 "for config %x:%x (%s)\n",
3055 model, tbl->subvendor, tbl->subdevice,
3056 (tbl->name ? tbl->name : "Unknown device"));
3057#endif
3058 return tbl->value;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003059 }
3060 return -1;
3061}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003062EXPORT_SYMBOL_HDA(snd_hda_check_board_config);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003063
3064/**
Mauro Carvalho Chehab2eda3442008-08-11 10:18:39 +02003065 * snd_hda_check_board_codec_sid_config - compare the current codec
3066 subsystem ID with the
3067 config table
3068
3069 This is important for Gateway notebooks with SB450 HDA Audio
3070 where the vendor ID of the PCI device is:
3071 ATI Technologies Inc SB450 HDA Audio [1002:437b]
3072 and the vendor/subvendor are found only at the codec.
3073
3074 * @codec: the HDA codec
3075 * @num_configs: number of config enums
3076 * @models: array of model name strings
3077 * @tbl: configuration table, terminated by null entries
3078 *
3079 * Compares the modelname or PCI subsystem id of the current codec with the
3080 * given configuration table. If a matching entry is found, returns its
3081 * config value (supposed to be 0 or positive).
3082 *
3083 * If no entries are matching, the function returns a negative value.
3084 */
3085int snd_hda_check_board_codec_sid_config(struct hda_codec *codec,
3086 int num_configs, const char **models,
3087 const struct snd_pci_quirk *tbl)
3088{
3089 const struct snd_pci_quirk *q;
3090
3091 /* Search for codec ID */
3092 for (q = tbl; q->subvendor; q++) {
3093 unsigned long vendorid = (q->subdevice) | (q->subvendor << 16);
3094
3095 if (vendorid == codec->subsystem_id)
3096 break;
3097 }
3098
3099 if (!q->subvendor)
3100 return -1;
3101
3102 tbl = q;
3103
3104 if (tbl->value >= 0 && tbl->value < num_configs) {
3105#ifdef CONFIG_SND_DEBUG_DETECT
3106 char tmp[10];
3107 const char *model = NULL;
3108 if (models)
3109 model = models[tbl->value];
3110 if (!model) {
3111 sprintf(tmp, "#%d", tbl->value);
3112 model = tmp;
3113 }
3114 snd_printdd(KERN_INFO "hda_codec: model '%s' is selected "
3115 "for config %x:%x (%s)\n",
3116 model, tbl->subvendor, tbl->subdevice,
3117 (tbl->name ? tbl->name : "Unknown device"));
3118#endif
3119 return tbl->value;
3120 }
3121 return -1;
3122}
3123EXPORT_SYMBOL_HDA(snd_hda_check_board_codec_sid_config);
3124
3125/**
Linus Torvalds1da177e2005-04-16 15:20:36 -07003126 * snd_hda_add_new_ctls - create controls from the array
3127 * @codec: the HDA codec
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01003128 * @knew: the array of struct snd_kcontrol_new
Linus Torvalds1da177e2005-04-16 15:20:36 -07003129 *
3130 * This helper function creates and add new controls in the given array.
3131 * The array must be terminated with an empty entry as terminator.
3132 *
3133 * Returns 0 if successful, or a negative error code.
3134 */
Takashi Iwai12f288b2007-08-02 15:51:59 +02003135int snd_hda_add_new_ctls(struct hda_codec *codec, struct snd_kcontrol_new *knew)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003136{
Takashi Iwaicb53c622007-08-10 17:21:45 +02003137 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003138
3139 for (; knew->name; knew++) {
Takashi Iwai54d17402005-11-21 16:33:22 +01003140 struct snd_kcontrol *kctl;
3141 kctl = snd_ctl_new1(knew, codec);
Takashi Iwai0ba21762007-04-16 11:29:14 +02003142 if (!kctl)
Takashi Iwai54d17402005-11-21 16:33:22 +01003143 return -ENOMEM;
Takashi Iwaid13bd412008-07-30 15:01:45 +02003144 err = snd_hda_ctl_add(codec, kctl);
Takashi Iwai54d17402005-11-21 16:33:22 +01003145 if (err < 0) {
Takashi Iwai0ba21762007-04-16 11:29:14 +02003146 if (!codec->addr)
Takashi Iwai54d17402005-11-21 16:33:22 +01003147 return err;
3148 kctl = snd_ctl_new1(knew, codec);
Takashi Iwai0ba21762007-04-16 11:29:14 +02003149 if (!kctl)
Takashi Iwai54d17402005-11-21 16:33:22 +01003150 return -ENOMEM;
3151 kctl->id.device = codec->addr;
Takashi Iwaid13bd412008-07-30 15:01:45 +02003152 err = snd_hda_ctl_add(codec, kctl);
Takashi Iwai0ba21762007-04-16 11:29:14 +02003153 if (err < 0)
Takashi Iwai54d17402005-11-21 16:33:22 +01003154 return err;
3155 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003156 }
3157 return 0;
3158}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003159EXPORT_SYMBOL_HDA(snd_hda_add_new_ctls);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003160
Takashi Iwaicb53c622007-08-10 17:21:45 +02003161#ifdef CONFIG_SND_HDA_POWER_SAVE
3162static void hda_set_power_state(struct hda_codec *codec, hda_nid_t fg,
3163 unsigned int power_state);
3164
3165static void hda_power_work(struct work_struct *work)
3166{
3167 struct hda_codec *codec =
3168 container_of(work, struct hda_codec, power_work.work);
Takashi Iwai33fa35e2008-11-06 16:50:40 +01003169 struct hda_bus *bus = codec->bus;
Takashi Iwaicb53c622007-08-10 17:21:45 +02003170
Maxim Levitsky2e492462007-09-03 15:26:57 +02003171 if (!codec->power_on || codec->power_count) {
3172 codec->power_transition = 0;
Takashi Iwaicb53c622007-08-10 17:21:45 +02003173 return;
Maxim Levitsky2e492462007-09-03 15:26:57 +02003174 }
Takashi Iwaicb53c622007-08-10 17:21:45 +02003175
3176 hda_call_codec_suspend(codec);
Takashi Iwai33fa35e2008-11-06 16:50:40 +01003177 if (bus->ops.pm_notify)
3178 bus->ops.pm_notify(bus);
Takashi Iwaicb53c622007-08-10 17:21:45 +02003179}
3180
3181static void hda_keep_power_on(struct hda_codec *codec)
3182{
3183 codec->power_count++;
3184 codec->power_on = 1;
3185}
3186
3187void snd_hda_power_up(struct hda_codec *codec)
3188{
Takashi Iwai33fa35e2008-11-06 16:50:40 +01003189 struct hda_bus *bus = codec->bus;
3190
Takashi Iwaicb53c622007-08-10 17:21:45 +02003191 codec->power_count++;
Takashi Iwaia221e282007-08-16 16:35:33 +02003192 if (codec->power_on || codec->power_transition)
Takashi Iwaicb53c622007-08-10 17:21:45 +02003193 return;
3194
3195 codec->power_on = 1;
Takashi Iwai33fa35e2008-11-06 16:50:40 +01003196 if (bus->ops.pm_notify)
3197 bus->ops.pm_notify(bus);
Takashi Iwaicb53c622007-08-10 17:21:45 +02003198 hda_call_codec_resume(codec);
3199 cancel_delayed_work(&codec->power_work);
Takashi Iwaia221e282007-08-16 16:35:33 +02003200 codec->power_transition = 0;
Takashi Iwaicb53c622007-08-10 17:21:45 +02003201}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003202EXPORT_SYMBOL_HDA(snd_hda_power_up);
Takashi Iwai1289e9e2008-11-27 15:47:11 +01003203
3204#define power_save(codec) \
3205 ((codec)->bus->power_save ? *(codec)->bus->power_save : 0)
Takashi Iwaicb53c622007-08-10 17:21:45 +02003206
Takashi Iwaifee2fba2008-11-27 12:43:28 +01003207#define power_save(codec) \
3208 ((codec)->bus->power_save ? *(codec)->bus->power_save : 0)
3209
Takashi Iwaicb53c622007-08-10 17:21:45 +02003210void snd_hda_power_down(struct hda_codec *codec)
3211{
3212 --codec->power_count;
Takashi Iwaia221e282007-08-16 16:35:33 +02003213 if (!codec->power_on || codec->power_count || codec->power_transition)
Takashi Iwaicb53c622007-08-10 17:21:45 +02003214 return;
Takashi Iwaifee2fba2008-11-27 12:43:28 +01003215 if (power_save(codec)) {
Takashi Iwaia221e282007-08-16 16:35:33 +02003216 codec->power_transition = 1; /* avoid reentrance */
Takashi Iwaic107b412009-01-13 17:46:37 +01003217 queue_delayed_work(codec->bus->workq, &codec->power_work,
Takashi Iwaifee2fba2008-11-27 12:43:28 +01003218 msecs_to_jiffies(power_save(codec) * 1000));
Takashi Iwaia221e282007-08-16 16:35:33 +02003219 }
Takashi Iwaicb53c622007-08-10 17:21:45 +02003220}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003221EXPORT_SYMBOL_HDA(snd_hda_power_down);
Takashi Iwaicb53c622007-08-10 17:21:45 +02003222
3223int snd_hda_check_amp_list_power(struct hda_codec *codec,
3224 struct hda_loopback_check *check,
3225 hda_nid_t nid)
3226{
3227 struct hda_amp_list *p;
3228 int ch, v;
3229
3230 if (!check->amplist)
3231 return 0;
3232 for (p = check->amplist; p->nid; p++) {
3233 if (p->nid == nid)
3234 break;
3235 }
3236 if (!p->nid)
3237 return 0; /* nothing changed */
3238
3239 for (p = check->amplist; p->nid; p++) {
3240 for (ch = 0; ch < 2; ch++) {
3241 v = snd_hda_codec_amp_read(codec, p->nid, ch, p->dir,
3242 p->idx);
3243 if (!(v & HDA_AMP_MUTE) && v > 0) {
3244 if (!check->power_on) {
3245 check->power_on = 1;
3246 snd_hda_power_up(codec);
3247 }
3248 return 1;
3249 }
3250 }
3251 }
3252 if (check->power_on) {
3253 check->power_on = 0;
3254 snd_hda_power_down(codec);
3255 }
3256 return 0;
3257}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003258EXPORT_SYMBOL_HDA(snd_hda_check_amp_list_power);
Takashi Iwaicb53c622007-08-10 17:21:45 +02003259#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07003260
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01003261/*
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01003262 * Channel mode helper
3263 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003264int snd_hda_ch_mode_info(struct hda_codec *codec,
3265 struct snd_ctl_elem_info *uinfo,
3266 const struct hda_channel_mode *chmode,
3267 int num_chmodes)
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01003268{
3269 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
3270 uinfo->count = 1;
3271 uinfo->value.enumerated.items = num_chmodes;
3272 if (uinfo->value.enumerated.item >= num_chmodes)
3273 uinfo->value.enumerated.item = num_chmodes - 1;
3274 sprintf(uinfo->value.enumerated.name, "%dch",
3275 chmode[uinfo->value.enumerated.item].channels);
3276 return 0;
3277}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003278EXPORT_SYMBOL_HDA(snd_hda_ch_mode_info);
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01003279
Takashi Iwai0ba21762007-04-16 11:29:14 +02003280int snd_hda_ch_mode_get(struct hda_codec *codec,
3281 struct snd_ctl_elem_value *ucontrol,
3282 const struct hda_channel_mode *chmode,
3283 int num_chmodes,
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01003284 int max_channels)
3285{
3286 int i;
3287
3288 for (i = 0; i < num_chmodes; i++) {
3289 if (max_channels == chmode[i].channels) {
3290 ucontrol->value.enumerated.item[0] = i;
3291 break;
3292 }
3293 }
3294 return 0;
3295}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003296EXPORT_SYMBOL_HDA(snd_hda_ch_mode_get);
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01003297
Takashi Iwai0ba21762007-04-16 11:29:14 +02003298int snd_hda_ch_mode_put(struct hda_codec *codec,
3299 struct snd_ctl_elem_value *ucontrol,
3300 const struct hda_channel_mode *chmode,
3301 int num_chmodes,
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01003302 int *max_channelsp)
3303{
3304 unsigned int mode;
3305
3306 mode = ucontrol->value.enumerated.item[0];
Takashi Iwai68ea7b22007-11-15 15:54:38 +01003307 if (mode >= num_chmodes)
3308 return -EINVAL;
Takashi Iwai82beb8f2007-08-10 17:09:26 +02003309 if (*max_channelsp == chmode[mode].channels)
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01003310 return 0;
3311 /* change the current channel setting */
3312 *max_channelsp = chmode[mode].channels;
3313 if (chmode[mode].sequence)
Takashi Iwai82beb8f2007-08-10 17:09:26 +02003314 snd_hda_sequence_write_cache(codec, chmode[mode].sequence);
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01003315 return 1;
3316}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003317EXPORT_SYMBOL_HDA(snd_hda_ch_mode_put);
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01003318
Linus Torvalds1da177e2005-04-16 15:20:36 -07003319/*
3320 * input MUX helper
3321 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003322int snd_hda_input_mux_info(const struct hda_input_mux *imux,
3323 struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003324{
3325 unsigned int index;
3326
3327 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
3328 uinfo->count = 1;
3329 uinfo->value.enumerated.items = imux->num_items;
Takashi Iwai5513b0c2007-10-09 11:58:41 +02003330 if (!imux->num_items)
3331 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003332 index = uinfo->value.enumerated.item;
3333 if (index >= imux->num_items)
3334 index = imux->num_items - 1;
3335 strcpy(uinfo->value.enumerated.name, imux->items[index].label);
3336 return 0;
3337}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003338EXPORT_SYMBOL_HDA(snd_hda_input_mux_info);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003339
Takashi Iwai0ba21762007-04-16 11:29:14 +02003340int snd_hda_input_mux_put(struct hda_codec *codec,
3341 const struct hda_input_mux *imux,
3342 struct snd_ctl_elem_value *ucontrol,
3343 hda_nid_t nid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003344 unsigned int *cur_val)
3345{
3346 unsigned int idx;
3347
Takashi Iwai5513b0c2007-10-09 11:58:41 +02003348 if (!imux->num_items)
3349 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003350 idx = ucontrol->value.enumerated.item[0];
3351 if (idx >= imux->num_items)
3352 idx = imux->num_items - 1;
Takashi Iwai82beb8f2007-08-10 17:09:26 +02003353 if (*cur_val == idx)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003354 return 0;
Takashi Iwai82beb8f2007-08-10 17:09:26 +02003355 snd_hda_codec_write_cache(codec, nid, 0, AC_VERB_SET_CONNECT_SEL,
3356 imux->items[idx].index);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003357 *cur_val = idx;
3358 return 1;
3359}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003360EXPORT_SYMBOL_HDA(snd_hda_input_mux_put);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003361
3362
3363/*
3364 * Multi-channel / digital-out PCM helper functions
3365 */
3366
Takashi Iwai6b97eb42007-04-05 14:51:48 +02003367/* setup SPDIF output stream */
3368static void setup_dig_out_stream(struct hda_codec *codec, hda_nid_t nid,
3369 unsigned int stream_tag, unsigned int format)
3370{
3371 /* turn off SPDIF once; otherwise the IEC958 bits won't be updated */
Takashi Iwai2f728532008-09-25 16:32:41 +02003372 if (codec->spdif_status_reset && (codec->spdif_ctls & AC_DIG1_ENABLE))
3373 set_dig_out_convert(codec, nid,
3374 codec->spdif_ctls & ~AC_DIG1_ENABLE & 0xff,
3375 -1);
Takashi Iwai6b97eb42007-04-05 14:51:48 +02003376 snd_hda_codec_setup_stream(codec, nid, stream_tag, 0, format);
Takashi Iwai2f728532008-09-25 16:32:41 +02003377 if (codec->slave_dig_outs) {
3378 hda_nid_t *d;
3379 for (d = codec->slave_dig_outs; *d; d++)
3380 snd_hda_codec_setup_stream(codec, *d, stream_tag, 0,
3381 format);
Matthew Ranostayde51ca12008-09-07 14:31:40 -04003382 }
Takashi Iwai2f728532008-09-25 16:32:41 +02003383 /* turn on again (if needed) */
3384 if (codec->spdif_status_reset && (codec->spdif_ctls & AC_DIG1_ENABLE))
3385 set_dig_out_convert(codec, nid,
3386 codec->spdif_ctls & 0xff, -1);
3387}
Matthew Ranostayde51ca12008-09-07 14:31:40 -04003388
Takashi Iwai2f728532008-09-25 16:32:41 +02003389static void cleanup_dig_out_stream(struct hda_codec *codec, hda_nid_t nid)
3390{
3391 snd_hda_codec_cleanup_stream(codec, nid);
3392 if (codec->slave_dig_outs) {
3393 hda_nid_t *d;
3394 for (d = codec->slave_dig_outs; *d; d++)
3395 snd_hda_codec_cleanup_stream(codec, *d);
3396 }
Takashi Iwai6b97eb42007-04-05 14:51:48 +02003397}
3398
Linus Torvalds1da177e2005-04-16 15:20:36 -07003399/*
3400 * open the digital out in the exclusive mode
3401 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003402int snd_hda_multi_out_dig_open(struct hda_codec *codec,
3403 struct hda_multi_out *mout)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003404{
Ingo Molnar62932df2006-01-16 16:34:20 +01003405 mutex_lock(&codec->spdif_mutex);
Takashi Iwai5930ca42007-04-16 11:23:56 +02003406 if (mout->dig_out_used == HDA_DIG_ANALOG_DUP)
3407 /* already opened as analog dup; reset it once */
Takashi Iwai2f728532008-09-25 16:32:41 +02003408 cleanup_dig_out_stream(codec, mout->dig_out_nid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003409 mout->dig_out_used = HDA_DIG_EXCLUSIVE;
Ingo Molnar62932df2006-01-16 16:34:20 +01003410 mutex_unlock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003411 return 0;
3412}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003413EXPORT_SYMBOL_HDA(snd_hda_multi_out_dig_open);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003414
Takashi Iwai6b97eb42007-04-05 14:51:48 +02003415int snd_hda_multi_out_dig_prepare(struct hda_codec *codec,
3416 struct hda_multi_out *mout,
3417 unsigned int stream_tag,
3418 unsigned int format,
3419 struct snd_pcm_substream *substream)
3420{
3421 mutex_lock(&codec->spdif_mutex);
3422 setup_dig_out_stream(codec, mout->dig_out_nid, stream_tag, format);
3423 mutex_unlock(&codec->spdif_mutex);
3424 return 0;
3425}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003426EXPORT_SYMBOL_HDA(snd_hda_multi_out_dig_prepare);
Takashi Iwai6b97eb42007-04-05 14:51:48 +02003427
Takashi Iwai9411e212009-02-13 11:32:28 +01003428int snd_hda_multi_out_dig_cleanup(struct hda_codec *codec,
3429 struct hda_multi_out *mout)
3430{
3431 mutex_lock(&codec->spdif_mutex);
3432 cleanup_dig_out_stream(codec, mout->dig_out_nid);
3433 mutex_unlock(&codec->spdif_mutex);
3434 return 0;
3435}
3436EXPORT_SYMBOL_HDA(snd_hda_multi_out_dig_cleanup);
3437
Linus Torvalds1da177e2005-04-16 15:20:36 -07003438/*
3439 * release the digital out
3440 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003441int snd_hda_multi_out_dig_close(struct hda_codec *codec,
3442 struct hda_multi_out *mout)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003443{
Ingo Molnar62932df2006-01-16 16:34:20 +01003444 mutex_lock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003445 mout->dig_out_used = 0;
Ingo Molnar62932df2006-01-16 16:34:20 +01003446 mutex_unlock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003447 return 0;
3448}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003449EXPORT_SYMBOL_HDA(snd_hda_multi_out_dig_close);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003450
3451/*
3452 * set up more restrictions for analog out
3453 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003454int snd_hda_multi_out_analog_open(struct hda_codec *codec,
3455 struct hda_multi_out *mout,
Takashi Iwai9a081602008-02-12 18:37:26 +01003456 struct snd_pcm_substream *substream,
3457 struct hda_pcm_stream *hinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003458{
Takashi Iwai9a081602008-02-12 18:37:26 +01003459 struct snd_pcm_runtime *runtime = substream->runtime;
3460 runtime->hw.channels_max = mout->max_channels;
3461 if (mout->dig_out_nid) {
3462 if (!mout->analog_rates) {
3463 mout->analog_rates = hinfo->rates;
3464 mout->analog_formats = hinfo->formats;
3465 mout->analog_maxbps = hinfo->maxbps;
3466 } else {
3467 runtime->hw.rates = mout->analog_rates;
3468 runtime->hw.formats = mout->analog_formats;
3469 hinfo->maxbps = mout->analog_maxbps;
3470 }
3471 if (!mout->spdif_rates) {
3472 snd_hda_query_supported_pcm(codec, mout->dig_out_nid,
3473 &mout->spdif_rates,
3474 &mout->spdif_formats,
3475 &mout->spdif_maxbps);
3476 }
3477 mutex_lock(&codec->spdif_mutex);
3478 if (mout->share_spdif) {
Takashi Iwai022b4662009-07-03 23:03:30 +02003479 if ((runtime->hw.rates & mout->spdif_rates) &&
3480 (runtime->hw.formats & mout->spdif_formats)) {
3481 runtime->hw.rates &= mout->spdif_rates;
3482 runtime->hw.formats &= mout->spdif_formats;
3483 if (mout->spdif_maxbps < hinfo->maxbps)
3484 hinfo->maxbps = mout->spdif_maxbps;
3485 } else {
3486 mout->share_spdif = 0;
3487 /* FIXME: need notify? */
3488 }
Takashi Iwai9a081602008-02-12 18:37:26 +01003489 }
Frederik Deweerdteaa99852008-04-14 13:11:44 +02003490 mutex_unlock(&codec->spdif_mutex);
Takashi Iwai9a081602008-02-12 18:37:26 +01003491 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003492 return snd_pcm_hw_constraint_step(substream->runtime, 0,
3493 SNDRV_PCM_HW_PARAM_CHANNELS, 2);
3494}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003495EXPORT_SYMBOL_HDA(snd_hda_multi_out_analog_open);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003496
3497/*
3498 * set up the i/o for analog out
3499 * when the digital out is available, copy the front out to digital out, too.
3500 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003501int snd_hda_multi_out_analog_prepare(struct hda_codec *codec,
3502 struct hda_multi_out *mout,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003503 unsigned int stream_tag,
3504 unsigned int format,
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01003505 struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003506{
3507 hda_nid_t *nids = mout->dac_nids;
3508 int chs = substream->runtime->channels;
3509 int i;
3510
Ingo Molnar62932df2006-01-16 16:34:20 +01003511 mutex_lock(&codec->spdif_mutex);
Takashi Iwai9a081602008-02-12 18:37:26 +01003512 if (mout->dig_out_nid && mout->share_spdif &&
3513 mout->dig_out_used != HDA_DIG_EXCLUSIVE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003514 if (chs == 2 &&
Takashi Iwai0ba21762007-04-16 11:29:14 +02003515 snd_hda_is_supported_format(codec, mout->dig_out_nid,
3516 format) &&
3517 !(codec->spdif_status & IEC958_AES0_NONAUDIO)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003518 mout->dig_out_used = HDA_DIG_ANALOG_DUP;
Takashi Iwai6b97eb42007-04-05 14:51:48 +02003519 setup_dig_out_stream(codec, mout->dig_out_nid,
3520 stream_tag, format);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003521 } else {
3522 mout->dig_out_used = 0;
Takashi Iwai2f728532008-09-25 16:32:41 +02003523 cleanup_dig_out_stream(codec, mout->dig_out_nid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003524 }
3525 }
Ingo Molnar62932df2006-01-16 16:34:20 +01003526 mutex_unlock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003527
3528 /* front */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003529 snd_hda_codec_setup_stream(codec, nids[HDA_FRONT], stream_tag,
3530 0, format);
Takashi Iwaid29240c2007-10-26 12:35:56 +02003531 if (!mout->no_share_stream &&
3532 mout->hp_nid && mout->hp_nid != nids[HDA_FRONT])
Linus Torvalds1da177e2005-04-16 15:20:36 -07003533 /* headphone out will just decode front left/right (stereo) */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003534 snd_hda_codec_setup_stream(codec, mout->hp_nid, stream_tag,
3535 0, format);
Takashi Iwai82bc9552006-03-21 11:24:42 +01003536 /* extra outputs copied from front */
3537 for (i = 0; i < ARRAY_SIZE(mout->extra_out_nid); i++)
Takashi Iwaid29240c2007-10-26 12:35:56 +02003538 if (!mout->no_share_stream && mout->extra_out_nid[i])
Takashi Iwai82bc9552006-03-21 11:24:42 +01003539 snd_hda_codec_setup_stream(codec,
3540 mout->extra_out_nid[i],
3541 stream_tag, 0, format);
3542
Linus Torvalds1da177e2005-04-16 15:20:36 -07003543 /* surrounds */
3544 for (i = 1; i < mout->num_dacs; i++) {
Takashi Iwai4b3acaf2005-06-10 19:48:10 +02003545 if (chs >= (i + 1) * 2) /* independent out */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003546 snd_hda_codec_setup_stream(codec, nids[i], stream_tag,
3547 i * 2, format);
Takashi Iwaid29240c2007-10-26 12:35:56 +02003548 else if (!mout->no_share_stream) /* copy front */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003549 snd_hda_codec_setup_stream(codec, nids[i], stream_tag,
3550 0, format);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003551 }
3552 return 0;
3553}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003554EXPORT_SYMBOL_HDA(snd_hda_multi_out_analog_prepare);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003555
3556/*
3557 * clean up the setting for analog out
3558 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003559int snd_hda_multi_out_analog_cleanup(struct hda_codec *codec,
3560 struct hda_multi_out *mout)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003561{
3562 hda_nid_t *nids = mout->dac_nids;
3563 int i;
3564
3565 for (i = 0; i < mout->num_dacs; i++)
Takashi Iwai888afa12008-03-18 09:57:50 +01003566 snd_hda_codec_cleanup_stream(codec, nids[i]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003567 if (mout->hp_nid)
Takashi Iwai888afa12008-03-18 09:57:50 +01003568 snd_hda_codec_cleanup_stream(codec, mout->hp_nid);
Takashi Iwai82bc9552006-03-21 11:24:42 +01003569 for (i = 0; i < ARRAY_SIZE(mout->extra_out_nid); i++)
3570 if (mout->extra_out_nid[i])
Takashi Iwai888afa12008-03-18 09:57:50 +01003571 snd_hda_codec_cleanup_stream(codec,
3572 mout->extra_out_nid[i]);
Ingo Molnar62932df2006-01-16 16:34:20 +01003573 mutex_lock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003574 if (mout->dig_out_nid && mout->dig_out_used == HDA_DIG_ANALOG_DUP) {
Takashi Iwai2f728532008-09-25 16:32:41 +02003575 cleanup_dig_out_stream(codec, mout->dig_out_nid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003576 mout->dig_out_used = 0;
3577 }
Ingo Molnar62932df2006-01-16 16:34:20 +01003578 mutex_unlock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003579 return 0;
3580}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003581EXPORT_SYMBOL_HDA(snd_hda_multi_out_analog_cleanup);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003582
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003583/*
Wu Fengguang6b345002008-10-07 14:21:41 +08003584 * Helper for automatic pin configuration
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003585 */
Kailang Yangdf694da2005-12-05 19:42:22 +01003586
Takashi Iwai12f288b2007-08-02 15:51:59 +02003587static int is_in_nid_list(hda_nid_t nid, hda_nid_t *list)
Kailang Yangdf694da2005-12-05 19:42:22 +01003588{
3589 for (; *list; list++)
3590 if (*list == nid)
3591 return 1;
3592 return 0;
3593}
3594
Steve Longerbeam81937d32007-05-08 15:33:03 +02003595
3596/*
3597 * Sort an associated group of pins according to their sequence numbers.
3598 */
3599static void sort_pins_by_sequence(hda_nid_t * pins, short * sequences,
3600 int num_pins)
3601{
3602 int i, j;
3603 short seq;
3604 hda_nid_t nid;
3605
3606 for (i = 0; i < num_pins; i++) {
3607 for (j = i + 1; j < num_pins; j++) {
3608 if (sequences[i] > sequences[j]) {
3609 seq = sequences[i];
3610 sequences[i] = sequences[j];
3611 sequences[j] = seq;
3612 nid = pins[i];
3613 pins[i] = pins[j];
3614 pins[j] = nid;
3615 }
3616 }
3617 }
3618}
3619
3620
Takashi Iwai82bc9552006-03-21 11:24:42 +01003621/*
3622 * Parse all pin widgets and store the useful pin nids to cfg
3623 *
3624 * The number of line-outs or any primary output is stored in line_outs,
3625 * and the corresponding output pins are assigned to line_out_pins[],
3626 * in the order of front, rear, CLFE, side, ...
3627 *
3628 * If more extra outputs (speaker and headphone) are found, the pins are
Takashi Iwaieb06ed82006-09-20 17:10:27 +02003629 * assisnged to hp_pins[] and speaker_pins[], respectively. If no line-out jack
Takashi Iwai82bc9552006-03-21 11:24:42 +01003630 * is detected, one of speaker of HP pins is assigned as the primary
3631 * output, i.e. to line_out_pins[0]. So, line_outs is always positive
3632 * if any analog output exists.
3633 *
3634 * The analog input pins are assigned to input_pins array.
3635 * The digital input/output pins are assigned to dig_in_pin and dig_out_pin,
3636 * respectively.
3637 */
Takashi Iwai12f288b2007-08-02 15:51:59 +02003638int snd_hda_parse_pin_def_config(struct hda_codec *codec,
3639 struct auto_pin_cfg *cfg,
3640 hda_nid_t *ignore_nids)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003641{
Takashi Iwai0ef6ce72008-01-22 15:35:37 +01003642 hda_nid_t nid, end_nid;
Steve Longerbeam81937d32007-05-08 15:33:03 +02003643 short seq, assoc_line_out, assoc_speaker;
3644 short sequences_line_out[ARRAY_SIZE(cfg->line_out_pins)];
3645 short sequences_speaker[ARRAY_SIZE(cfg->speaker_pins)];
Takashi Iwaif889fa92007-10-31 15:49:32 +01003646 short sequences_hp[ARRAY_SIZE(cfg->hp_pins)];
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003647
3648 memset(cfg, 0, sizeof(*cfg));
3649
Steve Longerbeam81937d32007-05-08 15:33:03 +02003650 memset(sequences_line_out, 0, sizeof(sequences_line_out));
3651 memset(sequences_speaker, 0, sizeof(sequences_speaker));
Takashi Iwaif889fa92007-10-31 15:49:32 +01003652 memset(sequences_hp, 0, sizeof(sequences_hp));
Steve Longerbeam81937d32007-05-08 15:33:03 +02003653 assoc_line_out = assoc_speaker = 0;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003654
Takashi Iwai0ef6ce72008-01-22 15:35:37 +01003655 end_nid = codec->start_nid + codec->num_nodes;
3656 for (nid = codec->start_nid; nid < end_nid; nid++) {
Takashi Iwai54d17402005-11-21 16:33:22 +01003657 unsigned int wid_caps = get_wcaps(codec, nid);
Takashi Iwai0ba21762007-04-16 11:29:14 +02003658 unsigned int wid_type =
3659 (wid_caps & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003660 unsigned int def_conf;
3661 short assoc, loc;
3662
3663 /* read all default configuration for pin complex */
3664 if (wid_type != AC_WID_PIN)
3665 continue;
Kailang Yangdf694da2005-12-05 19:42:22 +01003666 /* ignore the given nids (e.g. pc-beep returns error) */
3667 if (ignore_nids && is_in_nid_list(nid, ignore_nids))
3668 continue;
3669
Takashi Iwaic17a1ab2009-02-23 09:28:12 +01003670 def_conf = snd_hda_codec_get_pincfg(codec, nid);
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003671 if (get_defcfg_connect(def_conf) == AC_JACK_PORT_NONE)
3672 continue;
3673 loc = get_defcfg_location(def_conf);
3674 switch (get_defcfg_device(def_conf)) {
3675 case AC_JACK_LINE_OUT:
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003676 seq = get_defcfg_sequence(def_conf);
3677 assoc = get_defcfg_association(def_conf);
Matthew Ranostay90da78b2008-01-24 11:48:01 +01003678
3679 if (!(wid_caps & AC_WCAP_STEREO))
3680 if (!cfg->mono_out_pin)
3681 cfg->mono_out_pin = nid;
Takashi Iwai0ba21762007-04-16 11:29:14 +02003682 if (!assoc)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003683 continue;
Takashi Iwai0ba21762007-04-16 11:29:14 +02003684 if (!assoc_line_out)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003685 assoc_line_out = assoc;
3686 else if (assoc_line_out != assoc)
3687 continue;
3688 if (cfg->line_outs >= ARRAY_SIZE(cfg->line_out_pins))
3689 continue;
3690 cfg->line_out_pins[cfg->line_outs] = nid;
Steve Longerbeam81937d32007-05-08 15:33:03 +02003691 sequences_line_out[cfg->line_outs] = seq;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003692 cfg->line_outs++;
3693 break;
Takashi Iwai8d88bc32005-11-17 11:09:23 +01003694 case AC_JACK_SPEAKER:
Steve Longerbeam81937d32007-05-08 15:33:03 +02003695 seq = get_defcfg_sequence(def_conf);
3696 assoc = get_defcfg_association(def_conf);
3697 if (! assoc)
3698 continue;
3699 if (! assoc_speaker)
3700 assoc_speaker = assoc;
3701 else if (assoc_speaker != assoc)
3702 continue;
Takashi Iwai82bc9552006-03-21 11:24:42 +01003703 if (cfg->speaker_outs >= ARRAY_SIZE(cfg->speaker_pins))
3704 continue;
3705 cfg->speaker_pins[cfg->speaker_outs] = nid;
Steve Longerbeam81937d32007-05-08 15:33:03 +02003706 sequences_speaker[cfg->speaker_outs] = seq;
Takashi Iwai82bc9552006-03-21 11:24:42 +01003707 cfg->speaker_outs++;
Takashi Iwai8d88bc32005-11-17 11:09:23 +01003708 break;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003709 case AC_JACK_HP_OUT:
Takashi Iwaif889fa92007-10-31 15:49:32 +01003710 seq = get_defcfg_sequence(def_conf);
3711 assoc = get_defcfg_association(def_conf);
Takashi Iwaieb06ed82006-09-20 17:10:27 +02003712 if (cfg->hp_outs >= ARRAY_SIZE(cfg->hp_pins))
3713 continue;
3714 cfg->hp_pins[cfg->hp_outs] = nid;
Takashi Iwaif889fa92007-10-31 15:49:32 +01003715 sequences_hp[cfg->hp_outs] = (assoc << 4) | seq;
Takashi Iwaieb06ed82006-09-20 17:10:27 +02003716 cfg->hp_outs++;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003717 break;
Takashi Iwai314634b2006-09-21 11:56:18 +02003718 case AC_JACK_MIC_IN: {
3719 int preferred, alt;
3720 if (loc == AC_JACK_LOC_FRONT) {
3721 preferred = AUTO_PIN_FRONT_MIC;
3722 alt = AUTO_PIN_MIC;
3723 } else {
3724 preferred = AUTO_PIN_MIC;
3725 alt = AUTO_PIN_FRONT_MIC;
3726 }
3727 if (!cfg->input_pins[preferred])
3728 cfg->input_pins[preferred] = nid;
3729 else if (!cfg->input_pins[alt])
3730 cfg->input_pins[alt] = nid;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003731 break;
Takashi Iwai314634b2006-09-21 11:56:18 +02003732 }
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003733 case AC_JACK_LINE_IN:
3734 if (loc == AC_JACK_LOC_FRONT)
3735 cfg->input_pins[AUTO_PIN_FRONT_LINE] = nid;
3736 else
3737 cfg->input_pins[AUTO_PIN_LINE] = nid;
3738 break;
3739 case AC_JACK_CD:
3740 cfg->input_pins[AUTO_PIN_CD] = nid;
3741 break;
3742 case AC_JACK_AUX:
3743 cfg->input_pins[AUTO_PIN_AUX] = nid;
3744 break;
3745 case AC_JACK_SPDIF_OUT:
Takashi Iwai1b52ae72009-01-20 17:17:29 +01003746 case AC_JACK_DIG_OTHER_OUT:
Takashi Iwai0852d7a2009-02-11 11:35:15 +01003747 if (cfg->dig_outs >= ARRAY_SIZE(cfg->dig_out_pins))
3748 continue;
3749 cfg->dig_out_pins[cfg->dig_outs] = nid;
3750 cfg->dig_out_type[cfg->dig_outs] =
3751 (loc == AC_JACK_LOC_HDMI) ?
3752 HDA_PCM_TYPE_HDMI : HDA_PCM_TYPE_SPDIF;
3753 cfg->dig_outs++;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003754 break;
3755 case AC_JACK_SPDIF_IN:
Takashi Iwai1b52ae72009-01-20 17:17:29 +01003756 case AC_JACK_DIG_OTHER_IN:
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003757 cfg->dig_in_pin = nid;
Takashi Iwai2297bd62009-01-20 18:24:13 +01003758 if (loc == AC_JACK_LOC_HDMI)
3759 cfg->dig_in_type = HDA_PCM_TYPE_HDMI;
3760 else
3761 cfg->dig_in_type = HDA_PCM_TYPE_SPDIF;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003762 break;
3763 }
3764 }
3765
Takashi Iwai5832fcf82008-02-12 18:30:12 +01003766 /* FIX-UP:
3767 * If no line-out is defined but multiple HPs are found,
3768 * some of them might be the real line-outs.
3769 */
3770 if (!cfg->line_outs && cfg->hp_outs > 1) {
3771 int i = 0;
3772 while (i < cfg->hp_outs) {
3773 /* The real HPs should have the sequence 0x0f */
3774 if ((sequences_hp[i] & 0x0f) == 0x0f) {
3775 i++;
3776 continue;
3777 }
3778 /* Move it to the line-out table */
3779 cfg->line_out_pins[cfg->line_outs] = cfg->hp_pins[i];
3780 sequences_line_out[cfg->line_outs] = sequences_hp[i];
3781 cfg->line_outs++;
3782 cfg->hp_outs--;
3783 memmove(cfg->hp_pins + i, cfg->hp_pins + i + 1,
3784 sizeof(cfg->hp_pins[0]) * (cfg->hp_outs - i));
3785 memmove(sequences_hp + i - 1, sequences_hp + i,
3786 sizeof(sequences_hp[0]) * (cfg->hp_outs - i));
3787 }
3788 }
3789
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003790 /* sort by sequence */
Steve Longerbeam81937d32007-05-08 15:33:03 +02003791 sort_pins_by_sequence(cfg->line_out_pins, sequences_line_out,
3792 cfg->line_outs);
3793 sort_pins_by_sequence(cfg->speaker_pins, sequences_speaker,
3794 cfg->speaker_outs);
Takashi Iwaif889fa92007-10-31 15:49:32 +01003795 sort_pins_by_sequence(cfg->hp_pins, sequences_hp,
3796 cfg->hp_outs);
Steve Longerbeam81937d32007-05-08 15:33:03 +02003797
Takashi Iwaif889fa92007-10-31 15:49:32 +01003798 /* if we have only one mic, make it AUTO_PIN_MIC */
3799 if (!cfg->input_pins[AUTO_PIN_MIC] &&
3800 cfg->input_pins[AUTO_PIN_FRONT_MIC]) {
3801 cfg->input_pins[AUTO_PIN_MIC] =
3802 cfg->input_pins[AUTO_PIN_FRONT_MIC];
3803 cfg->input_pins[AUTO_PIN_FRONT_MIC] = 0;
3804 }
3805 /* ditto for line-in */
3806 if (!cfg->input_pins[AUTO_PIN_LINE] &&
3807 cfg->input_pins[AUTO_PIN_FRONT_LINE]) {
3808 cfg->input_pins[AUTO_PIN_LINE] =
3809 cfg->input_pins[AUTO_PIN_FRONT_LINE];
3810 cfg->input_pins[AUTO_PIN_FRONT_LINE] = 0;
3811 }
3812
Steve Longerbeam81937d32007-05-08 15:33:03 +02003813 /*
3814 * FIX-UP: if no line-outs are detected, try to use speaker or HP pin
3815 * as a primary output
3816 */
3817 if (!cfg->line_outs) {
3818 if (cfg->speaker_outs) {
3819 cfg->line_outs = cfg->speaker_outs;
3820 memcpy(cfg->line_out_pins, cfg->speaker_pins,
3821 sizeof(cfg->speaker_pins));
3822 cfg->speaker_outs = 0;
3823 memset(cfg->speaker_pins, 0, sizeof(cfg->speaker_pins));
3824 cfg->line_out_type = AUTO_PIN_SPEAKER_OUT;
3825 } else if (cfg->hp_outs) {
3826 cfg->line_outs = cfg->hp_outs;
3827 memcpy(cfg->line_out_pins, cfg->hp_pins,
3828 sizeof(cfg->hp_pins));
3829 cfg->hp_outs = 0;
3830 memset(cfg->hp_pins, 0, sizeof(cfg->hp_pins));
3831 cfg->line_out_type = AUTO_PIN_HP_OUT;
3832 }
3833 }
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003834
Takashi Iwaicb8e2f82005-07-29 11:54:32 +02003835 /* Reorder the surround channels
3836 * ALSA sequence is front/surr/clfe/side
3837 * HDA sequence is:
3838 * 4-ch: front/surr => OK as it is
3839 * 6-ch: front/clfe/surr
Takashi Iwai9422db42007-04-20 16:11:43 +02003840 * 8-ch: front/clfe/rear/side|fc
Takashi Iwaicb8e2f82005-07-29 11:54:32 +02003841 */
3842 switch (cfg->line_outs) {
3843 case 3:
Takashi Iwaicb8e2f82005-07-29 11:54:32 +02003844 case 4:
3845 nid = cfg->line_out_pins[1];
Takashi Iwai9422db42007-04-20 16:11:43 +02003846 cfg->line_out_pins[1] = cfg->line_out_pins[2];
Takashi Iwaicb8e2f82005-07-29 11:54:32 +02003847 cfg->line_out_pins[2] = nid;
3848 break;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003849 }
3850
Takashi Iwai82bc9552006-03-21 11:24:42 +01003851 /*
3852 * debug prints of the parsed results
3853 */
3854 snd_printd("autoconfig: line_outs=%d (0x%x/0x%x/0x%x/0x%x/0x%x)\n",
3855 cfg->line_outs, cfg->line_out_pins[0], cfg->line_out_pins[1],
3856 cfg->line_out_pins[2], cfg->line_out_pins[3],
3857 cfg->line_out_pins[4]);
3858 snd_printd(" speaker_outs=%d (0x%x/0x%x/0x%x/0x%x/0x%x)\n",
3859 cfg->speaker_outs, cfg->speaker_pins[0],
3860 cfg->speaker_pins[1], cfg->speaker_pins[2],
3861 cfg->speaker_pins[3], cfg->speaker_pins[4]);
Takashi Iwaieb06ed82006-09-20 17:10:27 +02003862 snd_printd(" hp_outs=%d (0x%x/0x%x/0x%x/0x%x/0x%x)\n",
3863 cfg->hp_outs, cfg->hp_pins[0],
3864 cfg->hp_pins[1], cfg->hp_pins[2],
3865 cfg->hp_pins[3], cfg->hp_pins[4]);
Matthew Ranostay90da78b2008-01-24 11:48:01 +01003866 snd_printd(" mono: mono_out=0x%x\n", cfg->mono_out_pin);
Takashi Iwai0852d7a2009-02-11 11:35:15 +01003867 if (cfg->dig_outs)
3868 snd_printd(" dig-out=0x%x/0x%x\n",
3869 cfg->dig_out_pins[0], cfg->dig_out_pins[1]);
Takashi Iwai82bc9552006-03-21 11:24:42 +01003870 snd_printd(" inputs: mic=0x%x, fmic=0x%x, line=0x%x, fline=0x%x,"
3871 " cd=0x%x, aux=0x%x\n",
3872 cfg->input_pins[AUTO_PIN_MIC],
3873 cfg->input_pins[AUTO_PIN_FRONT_MIC],
3874 cfg->input_pins[AUTO_PIN_LINE],
3875 cfg->input_pins[AUTO_PIN_FRONT_LINE],
3876 cfg->input_pins[AUTO_PIN_CD],
3877 cfg->input_pins[AUTO_PIN_AUX]);
Takashi Iwai32d2c7f2009-02-11 11:33:13 +01003878 if (cfg->dig_in_pin)
Takashi Iwai89ce9e82009-01-20 17:15:57 +01003879 snd_printd(" dig-in=0x%x\n", cfg->dig_in_pin);
Takashi Iwai82bc9552006-03-21 11:24:42 +01003880
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003881 return 0;
3882}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003883EXPORT_SYMBOL_HDA(snd_hda_parse_pin_def_config);
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003884
Takashi Iwai4a471b72005-12-07 13:56:29 +01003885/* labels for input pins */
3886const char *auto_pin_cfg_labels[AUTO_PIN_LAST] = {
3887 "Mic", "Front Mic", "Line", "Front Line", "CD", "Aux"
3888};
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003889EXPORT_SYMBOL_HDA(auto_pin_cfg_labels);
Takashi Iwai4a471b72005-12-07 13:56:29 +01003890
3891
Linus Torvalds1da177e2005-04-16 15:20:36 -07003892#ifdef CONFIG_PM
3893/*
3894 * power management
3895 */
3896
3897/**
3898 * snd_hda_suspend - suspend the codecs
3899 * @bus: the HDA bus
Linus Torvalds1da177e2005-04-16 15:20:36 -07003900 *
3901 * Returns 0 if successful.
3902 */
Takashi Iwai8dd78332009-06-02 01:16:07 +02003903int snd_hda_suspend(struct hda_bus *bus)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003904{
Takashi Iwai0ba21762007-04-16 11:29:14 +02003905 struct hda_codec *codec;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003906
Takashi Iwai0ba21762007-04-16 11:29:14 +02003907 list_for_each_entry(codec, &bus->codec_list, list) {
Takashi Iwai0b7a2e92007-08-14 15:18:26 +02003908#ifdef CONFIG_SND_HDA_POWER_SAVE
3909 if (!codec->power_on)
3910 continue;
3911#endif
Takashi Iwaicb53c622007-08-10 17:21:45 +02003912 hda_call_codec_suspend(codec);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003913 }
3914 return 0;
3915}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003916EXPORT_SYMBOL_HDA(snd_hda_suspend);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003917
3918/**
3919 * snd_hda_resume - resume the codecs
3920 * @bus: the HDA bus
Linus Torvalds1da177e2005-04-16 15:20:36 -07003921 *
3922 * Returns 0 if successful.
Takashi Iwaicb53c622007-08-10 17:21:45 +02003923 *
3924 * This fucntion is defined only when POWER_SAVE isn't set.
3925 * In the power-save mode, the codec is resumed dynamically.
Linus Torvalds1da177e2005-04-16 15:20:36 -07003926 */
3927int snd_hda_resume(struct hda_bus *bus)
3928{
Takashi Iwai0ba21762007-04-16 11:29:14 +02003929 struct hda_codec *codec;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003930
Takashi Iwai0ba21762007-04-16 11:29:14 +02003931 list_for_each_entry(codec, &bus->codec_list, list) {
Maxim Levitskyd804ad92007-09-03 15:28:04 +02003932 if (snd_hda_codec_needs_resume(codec))
3933 hda_call_codec_resume(codec);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003934 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003935 return 0;
3936}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003937EXPORT_SYMBOL_HDA(snd_hda_resume);
Takashi Iwai1289e9e2008-11-27 15:47:11 +01003938#endif /* CONFIG_PM */
Takashi Iwaib2e18592008-07-30 15:01:44 +02003939
3940/*
3941 * generic arrays
3942 */
3943
3944/* get a new element from the given array
3945 * if it exceeds the pre-allocated array size, re-allocate the array
3946 */
3947void *snd_array_new(struct snd_array *array)
3948{
3949 if (array->used >= array->alloced) {
3950 int num = array->alloced + array->alloc_align;
Takashi Iwaib910d9a2008-11-07 00:26:52 +01003951 void *nlist;
3952 if (snd_BUG_ON(num >= 4096))
3953 return NULL;
3954 nlist = kcalloc(num + 1, array->elem_size, GFP_KERNEL);
Takashi Iwaib2e18592008-07-30 15:01:44 +02003955 if (!nlist)
3956 return NULL;
3957 if (array->list) {
3958 memcpy(nlist, array->list,
3959 array->elem_size * array->alloced);
3960 kfree(array->list);
3961 }
3962 array->list = nlist;
3963 array->alloced = num;
3964 }
Takashi Iwaif43aa022008-11-10 16:24:26 +01003965 return snd_array_elem(array, array->used++);
Takashi Iwaib2e18592008-07-30 15:01:44 +02003966}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003967EXPORT_SYMBOL_HDA(snd_array_new);
Takashi Iwaib2e18592008-07-30 15:01:44 +02003968
3969/* free the given array elements */
3970void snd_array_free(struct snd_array *array)
3971{
3972 kfree(array->list);
3973 array->used = 0;
3974 array->alloced = 0;
3975 array->list = NULL;
3976}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003977EXPORT_SYMBOL_HDA(snd_array_free);
Takashi Iwaib2022262008-11-21 21:24:03 +01003978
3979/*
3980 * used by hda_proc.c and hda_eld.c
3981 */
3982void snd_print_pcm_rates(int pcm, char *buf, int buflen)
3983{
3984 static unsigned int rates[] = {
3985 8000, 11025, 16000, 22050, 32000, 44100, 48000, 88200,
3986 96000, 176400, 192000, 384000
3987 };
3988 int i, j;
3989
3990 for (i = 0, j = 0; i < ARRAY_SIZE(rates); i++)
3991 if (pcm & (1 << i))
3992 j += snprintf(buf + j, buflen - j, " %d", rates[i]);
3993
3994 buf[j] = '\0'; /* necessary when j == 0 */
3995}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003996EXPORT_SYMBOL_HDA(snd_print_pcm_rates);
Takashi Iwaib2022262008-11-21 21:24:03 +01003997
3998void snd_print_pcm_bits(int pcm, char *buf, int buflen)
3999{
4000 static unsigned int bits[] = { 8, 16, 20, 24, 32 };
4001 int i, j;
4002
4003 for (i = 0, j = 0; i < ARRAY_SIZE(bits); i++)
4004 if (pcm & (AC_SUPPCM_BITS_8 << i))
4005 j += snprintf(buf + j, buflen - j, " %d", bits[i]);
4006
4007 buf[j] = '\0'; /* necessary when j == 0 */
4008}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01004009EXPORT_SYMBOL_HDA(snd_print_pcm_bits);
Takashi Iwai1289e9e2008-11-27 15:47:11 +01004010
4011MODULE_DESCRIPTION("HDA codec core");
4012MODULE_LICENSE("GPL");