blob: ec352c6ae49a023e1b15a7ee867b8993056659d7 [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)
177 *res = bus->ops.get_response(bus);
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);
Takashi Iwai3c6aae42009-07-10 12:52:27 +0200319 if (parm == -1 && codec->bus->rirb_error)
320 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700321 conn_list[0] = parm & mask;
322 return 1;
323 }
324
325 /* multi connection */
326 conns = 0;
Takashi Iwai54d17402005-11-21 16:33:22 +0100327 prev_nid = 0;
328 for (i = 0; i < conn_len; i++) {
329 int range_val;
330 hda_nid_t val, n;
331
Takashi Iwai3c6aae42009-07-10 12:52:27 +0200332 if (i % num_elems == 0) {
Takashi Iwai54d17402005-11-21 16:33:22 +0100333 parm = snd_hda_codec_read(codec, nid, 0,
334 AC_VERB_GET_CONNECT_LIST, i);
Takashi Iwai3c6aae42009-07-10 12:52:27 +0200335 if (parm == -1 && codec->bus->rirb_error)
336 return -EIO;
337 }
Takashi Iwai0ba21762007-04-16 11:29:14 +0200338 range_val = !!(parm & (1 << (shift-1))); /* ranges */
Takashi Iwai54d17402005-11-21 16:33:22 +0100339 val = parm & mask;
340 parm >>= shift;
341 if (range_val) {
342 /* ranges between the previous and this one */
Takashi Iwai0ba21762007-04-16 11:29:14 +0200343 if (!prev_nid || prev_nid >= val) {
344 snd_printk(KERN_WARNING "hda_codec: "
345 "invalid dep_range_val %x:%x\n",
346 prev_nid, val);
Takashi Iwai54d17402005-11-21 16:33:22 +0100347 continue;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700348 }
Takashi Iwai54d17402005-11-21 16:33:22 +0100349 for (n = prev_nid + 1; n <= val; n++) {
350 if (conns >= max_conns) {
Takashi Iwai0ba21762007-04-16 11:29:14 +0200351 snd_printk(KERN_ERR
352 "Too many connections\n");
Takashi Iwai54d17402005-11-21 16:33:22 +0100353 return -EINVAL;
354 }
355 conn_list[conns++] = n;
356 }
357 } else {
358 if (conns >= max_conns) {
359 snd_printk(KERN_ERR "Too many connections\n");
360 return -EINVAL;
361 }
362 conn_list[conns++] = val;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700363 }
Takashi Iwai54d17402005-11-21 16:33:22 +0100364 prev_nid = val;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700365 }
366 return conns;
367}
Takashi Iwaiff7a3262008-11-28 15:17:06 +0100368EXPORT_SYMBOL_HDA(snd_hda_get_connections);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700369
370
371/**
372 * snd_hda_queue_unsol_event - add an unsolicited event to queue
373 * @bus: the BUS
374 * @res: unsolicited event (lower 32bit of RIRB entry)
375 * @res_ex: codec addr and flags (upper 32bit or RIRB entry)
376 *
377 * Adds the given event to the queue. The events are processed in
378 * the workqueue asynchronously. Call this function in the interrupt
379 * hanlder when RIRB receives an unsolicited event.
380 *
381 * Returns 0 if successful, or a negative error code.
382 */
383int snd_hda_queue_unsol_event(struct hda_bus *bus, u32 res, u32 res_ex)
384{
385 struct hda_bus_unsolicited *unsol;
386 unsigned int wp;
387
Takashi Iwai0ba21762007-04-16 11:29:14 +0200388 unsol = bus->unsol;
389 if (!unsol)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700390 return 0;
391
392 wp = (unsol->wp + 1) % HDA_UNSOL_QUEUE_SIZE;
393 unsol->wp = wp;
394
395 wp <<= 1;
396 unsol->queue[wp] = res;
397 unsol->queue[wp + 1] = res_ex;
398
Takashi Iwai6acaed32009-01-12 10:09:24 +0100399 queue_work(bus->workq, &unsol->work);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700400
401 return 0;
402}
Takashi Iwaiff7a3262008-11-28 15:17:06 +0100403EXPORT_SYMBOL_HDA(snd_hda_queue_unsol_event);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700404
405/*
Wu Fengguang5c1d1a92008-10-07 14:17:53 +0800406 * process queued unsolicited events
Linus Torvalds1da177e2005-04-16 15:20:36 -0700407 */
David Howellsc4028952006-11-22 14:57:56 +0000408static void process_unsol_events(struct work_struct *work)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700409{
David Howellsc4028952006-11-22 14:57:56 +0000410 struct hda_bus_unsolicited *unsol =
411 container_of(work, struct hda_bus_unsolicited, work);
412 struct hda_bus *bus = unsol->bus;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700413 struct hda_codec *codec;
414 unsigned int rp, caddr, res;
415
416 while (unsol->rp != unsol->wp) {
417 rp = (unsol->rp + 1) % HDA_UNSOL_QUEUE_SIZE;
418 unsol->rp = rp;
419 rp <<= 1;
420 res = unsol->queue[rp];
421 caddr = unsol->queue[rp + 1];
Takashi Iwai0ba21762007-04-16 11:29:14 +0200422 if (!(caddr & (1 << 4))) /* no unsolicited event? */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700423 continue;
424 codec = bus->caddr_tbl[caddr & 0x0f];
425 if (codec && codec->patch_ops.unsol_event)
426 codec->patch_ops.unsol_event(codec, res);
427 }
428}
429
430/*
431 * initialize unsolicited queue
432 */
Takashi Iwai6c1f45e2008-07-30 15:01:45 +0200433static int init_unsol_queue(struct hda_bus *bus)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700434{
435 struct hda_bus_unsolicited *unsol;
436
Takashi Iwai9f146bb2005-11-17 11:07:49 +0100437 if (bus->unsol) /* already initialized */
438 return 0;
439
Takashi Iwaie560d8d2005-09-09 14:21:46 +0200440 unsol = kzalloc(sizeof(*unsol), GFP_KERNEL);
Takashi Iwai0ba21762007-04-16 11:29:14 +0200441 if (!unsol) {
442 snd_printk(KERN_ERR "hda_codec: "
443 "can't allocate unsolicited queue\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700444 return -ENOMEM;
445 }
David Howellsc4028952006-11-22 14:57:56 +0000446 INIT_WORK(&unsol->work, process_unsol_events);
447 unsol->bus = bus;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700448 bus->unsol = unsol;
449 return 0;
450}
451
452/*
453 * destructor
454 */
455static void snd_hda_codec_free(struct hda_codec *codec);
456
457static int snd_hda_bus_free(struct hda_bus *bus)
458{
Takashi Iwai0ba21762007-04-16 11:29:14 +0200459 struct hda_codec *codec, *n;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700460
Takashi Iwai0ba21762007-04-16 11:29:14 +0200461 if (!bus)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700462 return 0;
Takashi Iwai6acaed32009-01-12 10:09:24 +0100463 if (bus->workq)
464 flush_workqueue(bus->workq);
465 if (bus->unsol)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700466 kfree(bus->unsol);
Takashi Iwai0ba21762007-04-16 11:29:14 +0200467 list_for_each_entry_safe(codec, n, &bus->codec_list, list) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700468 snd_hda_codec_free(codec);
469 }
470 if (bus->ops.private_free)
471 bus->ops.private_free(bus);
Takashi Iwai6acaed32009-01-12 10:09:24 +0100472 if (bus->workq)
473 destroy_workqueue(bus->workq);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700474 kfree(bus);
475 return 0;
476}
477
Takashi Iwaic8b6bf92005-11-17 14:57:47 +0100478static int snd_hda_bus_dev_free(struct snd_device *device)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700479{
480 struct hda_bus *bus = device->device_data;
Takashi Iwaib94d35392008-11-21 09:08:06 +0100481 bus->shutdown = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700482 return snd_hda_bus_free(bus);
483}
484
Takashi Iwaid7ffba12008-07-30 15:01:46 +0200485#ifdef CONFIG_SND_HDA_HWDEP
486static int snd_hda_bus_dev_register(struct snd_device *device)
487{
488 struct hda_bus *bus = device->device_data;
489 struct hda_codec *codec;
490 list_for_each_entry(codec, &bus->codec_list, list) {
491 snd_hda_hwdep_add_sysfs(codec);
492 }
493 return 0;
494}
495#else
496#define snd_hda_bus_dev_register NULL
497#endif
498
Linus Torvalds1da177e2005-04-16 15:20:36 -0700499/**
500 * snd_hda_bus_new - create a HDA bus
501 * @card: the card entry
502 * @temp: the template for hda_bus information
503 * @busp: the pointer to store the created bus instance
504 *
505 * Returns 0 if successful, or a negative error code.
506 */
Takashi Iwai1289e9e2008-11-27 15:47:11 +0100507int /*__devinit*/ snd_hda_bus_new(struct snd_card *card,
Takashi Iwai756e2b02007-04-16 11:27:07 +0200508 const struct hda_bus_template *temp,
509 struct hda_bus **busp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700510{
511 struct hda_bus *bus;
512 int err;
Takashi Iwaic8b6bf92005-11-17 14:57:47 +0100513 static struct snd_device_ops dev_ops = {
Takashi Iwaid7ffba12008-07-30 15:01:46 +0200514 .dev_register = snd_hda_bus_dev_register,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700515 .dev_free = snd_hda_bus_dev_free,
516 };
517
Takashi Iwaida3cec32008-08-08 17:12:14 +0200518 if (snd_BUG_ON(!temp))
519 return -EINVAL;
520 if (snd_BUG_ON(!temp->ops.command || !temp->ops.get_response))
521 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700522
523 if (busp)
524 *busp = NULL;
525
Takashi Iwaie560d8d2005-09-09 14:21:46 +0200526 bus = kzalloc(sizeof(*bus), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700527 if (bus == NULL) {
528 snd_printk(KERN_ERR "can't allocate struct hda_bus\n");
529 return -ENOMEM;
530 }
531
532 bus->card = card;
533 bus->private_data = temp->private_data;
534 bus->pci = temp->pci;
535 bus->modelname = temp->modelname;
Takashi Iwaifee2fba2008-11-27 12:43:28 +0100536 bus->power_save = temp->power_save;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700537 bus->ops = temp->ops;
538
Ingo Molnar62932df2006-01-16 16:34:20 +0100539 mutex_init(&bus->cmd_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700540 INIT_LIST_HEAD(&bus->codec_list);
541
Takashi Iwaie8c0ee52009-02-05 07:34:28 +0100542 snprintf(bus->workq_name, sizeof(bus->workq_name),
543 "hd-audio%d", card->number);
544 bus->workq = create_singlethread_workqueue(bus->workq_name);
Takashi Iwai6acaed32009-01-12 10:09:24 +0100545 if (!bus->workq) {
Takashi Iwaie8c0ee52009-02-05 07:34:28 +0100546 snd_printk(KERN_ERR "cannot create workqueue %s\n",
547 bus->workq_name);
Takashi Iwai6acaed32009-01-12 10:09:24 +0100548 kfree(bus);
549 return -ENOMEM;
550 }
551
Takashi Iwai0ba21762007-04-16 11:29:14 +0200552 err = snd_device_new(card, SNDRV_DEV_BUS, bus, &dev_ops);
553 if (err < 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700554 snd_hda_bus_free(bus);
555 return err;
556 }
557 if (busp)
558 *busp = bus;
559 return 0;
560}
Takashi Iwaiff7a3262008-11-28 15:17:06 +0100561EXPORT_SYMBOL_HDA(snd_hda_bus_new);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700562
Takashi Iwai82467612007-07-27 19:15:54 +0200563#ifdef CONFIG_SND_HDA_GENERIC
564#define is_generic_config(codec) \
Takashi Iwaif44ac832008-07-30 15:01:45 +0200565 (codec->modelname && !strcmp(codec->modelname, "generic"))
Takashi Iwai82467612007-07-27 19:15:54 +0200566#else
567#define is_generic_config(codec) 0
568#endif
569
Takashi Iwai645f10c2008-11-28 15:07:37 +0100570#ifdef MODULE
Takashi Iwai1289e9e2008-11-27 15:47:11 +0100571#define HDA_MODREQ_MAX_COUNT 2 /* two request_modules()'s */
572#else
Takashi Iwai645f10c2008-11-28 15:07:37 +0100573#define HDA_MODREQ_MAX_COUNT 0 /* all presets are statically linked */
Takashi Iwai1289e9e2008-11-27 15:47:11 +0100574#endif
575
Linus Torvalds1da177e2005-04-16 15:20:36 -0700576/*
577 * find a matching codec preset
578 */
Takashi Iwai6c1f45e2008-07-30 15:01:45 +0200579static const struct hda_codec_preset *
Takashi Iwai756e2b02007-04-16 11:27:07 +0200580find_codec_preset(struct hda_codec *codec)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700581{
Takashi Iwai1289e9e2008-11-27 15:47:11 +0100582 struct hda_codec_preset_list *tbl;
583 const struct hda_codec_preset *preset;
584 int mod_requested = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700585
Takashi Iwai82467612007-07-27 19:15:54 +0200586 if (is_generic_config(codec))
Takashi Iwaid5ad6302007-03-07 15:55:59 +0100587 return NULL; /* use the generic parser */
588
Takashi Iwai1289e9e2008-11-27 15:47:11 +0100589 again:
590 mutex_lock(&preset_mutex);
591 list_for_each_entry(tbl, &hda_preset_tables, list) {
592 if (!try_module_get(tbl->owner)) {
593 snd_printk(KERN_ERR "hda_codec: cannot module_get\n");
594 continue;
595 }
596 for (preset = tbl->preset; preset->id; preset++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700597 u32 mask = preset->mask;
Marc Boucherca7cfae2008-01-22 15:32:25 +0100598 if (preset->afg && preset->afg != codec->afg)
599 continue;
600 if (preset->mfg && preset->mfg != codec->mfg)
601 continue;
Takashi Iwai0ba21762007-04-16 11:29:14 +0200602 if (!mask)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700603 mask = ~0;
Takashi Iwai9c7f8522006-06-28 15:08:22 +0200604 if (preset->id == (codec->vendor_id & mask) &&
Takashi Iwai0ba21762007-04-16 11:29:14 +0200605 (!preset->rev ||
Takashi Iwai1289e9e2008-11-27 15:47:11 +0100606 preset->rev == codec->revision_id)) {
607 mutex_unlock(&preset_mutex);
608 codec->owner = tbl->owner;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700609 return preset;
Takashi Iwai1289e9e2008-11-27 15:47:11 +0100610 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700611 }
Takashi Iwai1289e9e2008-11-27 15:47:11 +0100612 module_put(tbl->owner);
613 }
614 mutex_unlock(&preset_mutex);
615
616 if (mod_requested < HDA_MODREQ_MAX_COUNT) {
617 char name[32];
618 if (!mod_requested)
619 snprintf(name, sizeof(name), "snd-hda-codec-id:%08x",
620 codec->vendor_id);
621 else
622 snprintf(name, sizeof(name), "snd-hda-codec-id:%04x*",
623 (codec->vendor_id >> 16) & 0xffff);
624 request_module(name);
625 mod_requested++;
626 goto again;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700627 }
628 return NULL;
629}
630
631/*
Takashi Iwaif44ac832008-07-30 15:01:45 +0200632 * get_codec_name - store the codec name
Linus Torvalds1da177e2005-04-16 15:20:36 -0700633 */
Takashi Iwaif44ac832008-07-30 15:01:45 +0200634static int get_codec_name(struct hda_codec *codec)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700635{
636 const struct hda_vendor_id *c;
637 const char *vendor = NULL;
638 u16 vendor_id = codec->vendor_id >> 16;
Takashi Iwai812a2cc2009-05-16 10:00:49 +0200639 char tmp[16];
640
641 if (codec->vendor_name)
642 goto get_chip_name;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700643
644 for (c = hda_vendor_ids; c->id; c++) {
645 if (c->id == vendor_id) {
646 vendor = c->name;
647 break;
648 }
649 }
Takashi Iwai0ba21762007-04-16 11:29:14 +0200650 if (!vendor) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700651 sprintf(tmp, "Generic %04x", vendor_id);
652 vendor = tmp;
653 }
Takashi Iwai812a2cc2009-05-16 10:00:49 +0200654 codec->vendor_name = kstrdup(vendor, GFP_KERNEL);
655 if (!codec->vendor_name)
656 return -ENOMEM;
657
658 get_chip_name:
659 if (codec->chip_name)
660 return 0;
661
Linus Torvalds1da177e2005-04-16 15:20:36 -0700662 if (codec->preset && codec->preset->name)
Takashi Iwai812a2cc2009-05-16 10:00:49 +0200663 codec->chip_name = kstrdup(codec->preset->name, GFP_KERNEL);
664 else {
665 sprintf(tmp, "ID %x", codec->vendor_id & 0xffff);
666 codec->chip_name = kstrdup(tmp, GFP_KERNEL);
667 }
668 if (!codec->chip_name)
Takashi Iwaif44ac832008-07-30 15:01:45 +0200669 return -ENOMEM;
670 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700671}
672
673/*
Sasha Khapyorsky673b6832005-08-11 11:00:16 +0200674 * look for an AFG and MFG nodes
Linus Torvalds1da177e2005-04-16 15:20:36 -0700675 */
Takashi Iwai1289e9e2008-11-27 15:47:11 +0100676static void /*__devinit*/ setup_fg_nodes(struct hda_codec *codec)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700677{
Takashi Iwai93e82ae2009-04-17 18:04:41 +0200678 int i, total_nodes, function_id;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700679 hda_nid_t nid;
680
681 total_nodes = snd_hda_get_sub_nodes(codec, AC_NODE_ROOT, &nid);
682 for (i = 0; i < total_nodes; i++, nid++) {
Takashi Iwai93e82ae2009-04-17 18:04:41 +0200683 function_id = snd_hda_param_read(codec, nid,
Pascal de Bruijn234b4342009-03-23 11:15:59 +0100684 AC_PAR_FUNCTION_TYPE) & 0xff;
Takashi Iwai93e82ae2009-04-17 18:04:41 +0200685 switch (function_id) {
Sasha Khapyorsky673b6832005-08-11 11:00:16 +0200686 case AC_GRP_AUDIO_FUNCTION:
687 codec->afg = nid;
Takashi Iwai93e82ae2009-04-17 18:04:41 +0200688 codec->function_id = function_id;
Sasha Khapyorsky673b6832005-08-11 11:00:16 +0200689 break;
690 case AC_GRP_MODEM_FUNCTION:
691 codec->mfg = nid;
Takashi Iwai93e82ae2009-04-17 18:04:41 +0200692 codec->function_id = function_id;
Sasha Khapyorsky673b6832005-08-11 11:00:16 +0200693 break;
694 default:
695 break;
696 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700697 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700698}
699
700/*
Takashi Iwai54d17402005-11-21 16:33:22 +0100701 * read widget caps for each widget and store in cache
702 */
703static int read_widget_caps(struct hda_codec *codec, hda_nid_t fg_node)
704{
705 int i;
706 hda_nid_t nid;
707
708 codec->num_nodes = snd_hda_get_sub_nodes(codec, fg_node,
709 &codec->start_nid);
710 codec->wcaps = kmalloc(codec->num_nodes * 4, GFP_KERNEL);
Takashi Iwai0ba21762007-04-16 11:29:14 +0200711 if (!codec->wcaps)
Takashi Iwai54d17402005-11-21 16:33:22 +0100712 return -ENOMEM;
713 nid = codec->start_nid;
714 for (i = 0; i < codec->num_nodes; i++, nid++)
715 codec->wcaps[i] = snd_hda_param_read(codec, nid,
716 AC_PAR_AUDIO_WIDGET_CAP);
717 return 0;
718}
719
Takashi Iwai3be14142009-02-20 14:11:16 +0100720/* read all pin default configurations and save codec->init_pins */
721static int read_pin_defaults(struct hda_codec *codec)
722{
723 int i;
724 hda_nid_t nid = codec->start_nid;
725
726 for (i = 0; i < codec->num_nodes; i++, nid++) {
727 struct hda_pincfg *pin;
728 unsigned int wcaps = get_wcaps(codec, nid);
729 unsigned int wid_type = (wcaps & AC_WCAP_TYPE) >>
730 AC_WCAP_TYPE_SHIFT;
731 if (wid_type != AC_WID_PIN)
732 continue;
733 pin = snd_array_new(&codec->init_pins);
734 if (!pin)
735 return -ENOMEM;
736 pin->nid = nid;
737 pin->cfg = snd_hda_codec_read(codec, nid, 0,
738 AC_VERB_GET_CONFIG_DEFAULT, 0);
739 }
740 return 0;
741}
742
743/* look up the given pin config list and return the item matching with NID */
744static struct hda_pincfg *look_up_pincfg(struct hda_codec *codec,
745 struct snd_array *array,
746 hda_nid_t nid)
747{
748 int i;
749 for (i = 0; i < array->used; i++) {
750 struct hda_pincfg *pin = snd_array_elem(array, i);
751 if (pin->nid == nid)
752 return pin;
753 }
754 return NULL;
755}
756
757/* write a config value for the given NID */
758static void set_pincfg(struct hda_codec *codec, hda_nid_t nid,
759 unsigned int cfg)
760{
761 int i;
762 for (i = 0; i < 4; i++) {
763 snd_hda_codec_write(codec, nid, 0,
764 AC_VERB_SET_CONFIG_DEFAULT_BYTES_0 + i,
765 cfg & 0xff);
766 cfg >>= 8;
767 }
768}
769
770/* set the current pin config value for the given NID.
771 * the value is cached, and read via snd_hda_codec_get_pincfg()
772 */
773int snd_hda_add_pincfg(struct hda_codec *codec, struct snd_array *list,
774 hda_nid_t nid, unsigned int cfg)
775{
776 struct hda_pincfg *pin;
Takashi Iwai5e7b8e02009-02-23 09:45:59 +0100777 unsigned int oldcfg;
Takashi Iwai3be14142009-02-20 14:11:16 +0100778
Takashi Iwai5e7b8e02009-02-23 09:45:59 +0100779 oldcfg = snd_hda_codec_get_pincfg(codec, nid);
Takashi Iwai3be14142009-02-20 14:11:16 +0100780 pin = look_up_pincfg(codec, list, nid);
781 if (!pin) {
782 pin = snd_array_new(list);
783 if (!pin)
784 return -ENOMEM;
785 pin->nid = nid;
786 }
787 pin->cfg = cfg;
Takashi Iwai5e7b8e02009-02-23 09:45:59 +0100788
789 /* change only when needed; e.g. if the pincfg is already present
790 * in user_pins[], don't write it
791 */
792 cfg = snd_hda_codec_get_pincfg(codec, nid);
793 if (oldcfg != cfg)
794 set_pincfg(codec, nid, cfg);
Takashi Iwai3be14142009-02-20 14:11:16 +0100795 return 0;
796}
797
798int snd_hda_codec_set_pincfg(struct hda_codec *codec,
799 hda_nid_t nid, unsigned int cfg)
800{
Takashi Iwai346ff702009-02-23 09:42:57 +0100801 return snd_hda_add_pincfg(codec, &codec->driver_pins, nid, cfg);
Takashi Iwai3be14142009-02-20 14:11:16 +0100802}
803EXPORT_SYMBOL_HDA(snd_hda_codec_set_pincfg);
804
805/* get the current pin config value of the given pin NID */
806unsigned int snd_hda_codec_get_pincfg(struct hda_codec *codec, hda_nid_t nid)
807{
808 struct hda_pincfg *pin;
809
Takashi Iwai3be14142009-02-20 14:11:16 +0100810#ifdef CONFIG_SND_HDA_HWDEP
Takashi Iwai346ff702009-02-23 09:42:57 +0100811 pin = look_up_pincfg(codec, &codec->user_pins, nid);
Takashi Iwai3be14142009-02-20 14:11:16 +0100812 if (pin)
813 return pin->cfg;
814#endif
Takashi Iwai5e7b8e02009-02-23 09:45:59 +0100815 pin = look_up_pincfg(codec, &codec->driver_pins, nid);
816 if (pin)
817 return pin->cfg;
Takashi Iwai3be14142009-02-20 14:11:16 +0100818 pin = look_up_pincfg(codec, &codec->init_pins, nid);
819 if (pin)
820 return pin->cfg;
821 return 0;
822}
823EXPORT_SYMBOL_HDA(snd_hda_codec_get_pincfg);
824
825/* restore all current pin configs */
826static void restore_pincfgs(struct hda_codec *codec)
827{
828 int i;
829 for (i = 0; i < codec->init_pins.used; i++) {
830 struct hda_pincfg *pin = snd_array_elem(&codec->init_pins, i);
831 set_pincfg(codec, pin->nid,
832 snd_hda_codec_get_pincfg(codec, pin->nid));
833 }
834}
Takashi Iwai54d17402005-11-21 16:33:22 +0100835
Takashi Iwai01751f52007-08-10 16:59:39 +0200836static void init_hda_cache(struct hda_cache_rec *cache,
837 unsigned int record_size);
Takashi Iwai1fcaee62007-08-23 00:01:09 +0200838static void free_hda_cache(struct hda_cache_rec *cache);
Takashi Iwai01751f52007-08-10 16:59:39 +0200839
Takashi Iwai3be14142009-02-20 14:11:16 +0100840/* restore the initial pin cfgs and release all pincfg lists */
841static void restore_init_pincfgs(struct hda_codec *codec)
842{
Takashi Iwai346ff702009-02-23 09:42:57 +0100843 /* first free driver_pins and user_pins, then call restore_pincfg
Takashi Iwai3be14142009-02-20 14:11:16 +0100844 * so that only the values in init_pins are restored
845 */
Takashi Iwai346ff702009-02-23 09:42:57 +0100846 snd_array_free(&codec->driver_pins);
Takashi Iwai3be14142009-02-20 14:11:16 +0100847#ifdef CONFIG_SND_HDA_HWDEP
Takashi Iwai346ff702009-02-23 09:42:57 +0100848 snd_array_free(&codec->user_pins);
Takashi Iwai3be14142009-02-20 14:11:16 +0100849#endif
850 restore_pincfgs(codec);
851 snd_array_free(&codec->init_pins);
852}
853
Takashi Iwai54d17402005-11-21 16:33:22 +0100854/*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700855 * codec destructor
856 */
857static void snd_hda_codec_free(struct hda_codec *codec)
858{
Takashi Iwai0ba21762007-04-16 11:29:14 +0200859 if (!codec)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700860 return;
Takashi Iwai3be14142009-02-20 14:11:16 +0100861 restore_init_pincfgs(codec);
Takashi Iwaicb53c622007-08-10 17:21:45 +0200862#ifdef CONFIG_SND_HDA_POWER_SAVE
863 cancel_delayed_work(&codec->power_work);
Takashi Iwai6acaed32009-01-12 10:09:24 +0100864 flush_workqueue(codec->bus->workq);
Takashi Iwaicb53c622007-08-10 17:21:45 +0200865#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700866 list_del(&codec->list);
Takashi Iwaid13bd412008-07-30 15:01:45 +0200867 snd_array_free(&codec->mixers);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700868 codec->bus->caddr_tbl[codec->addr] = NULL;
869 if (codec->patch_ops.free)
870 codec->patch_ops.free(codec);
Takashi Iwai1289e9e2008-11-27 15:47:11 +0100871 module_put(codec->owner);
Takashi Iwai01751f52007-08-10 16:59:39 +0200872 free_hda_cache(&codec->amp_cache);
Takashi Iwaib3ac5632007-08-10 17:03:40 +0200873 free_hda_cache(&codec->cmd_cache);
Takashi Iwai812a2cc2009-05-16 10:00:49 +0200874 kfree(codec->vendor_name);
875 kfree(codec->chip_name);
Takashi Iwaif44ac832008-07-30 15:01:45 +0200876 kfree(codec->modelname);
Takashi Iwai54d17402005-11-21 16:33:22 +0100877 kfree(codec->wcaps);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700878 kfree(codec);
879}
880
Takashi Iwaibb6ac722009-03-13 09:02:42 +0100881static void hda_set_power_state(struct hda_codec *codec, hda_nid_t fg,
882 unsigned int power_state);
883
Linus Torvalds1da177e2005-04-16 15:20:36 -0700884/**
885 * snd_hda_codec_new - create a HDA codec
886 * @bus: the bus to assign
887 * @codec_addr: the codec address
888 * @codecp: the pointer to store the generated codec
889 *
890 * Returns 0 if successful, or a negative error code.
891 */
Takashi Iwai1289e9e2008-11-27 15:47:11 +0100892int /*__devinit*/ snd_hda_codec_new(struct hda_bus *bus, unsigned int codec_addr,
Takashi Iwaia1e21c92009-06-17 09:33:52 +0200893 struct hda_codec **codecp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700894{
895 struct hda_codec *codec;
Jaroslav Kyselaba443682008-08-13 20:55:32 +0200896 char component[31];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700897 int err;
898
Takashi Iwaida3cec32008-08-08 17:12:14 +0200899 if (snd_BUG_ON(!bus))
900 return -EINVAL;
901 if (snd_BUG_ON(codec_addr > HDA_MAX_CODEC_ADDRESS))
902 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700903
904 if (bus->caddr_tbl[codec_addr]) {
Takashi Iwai0ba21762007-04-16 11:29:14 +0200905 snd_printk(KERN_ERR "hda_codec: "
906 "address 0x%x is already occupied\n", codec_addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700907 return -EBUSY;
908 }
909
Takashi Iwaie560d8d2005-09-09 14:21:46 +0200910 codec = kzalloc(sizeof(*codec), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700911 if (codec == NULL) {
912 snd_printk(KERN_ERR "can't allocate struct hda_codec\n");
913 return -ENOMEM;
914 }
915
916 codec->bus = bus;
917 codec->addr = codec_addr;
Ingo Molnar62932df2006-01-16 16:34:20 +0100918 mutex_init(&codec->spdif_mutex);
Wu Fengguang5a9e02e2009-01-09 16:45:24 +0800919 mutex_init(&codec->control_mutex);
Takashi Iwai01751f52007-08-10 16:59:39 +0200920 init_hda_cache(&codec->amp_cache, sizeof(struct hda_amp_info));
Takashi Iwaib3ac5632007-08-10 17:03:40 +0200921 init_hda_cache(&codec->cmd_cache, sizeof(struct hda_cache_head));
Takashi Iwaid13bd412008-07-30 15:01:45 +0200922 snd_array_init(&codec->mixers, sizeof(struct snd_kcontrol *), 32);
Takashi Iwai3be14142009-02-20 14:11:16 +0100923 snd_array_init(&codec->init_pins, sizeof(struct hda_pincfg), 16);
Takashi Iwai346ff702009-02-23 09:42:57 +0100924 snd_array_init(&codec->driver_pins, sizeof(struct hda_pincfg), 16);
Takashi Iwai6c1f45e2008-07-30 15:01:45 +0200925 if (codec->bus->modelname) {
926 codec->modelname = kstrdup(codec->bus->modelname, GFP_KERNEL);
927 if (!codec->modelname) {
928 snd_hda_codec_free(codec);
929 return -ENODEV;
930 }
931 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700932
Takashi Iwaicb53c622007-08-10 17:21:45 +0200933#ifdef CONFIG_SND_HDA_POWER_SAVE
934 INIT_DELAYED_WORK(&codec->power_work, hda_power_work);
935 /* snd_hda_codec_new() marks the codec as power-up, and leave it as is.
936 * the caller has to power down appropriatley after initialization
937 * phase.
938 */
939 hda_keep_power_on(codec);
940#endif
941
Linus Torvalds1da177e2005-04-16 15:20:36 -0700942 list_add_tail(&codec->list, &bus->codec_list);
943 bus->caddr_tbl[codec_addr] = codec;
944
Takashi Iwai0ba21762007-04-16 11:29:14 +0200945 codec->vendor_id = snd_hda_param_read(codec, AC_NODE_ROOT,
946 AC_PAR_VENDOR_ID);
Takashi Iwai111d3af2006-02-16 18:17:58 +0100947 if (codec->vendor_id == -1)
948 /* read again, hopefully the access method was corrected
949 * in the last read...
950 */
951 codec->vendor_id = snd_hda_param_read(codec, AC_NODE_ROOT,
952 AC_PAR_VENDOR_ID);
Takashi Iwai0ba21762007-04-16 11:29:14 +0200953 codec->subsystem_id = snd_hda_param_read(codec, AC_NODE_ROOT,
954 AC_PAR_SUBSYSTEM_ID);
955 codec->revision_id = snd_hda_param_read(codec, AC_NODE_ROOT,
956 AC_PAR_REV_ID);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700957
Sasha Khapyorsky673b6832005-08-11 11:00:16 +0200958 setup_fg_nodes(codec);
Takashi Iwai0ba21762007-04-16 11:29:14 +0200959 if (!codec->afg && !codec->mfg) {
Sasha Khapyorsky673b6832005-08-11 11:00:16 +0200960 snd_printdd("hda_codec: no AFG or MFG node found\n");
Takashi Iwai3be14142009-02-20 14:11:16 +0100961 err = -ENODEV;
962 goto error;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700963 }
964
Takashi Iwai3be14142009-02-20 14:11:16 +0100965 err = read_widget_caps(codec, codec->afg ? codec->afg : codec->mfg);
966 if (err < 0) {
Takashi Iwai54d17402005-11-21 16:33:22 +0100967 snd_printk(KERN_ERR "hda_codec: cannot malloc\n");
Takashi Iwai3be14142009-02-20 14:11:16 +0100968 goto error;
Takashi Iwai54d17402005-11-21 16:33:22 +0100969 }
Takashi Iwai3be14142009-02-20 14:11:16 +0100970 err = read_pin_defaults(codec);
971 if (err < 0)
972 goto error;
Takashi Iwai54d17402005-11-21 16:33:22 +0100973
Takashi Iwai0ba21762007-04-16 11:29:14 +0200974 if (!codec->subsystem_id) {
Takashi Iwai86284e42005-10-11 15:05:54 +0200975 hda_nid_t nid = codec->afg ? codec->afg : codec->mfg;
Takashi Iwai0ba21762007-04-16 11:29:14 +0200976 codec->subsystem_id =
977 snd_hda_codec_read(codec, nid, 0,
978 AC_VERB_GET_SUBSYSTEM_ID, 0);
Takashi Iwai86284e42005-10-11 15:05:54 +0200979 }
980
Takashi Iwaibb6ac722009-03-13 09:02:42 +0100981 /* power-up all before initialization */
982 hda_set_power_state(codec,
983 codec->afg ? codec->afg : codec->mfg,
984 AC_PWRST_D0);
985
Takashi Iwai6c1f45e2008-07-30 15:01:45 +0200986 snd_hda_codec_proc_new(codec);
987
Takashi Iwai6c1f45e2008-07-30 15:01:45 +0200988 snd_hda_create_hwdep(codec);
Takashi Iwai6c1f45e2008-07-30 15:01:45 +0200989
990 sprintf(component, "HDA:%08x,%08x,%08x", codec->vendor_id,
991 codec->subsystem_id, codec->revision_id);
992 snd_component_add(codec->bus->card, component);
993
994 if (codecp)
995 *codecp = codec;
996 return 0;
Takashi Iwai3be14142009-02-20 14:11:16 +0100997
998 error:
999 snd_hda_codec_free(codec);
1000 return err;
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001001}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001002EXPORT_SYMBOL_HDA(snd_hda_codec_new);
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001003
1004int snd_hda_codec_configure(struct hda_codec *codec)
1005{
1006 int err;
1007
Takashi Iwaid5ad6302007-03-07 15:55:59 +01001008 codec->preset = find_codec_preset(codec);
Takashi Iwai812a2cc2009-05-16 10:00:49 +02001009 if (!codec->vendor_name || !codec->chip_name) {
Takashi Iwaif44ac832008-07-30 15:01:45 +02001010 err = get_codec_name(codec);
1011 if (err < 0)
1012 return err;
1013 }
Takashi Iwai43ea1d42007-04-26 19:12:08 +02001014 /* audio codec should override the mixer name */
Takashi Iwaif44ac832008-07-30 15:01:45 +02001015 if (codec->afg || !*codec->bus->card->mixername)
Takashi Iwai812a2cc2009-05-16 10:00:49 +02001016 snprintf(codec->bus->card->mixername,
1017 sizeof(codec->bus->card->mixername),
1018 "%s %s", codec->vendor_name, codec->chip_name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001019
Takashi Iwai82467612007-07-27 19:15:54 +02001020 if (is_generic_config(codec)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001021 err = snd_hda_parse_generic_codec(codec);
Takashi Iwai82467612007-07-27 19:15:54 +02001022 goto patched;
1023 }
Takashi Iwai82467612007-07-27 19:15:54 +02001024 if (codec->preset && codec->preset->patch) {
1025 err = codec->preset->patch(codec);
1026 goto patched;
1027 }
1028
1029 /* call the default parser */
Takashi Iwai82467612007-07-27 19:15:54 +02001030 err = snd_hda_parse_generic_codec(codec);
Takashi Iwai35a1e0c2007-10-19 08:13:40 +02001031 if (err < 0)
1032 printk(KERN_ERR "hda-codec: No codec parser is available\n");
Takashi Iwai82467612007-07-27 19:15:54 +02001033
1034 patched:
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001035 if (!err && codec->patch_ops.unsol_event)
1036 err = init_unsol_queue(codec->bus);
1037 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001038}
Takashi Iwaia1e21c92009-06-17 09:33:52 +02001039EXPORT_SYMBOL_HDA(snd_hda_codec_configure);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001040
1041/**
1042 * snd_hda_codec_setup_stream - set up the codec for streaming
1043 * @codec: the CODEC to set up
1044 * @nid: the NID to set up
1045 * @stream_tag: stream tag to pass, it's between 0x1 and 0xf.
1046 * @channel_id: channel id to pass, zero based.
1047 * @format: stream format.
1048 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02001049void snd_hda_codec_setup_stream(struct hda_codec *codec, hda_nid_t nid,
1050 u32 stream_tag,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001051 int channel_id, int format)
1052{
Takashi Iwai0ba21762007-04-16 11:29:14 +02001053 if (!nid)
Takashi Iwaid21b37e2005-04-20 13:45:55 +02001054 return;
1055
Takashi Iwai0ba21762007-04-16 11:29:14 +02001056 snd_printdd("hda_codec_setup_stream: "
1057 "NID=0x%x, stream=0x%x, channel=%d, format=0x%x\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07001058 nid, stream_tag, channel_id, format);
1059 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CHANNEL_STREAMID,
1060 (stream_tag << 4) | channel_id);
1061 msleep(1);
1062 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_STREAM_FORMAT, format);
1063}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001064EXPORT_SYMBOL_HDA(snd_hda_codec_setup_stream);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001065
Takashi Iwai888afa12008-03-18 09:57:50 +01001066void snd_hda_codec_cleanup_stream(struct hda_codec *codec, hda_nid_t nid)
1067{
1068 if (!nid)
1069 return;
1070
1071 snd_printdd("hda_codec_cleanup_stream: NID=0x%x\n", nid);
1072 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CHANNEL_STREAMID, 0);
1073#if 0 /* keep the format */
1074 msleep(1);
1075 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_STREAM_FORMAT, 0);
1076#endif
1077}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001078EXPORT_SYMBOL_HDA(snd_hda_codec_cleanup_stream);
Takashi Iwai888afa12008-03-18 09:57:50 +01001079
Linus Torvalds1da177e2005-04-16 15:20:36 -07001080/*
1081 * amp access functions
1082 */
1083
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001084/* FIXME: more better hash key? */
1085#define HDA_HASH_KEY(nid,dir,idx) (u32)((nid) + ((idx) << 16) + ((dir) << 24))
Takashi Iwai1327a322009-03-23 13:07:47 +01001086#define HDA_HASH_PINCAP_KEY(nid) (u32)((nid) + (0x02 << 24))
Takashi Iwai92c7c8a2009-03-24 07:32:14 +01001087#define HDA_HASH_PARPCM_KEY(nid) (u32)((nid) + (0x03 << 24))
1088#define HDA_HASH_PARSTR_KEY(nid) (u32)((nid) + (0x04 << 24))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001089#define INFO_AMP_CAPS (1<<0)
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001090#define INFO_AMP_VOL(ch) (1 << (1 + (ch)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001091
1092/* initialize the hash table */
Takashi Iwai1289e9e2008-11-27 15:47:11 +01001093static void /*__devinit*/ init_hda_cache(struct hda_cache_rec *cache,
Takashi Iwai01751f52007-08-10 16:59:39 +02001094 unsigned int record_size)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001095{
Takashi Iwai01751f52007-08-10 16:59:39 +02001096 memset(cache, 0, sizeof(*cache));
1097 memset(cache->hash, 0xff, sizeof(cache->hash));
Takashi Iwai603c4012008-07-30 15:01:44 +02001098 snd_array_init(&cache->buf, record_size, 64);
Takashi Iwai01751f52007-08-10 16:59:39 +02001099}
1100
Takashi Iwai1fcaee62007-08-23 00:01:09 +02001101static void free_hda_cache(struct hda_cache_rec *cache)
Takashi Iwai01751f52007-08-10 16:59:39 +02001102{
Takashi Iwai603c4012008-07-30 15:01:44 +02001103 snd_array_free(&cache->buf);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001104}
1105
1106/* query the hash. allocate an entry if not found. */
Takashi Iwai01751f52007-08-10 16:59:39 +02001107static struct hda_cache_head *get_alloc_hash(struct hda_cache_rec *cache,
1108 u32 key)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001109{
Takashi Iwai01751f52007-08-10 16:59:39 +02001110 u16 idx = key % (u16)ARRAY_SIZE(cache->hash);
1111 u16 cur = cache->hash[idx];
1112 struct hda_cache_head *info;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001113
1114 while (cur != 0xffff) {
Takashi Iwaif43aa022008-11-10 16:24:26 +01001115 info = snd_array_elem(&cache->buf, cur);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001116 if (info->key == key)
1117 return info;
1118 cur = info->next;
1119 }
1120
1121 /* add a new hash entry */
Takashi Iwai603c4012008-07-30 15:01:44 +02001122 info = snd_array_new(&cache->buf);
Takashi Iwaic2174292008-11-07 00:23:30 +01001123 if (!info)
1124 return NULL;
Takashi Iwaif43aa022008-11-10 16:24:26 +01001125 cur = snd_array_index(&cache->buf, info);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001126 info->key = key;
Takashi Iwai01751f52007-08-10 16:59:39 +02001127 info->val = 0;
1128 info->next = cache->hash[idx];
1129 cache->hash[idx] = cur;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001130
1131 return info;
1132}
1133
Takashi Iwai01751f52007-08-10 16:59:39 +02001134/* query and allocate an amp hash entry */
1135static inline struct hda_amp_info *
1136get_alloc_amp_hash(struct hda_codec *codec, u32 key)
1137{
1138 return (struct hda_amp_info *)get_alloc_hash(&codec->amp_cache, key);
1139}
1140
Linus Torvalds1da177e2005-04-16 15:20:36 -07001141/*
1142 * query AMP capabilities for the given widget and direction
1143 */
Matthew Ranostay09a99952008-01-24 11:49:21 +01001144u32 query_amp_caps(struct hda_codec *codec, hda_nid_t nid, int direction)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001145{
Takashi Iwai0ba21762007-04-16 11:29:14 +02001146 struct hda_amp_info *info;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001147
Takashi Iwai0ba21762007-04-16 11:29:14 +02001148 info = get_alloc_amp_hash(codec, HDA_HASH_KEY(nid, direction, 0));
1149 if (!info)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001150 return 0;
Takashi Iwai01751f52007-08-10 16:59:39 +02001151 if (!(info->head.val & INFO_AMP_CAPS)) {
Takashi Iwai0ba21762007-04-16 11:29:14 +02001152 if (!(get_wcaps(codec, nid) & AC_WCAP_AMP_OVRD))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001153 nid = codec->afg;
Takashi Iwai0ba21762007-04-16 11:29:14 +02001154 info->amp_caps = snd_hda_param_read(codec, nid,
1155 direction == HDA_OUTPUT ?
1156 AC_PAR_AMP_OUT_CAP :
1157 AC_PAR_AMP_IN_CAP);
Takashi Iwaib75e53f2007-05-10 16:56:09 +02001158 if (info->amp_caps)
Takashi Iwai01751f52007-08-10 16:59:39 +02001159 info->head.val |= INFO_AMP_CAPS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001160 }
1161 return info->amp_caps;
1162}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001163EXPORT_SYMBOL_HDA(query_amp_caps);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001164
Takashi Iwai897cc182007-05-29 19:01:37 +02001165int snd_hda_override_amp_caps(struct hda_codec *codec, hda_nid_t nid, int dir,
1166 unsigned int caps)
1167{
1168 struct hda_amp_info *info;
1169
1170 info = get_alloc_amp_hash(codec, HDA_HASH_KEY(nid, dir, 0));
1171 if (!info)
1172 return -EINVAL;
1173 info->amp_caps = caps;
Takashi Iwai01751f52007-08-10 16:59:39 +02001174 info->head.val |= INFO_AMP_CAPS;
Takashi Iwai897cc182007-05-29 19:01:37 +02001175 return 0;
1176}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001177EXPORT_SYMBOL_HDA(snd_hda_override_amp_caps);
Takashi Iwai897cc182007-05-29 19:01:37 +02001178
Takashi Iwai92c7c8a2009-03-24 07:32:14 +01001179static unsigned int
1180query_caps_hash(struct hda_codec *codec, hda_nid_t nid, u32 key,
1181 unsigned int (*func)(struct hda_codec *, hda_nid_t))
Takashi Iwai1327a322009-03-23 13:07:47 +01001182{
1183 struct hda_amp_info *info;
1184
Takashi Iwai92c7c8a2009-03-24 07:32:14 +01001185 info = get_alloc_amp_hash(codec, key);
Takashi Iwai1327a322009-03-23 13:07:47 +01001186 if (!info)
1187 return 0;
1188 if (!info->head.val) {
Takashi Iwai1327a322009-03-23 13:07:47 +01001189 info->head.val |= INFO_AMP_CAPS;
Takashi Iwai92c7c8a2009-03-24 07:32:14 +01001190 info->amp_caps = func(codec, nid);
Takashi Iwai1327a322009-03-23 13:07:47 +01001191 }
1192 return info->amp_caps;
1193}
Takashi Iwai92c7c8a2009-03-24 07:32:14 +01001194
1195static unsigned int read_pin_cap(struct hda_codec *codec, hda_nid_t nid)
1196{
1197 return snd_hda_param_read(codec, nid, AC_PAR_PIN_CAP);
1198}
1199
1200u32 snd_hda_query_pin_caps(struct hda_codec *codec, hda_nid_t nid)
1201{
1202 return query_caps_hash(codec, nid, HDA_HASH_PINCAP_KEY(nid),
1203 read_pin_cap);
1204}
Takashi Iwai1327a322009-03-23 13:07:47 +01001205EXPORT_SYMBOL_HDA(snd_hda_query_pin_caps);
1206
Linus Torvalds1da177e2005-04-16 15:20:36 -07001207/*
1208 * read the current volume to info
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001209 * if the cache exists, read the cache value.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001210 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02001211static unsigned int get_vol_mute(struct hda_codec *codec,
1212 struct hda_amp_info *info, hda_nid_t nid,
1213 int ch, int direction, int index)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001214{
1215 u32 val, parm;
1216
Takashi Iwai01751f52007-08-10 16:59:39 +02001217 if (info->head.val & INFO_AMP_VOL(ch))
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001218 return info->vol[ch];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001219
1220 parm = ch ? AC_AMP_GET_RIGHT : AC_AMP_GET_LEFT;
1221 parm |= direction == HDA_OUTPUT ? AC_AMP_GET_OUTPUT : AC_AMP_GET_INPUT;
1222 parm |= index;
Takashi Iwai0ba21762007-04-16 11:29:14 +02001223 val = snd_hda_codec_read(codec, nid, 0,
1224 AC_VERB_GET_AMP_GAIN_MUTE, parm);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001225 info->vol[ch] = val & 0xff;
Takashi Iwai01751f52007-08-10 16:59:39 +02001226 info->head.val |= INFO_AMP_VOL(ch);
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001227 return info->vol[ch];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001228}
1229
1230/*
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001231 * write the current volume in info to the h/w and update the cache
Linus Torvalds1da177e2005-04-16 15:20:36 -07001232 */
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001233static void put_vol_mute(struct hda_codec *codec, struct hda_amp_info *info,
Takashi Iwai0ba21762007-04-16 11:29:14 +02001234 hda_nid_t nid, int ch, int direction, int index,
1235 int val)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001236{
1237 u32 parm;
1238
1239 parm = ch ? AC_AMP_SET_RIGHT : AC_AMP_SET_LEFT;
1240 parm |= direction == HDA_OUTPUT ? AC_AMP_SET_OUTPUT : AC_AMP_SET_INPUT;
1241 parm |= index << AC_AMP_SET_INDEX_SHIFT;
1242 parm |= val;
1243 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, parm);
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001244 info->vol[ch] = val;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001245}
1246
1247/*
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001248 * read AMP value. The volume is between 0 to 0x7f, 0x80 = mute bit.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001249 */
Takashi Iwai834be882006-03-01 14:16:17 +01001250int snd_hda_codec_amp_read(struct hda_codec *codec, hda_nid_t nid, int ch,
1251 int direction, int index)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001252{
Takashi Iwai0ba21762007-04-16 11:29:14 +02001253 struct hda_amp_info *info;
1254 info = get_alloc_amp_hash(codec, HDA_HASH_KEY(nid, direction, index));
1255 if (!info)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001256 return 0;
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001257 return get_vol_mute(codec, info, nid, ch, direction, index);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001258}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001259EXPORT_SYMBOL_HDA(snd_hda_codec_amp_read);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001260
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001261/*
1262 * update the AMP value, mask = bit mask to set, val = the value
1263 */
Takashi Iwai834be882006-03-01 14:16:17 +01001264int snd_hda_codec_amp_update(struct hda_codec *codec, hda_nid_t nid, int ch,
1265 int direction, int idx, int mask, int val)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001266{
Takashi Iwai0ba21762007-04-16 11:29:14 +02001267 struct hda_amp_info *info;
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001268
Takashi Iwai0ba21762007-04-16 11:29:14 +02001269 info = get_alloc_amp_hash(codec, HDA_HASH_KEY(nid, direction, idx));
1270 if (!info)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001271 return 0;
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001272 val &= mask;
1273 val |= get_vol_mute(codec, info, nid, ch, direction, idx) & ~mask;
Takashi Iwai82beb8f2007-08-10 17:09:26 +02001274 if (info->vol[ch] == val)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001275 return 0;
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001276 put_vol_mute(codec, info, nid, ch, direction, idx, val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001277 return 1;
1278}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001279EXPORT_SYMBOL_HDA(snd_hda_codec_amp_update);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001280
Takashi Iwai47fd8302007-08-10 17:11:07 +02001281/*
1282 * update the AMP stereo with the same mask and value
1283 */
1284int snd_hda_codec_amp_stereo(struct hda_codec *codec, hda_nid_t nid,
1285 int direction, int idx, int mask, int val)
1286{
1287 int ch, ret = 0;
1288 for (ch = 0; ch < 2; ch++)
1289 ret |= snd_hda_codec_amp_update(codec, nid, ch, direction,
1290 idx, mask, val);
1291 return ret;
1292}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001293EXPORT_SYMBOL_HDA(snd_hda_codec_amp_stereo);
Takashi Iwai47fd8302007-08-10 17:11:07 +02001294
Takashi Iwaicb53c622007-08-10 17:21:45 +02001295#ifdef SND_HDA_NEEDS_RESUME
Takashi Iwaib3ac5632007-08-10 17:03:40 +02001296/* resume the all amp commands from the cache */
1297void snd_hda_codec_resume_amp(struct hda_codec *codec)
1298{
Takashi Iwai603c4012008-07-30 15:01:44 +02001299 struct hda_amp_info *buffer = codec->amp_cache.buf.list;
Takashi Iwaib3ac5632007-08-10 17:03:40 +02001300 int i;
1301
Takashi Iwai603c4012008-07-30 15:01:44 +02001302 for (i = 0; i < codec->amp_cache.buf.used; i++, buffer++) {
Takashi Iwaib3ac5632007-08-10 17:03:40 +02001303 u32 key = buffer->head.key;
1304 hda_nid_t nid;
1305 unsigned int idx, dir, ch;
1306 if (!key)
1307 continue;
1308 nid = key & 0xff;
1309 idx = (key >> 16) & 0xff;
1310 dir = (key >> 24) & 0xff;
1311 for (ch = 0; ch < 2; ch++) {
1312 if (!(buffer->head.val & INFO_AMP_VOL(ch)))
1313 continue;
1314 put_vol_mute(codec, buffer, nid, ch, dir, idx,
1315 buffer->vol[ch]);
1316 }
1317 }
1318}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001319EXPORT_SYMBOL_HDA(snd_hda_codec_resume_amp);
Takashi Iwaicb53c622007-08-10 17:21:45 +02001320#endif /* SND_HDA_NEEDS_RESUME */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001321
Linus Torvalds1da177e2005-04-16 15:20:36 -07001322/* volume */
Takashi Iwai0ba21762007-04-16 11:29:14 +02001323int snd_hda_mixer_amp_volume_info(struct snd_kcontrol *kcontrol,
1324 struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001325{
1326 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1327 u16 nid = get_amp_nid(kcontrol);
1328 u8 chs = get_amp_channels(kcontrol);
1329 int dir = get_amp_direction(kcontrol);
Takashi Iwai29fdbec2009-01-20 13:07:55 +01001330 unsigned int ofs = get_amp_offset(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001331 u32 caps;
1332
1333 caps = query_amp_caps(codec, nid, dir);
Takashi Iwai0ba21762007-04-16 11:29:14 +02001334 /* num steps */
1335 caps = (caps & AC_AMPCAP_NUM_STEPS) >> AC_AMPCAP_NUM_STEPS_SHIFT;
1336 if (!caps) {
1337 printk(KERN_WARNING "hda_codec: "
Takashi Iwai9c8f2ab2008-01-11 16:12:23 +01001338 "num_steps = 0 for NID=0x%x (ctl = %s)\n", nid,
1339 kcontrol->id.name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001340 return -EINVAL;
1341 }
Takashi Iwai29fdbec2009-01-20 13:07:55 +01001342 if (ofs < caps)
1343 caps -= ofs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001344 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
1345 uinfo->count = chs == 3 ? 2 : 1;
1346 uinfo->value.integer.min = 0;
1347 uinfo->value.integer.max = caps;
1348 return 0;
1349}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001350EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_volume_info);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001351
Takashi Iwai29fdbec2009-01-20 13:07:55 +01001352
1353static inline unsigned int
1354read_amp_value(struct hda_codec *codec, hda_nid_t nid,
1355 int ch, int dir, int idx, unsigned int ofs)
1356{
1357 unsigned int val;
1358 val = snd_hda_codec_amp_read(codec, nid, ch, dir, idx);
1359 val &= HDA_AMP_VOLMASK;
1360 if (val >= ofs)
1361 val -= ofs;
1362 else
1363 val = 0;
1364 return val;
1365}
1366
1367static inline int
1368update_amp_value(struct hda_codec *codec, hda_nid_t nid,
1369 int ch, int dir, int idx, unsigned int ofs,
1370 unsigned int val)
1371{
1372 if (val > 0)
1373 val += ofs;
1374 return snd_hda_codec_amp_update(codec, nid, ch, dir, idx,
1375 HDA_AMP_VOLMASK, val);
1376}
1377
Takashi Iwai0ba21762007-04-16 11:29:14 +02001378int snd_hda_mixer_amp_volume_get(struct snd_kcontrol *kcontrol,
1379 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001380{
1381 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1382 hda_nid_t nid = get_amp_nid(kcontrol);
1383 int chs = get_amp_channels(kcontrol);
1384 int dir = get_amp_direction(kcontrol);
1385 int idx = get_amp_index(kcontrol);
Takashi Iwai29fdbec2009-01-20 13:07:55 +01001386 unsigned int ofs = get_amp_offset(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001387 long *valp = ucontrol->value.integer.value;
1388
1389 if (chs & 1)
Takashi Iwai29fdbec2009-01-20 13:07:55 +01001390 *valp++ = read_amp_value(codec, nid, 0, dir, idx, ofs);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001391 if (chs & 2)
Takashi Iwai29fdbec2009-01-20 13:07:55 +01001392 *valp = read_amp_value(codec, nid, 1, dir, idx, ofs);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001393 return 0;
1394}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001395EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_volume_get);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001396
Takashi Iwai0ba21762007-04-16 11:29:14 +02001397int snd_hda_mixer_amp_volume_put(struct snd_kcontrol *kcontrol,
1398 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001399{
1400 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1401 hda_nid_t nid = get_amp_nid(kcontrol);
1402 int chs = get_amp_channels(kcontrol);
1403 int dir = get_amp_direction(kcontrol);
1404 int idx = get_amp_index(kcontrol);
Takashi Iwai29fdbec2009-01-20 13:07:55 +01001405 unsigned int ofs = get_amp_offset(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001406 long *valp = ucontrol->value.integer.value;
1407 int change = 0;
1408
Takashi Iwaicb53c622007-08-10 17:21:45 +02001409 snd_hda_power_up(codec);
Nicolas Grazianob9f5a892005-07-29 12:17:20 +02001410 if (chs & 1) {
Takashi Iwai29fdbec2009-01-20 13:07:55 +01001411 change = update_amp_value(codec, nid, 0, dir, idx, ofs, *valp);
Nicolas Grazianob9f5a892005-07-29 12:17:20 +02001412 valp++;
1413 }
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001414 if (chs & 2)
Takashi Iwai29fdbec2009-01-20 13:07:55 +01001415 change |= update_amp_value(codec, nid, 1, dir, idx, ofs, *valp);
Takashi Iwaicb53c622007-08-10 17:21:45 +02001416 snd_hda_power_down(codec);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001417 return change;
1418}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001419EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_volume_put);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001420
Jaroslav Kysela302e9c52006-07-05 17:39:49 +02001421int snd_hda_mixer_amp_tlv(struct snd_kcontrol *kcontrol, int op_flag,
1422 unsigned int size, unsigned int __user *_tlv)
1423{
1424 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1425 hda_nid_t nid = get_amp_nid(kcontrol);
1426 int dir = get_amp_direction(kcontrol);
Takashi Iwai29fdbec2009-01-20 13:07:55 +01001427 unsigned int ofs = get_amp_offset(kcontrol);
Jaroslav Kysela302e9c52006-07-05 17:39:49 +02001428 u32 caps, val1, val2;
1429
1430 if (size < 4 * sizeof(unsigned int))
1431 return -ENOMEM;
1432 caps = query_amp_caps(codec, nid, dir);
Takashi Iwai0ba21762007-04-16 11:29:14 +02001433 val2 = (caps & AC_AMPCAP_STEP_SIZE) >> AC_AMPCAP_STEP_SIZE_SHIFT;
1434 val2 = (val2 + 1) * 25;
Jaroslav Kysela302e9c52006-07-05 17:39:49 +02001435 val1 = -((caps & AC_AMPCAP_OFFSET) >> AC_AMPCAP_OFFSET_SHIFT);
Takashi Iwai29fdbec2009-01-20 13:07:55 +01001436 val1 += ofs;
Jaroslav Kysela302e9c52006-07-05 17:39:49 +02001437 val1 = ((int)val1) * ((int)val2);
Jaroslav Kysela302e9c52006-07-05 17:39:49 +02001438 if (put_user(SNDRV_CTL_TLVT_DB_SCALE, _tlv))
1439 return -EFAULT;
1440 if (put_user(2 * sizeof(unsigned int), _tlv + 1))
1441 return -EFAULT;
1442 if (put_user(val1, _tlv + 2))
1443 return -EFAULT;
1444 if (put_user(val2, _tlv + 3))
1445 return -EFAULT;
1446 return 0;
1447}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001448EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_tlv);
Jaroslav Kysela302e9c52006-07-05 17:39:49 +02001449
Takashi Iwai2134ea42008-01-10 16:53:55 +01001450/*
1451 * set (static) TLV for virtual master volume; recalculated as max 0dB
1452 */
1453void snd_hda_set_vmaster_tlv(struct hda_codec *codec, hda_nid_t nid, int dir,
1454 unsigned int *tlv)
1455{
1456 u32 caps;
1457 int nums, step;
1458
1459 caps = query_amp_caps(codec, nid, dir);
1460 nums = (caps & AC_AMPCAP_NUM_STEPS) >> AC_AMPCAP_NUM_STEPS_SHIFT;
1461 step = (caps & AC_AMPCAP_STEP_SIZE) >> AC_AMPCAP_STEP_SIZE_SHIFT;
1462 step = (step + 1) * 25;
1463 tlv[0] = SNDRV_CTL_TLVT_DB_SCALE;
1464 tlv[1] = 2 * sizeof(unsigned int);
1465 tlv[2] = -nums * step;
1466 tlv[3] = step;
1467}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001468EXPORT_SYMBOL_HDA(snd_hda_set_vmaster_tlv);
Takashi Iwai2134ea42008-01-10 16:53:55 +01001469
1470/* find a mixer control element with the given name */
Takashi Iwai09f99702008-02-04 12:31:13 +01001471static struct snd_kcontrol *
1472_snd_hda_find_mixer_ctl(struct hda_codec *codec,
1473 const char *name, int idx)
Takashi Iwai2134ea42008-01-10 16:53:55 +01001474{
1475 struct snd_ctl_elem_id id;
1476 memset(&id, 0, sizeof(id));
1477 id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
Takashi Iwai09f99702008-02-04 12:31:13 +01001478 id.index = idx;
Takashi Iwai18cb7102009-04-16 10:22:24 +02001479 if (snd_BUG_ON(strlen(name) >= sizeof(id.name)))
1480 return NULL;
Takashi Iwai2134ea42008-01-10 16:53:55 +01001481 strcpy(id.name, name);
1482 return snd_ctl_find_id(codec->bus->card, &id);
1483}
1484
Takashi Iwai09f99702008-02-04 12:31:13 +01001485struct snd_kcontrol *snd_hda_find_mixer_ctl(struct hda_codec *codec,
1486 const char *name)
1487{
1488 return _snd_hda_find_mixer_ctl(codec, name, 0);
1489}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001490EXPORT_SYMBOL_HDA(snd_hda_find_mixer_ctl);
Takashi Iwai09f99702008-02-04 12:31:13 +01001491
Takashi Iwaid13bd412008-07-30 15:01:45 +02001492/* Add a control element and assign to the codec */
1493int snd_hda_ctl_add(struct hda_codec *codec, struct snd_kcontrol *kctl)
1494{
1495 int err;
1496 struct snd_kcontrol **knewp;
1497
1498 err = snd_ctl_add(codec->bus->card, kctl);
1499 if (err < 0)
1500 return err;
1501 knewp = snd_array_new(&codec->mixers);
1502 if (!knewp)
1503 return -ENOMEM;
1504 *knewp = kctl;
1505 return 0;
1506}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001507EXPORT_SYMBOL_HDA(snd_hda_ctl_add);
Takashi Iwaid13bd412008-07-30 15:01:45 +02001508
1509/* Clear all controls assigned to the given codec */
1510void snd_hda_ctls_clear(struct hda_codec *codec)
1511{
1512 int i;
1513 struct snd_kcontrol **kctls = codec->mixers.list;
1514 for (i = 0; i < codec->mixers.used; i++)
1515 snd_ctl_remove(codec->bus->card, kctls[i]);
1516 snd_array_free(&codec->mixers);
1517}
1518
Takashi Iwaia65d6292009-02-23 16:57:04 +01001519/* pseudo device locking
1520 * toggle card->shutdown to allow/disallow the device access (as a hack)
1521 */
1522static int hda_lock_devices(struct snd_card *card)
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001523{
Takashi Iwaia65d6292009-02-23 16:57:04 +01001524 spin_lock(&card->files_lock);
1525 if (card->shutdown) {
1526 spin_unlock(&card->files_lock);
1527 return -EINVAL;
1528 }
1529 card->shutdown = 1;
1530 spin_unlock(&card->files_lock);
1531 return 0;
1532}
1533
1534static void hda_unlock_devices(struct snd_card *card)
1535{
1536 spin_lock(&card->files_lock);
1537 card->shutdown = 0;
1538 spin_unlock(&card->files_lock);
1539}
1540
1541int snd_hda_codec_reset(struct hda_codec *codec)
1542{
1543 struct snd_card *card = codec->bus->card;
1544 int i, pcm;
1545
1546 if (hda_lock_devices(card) < 0)
1547 return -EBUSY;
1548 /* check whether the codec isn't used by any mixer or PCM streams */
1549 if (!list_empty(&card->ctl_files)) {
1550 hda_unlock_devices(card);
1551 return -EBUSY;
1552 }
1553 for (pcm = 0; pcm < codec->num_pcms; pcm++) {
1554 struct hda_pcm *cpcm = &codec->pcm_info[pcm];
1555 if (!cpcm->pcm)
1556 continue;
1557 if (cpcm->pcm->streams[0].substream_opened ||
1558 cpcm->pcm->streams[1].substream_opened) {
1559 hda_unlock_devices(card);
1560 return -EBUSY;
1561 }
1562 }
1563
1564 /* OK, let it free */
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001565
1566#ifdef CONFIG_SND_HDA_POWER_SAVE
1567 cancel_delayed_work(&codec->power_work);
Takashi Iwai6acaed32009-01-12 10:09:24 +01001568 flush_workqueue(codec->bus->workq);
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001569#endif
1570 snd_hda_ctls_clear(codec);
1571 /* relase PCMs */
1572 for (i = 0; i < codec->num_pcms; i++) {
Takashi Iwai529bd6c2008-11-27 14:17:01 +01001573 if (codec->pcm_info[i].pcm) {
Takashi Iwaia65d6292009-02-23 16:57:04 +01001574 snd_device_free(card, codec->pcm_info[i].pcm);
Takashi Iwai529bd6c2008-11-27 14:17:01 +01001575 clear_bit(codec->pcm_info[i].device,
1576 codec->bus->pcm_dev_bits);
1577 }
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001578 }
1579 if (codec->patch_ops.free)
1580 codec->patch_ops.free(codec);
Takashi Iwai56d17712008-11-28 14:36:23 +01001581 codec->proc_widget_hook = NULL;
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001582 codec->spec = NULL;
1583 free_hda_cache(&codec->amp_cache);
1584 free_hda_cache(&codec->cmd_cache);
Takashi Iwai827057f2008-12-19 10:12:02 +01001585 init_hda_cache(&codec->amp_cache, sizeof(struct hda_amp_info));
1586 init_hda_cache(&codec->cmd_cache, sizeof(struct hda_cache_head));
Takashi Iwai346ff702009-02-23 09:42:57 +01001587 /* free only driver_pins so that init_pins + user_pins are restored */
1588 snd_array_free(&codec->driver_pins);
Takashi Iwai3be14142009-02-20 14:11:16 +01001589 restore_pincfgs(codec);
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001590 codec->num_pcms = 0;
1591 codec->pcm_info = NULL;
1592 codec->preset = NULL;
Takashi Iwaid1f1af22009-03-02 10:35:29 +01001593 memset(&codec->patch_ops, 0, sizeof(codec->patch_ops));
1594 codec->slave_dig_outs = NULL;
1595 codec->spdif_status_reset = 0;
Takashi Iwai1289e9e2008-11-27 15:47:11 +01001596 module_put(codec->owner);
1597 codec->owner = NULL;
Takashi Iwaia65d6292009-02-23 16:57:04 +01001598
1599 /* allow device access again */
1600 hda_unlock_devices(card);
1601 return 0;
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001602}
1603
Takashi Iwai2134ea42008-01-10 16:53:55 +01001604/* create a virtual master control and add slaves */
1605int snd_hda_add_vmaster(struct hda_codec *codec, char *name,
1606 unsigned int *tlv, const char **slaves)
1607{
1608 struct snd_kcontrol *kctl;
1609 const char **s;
1610 int err;
1611
Takashi Iwai2f085542008-02-22 18:43:50 +01001612 for (s = slaves; *s && !snd_hda_find_mixer_ctl(codec, *s); s++)
1613 ;
1614 if (!*s) {
1615 snd_printdd("No slave found for %s\n", name);
1616 return 0;
1617 }
Takashi Iwai2134ea42008-01-10 16:53:55 +01001618 kctl = snd_ctl_make_virtual_master(name, tlv);
1619 if (!kctl)
1620 return -ENOMEM;
Takashi Iwaid13bd412008-07-30 15:01:45 +02001621 err = snd_hda_ctl_add(codec, kctl);
Takashi Iwai2134ea42008-01-10 16:53:55 +01001622 if (err < 0)
1623 return err;
1624
1625 for (s = slaves; *s; s++) {
1626 struct snd_kcontrol *sctl;
Takashi Iwai7a411ee2009-03-06 10:08:14 +01001627 int i = 0;
1628 for (;;) {
1629 sctl = _snd_hda_find_mixer_ctl(codec, *s, i);
1630 if (!sctl) {
1631 if (!i)
1632 snd_printdd("Cannot find slave %s, "
1633 "skipped\n", *s);
1634 break;
1635 }
1636 err = snd_ctl_add_slave(kctl, sctl);
1637 if (err < 0)
1638 return err;
1639 i++;
Takashi Iwai2134ea42008-01-10 16:53:55 +01001640 }
Takashi Iwai2134ea42008-01-10 16:53:55 +01001641 }
1642 return 0;
1643}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001644EXPORT_SYMBOL_HDA(snd_hda_add_vmaster);
Takashi Iwai2134ea42008-01-10 16:53:55 +01001645
Linus Torvalds1da177e2005-04-16 15:20:36 -07001646/* switch */
Takashi Iwai0ba21762007-04-16 11:29:14 +02001647int snd_hda_mixer_amp_switch_info(struct snd_kcontrol *kcontrol,
1648 struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001649{
1650 int chs = get_amp_channels(kcontrol);
1651
1652 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
1653 uinfo->count = chs == 3 ? 2 : 1;
1654 uinfo->value.integer.min = 0;
1655 uinfo->value.integer.max = 1;
1656 return 0;
1657}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001658EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_switch_info);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001659
Takashi Iwai0ba21762007-04-16 11:29:14 +02001660int snd_hda_mixer_amp_switch_get(struct snd_kcontrol *kcontrol,
1661 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001662{
1663 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1664 hda_nid_t nid = get_amp_nid(kcontrol);
1665 int chs = get_amp_channels(kcontrol);
1666 int dir = get_amp_direction(kcontrol);
1667 int idx = get_amp_index(kcontrol);
1668 long *valp = ucontrol->value.integer.value;
1669
1670 if (chs & 1)
Takashi Iwai0ba21762007-04-16 11:29:14 +02001671 *valp++ = (snd_hda_codec_amp_read(codec, nid, 0, dir, idx) &
Takashi Iwai47fd8302007-08-10 17:11:07 +02001672 HDA_AMP_MUTE) ? 0 : 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001673 if (chs & 2)
Takashi Iwai0ba21762007-04-16 11:29:14 +02001674 *valp = (snd_hda_codec_amp_read(codec, nid, 1, dir, idx) &
Takashi Iwai47fd8302007-08-10 17:11:07 +02001675 HDA_AMP_MUTE) ? 0 : 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001676 return 0;
1677}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001678EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_switch_get);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001679
Takashi Iwai0ba21762007-04-16 11:29:14 +02001680int snd_hda_mixer_amp_switch_put(struct snd_kcontrol *kcontrol,
1681 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001682{
1683 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1684 hda_nid_t nid = get_amp_nid(kcontrol);
1685 int chs = get_amp_channels(kcontrol);
1686 int dir = get_amp_direction(kcontrol);
1687 int idx = get_amp_index(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001688 long *valp = ucontrol->value.integer.value;
1689 int change = 0;
1690
Takashi Iwaicb53c622007-08-10 17:21:45 +02001691 snd_hda_power_up(codec);
Nicolas Grazianob9f5a892005-07-29 12:17:20 +02001692 if (chs & 1) {
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001693 change = snd_hda_codec_amp_update(codec, nid, 0, dir, idx,
Takashi Iwai47fd8302007-08-10 17:11:07 +02001694 HDA_AMP_MUTE,
1695 *valp ? 0 : HDA_AMP_MUTE);
Nicolas Grazianob9f5a892005-07-29 12:17:20 +02001696 valp++;
1697 }
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001698 if (chs & 2)
1699 change |= snd_hda_codec_amp_update(codec, nid, 1, dir, idx,
Takashi Iwai47fd8302007-08-10 17:11:07 +02001700 HDA_AMP_MUTE,
1701 *valp ? 0 : HDA_AMP_MUTE);
Takashi Iwaicb53c622007-08-10 17:21:45 +02001702#ifdef CONFIG_SND_HDA_POWER_SAVE
1703 if (codec->patch_ops.check_power_status)
1704 codec->patch_ops.check_power_status(codec, nid);
1705#endif
1706 snd_hda_power_down(codec);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001707 return change;
1708}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001709EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_switch_put);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001710
1711/*
Takashi Iwai985be542005-11-02 18:26:49 +01001712 * bound volume controls
1713 *
1714 * bind multiple volumes (# indices, from 0)
1715 */
1716
1717#define AMP_VAL_IDX_SHIFT 19
1718#define AMP_VAL_IDX_MASK (0x0f<<19)
1719
Takashi Iwai0ba21762007-04-16 11:29:14 +02001720int snd_hda_mixer_bind_switch_get(struct snd_kcontrol *kcontrol,
1721 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai985be542005-11-02 18:26:49 +01001722{
1723 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1724 unsigned long pval;
1725 int err;
1726
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001727 mutex_lock(&codec->control_mutex);
Takashi Iwai985be542005-11-02 18:26:49 +01001728 pval = kcontrol->private_value;
1729 kcontrol->private_value = pval & ~AMP_VAL_IDX_MASK; /* index 0 */
1730 err = snd_hda_mixer_amp_switch_get(kcontrol, ucontrol);
1731 kcontrol->private_value = pval;
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001732 mutex_unlock(&codec->control_mutex);
Takashi Iwai985be542005-11-02 18:26:49 +01001733 return err;
1734}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001735EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_switch_get);
Takashi Iwai985be542005-11-02 18:26:49 +01001736
Takashi Iwai0ba21762007-04-16 11:29:14 +02001737int snd_hda_mixer_bind_switch_put(struct snd_kcontrol *kcontrol,
1738 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai985be542005-11-02 18:26:49 +01001739{
1740 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1741 unsigned long pval;
1742 int i, indices, err = 0, change = 0;
1743
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001744 mutex_lock(&codec->control_mutex);
Takashi Iwai985be542005-11-02 18:26:49 +01001745 pval = kcontrol->private_value;
1746 indices = (pval & AMP_VAL_IDX_MASK) >> AMP_VAL_IDX_SHIFT;
1747 for (i = 0; i < indices; i++) {
Takashi Iwai0ba21762007-04-16 11:29:14 +02001748 kcontrol->private_value = (pval & ~AMP_VAL_IDX_MASK) |
1749 (i << AMP_VAL_IDX_SHIFT);
Takashi Iwai985be542005-11-02 18:26:49 +01001750 err = snd_hda_mixer_amp_switch_put(kcontrol, ucontrol);
1751 if (err < 0)
1752 break;
1753 change |= err;
1754 }
1755 kcontrol->private_value = pval;
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001756 mutex_unlock(&codec->control_mutex);
Takashi Iwai985be542005-11-02 18:26:49 +01001757 return err < 0 ? err : change;
1758}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001759EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_switch_put);
Takashi Iwai985be542005-11-02 18:26:49 +01001760
1761/*
Takashi Iwai532d5382007-07-27 19:02:40 +02001762 * generic bound volume/swtich controls
1763 */
1764int snd_hda_mixer_bind_ctls_info(struct snd_kcontrol *kcontrol,
1765 struct snd_ctl_elem_info *uinfo)
1766{
1767 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1768 struct hda_bind_ctls *c;
1769 int err;
1770
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001771 mutex_lock(&codec->control_mutex);
Serge A. Suchkov14c65f92008-02-22 18:43:16 +01001772 c = (struct hda_bind_ctls *)kcontrol->private_value;
Takashi Iwai532d5382007-07-27 19:02:40 +02001773 kcontrol->private_value = *c->values;
1774 err = c->ops->info(kcontrol, uinfo);
1775 kcontrol->private_value = (long)c;
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001776 mutex_unlock(&codec->control_mutex);
Takashi Iwai532d5382007-07-27 19:02:40 +02001777 return err;
1778}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001779EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_ctls_info);
Takashi Iwai532d5382007-07-27 19:02:40 +02001780
1781int snd_hda_mixer_bind_ctls_get(struct snd_kcontrol *kcontrol,
1782 struct snd_ctl_elem_value *ucontrol)
1783{
1784 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1785 struct hda_bind_ctls *c;
1786 int err;
1787
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001788 mutex_lock(&codec->control_mutex);
Serge A. Suchkov14c65f92008-02-22 18:43:16 +01001789 c = (struct hda_bind_ctls *)kcontrol->private_value;
Takashi Iwai532d5382007-07-27 19:02:40 +02001790 kcontrol->private_value = *c->values;
1791 err = c->ops->get(kcontrol, ucontrol);
1792 kcontrol->private_value = (long)c;
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001793 mutex_unlock(&codec->control_mutex);
Takashi Iwai532d5382007-07-27 19:02:40 +02001794 return err;
1795}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001796EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_ctls_get);
Takashi Iwai532d5382007-07-27 19:02:40 +02001797
1798int snd_hda_mixer_bind_ctls_put(struct snd_kcontrol *kcontrol,
1799 struct snd_ctl_elem_value *ucontrol)
1800{
1801 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1802 struct hda_bind_ctls *c;
1803 unsigned long *vals;
1804 int err = 0, change = 0;
1805
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001806 mutex_lock(&codec->control_mutex);
Serge A. Suchkov14c65f92008-02-22 18:43:16 +01001807 c = (struct hda_bind_ctls *)kcontrol->private_value;
Takashi Iwai532d5382007-07-27 19:02:40 +02001808 for (vals = c->values; *vals; vals++) {
1809 kcontrol->private_value = *vals;
1810 err = c->ops->put(kcontrol, ucontrol);
1811 if (err < 0)
1812 break;
1813 change |= err;
1814 }
1815 kcontrol->private_value = (long)c;
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001816 mutex_unlock(&codec->control_mutex);
Takashi Iwai532d5382007-07-27 19:02:40 +02001817 return err < 0 ? err : change;
1818}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001819EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_ctls_put);
Takashi Iwai532d5382007-07-27 19:02:40 +02001820
1821int snd_hda_mixer_bind_tlv(struct snd_kcontrol *kcontrol, int op_flag,
1822 unsigned int size, unsigned int __user *tlv)
1823{
1824 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1825 struct hda_bind_ctls *c;
1826 int err;
1827
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001828 mutex_lock(&codec->control_mutex);
Serge A. Suchkov14c65f92008-02-22 18:43:16 +01001829 c = (struct hda_bind_ctls *)kcontrol->private_value;
Takashi Iwai532d5382007-07-27 19:02:40 +02001830 kcontrol->private_value = *c->values;
1831 err = c->ops->tlv(kcontrol, op_flag, size, tlv);
1832 kcontrol->private_value = (long)c;
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001833 mutex_unlock(&codec->control_mutex);
Takashi Iwai532d5382007-07-27 19:02:40 +02001834 return err;
1835}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001836EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_tlv);
Takashi Iwai532d5382007-07-27 19:02:40 +02001837
1838struct hda_ctl_ops snd_hda_bind_vol = {
1839 .info = snd_hda_mixer_amp_volume_info,
1840 .get = snd_hda_mixer_amp_volume_get,
1841 .put = snd_hda_mixer_amp_volume_put,
1842 .tlv = snd_hda_mixer_amp_tlv
1843};
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001844EXPORT_SYMBOL_HDA(snd_hda_bind_vol);
Takashi Iwai532d5382007-07-27 19:02:40 +02001845
1846struct hda_ctl_ops snd_hda_bind_sw = {
1847 .info = snd_hda_mixer_amp_switch_info,
1848 .get = snd_hda_mixer_amp_switch_get,
1849 .put = snd_hda_mixer_amp_switch_put,
1850 .tlv = snd_hda_mixer_amp_tlv
1851};
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001852EXPORT_SYMBOL_HDA(snd_hda_bind_sw);
Takashi Iwai532d5382007-07-27 19:02:40 +02001853
1854/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07001855 * SPDIF out controls
1856 */
1857
Takashi Iwai0ba21762007-04-16 11:29:14 +02001858static int snd_hda_spdif_mask_info(struct snd_kcontrol *kcontrol,
1859 struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001860{
1861 uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
1862 uinfo->count = 1;
1863 return 0;
1864}
1865
Takashi Iwai0ba21762007-04-16 11:29:14 +02001866static int snd_hda_spdif_cmask_get(struct snd_kcontrol *kcontrol,
1867 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001868{
1869 ucontrol->value.iec958.status[0] = IEC958_AES0_PROFESSIONAL |
1870 IEC958_AES0_NONAUDIO |
1871 IEC958_AES0_CON_EMPHASIS_5015 |
1872 IEC958_AES0_CON_NOT_COPYRIGHT;
1873 ucontrol->value.iec958.status[1] = IEC958_AES1_CON_CATEGORY |
1874 IEC958_AES1_CON_ORIGINAL;
1875 return 0;
1876}
1877
Takashi Iwai0ba21762007-04-16 11:29:14 +02001878static int snd_hda_spdif_pmask_get(struct snd_kcontrol *kcontrol,
1879 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001880{
1881 ucontrol->value.iec958.status[0] = IEC958_AES0_PROFESSIONAL |
1882 IEC958_AES0_NONAUDIO |
1883 IEC958_AES0_PRO_EMPHASIS_5015;
1884 return 0;
1885}
1886
Takashi Iwai0ba21762007-04-16 11:29:14 +02001887static int snd_hda_spdif_default_get(struct snd_kcontrol *kcontrol,
1888 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001889{
1890 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1891
1892 ucontrol->value.iec958.status[0] = codec->spdif_status & 0xff;
1893 ucontrol->value.iec958.status[1] = (codec->spdif_status >> 8) & 0xff;
1894 ucontrol->value.iec958.status[2] = (codec->spdif_status >> 16) & 0xff;
1895 ucontrol->value.iec958.status[3] = (codec->spdif_status >> 24) & 0xff;
1896
1897 return 0;
1898}
1899
1900/* convert from SPDIF status bits to HDA SPDIF bits
1901 * bit 0 (DigEn) is always set zero (to be filled later)
1902 */
1903static unsigned short convert_from_spdif_status(unsigned int sbits)
1904{
1905 unsigned short val = 0;
1906
1907 if (sbits & IEC958_AES0_PROFESSIONAL)
Takashi Iwai0ba21762007-04-16 11:29:14 +02001908 val |= AC_DIG1_PROFESSIONAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001909 if (sbits & IEC958_AES0_NONAUDIO)
Takashi Iwai0ba21762007-04-16 11:29:14 +02001910 val |= AC_DIG1_NONAUDIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001911 if (sbits & IEC958_AES0_PROFESSIONAL) {
Takashi Iwai0ba21762007-04-16 11:29:14 +02001912 if ((sbits & IEC958_AES0_PRO_EMPHASIS) ==
1913 IEC958_AES0_PRO_EMPHASIS_5015)
1914 val |= AC_DIG1_EMPHASIS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001915 } else {
Takashi Iwai0ba21762007-04-16 11:29:14 +02001916 if ((sbits & IEC958_AES0_CON_EMPHASIS) ==
1917 IEC958_AES0_CON_EMPHASIS_5015)
1918 val |= AC_DIG1_EMPHASIS;
1919 if (!(sbits & IEC958_AES0_CON_NOT_COPYRIGHT))
1920 val |= AC_DIG1_COPYRIGHT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001921 if (sbits & (IEC958_AES1_CON_ORIGINAL << 8))
Takashi Iwai0ba21762007-04-16 11:29:14 +02001922 val |= AC_DIG1_LEVEL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001923 val |= sbits & (IEC958_AES1_CON_CATEGORY << 8);
1924 }
1925 return val;
1926}
1927
1928/* convert to SPDIF status bits from HDA SPDIF bits
1929 */
1930static unsigned int convert_to_spdif_status(unsigned short val)
1931{
1932 unsigned int sbits = 0;
1933
Takashi Iwai0ba21762007-04-16 11:29:14 +02001934 if (val & AC_DIG1_NONAUDIO)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001935 sbits |= IEC958_AES0_NONAUDIO;
Takashi Iwai0ba21762007-04-16 11:29:14 +02001936 if (val & AC_DIG1_PROFESSIONAL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001937 sbits |= IEC958_AES0_PROFESSIONAL;
1938 if (sbits & IEC958_AES0_PROFESSIONAL) {
Takashi Iwai0ba21762007-04-16 11:29:14 +02001939 if (sbits & AC_DIG1_EMPHASIS)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001940 sbits |= IEC958_AES0_PRO_EMPHASIS_5015;
1941 } else {
Takashi Iwai0ba21762007-04-16 11:29:14 +02001942 if (val & AC_DIG1_EMPHASIS)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001943 sbits |= IEC958_AES0_CON_EMPHASIS_5015;
Takashi Iwai0ba21762007-04-16 11:29:14 +02001944 if (!(val & AC_DIG1_COPYRIGHT))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001945 sbits |= IEC958_AES0_CON_NOT_COPYRIGHT;
Takashi Iwai0ba21762007-04-16 11:29:14 +02001946 if (val & AC_DIG1_LEVEL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001947 sbits |= (IEC958_AES1_CON_ORIGINAL << 8);
1948 sbits |= val & (0x7f << 8);
1949 }
1950 return sbits;
1951}
1952
Takashi Iwai2f728532008-09-25 16:32:41 +02001953/* set digital convert verbs both for the given NID and its slaves */
1954static void set_dig_out(struct hda_codec *codec, hda_nid_t nid,
1955 int verb, int val)
1956{
1957 hda_nid_t *d;
1958
Takashi Iwai9e976972008-11-25 08:17:20 +01001959 snd_hda_codec_write_cache(codec, nid, 0, verb, val);
Takashi Iwai2f728532008-09-25 16:32:41 +02001960 d = codec->slave_dig_outs;
1961 if (!d)
1962 return;
1963 for (; *d; d++)
Takashi Iwai9e976972008-11-25 08:17:20 +01001964 snd_hda_codec_write_cache(codec, *d, 0, verb, val);
Takashi Iwai2f728532008-09-25 16:32:41 +02001965}
1966
1967static inline void set_dig_out_convert(struct hda_codec *codec, hda_nid_t nid,
1968 int dig1, int dig2)
1969{
1970 if (dig1 != -1)
1971 set_dig_out(codec, nid, AC_VERB_SET_DIGI_CONVERT_1, dig1);
1972 if (dig2 != -1)
1973 set_dig_out(codec, nid, AC_VERB_SET_DIGI_CONVERT_2, dig2);
1974}
1975
Takashi Iwai0ba21762007-04-16 11:29:14 +02001976static int snd_hda_spdif_default_put(struct snd_kcontrol *kcontrol,
1977 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001978{
1979 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1980 hda_nid_t nid = kcontrol->private_value;
1981 unsigned short val;
1982 int change;
1983
Ingo Molnar62932df2006-01-16 16:34:20 +01001984 mutex_lock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001985 codec->spdif_status = ucontrol->value.iec958.status[0] |
1986 ((unsigned int)ucontrol->value.iec958.status[1] << 8) |
1987 ((unsigned int)ucontrol->value.iec958.status[2] << 16) |
1988 ((unsigned int)ucontrol->value.iec958.status[3] << 24);
1989 val = convert_from_spdif_status(codec->spdif_status);
1990 val |= codec->spdif_ctls & 1;
1991 change = codec->spdif_ctls != val;
1992 codec->spdif_ctls = val;
1993
Takashi Iwai2f728532008-09-25 16:32:41 +02001994 if (change)
1995 set_dig_out_convert(codec, nid, val & 0xff, (val >> 8) & 0xff);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001996
Ingo Molnar62932df2006-01-16 16:34:20 +01001997 mutex_unlock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001998 return change;
1999}
2000
Takashi Iwaia5ce8892007-07-23 15:42:26 +02002001#define snd_hda_spdif_out_switch_info snd_ctl_boolean_mono_info
Linus Torvalds1da177e2005-04-16 15:20:36 -07002002
Takashi Iwai0ba21762007-04-16 11:29:14 +02002003static int snd_hda_spdif_out_switch_get(struct snd_kcontrol *kcontrol,
2004 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002005{
2006 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2007
Takashi Iwai0ba21762007-04-16 11:29:14 +02002008 ucontrol->value.integer.value[0] = codec->spdif_ctls & AC_DIG1_ENABLE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002009 return 0;
2010}
2011
Takashi Iwai0ba21762007-04-16 11:29:14 +02002012static int snd_hda_spdif_out_switch_put(struct snd_kcontrol *kcontrol,
2013 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002014{
2015 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2016 hda_nid_t nid = kcontrol->private_value;
2017 unsigned short val;
2018 int change;
2019
Ingo Molnar62932df2006-01-16 16:34:20 +01002020 mutex_lock(&codec->spdif_mutex);
Takashi Iwai0ba21762007-04-16 11:29:14 +02002021 val = codec->spdif_ctls & ~AC_DIG1_ENABLE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002022 if (ucontrol->value.integer.value[0])
Takashi Iwai0ba21762007-04-16 11:29:14 +02002023 val |= AC_DIG1_ENABLE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002024 change = codec->spdif_ctls != val;
Takashi Iwai82beb8f2007-08-10 17:09:26 +02002025 if (change) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002026 codec->spdif_ctls = val;
Takashi Iwai2f728532008-09-25 16:32:41 +02002027 set_dig_out_convert(codec, nid, val & 0xff, -1);
Takashi Iwai0ba21762007-04-16 11:29:14 +02002028 /* unmute amp switch (if any) */
2029 if ((get_wcaps(codec, nid) & AC_WCAP_OUT_AMP) &&
Takashi Iwai47fd8302007-08-10 17:11:07 +02002030 (val & AC_DIG1_ENABLE))
2031 snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0,
2032 HDA_AMP_MUTE, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002033 }
Ingo Molnar62932df2006-01-16 16:34:20 +01002034 mutex_unlock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002035 return change;
2036}
2037
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01002038static struct snd_kcontrol_new dig_mixes[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002039 {
2040 .access = SNDRV_CTL_ELEM_ACCESS_READ,
2041 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2042 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,CON_MASK),
2043 .info = snd_hda_spdif_mask_info,
2044 .get = snd_hda_spdif_cmask_get,
2045 },
2046 {
2047 .access = SNDRV_CTL_ELEM_ACCESS_READ,
2048 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2049 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,PRO_MASK),
2050 .info = snd_hda_spdif_mask_info,
2051 .get = snd_hda_spdif_pmask_get,
2052 },
2053 {
2054 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2055 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT),
2056 .info = snd_hda_spdif_mask_info,
2057 .get = snd_hda_spdif_default_get,
2058 .put = snd_hda_spdif_default_put,
2059 },
2060 {
2061 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2062 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,SWITCH),
2063 .info = snd_hda_spdif_out_switch_info,
2064 .get = snd_hda_spdif_out_switch_get,
2065 .put = snd_hda_spdif_out_switch_put,
2066 },
2067 { } /* end */
2068};
2069
Takashi Iwai09f99702008-02-04 12:31:13 +01002070#define SPDIF_MAX_IDX 4 /* 4 instances should be enough to probe */
2071
Linus Torvalds1da177e2005-04-16 15:20:36 -07002072/**
2073 * snd_hda_create_spdif_out_ctls - create Output SPDIF-related controls
2074 * @codec: the HDA codec
2075 * @nid: audio out widget NID
2076 *
2077 * Creates controls related with the SPDIF output.
2078 * Called from each patch supporting the SPDIF out.
2079 *
2080 * Returns 0 if successful, or a negative error code.
2081 */
Takashi Iwai12f288b2007-08-02 15:51:59 +02002082int snd_hda_create_spdif_out_ctls(struct hda_codec *codec, hda_nid_t nid)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002083{
2084 int err;
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01002085 struct snd_kcontrol *kctl;
2086 struct snd_kcontrol_new *dig_mix;
Takashi Iwai09f99702008-02-04 12:31:13 +01002087 int idx;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002088
Takashi Iwai09f99702008-02-04 12:31:13 +01002089 for (idx = 0; idx < SPDIF_MAX_IDX; idx++) {
2090 if (!_snd_hda_find_mixer_ctl(codec, "IEC958 Playback Switch",
2091 idx))
2092 break;
2093 }
2094 if (idx >= SPDIF_MAX_IDX) {
2095 printk(KERN_ERR "hda_codec: too many IEC958 outputs\n");
2096 return -EBUSY;
2097 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002098 for (dig_mix = dig_mixes; dig_mix->name; dig_mix++) {
2099 kctl = snd_ctl_new1(dig_mix, codec);
Takashi Iwaib91f0802008-11-04 08:43:08 +01002100 if (!kctl)
2101 return -ENOMEM;
Takashi Iwai09f99702008-02-04 12:31:13 +01002102 kctl->id.index = idx;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002103 kctl->private_value = nid;
Takashi Iwaid13bd412008-07-30 15:01:45 +02002104 err = snd_hda_ctl_add(codec, kctl);
Takashi Iwai0ba21762007-04-16 11:29:14 +02002105 if (err < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002106 return err;
2107 }
Takashi Iwai0ba21762007-04-16 11:29:14 +02002108 codec->spdif_ctls =
Andrew Paprocki3982d172007-12-19 12:13:44 +01002109 snd_hda_codec_read(codec, nid, 0,
2110 AC_VERB_GET_DIGI_CONVERT_1, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002111 codec->spdif_status = convert_to_spdif_status(codec->spdif_ctls);
2112 return 0;
2113}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002114EXPORT_SYMBOL_HDA(snd_hda_create_spdif_out_ctls);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002115
2116/*
Takashi Iwai9a081602008-02-12 18:37:26 +01002117 * SPDIF sharing with analog output
2118 */
2119static int spdif_share_sw_get(struct snd_kcontrol *kcontrol,
2120 struct snd_ctl_elem_value *ucontrol)
2121{
2122 struct hda_multi_out *mout = snd_kcontrol_chip(kcontrol);
2123 ucontrol->value.integer.value[0] = mout->share_spdif;
2124 return 0;
2125}
2126
2127static int spdif_share_sw_put(struct snd_kcontrol *kcontrol,
2128 struct snd_ctl_elem_value *ucontrol)
2129{
2130 struct hda_multi_out *mout = snd_kcontrol_chip(kcontrol);
2131 mout->share_spdif = !!ucontrol->value.integer.value[0];
2132 return 0;
2133}
2134
2135static struct snd_kcontrol_new spdif_share_sw = {
2136 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2137 .name = "IEC958 Default PCM Playback Switch",
2138 .info = snd_ctl_boolean_mono_info,
2139 .get = spdif_share_sw_get,
2140 .put = spdif_share_sw_put,
2141};
2142
2143int snd_hda_create_spdif_share_sw(struct hda_codec *codec,
2144 struct hda_multi_out *mout)
2145{
2146 if (!mout->dig_out_nid)
2147 return 0;
2148 /* ATTENTION: here mout is passed as private_data, instead of codec */
Takashi Iwaid13bd412008-07-30 15:01:45 +02002149 return snd_hda_ctl_add(codec,
Takashi Iwai9a081602008-02-12 18:37:26 +01002150 snd_ctl_new1(&spdif_share_sw, mout));
2151}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002152EXPORT_SYMBOL_HDA(snd_hda_create_spdif_share_sw);
Takashi Iwai9a081602008-02-12 18:37:26 +01002153
2154/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002155 * SPDIF input
2156 */
2157
2158#define snd_hda_spdif_in_switch_info snd_hda_spdif_out_switch_info
2159
Takashi Iwai0ba21762007-04-16 11:29:14 +02002160static int snd_hda_spdif_in_switch_get(struct snd_kcontrol *kcontrol,
2161 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002162{
2163 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2164
2165 ucontrol->value.integer.value[0] = codec->spdif_in_enable;
2166 return 0;
2167}
2168
Takashi Iwai0ba21762007-04-16 11:29:14 +02002169static int snd_hda_spdif_in_switch_put(struct snd_kcontrol *kcontrol,
2170 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002171{
2172 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2173 hda_nid_t nid = kcontrol->private_value;
2174 unsigned int val = !!ucontrol->value.integer.value[0];
2175 int change;
2176
Ingo Molnar62932df2006-01-16 16:34:20 +01002177 mutex_lock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002178 change = codec->spdif_in_enable != val;
Takashi Iwai82beb8f2007-08-10 17:09:26 +02002179 if (change) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002180 codec->spdif_in_enable = val;
Takashi Iwai82beb8f2007-08-10 17:09:26 +02002181 snd_hda_codec_write_cache(codec, nid, 0,
2182 AC_VERB_SET_DIGI_CONVERT_1, val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002183 }
Ingo Molnar62932df2006-01-16 16:34:20 +01002184 mutex_unlock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002185 return change;
2186}
2187
Takashi Iwai0ba21762007-04-16 11:29:14 +02002188static int snd_hda_spdif_in_status_get(struct snd_kcontrol *kcontrol,
2189 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002190{
2191 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2192 hda_nid_t nid = kcontrol->private_value;
2193 unsigned short val;
2194 unsigned int sbits;
2195
Andrew Paprocki3982d172007-12-19 12:13:44 +01002196 val = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_DIGI_CONVERT_1, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002197 sbits = convert_to_spdif_status(val);
2198 ucontrol->value.iec958.status[0] = sbits;
2199 ucontrol->value.iec958.status[1] = sbits >> 8;
2200 ucontrol->value.iec958.status[2] = sbits >> 16;
2201 ucontrol->value.iec958.status[3] = sbits >> 24;
2202 return 0;
2203}
2204
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01002205static struct snd_kcontrol_new dig_in_ctls[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002206 {
2207 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2208 .name = SNDRV_CTL_NAME_IEC958("",CAPTURE,SWITCH),
2209 .info = snd_hda_spdif_in_switch_info,
2210 .get = snd_hda_spdif_in_switch_get,
2211 .put = snd_hda_spdif_in_switch_put,
2212 },
2213 {
2214 .access = SNDRV_CTL_ELEM_ACCESS_READ,
2215 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2216 .name = SNDRV_CTL_NAME_IEC958("",CAPTURE,DEFAULT),
2217 .info = snd_hda_spdif_mask_info,
2218 .get = snd_hda_spdif_in_status_get,
2219 },
2220 { } /* end */
2221};
2222
2223/**
2224 * snd_hda_create_spdif_in_ctls - create Input SPDIF-related controls
2225 * @codec: the HDA codec
2226 * @nid: audio in widget NID
2227 *
2228 * Creates controls related with the SPDIF input.
2229 * Called from each patch supporting the SPDIF in.
2230 *
2231 * Returns 0 if successful, or a negative error code.
2232 */
Takashi Iwai12f288b2007-08-02 15:51:59 +02002233int snd_hda_create_spdif_in_ctls(struct hda_codec *codec, hda_nid_t nid)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002234{
2235 int err;
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01002236 struct snd_kcontrol *kctl;
2237 struct snd_kcontrol_new *dig_mix;
Takashi Iwai09f99702008-02-04 12:31:13 +01002238 int idx;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002239
Takashi Iwai09f99702008-02-04 12:31:13 +01002240 for (idx = 0; idx < SPDIF_MAX_IDX; idx++) {
2241 if (!_snd_hda_find_mixer_ctl(codec, "IEC958 Capture Switch",
2242 idx))
2243 break;
2244 }
2245 if (idx >= SPDIF_MAX_IDX) {
2246 printk(KERN_ERR "hda_codec: too many IEC958 inputs\n");
2247 return -EBUSY;
2248 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002249 for (dig_mix = dig_in_ctls; dig_mix->name; dig_mix++) {
2250 kctl = snd_ctl_new1(dig_mix, codec);
Takashi Iwaic8dcdf82009-02-06 16:21:20 +01002251 if (!kctl)
2252 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002253 kctl->private_value = nid;
Takashi Iwaid13bd412008-07-30 15:01:45 +02002254 err = snd_hda_ctl_add(codec, kctl);
Takashi Iwai0ba21762007-04-16 11:29:14 +02002255 if (err < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002256 return err;
2257 }
Takashi Iwai0ba21762007-04-16 11:29:14 +02002258 codec->spdif_in_enable =
Andrew Paprocki3982d172007-12-19 12:13:44 +01002259 snd_hda_codec_read(codec, nid, 0,
2260 AC_VERB_GET_DIGI_CONVERT_1, 0) &
Takashi Iwai0ba21762007-04-16 11:29:14 +02002261 AC_DIG1_ENABLE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002262 return 0;
2263}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002264EXPORT_SYMBOL_HDA(snd_hda_create_spdif_in_ctls);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002265
Takashi Iwaicb53c622007-08-10 17:21:45 +02002266#ifdef SND_HDA_NEEDS_RESUME
Takashi Iwai82beb8f2007-08-10 17:09:26 +02002267/*
2268 * command cache
2269 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002270
Takashi Iwaib3ac5632007-08-10 17:03:40 +02002271/* build a 32bit cache key with the widget id and the command parameter */
2272#define build_cmd_cache_key(nid, verb) ((verb << 8) | nid)
2273#define get_cmd_cache_nid(key) ((key) & 0xff)
2274#define get_cmd_cache_cmd(key) (((key) >> 8) & 0xffff)
2275
2276/**
2277 * snd_hda_codec_write_cache - send a single command with caching
2278 * @codec: the HDA codec
2279 * @nid: NID to send the command
2280 * @direct: direct flag
2281 * @verb: the verb to send
2282 * @parm: the parameter for the verb
2283 *
2284 * Send a single command without waiting for response.
2285 *
2286 * Returns 0 if successful, or a negative error code.
2287 */
2288int snd_hda_codec_write_cache(struct hda_codec *codec, hda_nid_t nid,
2289 int direct, unsigned int verb, unsigned int parm)
2290{
Takashi Iwaiaa2936f2009-05-26 16:07:57 +02002291 int err = snd_hda_codec_write(codec, nid, direct, verb, parm);
2292 struct hda_cache_head *c;
2293 u32 key;
Takashi Iwai33fa35e2008-11-06 16:50:40 +01002294
Takashi Iwaiaa2936f2009-05-26 16:07:57 +02002295 if (err < 0)
2296 return err;
2297 /* parm may contain the verb stuff for get/set amp */
2298 verb = verb | (parm >> 8);
2299 parm &= 0xff;
2300 key = build_cmd_cache_key(nid, verb);
2301 mutex_lock(&codec->bus->cmd_mutex);
2302 c = get_alloc_hash(&codec->cmd_cache, key);
2303 if (c)
2304 c->val = parm;
2305 mutex_unlock(&codec->bus->cmd_mutex);
2306 return 0;
Takashi Iwaib3ac5632007-08-10 17:03:40 +02002307}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002308EXPORT_SYMBOL_HDA(snd_hda_codec_write_cache);
Takashi Iwaib3ac5632007-08-10 17:03:40 +02002309
2310/* resume the all commands from the cache */
2311void snd_hda_codec_resume_cache(struct hda_codec *codec)
2312{
Takashi Iwai603c4012008-07-30 15:01:44 +02002313 struct hda_cache_head *buffer = codec->cmd_cache.buf.list;
Takashi Iwaib3ac5632007-08-10 17:03:40 +02002314 int i;
2315
Takashi Iwai603c4012008-07-30 15:01:44 +02002316 for (i = 0; i < codec->cmd_cache.buf.used; i++, buffer++) {
Takashi Iwaib3ac5632007-08-10 17:03:40 +02002317 u32 key = buffer->key;
2318 if (!key)
2319 continue;
2320 snd_hda_codec_write(codec, get_cmd_cache_nid(key), 0,
2321 get_cmd_cache_cmd(key), buffer->val);
2322 }
2323}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002324EXPORT_SYMBOL_HDA(snd_hda_codec_resume_cache);
Takashi Iwaib3ac5632007-08-10 17:03:40 +02002325
2326/**
2327 * snd_hda_sequence_write_cache - sequence writes with caching
2328 * @codec: the HDA codec
2329 * @seq: VERB array to send
2330 *
2331 * Send the commands sequentially from the given array.
2332 * Thte commands are recorded on cache for power-save and resume.
2333 * The array must be terminated with NID=0.
2334 */
2335void snd_hda_sequence_write_cache(struct hda_codec *codec,
2336 const struct hda_verb *seq)
2337{
2338 for (; seq->nid; seq++)
2339 snd_hda_codec_write_cache(codec, seq->nid, 0, seq->verb,
2340 seq->param);
2341}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002342EXPORT_SYMBOL_HDA(snd_hda_sequence_write_cache);
Takashi Iwaicb53c622007-08-10 17:21:45 +02002343#endif /* SND_HDA_NEEDS_RESUME */
Takashi Iwaib3ac5632007-08-10 17:03:40 +02002344
Takashi Iwai54d17402005-11-21 16:33:22 +01002345/*
2346 * set power state of the codec
2347 */
2348static void hda_set_power_state(struct hda_codec *codec, hda_nid_t fg,
2349 unsigned int power_state)
2350{
Takashi Iwaicb53c622007-08-10 17:21:45 +02002351 hda_nid_t nid;
2352 int i;
Takashi Iwai54d17402005-11-21 16:33:22 +01002353
2354 snd_hda_codec_write(codec, fg, 0, AC_VERB_SET_POWER_STATE,
2355 power_state);
Marc Boucherd2595d82008-01-22 15:23:30 +01002356 msleep(10); /* partial workaround for "azx_get_response timeout" */
Takashi Iwai54d17402005-11-21 16:33:22 +01002357
Takashi Iwaicb53c622007-08-10 17:21:45 +02002358 nid = codec->start_nid;
2359 for (i = 0; i < codec->num_nodes; i++, nid++) {
Takashi Iwai7eba5c92007-11-14 14:53:42 +01002360 unsigned int wcaps = get_wcaps(codec, nid);
2361 if (wcaps & AC_WCAP_POWER) {
2362 unsigned int wid_type = (wcaps & AC_WCAP_TYPE) >>
2363 AC_WCAP_TYPE_SHIFT;
Takashi Iwaia3b48c82009-04-21 13:37:29 +02002364 if (power_state == AC_PWRST_D3 &&
2365 wid_type == AC_WID_PIN) {
Takashi Iwai7eba5c92007-11-14 14:53:42 +01002366 unsigned int pincap;
2367 /*
2368 * don't power down the widget if it controls
2369 * eapd and EAPD_BTLENABLE is set.
2370 */
Takashi Iwai14bafe32009-03-23 16:35:39 +01002371 pincap = snd_hda_query_pin_caps(codec, nid);
Takashi Iwai7eba5c92007-11-14 14:53:42 +01002372 if (pincap & AC_PINCAP_EAPD) {
2373 int eapd = snd_hda_codec_read(codec,
2374 nid, 0,
2375 AC_VERB_GET_EAPD_BTLENABLE, 0);
2376 eapd &= 0x02;
Takashi Iwaia3b48c82009-04-21 13:37:29 +02002377 if (eapd)
Takashi Iwai7eba5c92007-11-14 14:53:42 +01002378 continue;
2379 }
Takashi Iwai1194b5b2007-10-10 10:04:26 +02002380 }
Takashi Iwai54d17402005-11-21 16:33:22 +01002381 snd_hda_codec_write(codec, nid, 0,
2382 AC_VERB_SET_POWER_STATE,
2383 power_state);
Takashi Iwai1194b5b2007-10-10 10:04:26 +02002384 }
Takashi Iwai54d17402005-11-21 16:33:22 +01002385 }
2386
Takashi Iwaicb53c622007-08-10 17:21:45 +02002387 if (power_state == AC_PWRST_D0) {
2388 unsigned long end_time;
2389 int state;
Takashi Iwai54d17402005-11-21 16:33:22 +01002390 msleep(10);
Takashi Iwaicb53c622007-08-10 17:21:45 +02002391 /* wait until the codec reachs to D0 */
2392 end_time = jiffies + msecs_to_jiffies(500);
2393 do {
2394 state = snd_hda_codec_read(codec, fg, 0,
2395 AC_VERB_GET_POWER_STATE, 0);
2396 if (state == power_state)
2397 break;
2398 msleep(1);
2399 } while (time_after_eq(end_time, jiffies));
2400 }
Takashi Iwai54d17402005-11-21 16:33:22 +01002401}
2402
Takashi Iwai11aeff02008-07-30 15:01:46 +02002403#ifdef CONFIG_SND_HDA_HWDEP
2404/* execute additional init verbs */
2405static void hda_exec_init_verbs(struct hda_codec *codec)
2406{
2407 if (codec->init_verbs.list)
2408 snd_hda_sequence_write(codec, codec->init_verbs.list);
2409}
2410#else
2411static inline void hda_exec_init_verbs(struct hda_codec *codec) {}
2412#endif
2413
Takashi Iwaicb53c622007-08-10 17:21:45 +02002414#ifdef SND_HDA_NEEDS_RESUME
2415/*
2416 * call suspend and power-down; used both from PM and power-save
2417 */
2418static void hda_call_codec_suspend(struct hda_codec *codec)
2419{
2420 if (codec->patch_ops.suspend)
2421 codec->patch_ops.suspend(codec, PMSG_SUSPEND);
2422 hda_set_power_state(codec,
2423 codec->afg ? codec->afg : codec->mfg,
2424 AC_PWRST_D3);
2425#ifdef CONFIG_SND_HDA_POWER_SAVE
2426 cancel_delayed_work(&codec->power_work);
Takashi Iwai95e99fd2007-08-13 15:29:04 +02002427 codec->power_on = 0;
Takashi Iwaia221e282007-08-16 16:35:33 +02002428 codec->power_transition = 0;
Takashi Iwaicb53c622007-08-10 17:21:45 +02002429#endif
2430}
2431
2432/*
2433 * kick up codec; used both from PM and power-save
2434 */
2435static void hda_call_codec_resume(struct hda_codec *codec)
2436{
2437 hda_set_power_state(codec,
2438 codec->afg ? codec->afg : codec->mfg,
2439 AC_PWRST_D0);
Takashi Iwai3be14142009-02-20 14:11:16 +01002440 restore_pincfgs(codec); /* restore all current pin configs */
Takashi Iwai11aeff02008-07-30 15:01:46 +02002441 hda_exec_init_verbs(codec);
Takashi Iwaicb53c622007-08-10 17:21:45 +02002442 if (codec->patch_ops.resume)
2443 codec->patch_ops.resume(codec);
2444 else {
Takashi Iwai9d99f312007-08-14 15:15:52 +02002445 if (codec->patch_ops.init)
2446 codec->patch_ops.init(codec);
Takashi Iwaicb53c622007-08-10 17:21:45 +02002447 snd_hda_codec_resume_amp(codec);
2448 snd_hda_codec_resume_cache(codec);
2449 }
2450}
2451#endif /* SND_HDA_NEEDS_RESUME */
2452
Takashi Iwai54d17402005-11-21 16:33:22 +01002453
Linus Torvalds1da177e2005-04-16 15:20:36 -07002454/**
2455 * snd_hda_build_controls - build mixer controls
2456 * @bus: the BUS
2457 *
2458 * Creates mixer controls for each codec included in the bus.
2459 *
2460 * Returns 0 if successful, otherwise a negative error code.
2461 */
Takashi Iwai1289e9e2008-11-27 15:47:11 +01002462int /*__devinit*/ snd_hda_build_controls(struct hda_bus *bus)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002463{
Takashi Iwai0ba21762007-04-16 11:29:14 +02002464 struct hda_codec *codec;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002465
Takashi Iwai0ba21762007-04-16 11:29:14 +02002466 list_for_each_entry(codec, &bus->codec_list, list) {
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02002467 int err = snd_hda_codec_build_controls(codec);
Takashi Iwaif93d4612009-03-02 10:44:15 +01002468 if (err < 0) {
2469 printk(KERN_ERR "hda_codec: cannot build controls"
2470 "for #%d (error %d)\n", codec->addr, err);
2471 err = snd_hda_codec_reset(codec);
2472 if (err < 0) {
2473 printk(KERN_ERR
2474 "hda_codec: cannot revert codec\n");
2475 return err;
2476 }
2477 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002478 }
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02002479 return 0;
2480}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002481EXPORT_SYMBOL_HDA(snd_hda_build_controls);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002482
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02002483int snd_hda_codec_build_controls(struct hda_codec *codec)
2484{
2485 int err = 0;
Takashi Iwai11aeff02008-07-30 15:01:46 +02002486 hda_exec_init_verbs(codec);
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02002487 /* continue to initialize... */
2488 if (codec->patch_ops.init)
2489 err = codec->patch_ops.init(codec);
2490 if (!err && codec->patch_ops.build_controls)
2491 err = codec->patch_ops.build_controls(codec);
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02002492 if (err < 0)
2493 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002494 return 0;
2495}
2496
Linus Torvalds1da177e2005-04-16 15:20:36 -07002497/*
2498 * stream formats
2499 */
Takashi Iwaibefdf312005-08-22 13:57:55 +02002500struct hda_rate_tbl {
2501 unsigned int hz;
2502 unsigned int alsa_bits;
2503 unsigned int hda_fmt;
2504};
2505
2506static struct hda_rate_tbl rate_bits[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002507 /* rate in Hz, ALSA rate bitmask, HDA format value */
Nicolas Graziano9d8f53f2005-08-22 13:47:16 +02002508
2509 /* autodetected value used in snd_hda_query_supported_pcm */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002510 { 8000, SNDRV_PCM_RATE_8000, 0x0500 }, /* 1/6 x 48 */
2511 { 11025, SNDRV_PCM_RATE_11025, 0x4300 }, /* 1/4 x 44 */
2512 { 16000, SNDRV_PCM_RATE_16000, 0x0200 }, /* 1/3 x 48 */
2513 { 22050, SNDRV_PCM_RATE_22050, 0x4100 }, /* 1/2 x 44 */
2514 { 32000, SNDRV_PCM_RATE_32000, 0x0a00 }, /* 2/3 x 48 */
2515 { 44100, SNDRV_PCM_RATE_44100, 0x4000 }, /* 44 */
2516 { 48000, SNDRV_PCM_RATE_48000, 0x0000 }, /* 48 */
2517 { 88200, SNDRV_PCM_RATE_88200, 0x4800 }, /* 2 x 44 */
2518 { 96000, SNDRV_PCM_RATE_96000, 0x0800 }, /* 2 x 48 */
2519 { 176400, SNDRV_PCM_RATE_176400, 0x5800 },/* 4 x 44 */
2520 { 192000, SNDRV_PCM_RATE_192000, 0x1800 }, /* 4 x 48 */
Takashi Iwaia961f9f2007-04-12 13:08:09 +02002521#define AC_PAR_PCM_RATE_BITS 11
2522 /* up to bits 10, 384kHZ isn't supported properly */
2523
2524 /* not autodetected value */
2525 { 9600, SNDRV_PCM_RATE_KNOT, 0x0400 }, /* 1/5 x 48 */
Nicolas Graziano9d8f53f2005-08-22 13:47:16 +02002526
Takashi Iwaibefdf312005-08-22 13:57:55 +02002527 { 0 } /* terminator */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002528};
2529
2530/**
2531 * snd_hda_calc_stream_format - calculate format bitset
2532 * @rate: the sample rate
2533 * @channels: the number of channels
2534 * @format: the PCM format (SNDRV_PCM_FORMAT_XXX)
2535 * @maxbps: the max. bps
2536 *
2537 * Calculate the format bitset from the given rate, channels and th PCM format.
2538 *
2539 * Return zero if invalid.
2540 */
2541unsigned int snd_hda_calc_stream_format(unsigned int rate,
2542 unsigned int channels,
2543 unsigned int format,
2544 unsigned int maxbps)
2545{
2546 int i;
2547 unsigned int val = 0;
2548
Takashi Iwaibefdf312005-08-22 13:57:55 +02002549 for (i = 0; rate_bits[i].hz; i++)
2550 if (rate_bits[i].hz == rate) {
2551 val = rate_bits[i].hda_fmt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002552 break;
2553 }
Takashi Iwai0ba21762007-04-16 11:29:14 +02002554 if (!rate_bits[i].hz) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002555 snd_printdd("invalid rate %d\n", rate);
2556 return 0;
2557 }
2558
2559 if (channels == 0 || channels > 8) {
2560 snd_printdd("invalid channels %d\n", channels);
2561 return 0;
2562 }
2563 val |= channels - 1;
2564
2565 switch (snd_pcm_format_width(format)) {
2566 case 8: val |= 0x00; break;
2567 case 16: val |= 0x10; break;
2568 case 20:
2569 case 24:
2570 case 32:
Takashi Iwaib0bb3aa2009-07-03 23:25:37 +02002571 if (maxbps >= 32 || format == SNDRV_PCM_FORMAT_FLOAT_LE)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002572 val |= 0x40;
2573 else if (maxbps >= 24)
2574 val |= 0x30;
2575 else
2576 val |= 0x20;
2577 break;
2578 default:
Takashi Iwai0ba21762007-04-16 11:29:14 +02002579 snd_printdd("invalid format width %d\n",
2580 snd_pcm_format_width(format));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002581 return 0;
2582 }
2583
2584 return val;
2585}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002586EXPORT_SYMBOL_HDA(snd_hda_calc_stream_format);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002587
Takashi Iwai92c7c8a2009-03-24 07:32:14 +01002588static unsigned int get_pcm_param(struct hda_codec *codec, hda_nid_t nid)
2589{
2590 unsigned int val = 0;
2591 if (nid != codec->afg &&
2592 (get_wcaps(codec, nid) & AC_WCAP_FORMAT_OVRD))
2593 val = snd_hda_param_read(codec, nid, AC_PAR_PCM);
2594 if (!val || val == -1)
2595 val = snd_hda_param_read(codec, codec->afg, AC_PAR_PCM);
2596 if (!val || val == -1)
2597 return 0;
2598 return val;
2599}
2600
2601static unsigned int query_pcm_param(struct hda_codec *codec, hda_nid_t nid)
2602{
2603 return query_caps_hash(codec, nid, HDA_HASH_PARPCM_KEY(nid),
2604 get_pcm_param);
2605}
2606
2607static unsigned int get_stream_param(struct hda_codec *codec, hda_nid_t nid)
2608{
2609 unsigned int streams = snd_hda_param_read(codec, nid, AC_PAR_STREAM);
2610 if (!streams || streams == -1)
2611 streams = snd_hda_param_read(codec, codec->afg, AC_PAR_STREAM);
2612 if (!streams || streams == -1)
2613 return 0;
2614 return streams;
2615}
2616
2617static unsigned int query_stream_param(struct hda_codec *codec, hda_nid_t nid)
2618{
2619 return query_caps_hash(codec, nid, HDA_HASH_PARSTR_KEY(nid),
2620 get_stream_param);
2621}
2622
Linus Torvalds1da177e2005-04-16 15:20:36 -07002623/**
2624 * snd_hda_query_supported_pcm - query the supported PCM rates and formats
2625 * @codec: the HDA codec
2626 * @nid: NID to query
2627 * @ratesp: the pointer to store the detected rate bitflags
2628 * @formatsp: the pointer to store the detected formats
2629 * @bpsp: the pointer to store the detected format widths
2630 *
2631 * Queries the supported PCM rates and formats. The NULL @ratesp, @formatsp
2632 * or @bsps argument is ignored.
2633 *
2634 * Returns 0 if successful, otherwise a negative error code.
2635 */
Takashi Iwai986862bd2008-11-27 12:40:13 +01002636static int snd_hda_query_supported_pcm(struct hda_codec *codec, hda_nid_t nid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002637 u32 *ratesp, u64 *formatsp, unsigned int *bpsp)
2638{
Jaroslav Kyselaee504712009-03-17 14:30:31 +01002639 unsigned int i, val, wcaps;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002640
Jaroslav Kyselaee504712009-03-17 14:30:31 +01002641 wcaps = get_wcaps(codec, nid);
Takashi Iwai92c7c8a2009-03-24 07:32:14 +01002642 val = query_pcm_param(codec, nid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002643
2644 if (ratesp) {
2645 u32 rates = 0;
Takashi Iwaia961f9f2007-04-12 13:08:09 +02002646 for (i = 0; i < AC_PAR_PCM_RATE_BITS; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002647 if (val & (1 << i))
Takashi Iwaibefdf312005-08-22 13:57:55 +02002648 rates |= rate_bits[i].alsa_bits;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002649 }
Jaroslav Kyselaee504712009-03-17 14:30:31 +01002650 if (rates == 0) {
2651 snd_printk(KERN_ERR "hda_codec: rates == 0 "
2652 "(nid=0x%x, val=0x%x, ovrd=%i)\n",
2653 nid, val,
2654 (wcaps & AC_WCAP_FORMAT_OVRD) ? 1 : 0);
2655 return -EIO;
2656 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002657 *ratesp = rates;
2658 }
2659
2660 if (formatsp || bpsp) {
2661 u64 formats = 0;
Jaroslav Kyselaee504712009-03-17 14:30:31 +01002662 unsigned int streams, bps;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002663
Takashi Iwai92c7c8a2009-03-24 07:32:14 +01002664 streams = query_stream_param(codec, nid);
2665 if (!streams)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002666 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002667
2668 bps = 0;
2669 if (streams & AC_SUPFMT_PCM) {
2670 if (val & AC_SUPPCM_BITS_8) {
2671 formats |= SNDRV_PCM_FMTBIT_U8;
2672 bps = 8;
2673 }
2674 if (val & AC_SUPPCM_BITS_16) {
2675 formats |= SNDRV_PCM_FMTBIT_S16_LE;
2676 bps = 16;
2677 }
2678 if (wcaps & AC_WCAP_DIGITAL) {
2679 if (val & AC_SUPPCM_BITS_32)
2680 formats |= SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_LE;
2681 if (val & (AC_SUPPCM_BITS_20|AC_SUPPCM_BITS_24))
2682 formats |= SNDRV_PCM_FMTBIT_S32_LE;
2683 if (val & AC_SUPPCM_BITS_24)
2684 bps = 24;
2685 else if (val & AC_SUPPCM_BITS_20)
2686 bps = 20;
Takashi Iwai0ba21762007-04-16 11:29:14 +02002687 } else if (val & (AC_SUPPCM_BITS_20|AC_SUPPCM_BITS_24|
2688 AC_SUPPCM_BITS_32)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002689 formats |= SNDRV_PCM_FMTBIT_S32_LE;
2690 if (val & AC_SUPPCM_BITS_32)
2691 bps = 32;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002692 else if (val & AC_SUPPCM_BITS_24)
2693 bps = 24;
Nicolas Graziano33ef76512006-09-19 14:23:14 +02002694 else if (val & AC_SUPPCM_BITS_20)
2695 bps = 20;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002696 }
2697 }
Takashi Iwaib5025c52009-07-01 18:05:27 +02002698 if (streams & AC_SUPFMT_FLOAT32) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002699 formats |= SNDRV_PCM_FMTBIT_FLOAT_LE;
Takashi Iwaib0bb3aa2009-07-03 23:25:37 +02002700 if (!bps)
2701 bps = 32;
Takashi Iwaib5025c52009-07-01 18:05:27 +02002702 }
2703 if (streams == AC_SUPFMT_AC3) {
Takashi Iwai0ba21762007-04-16 11:29:14 +02002704 /* should be exclusive */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002705 /* temporary hack: we have still no proper support
2706 * for the direct AC3 stream...
2707 */
2708 formats |= SNDRV_PCM_FMTBIT_U8;
2709 bps = 8;
2710 }
Jaroslav Kyselaee504712009-03-17 14:30:31 +01002711 if (formats == 0) {
2712 snd_printk(KERN_ERR "hda_codec: formats == 0 "
2713 "(nid=0x%x, val=0x%x, ovrd=%i, "
2714 "streams=0x%x)\n",
2715 nid, val,
2716 (wcaps & AC_WCAP_FORMAT_OVRD) ? 1 : 0,
2717 streams);
2718 return -EIO;
2719 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002720 if (formatsp)
2721 *formatsp = formats;
2722 if (bpsp)
2723 *bpsp = bps;
2724 }
2725
2726 return 0;
2727}
2728
2729/**
Takashi Iwai0ba21762007-04-16 11:29:14 +02002730 * snd_hda_is_supported_format - check whether the given node supports
2731 * the format val
Linus Torvalds1da177e2005-04-16 15:20:36 -07002732 *
2733 * Returns 1 if supported, 0 if not.
2734 */
2735int snd_hda_is_supported_format(struct hda_codec *codec, hda_nid_t nid,
2736 unsigned int format)
2737{
2738 int i;
2739 unsigned int val = 0, rate, stream;
2740
Takashi Iwai92c7c8a2009-03-24 07:32:14 +01002741 val = query_pcm_param(codec, nid);
2742 if (!val)
2743 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002744
2745 rate = format & 0xff00;
Takashi Iwaia961f9f2007-04-12 13:08:09 +02002746 for (i = 0; i < AC_PAR_PCM_RATE_BITS; i++)
Takashi Iwaibefdf312005-08-22 13:57:55 +02002747 if (rate_bits[i].hda_fmt == rate) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002748 if (val & (1 << i))
2749 break;
2750 return 0;
2751 }
Takashi Iwaia961f9f2007-04-12 13:08:09 +02002752 if (i >= AC_PAR_PCM_RATE_BITS)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002753 return 0;
2754
Takashi Iwai92c7c8a2009-03-24 07:32:14 +01002755 stream = query_stream_param(codec, nid);
2756 if (!stream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002757 return 0;
2758
2759 if (stream & AC_SUPFMT_PCM) {
2760 switch (format & 0xf0) {
2761 case 0x00:
Takashi Iwai0ba21762007-04-16 11:29:14 +02002762 if (!(val & AC_SUPPCM_BITS_8))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002763 return 0;
2764 break;
2765 case 0x10:
Takashi Iwai0ba21762007-04-16 11:29:14 +02002766 if (!(val & AC_SUPPCM_BITS_16))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002767 return 0;
2768 break;
2769 case 0x20:
Takashi Iwai0ba21762007-04-16 11:29:14 +02002770 if (!(val & AC_SUPPCM_BITS_20))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002771 return 0;
2772 break;
2773 case 0x30:
Takashi Iwai0ba21762007-04-16 11:29:14 +02002774 if (!(val & AC_SUPPCM_BITS_24))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002775 return 0;
2776 break;
2777 case 0x40:
Takashi Iwai0ba21762007-04-16 11:29:14 +02002778 if (!(val & AC_SUPPCM_BITS_32))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002779 return 0;
2780 break;
2781 default:
2782 return 0;
2783 }
2784 } else {
2785 /* FIXME: check for float32 and AC3? */
2786 }
2787
2788 return 1;
2789}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002790EXPORT_SYMBOL_HDA(snd_hda_is_supported_format);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002791
2792/*
2793 * PCM stuff
2794 */
2795static int hda_pcm_default_open_close(struct hda_pcm_stream *hinfo,
2796 struct hda_codec *codec,
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01002797 struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002798{
2799 return 0;
2800}
2801
2802static int hda_pcm_default_prepare(struct hda_pcm_stream *hinfo,
2803 struct hda_codec *codec,
2804 unsigned int stream_tag,
2805 unsigned int format,
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01002806 struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002807{
2808 snd_hda_codec_setup_stream(codec, hinfo->nid, stream_tag, 0, format);
2809 return 0;
2810}
2811
2812static int hda_pcm_default_cleanup(struct hda_pcm_stream *hinfo,
2813 struct hda_codec *codec,
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01002814 struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002815{
Takashi Iwai888afa12008-03-18 09:57:50 +01002816 snd_hda_codec_cleanup_stream(codec, hinfo->nid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002817 return 0;
2818}
2819
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02002820static int set_pcm_default_values(struct hda_codec *codec,
2821 struct hda_pcm_stream *info)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002822{
Jaroslav Kyselaee504712009-03-17 14:30:31 +01002823 int err;
2824
Takashi Iwai0ba21762007-04-16 11:29:14 +02002825 /* query support PCM information from the given NID */
2826 if (info->nid && (!info->rates || !info->formats)) {
Jaroslav Kyselaee504712009-03-17 14:30:31 +01002827 err = snd_hda_query_supported_pcm(codec, info->nid,
Takashi Iwai0ba21762007-04-16 11:29:14 +02002828 info->rates ? NULL : &info->rates,
2829 info->formats ? NULL : &info->formats,
2830 info->maxbps ? NULL : &info->maxbps);
Jaroslav Kyselaee504712009-03-17 14:30:31 +01002831 if (err < 0)
2832 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002833 }
2834 if (info->ops.open == NULL)
2835 info->ops.open = hda_pcm_default_open_close;
2836 if (info->ops.close == NULL)
2837 info->ops.close = hda_pcm_default_open_close;
2838 if (info->ops.prepare == NULL) {
Takashi Iwaida3cec32008-08-08 17:12:14 +02002839 if (snd_BUG_ON(!info->nid))
2840 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002841 info->ops.prepare = hda_pcm_default_prepare;
2842 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002843 if (info->ops.cleanup == NULL) {
Takashi Iwaida3cec32008-08-08 17:12:14 +02002844 if (snd_BUG_ON(!info->nid))
2845 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002846 info->ops.cleanup = hda_pcm_default_cleanup;
2847 }
2848 return 0;
2849}
2850
Takashi Iwai176d5332008-07-30 15:01:44 +02002851/*
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002852 * get the empty PCM device number to assign
2853 */
2854static int get_empty_pcm_device(struct hda_bus *bus, int type)
2855{
2856 static const char *dev_name[HDA_PCM_NTYPES] = {
2857 "Audio", "SPDIF", "HDMI", "Modem"
2858 };
2859 /* starting device index for each PCM type */
2860 static int dev_idx[HDA_PCM_NTYPES] = {
2861 [HDA_PCM_TYPE_AUDIO] = 0,
2862 [HDA_PCM_TYPE_SPDIF] = 1,
2863 [HDA_PCM_TYPE_HDMI] = 3,
2864 [HDA_PCM_TYPE_MODEM] = 6
2865 };
2866 /* normal audio device indices; not linear to keep compatibility */
2867 static int audio_idx[4] = { 0, 2, 4, 5 };
2868 int i, dev;
2869
2870 switch (type) {
2871 case HDA_PCM_TYPE_AUDIO:
2872 for (i = 0; i < ARRAY_SIZE(audio_idx); i++) {
2873 dev = audio_idx[i];
2874 if (!test_bit(dev, bus->pcm_dev_bits))
Takashi Iwai82ad39f2009-03-03 15:00:35 +01002875 goto ok;
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002876 }
Takashi Iwai82ad39f2009-03-03 15:00:35 +01002877 snd_printk(KERN_WARNING "Too many audio devices\n");
2878 return -EAGAIN;
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002879 case HDA_PCM_TYPE_SPDIF:
2880 case HDA_PCM_TYPE_HDMI:
2881 case HDA_PCM_TYPE_MODEM:
2882 dev = dev_idx[type];
2883 if (test_bit(dev, bus->pcm_dev_bits)) {
2884 snd_printk(KERN_WARNING "%s already defined\n",
2885 dev_name[type]);
2886 return -EAGAIN;
2887 }
2888 break;
2889 default:
2890 snd_printk(KERN_WARNING "Invalid PCM type %d\n", type);
2891 return -EINVAL;
2892 }
Takashi Iwai82ad39f2009-03-03 15:00:35 +01002893 ok:
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002894 set_bit(dev, bus->pcm_dev_bits);
2895 return dev;
2896}
2897
2898/*
Takashi Iwai176d5332008-07-30 15:01:44 +02002899 * attach a new PCM stream
2900 */
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002901static int snd_hda_attach_pcm(struct hda_codec *codec, struct hda_pcm *pcm)
Takashi Iwai176d5332008-07-30 15:01:44 +02002902{
Takashi Iwai33fa35e2008-11-06 16:50:40 +01002903 struct hda_bus *bus = codec->bus;
Takashi Iwai176d5332008-07-30 15:01:44 +02002904 struct hda_pcm_stream *info;
2905 int stream, err;
2906
Takashi Iwaib91f0802008-11-04 08:43:08 +01002907 if (snd_BUG_ON(!pcm->name))
Takashi Iwai176d5332008-07-30 15:01:44 +02002908 return -EINVAL;
2909 for (stream = 0; stream < 2; stream++) {
2910 info = &pcm->stream[stream];
2911 if (info->substreams) {
2912 err = set_pcm_default_values(codec, info);
2913 if (err < 0)
2914 return err;
2915 }
2916 }
Takashi Iwai33fa35e2008-11-06 16:50:40 +01002917 return bus->ops.attach_pcm(bus, codec, pcm);
Takashi Iwai176d5332008-07-30 15:01:44 +02002918}
2919
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002920/* assign all PCMs of the given codec */
2921int snd_hda_codec_build_pcms(struct hda_codec *codec)
2922{
2923 unsigned int pcm;
2924 int err;
2925
2926 if (!codec->num_pcms) {
2927 if (!codec->patch_ops.build_pcms)
2928 return 0;
2929 err = codec->patch_ops.build_pcms(codec);
Takashi Iwai6e655bf2009-03-02 10:46:03 +01002930 if (err < 0) {
2931 printk(KERN_ERR "hda_codec: cannot build PCMs"
2932 "for #%d (error %d)\n", codec->addr, err);
2933 err = snd_hda_codec_reset(codec);
2934 if (err < 0) {
2935 printk(KERN_ERR
2936 "hda_codec: cannot revert codec\n");
2937 return err;
2938 }
2939 }
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002940 }
2941 for (pcm = 0; pcm < codec->num_pcms; pcm++) {
2942 struct hda_pcm *cpcm = &codec->pcm_info[pcm];
2943 int dev;
2944
2945 if (!cpcm->stream[0].substreams && !cpcm->stream[1].substreams)
Takashi Iwai41b5b012009-01-20 18:21:23 +01002946 continue; /* no substreams assigned */
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002947
2948 if (!cpcm->pcm) {
2949 dev = get_empty_pcm_device(codec->bus, cpcm->pcm_type);
2950 if (dev < 0)
Takashi Iwai6e655bf2009-03-02 10:46:03 +01002951 continue; /* no fatal error */
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002952 cpcm->device = dev;
2953 err = snd_hda_attach_pcm(codec, cpcm);
Takashi Iwai6e655bf2009-03-02 10:46:03 +01002954 if (err < 0) {
2955 printk(KERN_ERR "hda_codec: cannot attach "
2956 "PCM stream %d for codec #%d\n",
2957 dev, codec->addr);
2958 continue; /* no fatal error */
2959 }
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002960 }
2961 }
2962 return 0;
2963}
2964
Linus Torvalds1da177e2005-04-16 15:20:36 -07002965/**
2966 * snd_hda_build_pcms - build PCM information
2967 * @bus: the BUS
2968 *
2969 * Create PCM information for each codec included in the bus.
2970 *
2971 * The build_pcms codec patch is requested to set up codec->num_pcms and
2972 * codec->pcm_info properly. The array is referred by the top-level driver
2973 * to create its PCM instances.
2974 * The allocated codec->pcm_info should be released in codec->patch_ops.free
2975 * callback.
2976 *
2977 * At least, substreams, channels_min and channels_max must be filled for
2978 * each stream. substreams = 0 indicates that the stream doesn't exist.
2979 * When rates and/or formats are zero, the supported values are queried
2980 * from the given nid. The nid is used also by the default ops.prepare
2981 * and ops.cleanup callbacks.
2982 *
2983 * The driver needs to call ops.open in its open callback. Similarly,
2984 * ops.close is supposed to be called in the close callback.
2985 * ops.prepare should be called in the prepare or hw_params callback
2986 * with the proper parameters for set up.
2987 * ops.cleanup should be called in hw_free for clean up of streams.
2988 *
2989 * This function returns 0 if successfull, or a negative error code.
2990 */
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002991int __devinit snd_hda_build_pcms(struct hda_bus *bus)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002992{
Takashi Iwai0ba21762007-04-16 11:29:14 +02002993 struct hda_codec *codec;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002994
Takashi Iwai0ba21762007-04-16 11:29:14 +02002995 list_for_each_entry(codec, &bus->codec_list, list) {
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002996 int err = snd_hda_codec_build_pcms(codec);
2997 if (err < 0)
2998 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002999 }
3000 return 0;
3001}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003002EXPORT_SYMBOL_HDA(snd_hda_build_pcms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003003
Linus Torvalds1da177e2005-04-16 15:20:36 -07003004/**
3005 * snd_hda_check_board_config - compare the current codec with the config table
3006 * @codec: the HDA codec
Takashi Iwaif5fcc132006-11-24 17:07:44 +01003007 * @num_configs: number of config enums
3008 * @models: array of model name strings
Linus Torvalds1da177e2005-04-16 15:20:36 -07003009 * @tbl: configuration table, terminated by null entries
3010 *
3011 * Compares the modelname or PCI subsystem id of the current codec with the
3012 * given configuration table. If a matching entry is found, returns its
3013 * config value (supposed to be 0 or positive).
3014 *
3015 * If no entries are matching, the function returns a negative value.
3016 */
Takashi Iwai12f288b2007-08-02 15:51:59 +02003017int snd_hda_check_board_config(struct hda_codec *codec,
3018 int num_configs, const char **models,
3019 const struct snd_pci_quirk *tbl)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003020{
Takashi Iwaif44ac832008-07-30 15:01:45 +02003021 if (codec->modelname && models) {
Takashi Iwaif5fcc132006-11-24 17:07:44 +01003022 int i;
3023 for (i = 0; i < num_configs; i++) {
3024 if (models[i] &&
Takashi Iwaif44ac832008-07-30 15:01:45 +02003025 !strcmp(codec->modelname, models[i])) {
Takashi Iwaif5fcc132006-11-24 17:07:44 +01003026 snd_printd(KERN_INFO "hda_codec: model '%s' is "
3027 "selected\n", models[i]);
3028 return i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003029 }
3030 }
3031 }
3032
Takashi Iwaif5fcc132006-11-24 17:07:44 +01003033 if (!codec->bus->pci || !tbl)
3034 return -1;
3035
3036 tbl = snd_pci_quirk_lookup(codec->bus->pci, tbl);
3037 if (!tbl)
3038 return -1;
3039 if (tbl->value >= 0 && tbl->value < num_configs) {
Takashi Iwai62cf8722008-05-20 12:15:15 +02003040#ifdef CONFIG_SND_DEBUG_VERBOSE
Takashi Iwaif5fcc132006-11-24 17:07:44 +01003041 char tmp[10];
3042 const char *model = NULL;
3043 if (models)
3044 model = models[tbl->value];
3045 if (!model) {
3046 sprintf(tmp, "#%d", tbl->value);
3047 model = tmp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003048 }
Takashi Iwaif5fcc132006-11-24 17:07:44 +01003049 snd_printdd(KERN_INFO "hda_codec: model '%s' is selected "
3050 "for config %x:%x (%s)\n",
3051 model, tbl->subvendor, tbl->subdevice,
3052 (tbl->name ? tbl->name : "Unknown device"));
3053#endif
3054 return tbl->value;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003055 }
3056 return -1;
3057}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003058EXPORT_SYMBOL_HDA(snd_hda_check_board_config);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003059
3060/**
Mauro Carvalho Chehab2eda3442008-08-11 10:18:39 +02003061 * snd_hda_check_board_codec_sid_config - compare the current codec
3062 subsystem ID with the
3063 config table
3064
3065 This is important for Gateway notebooks with SB450 HDA Audio
3066 where the vendor ID of the PCI device is:
3067 ATI Technologies Inc SB450 HDA Audio [1002:437b]
3068 and the vendor/subvendor are found only at the codec.
3069
3070 * @codec: the HDA codec
3071 * @num_configs: number of config enums
3072 * @models: array of model name strings
3073 * @tbl: configuration table, terminated by null entries
3074 *
3075 * Compares the modelname or PCI subsystem id of the current codec with the
3076 * given configuration table. If a matching entry is found, returns its
3077 * config value (supposed to be 0 or positive).
3078 *
3079 * If no entries are matching, the function returns a negative value.
3080 */
3081int snd_hda_check_board_codec_sid_config(struct hda_codec *codec,
3082 int num_configs, const char **models,
3083 const struct snd_pci_quirk *tbl)
3084{
3085 const struct snd_pci_quirk *q;
3086
3087 /* Search for codec ID */
3088 for (q = tbl; q->subvendor; q++) {
3089 unsigned long vendorid = (q->subdevice) | (q->subvendor << 16);
3090
3091 if (vendorid == codec->subsystem_id)
3092 break;
3093 }
3094
3095 if (!q->subvendor)
3096 return -1;
3097
3098 tbl = q;
3099
3100 if (tbl->value >= 0 && tbl->value < num_configs) {
3101#ifdef CONFIG_SND_DEBUG_DETECT
3102 char tmp[10];
3103 const char *model = NULL;
3104 if (models)
3105 model = models[tbl->value];
3106 if (!model) {
3107 sprintf(tmp, "#%d", tbl->value);
3108 model = tmp;
3109 }
3110 snd_printdd(KERN_INFO "hda_codec: model '%s' is selected "
3111 "for config %x:%x (%s)\n",
3112 model, tbl->subvendor, tbl->subdevice,
3113 (tbl->name ? tbl->name : "Unknown device"));
3114#endif
3115 return tbl->value;
3116 }
3117 return -1;
3118}
3119EXPORT_SYMBOL_HDA(snd_hda_check_board_codec_sid_config);
3120
3121/**
Linus Torvalds1da177e2005-04-16 15:20:36 -07003122 * snd_hda_add_new_ctls - create controls from the array
3123 * @codec: the HDA codec
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01003124 * @knew: the array of struct snd_kcontrol_new
Linus Torvalds1da177e2005-04-16 15:20:36 -07003125 *
3126 * This helper function creates and add new controls in the given array.
3127 * The array must be terminated with an empty entry as terminator.
3128 *
3129 * Returns 0 if successful, or a negative error code.
3130 */
Takashi Iwai12f288b2007-08-02 15:51:59 +02003131int snd_hda_add_new_ctls(struct hda_codec *codec, struct snd_kcontrol_new *knew)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003132{
Takashi Iwaicb53c622007-08-10 17:21:45 +02003133 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003134
3135 for (; knew->name; knew++) {
Takashi Iwai54d17402005-11-21 16:33:22 +01003136 struct snd_kcontrol *kctl;
3137 kctl = snd_ctl_new1(knew, codec);
Takashi Iwai0ba21762007-04-16 11:29:14 +02003138 if (!kctl)
Takashi Iwai54d17402005-11-21 16:33:22 +01003139 return -ENOMEM;
Takashi Iwaid13bd412008-07-30 15:01:45 +02003140 err = snd_hda_ctl_add(codec, kctl);
Takashi Iwai54d17402005-11-21 16:33:22 +01003141 if (err < 0) {
Takashi Iwai0ba21762007-04-16 11:29:14 +02003142 if (!codec->addr)
Takashi Iwai54d17402005-11-21 16:33:22 +01003143 return err;
3144 kctl = snd_ctl_new1(knew, codec);
Takashi Iwai0ba21762007-04-16 11:29:14 +02003145 if (!kctl)
Takashi Iwai54d17402005-11-21 16:33:22 +01003146 return -ENOMEM;
3147 kctl->id.device = codec->addr;
Takashi Iwaid13bd412008-07-30 15:01:45 +02003148 err = snd_hda_ctl_add(codec, kctl);
Takashi Iwai0ba21762007-04-16 11:29:14 +02003149 if (err < 0)
Takashi Iwai54d17402005-11-21 16:33:22 +01003150 return err;
3151 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003152 }
3153 return 0;
3154}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003155EXPORT_SYMBOL_HDA(snd_hda_add_new_ctls);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003156
Takashi Iwaicb53c622007-08-10 17:21:45 +02003157#ifdef CONFIG_SND_HDA_POWER_SAVE
3158static void hda_set_power_state(struct hda_codec *codec, hda_nid_t fg,
3159 unsigned int power_state);
3160
3161static void hda_power_work(struct work_struct *work)
3162{
3163 struct hda_codec *codec =
3164 container_of(work, struct hda_codec, power_work.work);
Takashi Iwai33fa35e2008-11-06 16:50:40 +01003165 struct hda_bus *bus = codec->bus;
Takashi Iwaicb53c622007-08-10 17:21:45 +02003166
Maxim Levitsky2e492462007-09-03 15:26:57 +02003167 if (!codec->power_on || codec->power_count) {
3168 codec->power_transition = 0;
Takashi Iwaicb53c622007-08-10 17:21:45 +02003169 return;
Maxim Levitsky2e492462007-09-03 15:26:57 +02003170 }
Takashi Iwaicb53c622007-08-10 17:21:45 +02003171
3172 hda_call_codec_suspend(codec);
Takashi Iwai33fa35e2008-11-06 16:50:40 +01003173 if (bus->ops.pm_notify)
3174 bus->ops.pm_notify(bus);
Takashi Iwaicb53c622007-08-10 17:21:45 +02003175}
3176
3177static void hda_keep_power_on(struct hda_codec *codec)
3178{
3179 codec->power_count++;
3180 codec->power_on = 1;
3181}
3182
3183void snd_hda_power_up(struct hda_codec *codec)
3184{
Takashi Iwai33fa35e2008-11-06 16:50:40 +01003185 struct hda_bus *bus = codec->bus;
3186
Takashi Iwaicb53c622007-08-10 17:21:45 +02003187 codec->power_count++;
Takashi Iwaia221e282007-08-16 16:35:33 +02003188 if (codec->power_on || codec->power_transition)
Takashi Iwaicb53c622007-08-10 17:21:45 +02003189 return;
3190
3191 codec->power_on = 1;
Takashi Iwai33fa35e2008-11-06 16:50:40 +01003192 if (bus->ops.pm_notify)
3193 bus->ops.pm_notify(bus);
Takashi Iwaicb53c622007-08-10 17:21:45 +02003194 hda_call_codec_resume(codec);
3195 cancel_delayed_work(&codec->power_work);
Takashi Iwaia221e282007-08-16 16:35:33 +02003196 codec->power_transition = 0;
Takashi Iwaicb53c622007-08-10 17:21:45 +02003197}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003198EXPORT_SYMBOL_HDA(snd_hda_power_up);
Takashi Iwai1289e9e2008-11-27 15:47:11 +01003199
3200#define power_save(codec) \
3201 ((codec)->bus->power_save ? *(codec)->bus->power_save : 0)
Takashi Iwaicb53c622007-08-10 17:21:45 +02003202
Takashi Iwaifee2fba2008-11-27 12:43:28 +01003203#define power_save(codec) \
3204 ((codec)->bus->power_save ? *(codec)->bus->power_save : 0)
3205
Takashi Iwaicb53c622007-08-10 17:21:45 +02003206void snd_hda_power_down(struct hda_codec *codec)
3207{
3208 --codec->power_count;
Takashi Iwaia221e282007-08-16 16:35:33 +02003209 if (!codec->power_on || codec->power_count || codec->power_transition)
Takashi Iwaicb53c622007-08-10 17:21:45 +02003210 return;
Takashi Iwaifee2fba2008-11-27 12:43:28 +01003211 if (power_save(codec)) {
Takashi Iwaia221e282007-08-16 16:35:33 +02003212 codec->power_transition = 1; /* avoid reentrance */
Takashi Iwaic107b412009-01-13 17:46:37 +01003213 queue_delayed_work(codec->bus->workq, &codec->power_work,
Takashi Iwaifee2fba2008-11-27 12:43:28 +01003214 msecs_to_jiffies(power_save(codec) * 1000));
Takashi Iwaia221e282007-08-16 16:35:33 +02003215 }
Takashi Iwaicb53c622007-08-10 17:21:45 +02003216}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003217EXPORT_SYMBOL_HDA(snd_hda_power_down);
Takashi Iwaicb53c622007-08-10 17:21:45 +02003218
3219int snd_hda_check_amp_list_power(struct hda_codec *codec,
3220 struct hda_loopback_check *check,
3221 hda_nid_t nid)
3222{
3223 struct hda_amp_list *p;
3224 int ch, v;
3225
3226 if (!check->amplist)
3227 return 0;
3228 for (p = check->amplist; p->nid; p++) {
3229 if (p->nid == nid)
3230 break;
3231 }
3232 if (!p->nid)
3233 return 0; /* nothing changed */
3234
3235 for (p = check->amplist; p->nid; p++) {
3236 for (ch = 0; ch < 2; ch++) {
3237 v = snd_hda_codec_amp_read(codec, p->nid, ch, p->dir,
3238 p->idx);
3239 if (!(v & HDA_AMP_MUTE) && v > 0) {
3240 if (!check->power_on) {
3241 check->power_on = 1;
3242 snd_hda_power_up(codec);
3243 }
3244 return 1;
3245 }
3246 }
3247 }
3248 if (check->power_on) {
3249 check->power_on = 0;
3250 snd_hda_power_down(codec);
3251 }
3252 return 0;
3253}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003254EXPORT_SYMBOL_HDA(snd_hda_check_amp_list_power);
Takashi Iwaicb53c622007-08-10 17:21:45 +02003255#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07003256
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01003257/*
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01003258 * Channel mode helper
3259 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003260int snd_hda_ch_mode_info(struct hda_codec *codec,
3261 struct snd_ctl_elem_info *uinfo,
3262 const struct hda_channel_mode *chmode,
3263 int num_chmodes)
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01003264{
3265 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
3266 uinfo->count = 1;
3267 uinfo->value.enumerated.items = num_chmodes;
3268 if (uinfo->value.enumerated.item >= num_chmodes)
3269 uinfo->value.enumerated.item = num_chmodes - 1;
3270 sprintf(uinfo->value.enumerated.name, "%dch",
3271 chmode[uinfo->value.enumerated.item].channels);
3272 return 0;
3273}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003274EXPORT_SYMBOL_HDA(snd_hda_ch_mode_info);
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01003275
Takashi Iwai0ba21762007-04-16 11:29:14 +02003276int snd_hda_ch_mode_get(struct hda_codec *codec,
3277 struct snd_ctl_elem_value *ucontrol,
3278 const struct hda_channel_mode *chmode,
3279 int num_chmodes,
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01003280 int max_channels)
3281{
3282 int i;
3283
3284 for (i = 0; i < num_chmodes; i++) {
3285 if (max_channels == chmode[i].channels) {
3286 ucontrol->value.enumerated.item[0] = i;
3287 break;
3288 }
3289 }
3290 return 0;
3291}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003292EXPORT_SYMBOL_HDA(snd_hda_ch_mode_get);
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01003293
Takashi Iwai0ba21762007-04-16 11:29:14 +02003294int snd_hda_ch_mode_put(struct hda_codec *codec,
3295 struct snd_ctl_elem_value *ucontrol,
3296 const struct hda_channel_mode *chmode,
3297 int num_chmodes,
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01003298 int *max_channelsp)
3299{
3300 unsigned int mode;
3301
3302 mode = ucontrol->value.enumerated.item[0];
Takashi Iwai68ea7b22007-11-15 15:54:38 +01003303 if (mode >= num_chmodes)
3304 return -EINVAL;
Takashi Iwai82beb8f2007-08-10 17:09:26 +02003305 if (*max_channelsp == chmode[mode].channels)
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01003306 return 0;
3307 /* change the current channel setting */
3308 *max_channelsp = chmode[mode].channels;
3309 if (chmode[mode].sequence)
Takashi Iwai82beb8f2007-08-10 17:09:26 +02003310 snd_hda_sequence_write_cache(codec, chmode[mode].sequence);
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01003311 return 1;
3312}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003313EXPORT_SYMBOL_HDA(snd_hda_ch_mode_put);
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01003314
Linus Torvalds1da177e2005-04-16 15:20:36 -07003315/*
3316 * input MUX helper
3317 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003318int snd_hda_input_mux_info(const struct hda_input_mux *imux,
3319 struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003320{
3321 unsigned int index;
3322
3323 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
3324 uinfo->count = 1;
3325 uinfo->value.enumerated.items = imux->num_items;
Takashi Iwai5513b0c2007-10-09 11:58:41 +02003326 if (!imux->num_items)
3327 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003328 index = uinfo->value.enumerated.item;
3329 if (index >= imux->num_items)
3330 index = imux->num_items - 1;
3331 strcpy(uinfo->value.enumerated.name, imux->items[index].label);
3332 return 0;
3333}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003334EXPORT_SYMBOL_HDA(snd_hda_input_mux_info);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003335
Takashi Iwai0ba21762007-04-16 11:29:14 +02003336int snd_hda_input_mux_put(struct hda_codec *codec,
3337 const struct hda_input_mux *imux,
3338 struct snd_ctl_elem_value *ucontrol,
3339 hda_nid_t nid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003340 unsigned int *cur_val)
3341{
3342 unsigned int idx;
3343
Takashi Iwai5513b0c2007-10-09 11:58:41 +02003344 if (!imux->num_items)
3345 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003346 idx = ucontrol->value.enumerated.item[0];
3347 if (idx >= imux->num_items)
3348 idx = imux->num_items - 1;
Takashi Iwai82beb8f2007-08-10 17:09:26 +02003349 if (*cur_val == idx)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003350 return 0;
Takashi Iwai82beb8f2007-08-10 17:09:26 +02003351 snd_hda_codec_write_cache(codec, nid, 0, AC_VERB_SET_CONNECT_SEL,
3352 imux->items[idx].index);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003353 *cur_val = idx;
3354 return 1;
3355}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003356EXPORT_SYMBOL_HDA(snd_hda_input_mux_put);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003357
3358
3359/*
3360 * Multi-channel / digital-out PCM helper functions
3361 */
3362
Takashi Iwai6b97eb42007-04-05 14:51:48 +02003363/* setup SPDIF output stream */
3364static void setup_dig_out_stream(struct hda_codec *codec, hda_nid_t nid,
3365 unsigned int stream_tag, unsigned int format)
3366{
3367 /* turn off SPDIF once; otherwise the IEC958 bits won't be updated */
Takashi Iwai2f728532008-09-25 16:32:41 +02003368 if (codec->spdif_status_reset && (codec->spdif_ctls & AC_DIG1_ENABLE))
3369 set_dig_out_convert(codec, nid,
3370 codec->spdif_ctls & ~AC_DIG1_ENABLE & 0xff,
3371 -1);
Takashi Iwai6b97eb42007-04-05 14:51:48 +02003372 snd_hda_codec_setup_stream(codec, nid, stream_tag, 0, format);
Takashi Iwai2f728532008-09-25 16:32:41 +02003373 if (codec->slave_dig_outs) {
3374 hda_nid_t *d;
3375 for (d = codec->slave_dig_outs; *d; d++)
3376 snd_hda_codec_setup_stream(codec, *d, stream_tag, 0,
3377 format);
Matthew Ranostayde51ca12008-09-07 14:31:40 -04003378 }
Takashi Iwai2f728532008-09-25 16:32:41 +02003379 /* turn on again (if needed) */
3380 if (codec->spdif_status_reset && (codec->spdif_ctls & AC_DIG1_ENABLE))
3381 set_dig_out_convert(codec, nid,
3382 codec->spdif_ctls & 0xff, -1);
3383}
Matthew Ranostayde51ca12008-09-07 14:31:40 -04003384
Takashi Iwai2f728532008-09-25 16:32:41 +02003385static void cleanup_dig_out_stream(struct hda_codec *codec, hda_nid_t nid)
3386{
3387 snd_hda_codec_cleanup_stream(codec, nid);
3388 if (codec->slave_dig_outs) {
3389 hda_nid_t *d;
3390 for (d = codec->slave_dig_outs; *d; d++)
3391 snd_hda_codec_cleanup_stream(codec, *d);
3392 }
Takashi Iwai6b97eb42007-04-05 14:51:48 +02003393}
3394
Linus Torvalds1da177e2005-04-16 15:20:36 -07003395/*
3396 * open the digital out in the exclusive mode
3397 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003398int snd_hda_multi_out_dig_open(struct hda_codec *codec,
3399 struct hda_multi_out *mout)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003400{
Ingo Molnar62932df2006-01-16 16:34:20 +01003401 mutex_lock(&codec->spdif_mutex);
Takashi Iwai5930ca42007-04-16 11:23:56 +02003402 if (mout->dig_out_used == HDA_DIG_ANALOG_DUP)
3403 /* already opened as analog dup; reset it once */
Takashi Iwai2f728532008-09-25 16:32:41 +02003404 cleanup_dig_out_stream(codec, mout->dig_out_nid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003405 mout->dig_out_used = HDA_DIG_EXCLUSIVE;
Ingo Molnar62932df2006-01-16 16:34:20 +01003406 mutex_unlock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003407 return 0;
3408}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003409EXPORT_SYMBOL_HDA(snd_hda_multi_out_dig_open);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003410
Takashi Iwai6b97eb42007-04-05 14:51:48 +02003411int snd_hda_multi_out_dig_prepare(struct hda_codec *codec,
3412 struct hda_multi_out *mout,
3413 unsigned int stream_tag,
3414 unsigned int format,
3415 struct snd_pcm_substream *substream)
3416{
3417 mutex_lock(&codec->spdif_mutex);
3418 setup_dig_out_stream(codec, mout->dig_out_nid, stream_tag, format);
3419 mutex_unlock(&codec->spdif_mutex);
3420 return 0;
3421}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003422EXPORT_SYMBOL_HDA(snd_hda_multi_out_dig_prepare);
Takashi Iwai6b97eb42007-04-05 14:51:48 +02003423
Takashi Iwai9411e212009-02-13 11:32:28 +01003424int snd_hda_multi_out_dig_cleanup(struct hda_codec *codec,
3425 struct hda_multi_out *mout)
3426{
3427 mutex_lock(&codec->spdif_mutex);
3428 cleanup_dig_out_stream(codec, mout->dig_out_nid);
3429 mutex_unlock(&codec->spdif_mutex);
3430 return 0;
3431}
3432EXPORT_SYMBOL_HDA(snd_hda_multi_out_dig_cleanup);
3433
Linus Torvalds1da177e2005-04-16 15:20:36 -07003434/*
3435 * release the digital out
3436 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003437int snd_hda_multi_out_dig_close(struct hda_codec *codec,
3438 struct hda_multi_out *mout)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003439{
Ingo Molnar62932df2006-01-16 16:34:20 +01003440 mutex_lock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003441 mout->dig_out_used = 0;
Ingo Molnar62932df2006-01-16 16:34:20 +01003442 mutex_unlock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003443 return 0;
3444}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003445EXPORT_SYMBOL_HDA(snd_hda_multi_out_dig_close);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003446
3447/*
3448 * set up more restrictions for analog out
3449 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003450int snd_hda_multi_out_analog_open(struct hda_codec *codec,
3451 struct hda_multi_out *mout,
Takashi Iwai9a081602008-02-12 18:37:26 +01003452 struct snd_pcm_substream *substream,
3453 struct hda_pcm_stream *hinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003454{
Takashi Iwai9a081602008-02-12 18:37:26 +01003455 struct snd_pcm_runtime *runtime = substream->runtime;
3456 runtime->hw.channels_max = mout->max_channels;
3457 if (mout->dig_out_nid) {
3458 if (!mout->analog_rates) {
3459 mout->analog_rates = hinfo->rates;
3460 mout->analog_formats = hinfo->formats;
3461 mout->analog_maxbps = hinfo->maxbps;
3462 } else {
3463 runtime->hw.rates = mout->analog_rates;
3464 runtime->hw.formats = mout->analog_formats;
3465 hinfo->maxbps = mout->analog_maxbps;
3466 }
3467 if (!mout->spdif_rates) {
3468 snd_hda_query_supported_pcm(codec, mout->dig_out_nid,
3469 &mout->spdif_rates,
3470 &mout->spdif_formats,
3471 &mout->spdif_maxbps);
3472 }
3473 mutex_lock(&codec->spdif_mutex);
3474 if (mout->share_spdif) {
Takashi Iwai022b4662009-07-03 23:03:30 +02003475 if ((runtime->hw.rates & mout->spdif_rates) &&
3476 (runtime->hw.formats & mout->spdif_formats)) {
3477 runtime->hw.rates &= mout->spdif_rates;
3478 runtime->hw.formats &= mout->spdif_formats;
3479 if (mout->spdif_maxbps < hinfo->maxbps)
3480 hinfo->maxbps = mout->spdif_maxbps;
3481 } else {
3482 mout->share_spdif = 0;
3483 /* FIXME: need notify? */
3484 }
Takashi Iwai9a081602008-02-12 18:37:26 +01003485 }
Frederik Deweerdteaa99852008-04-14 13:11:44 +02003486 mutex_unlock(&codec->spdif_mutex);
Takashi Iwai9a081602008-02-12 18:37:26 +01003487 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003488 return snd_pcm_hw_constraint_step(substream->runtime, 0,
3489 SNDRV_PCM_HW_PARAM_CHANNELS, 2);
3490}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003491EXPORT_SYMBOL_HDA(snd_hda_multi_out_analog_open);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003492
3493/*
3494 * set up the i/o for analog out
3495 * when the digital out is available, copy the front out to digital out, too.
3496 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003497int snd_hda_multi_out_analog_prepare(struct hda_codec *codec,
3498 struct hda_multi_out *mout,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003499 unsigned int stream_tag,
3500 unsigned int format,
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01003501 struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003502{
3503 hda_nid_t *nids = mout->dac_nids;
3504 int chs = substream->runtime->channels;
3505 int i;
3506
Ingo Molnar62932df2006-01-16 16:34:20 +01003507 mutex_lock(&codec->spdif_mutex);
Takashi Iwai9a081602008-02-12 18:37:26 +01003508 if (mout->dig_out_nid && mout->share_spdif &&
3509 mout->dig_out_used != HDA_DIG_EXCLUSIVE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003510 if (chs == 2 &&
Takashi Iwai0ba21762007-04-16 11:29:14 +02003511 snd_hda_is_supported_format(codec, mout->dig_out_nid,
3512 format) &&
3513 !(codec->spdif_status & IEC958_AES0_NONAUDIO)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003514 mout->dig_out_used = HDA_DIG_ANALOG_DUP;
Takashi Iwai6b97eb42007-04-05 14:51:48 +02003515 setup_dig_out_stream(codec, mout->dig_out_nid,
3516 stream_tag, format);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003517 } else {
3518 mout->dig_out_used = 0;
Takashi Iwai2f728532008-09-25 16:32:41 +02003519 cleanup_dig_out_stream(codec, mout->dig_out_nid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003520 }
3521 }
Ingo Molnar62932df2006-01-16 16:34:20 +01003522 mutex_unlock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003523
3524 /* front */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003525 snd_hda_codec_setup_stream(codec, nids[HDA_FRONT], stream_tag,
3526 0, format);
Takashi Iwaid29240c2007-10-26 12:35:56 +02003527 if (!mout->no_share_stream &&
3528 mout->hp_nid && mout->hp_nid != nids[HDA_FRONT])
Linus Torvalds1da177e2005-04-16 15:20:36 -07003529 /* headphone out will just decode front left/right (stereo) */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003530 snd_hda_codec_setup_stream(codec, mout->hp_nid, stream_tag,
3531 0, format);
Takashi Iwai82bc9552006-03-21 11:24:42 +01003532 /* extra outputs copied from front */
3533 for (i = 0; i < ARRAY_SIZE(mout->extra_out_nid); i++)
Takashi Iwaid29240c2007-10-26 12:35:56 +02003534 if (!mout->no_share_stream && mout->extra_out_nid[i])
Takashi Iwai82bc9552006-03-21 11:24:42 +01003535 snd_hda_codec_setup_stream(codec,
3536 mout->extra_out_nid[i],
3537 stream_tag, 0, format);
3538
Linus Torvalds1da177e2005-04-16 15:20:36 -07003539 /* surrounds */
3540 for (i = 1; i < mout->num_dacs; i++) {
Takashi Iwai4b3acaf2005-06-10 19:48:10 +02003541 if (chs >= (i + 1) * 2) /* independent out */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003542 snd_hda_codec_setup_stream(codec, nids[i], stream_tag,
3543 i * 2, format);
Takashi Iwaid29240c2007-10-26 12:35:56 +02003544 else if (!mout->no_share_stream) /* copy front */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003545 snd_hda_codec_setup_stream(codec, nids[i], stream_tag,
3546 0, format);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003547 }
3548 return 0;
3549}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003550EXPORT_SYMBOL_HDA(snd_hda_multi_out_analog_prepare);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003551
3552/*
3553 * clean up the setting for analog out
3554 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003555int snd_hda_multi_out_analog_cleanup(struct hda_codec *codec,
3556 struct hda_multi_out *mout)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003557{
3558 hda_nid_t *nids = mout->dac_nids;
3559 int i;
3560
3561 for (i = 0; i < mout->num_dacs; i++)
Takashi Iwai888afa12008-03-18 09:57:50 +01003562 snd_hda_codec_cleanup_stream(codec, nids[i]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003563 if (mout->hp_nid)
Takashi Iwai888afa12008-03-18 09:57:50 +01003564 snd_hda_codec_cleanup_stream(codec, mout->hp_nid);
Takashi Iwai82bc9552006-03-21 11:24:42 +01003565 for (i = 0; i < ARRAY_SIZE(mout->extra_out_nid); i++)
3566 if (mout->extra_out_nid[i])
Takashi Iwai888afa12008-03-18 09:57:50 +01003567 snd_hda_codec_cleanup_stream(codec,
3568 mout->extra_out_nid[i]);
Ingo Molnar62932df2006-01-16 16:34:20 +01003569 mutex_lock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003570 if (mout->dig_out_nid && mout->dig_out_used == HDA_DIG_ANALOG_DUP) {
Takashi Iwai2f728532008-09-25 16:32:41 +02003571 cleanup_dig_out_stream(codec, mout->dig_out_nid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003572 mout->dig_out_used = 0;
3573 }
Ingo Molnar62932df2006-01-16 16:34:20 +01003574 mutex_unlock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003575 return 0;
3576}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003577EXPORT_SYMBOL_HDA(snd_hda_multi_out_analog_cleanup);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003578
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003579/*
Wu Fengguang6b345002008-10-07 14:21:41 +08003580 * Helper for automatic pin configuration
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003581 */
Kailang Yangdf694da2005-12-05 19:42:22 +01003582
Takashi Iwai12f288b2007-08-02 15:51:59 +02003583static int is_in_nid_list(hda_nid_t nid, hda_nid_t *list)
Kailang Yangdf694da2005-12-05 19:42:22 +01003584{
3585 for (; *list; list++)
3586 if (*list == nid)
3587 return 1;
3588 return 0;
3589}
3590
Steve Longerbeam81937d32007-05-08 15:33:03 +02003591
3592/*
3593 * Sort an associated group of pins according to their sequence numbers.
3594 */
3595static void sort_pins_by_sequence(hda_nid_t * pins, short * sequences,
3596 int num_pins)
3597{
3598 int i, j;
3599 short seq;
3600 hda_nid_t nid;
3601
3602 for (i = 0; i < num_pins; i++) {
3603 for (j = i + 1; j < num_pins; j++) {
3604 if (sequences[i] > sequences[j]) {
3605 seq = sequences[i];
3606 sequences[i] = sequences[j];
3607 sequences[j] = seq;
3608 nid = pins[i];
3609 pins[i] = pins[j];
3610 pins[j] = nid;
3611 }
3612 }
3613 }
3614}
3615
3616
Takashi Iwai82bc9552006-03-21 11:24:42 +01003617/*
3618 * Parse all pin widgets and store the useful pin nids to cfg
3619 *
3620 * The number of line-outs or any primary output is stored in line_outs,
3621 * and the corresponding output pins are assigned to line_out_pins[],
3622 * in the order of front, rear, CLFE, side, ...
3623 *
3624 * If more extra outputs (speaker and headphone) are found, the pins are
Takashi Iwaieb06ed82006-09-20 17:10:27 +02003625 * assisnged to hp_pins[] and speaker_pins[], respectively. If no line-out jack
Takashi Iwai82bc9552006-03-21 11:24:42 +01003626 * is detected, one of speaker of HP pins is assigned as the primary
3627 * output, i.e. to line_out_pins[0]. So, line_outs is always positive
3628 * if any analog output exists.
3629 *
3630 * The analog input pins are assigned to input_pins array.
3631 * The digital input/output pins are assigned to dig_in_pin and dig_out_pin,
3632 * respectively.
3633 */
Takashi Iwai12f288b2007-08-02 15:51:59 +02003634int snd_hda_parse_pin_def_config(struct hda_codec *codec,
3635 struct auto_pin_cfg *cfg,
3636 hda_nid_t *ignore_nids)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003637{
Takashi Iwai0ef6ce72008-01-22 15:35:37 +01003638 hda_nid_t nid, end_nid;
Steve Longerbeam81937d32007-05-08 15:33:03 +02003639 short seq, assoc_line_out, assoc_speaker;
3640 short sequences_line_out[ARRAY_SIZE(cfg->line_out_pins)];
3641 short sequences_speaker[ARRAY_SIZE(cfg->speaker_pins)];
Takashi Iwaif889fa92007-10-31 15:49:32 +01003642 short sequences_hp[ARRAY_SIZE(cfg->hp_pins)];
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003643
3644 memset(cfg, 0, sizeof(*cfg));
3645
Steve Longerbeam81937d32007-05-08 15:33:03 +02003646 memset(sequences_line_out, 0, sizeof(sequences_line_out));
3647 memset(sequences_speaker, 0, sizeof(sequences_speaker));
Takashi Iwaif889fa92007-10-31 15:49:32 +01003648 memset(sequences_hp, 0, sizeof(sequences_hp));
Steve Longerbeam81937d32007-05-08 15:33:03 +02003649 assoc_line_out = assoc_speaker = 0;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003650
Takashi Iwai0ef6ce72008-01-22 15:35:37 +01003651 end_nid = codec->start_nid + codec->num_nodes;
3652 for (nid = codec->start_nid; nid < end_nid; nid++) {
Takashi Iwai54d17402005-11-21 16:33:22 +01003653 unsigned int wid_caps = get_wcaps(codec, nid);
Takashi Iwai0ba21762007-04-16 11:29:14 +02003654 unsigned int wid_type =
3655 (wid_caps & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003656 unsigned int def_conf;
3657 short assoc, loc;
3658
3659 /* read all default configuration for pin complex */
3660 if (wid_type != AC_WID_PIN)
3661 continue;
Kailang Yangdf694da2005-12-05 19:42:22 +01003662 /* ignore the given nids (e.g. pc-beep returns error) */
3663 if (ignore_nids && is_in_nid_list(nid, ignore_nids))
3664 continue;
3665
Takashi Iwaic17a1ab2009-02-23 09:28:12 +01003666 def_conf = snd_hda_codec_get_pincfg(codec, nid);
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003667 if (get_defcfg_connect(def_conf) == AC_JACK_PORT_NONE)
3668 continue;
3669 loc = get_defcfg_location(def_conf);
3670 switch (get_defcfg_device(def_conf)) {
3671 case AC_JACK_LINE_OUT:
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003672 seq = get_defcfg_sequence(def_conf);
3673 assoc = get_defcfg_association(def_conf);
Matthew Ranostay90da78b2008-01-24 11:48:01 +01003674
3675 if (!(wid_caps & AC_WCAP_STEREO))
3676 if (!cfg->mono_out_pin)
3677 cfg->mono_out_pin = nid;
Takashi Iwai0ba21762007-04-16 11:29:14 +02003678 if (!assoc)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003679 continue;
Takashi Iwai0ba21762007-04-16 11:29:14 +02003680 if (!assoc_line_out)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003681 assoc_line_out = assoc;
3682 else if (assoc_line_out != assoc)
3683 continue;
3684 if (cfg->line_outs >= ARRAY_SIZE(cfg->line_out_pins))
3685 continue;
3686 cfg->line_out_pins[cfg->line_outs] = nid;
Steve Longerbeam81937d32007-05-08 15:33:03 +02003687 sequences_line_out[cfg->line_outs] = seq;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003688 cfg->line_outs++;
3689 break;
Takashi Iwai8d88bc32005-11-17 11:09:23 +01003690 case AC_JACK_SPEAKER:
Steve Longerbeam81937d32007-05-08 15:33:03 +02003691 seq = get_defcfg_sequence(def_conf);
3692 assoc = get_defcfg_association(def_conf);
3693 if (! assoc)
3694 continue;
3695 if (! assoc_speaker)
3696 assoc_speaker = assoc;
3697 else if (assoc_speaker != assoc)
3698 continue;
Takashi Iwai82bc9552006-03-21 11:24:42 +01003699 if (cfg->speaker_outs >= ARRAY_SIZE(cfg->speaker_pins))
3700 continue;
3701 cfg->speaker_pins[cfg->speaker_outs] = nid;
Steve Longerbeam81937d32007-05-08 15:33:03 +02003702 sequences_speaker[cfg->speaker_outs] = seq;
Takashi Iwai82bc9552006-03-21 11:24:42 +01003703 cfg->speaker_outs++;
Takashi Iwai8d88bc32005-11-17 11:09:23 +01003704 break;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003705 case AC_JACK_HP_OUT:
Takashi Iwaif889fa92007-10-31 15:49:32 +01003706 seq = get_defcfg_sequence(def_conf);
3707 assoc = get_defcfg_association(def_conf);
Takashi Iwaieb06ed82006-09-20 17:10:27 +02003708 if (cfg->hp_outs >= ARRAY_SIZE(cfg->hp_pins))
3709 continue;
3710 cfg->hp_pins[cfg->hp_outs] = nid;
Takashi Iwaif889fa92007-10-31 15:49:32 +01003711 sequences_hp[cfg->hp_outs] = (assoc << 4) | seq;
Takashi Iwaieb06ed82006-09-20 17:10:27 +02003712 cfg->hp_outs++;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003713 break;
Takashi Iwai314634b2006-09-21 11:56:18 +02003714 case AC_JACK_MIC_IN: {
3715 int preferred, alt;
3716 if (loc == AC_JACK_LOC_FRONT) {
3717 preferred = AUTO_PIN_FRONT_MIC;
3718 alt = AUTO_PIN_MIC;
3719 } else {
3720 preferred = AUTO_PIN_MIC;
3721 alt = AUTO_PIN_FRONT_MIC;
3722 }
3723 if (!cfg->input_pins[preferred])
3724 cfg->input_pins[preferred] = nid;
3725 else if (!cfg->input_pins[alt])
3726 cfg->input_pins[alt] = nid;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003727 break;
Takashi Iwai314634b2006-09-21 11:56:18 +02003728 }
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003729 case AC_JACK_LINE_IN:
3730 if (loc == AC_JACK_LOC_FRONT)
3731 cfg->input_pins[AUTO_PIN_FRONT_LINE] = nid;
3732 else
3733 cfg->input_pins[AUTO_PIN_LINE] = nid;
3734 break;
3735 case AC_JACK_CD:
3736 cfg->input_pins[AUTO_PIN_CD] = nid;
3737 break;
3738 case AC_JACK_AUX:
3739 cfg->input_pins[AUTO_PIN_AUX] = nid;
3740 break;
3741 case AC_JACK_SPDIF_OUT:
Takashi Iwai1b52ae72009-01-20 17:17:29 +01003742 case AC_JACK_DIG_OTHER_OUT:
Takashi Iwai0852d7a2009-02-11 11:35:15 +01003743 if (cfg->dig_outs >= ARRAY_SIZE(cfg->dig_out_pins))
3744 continue;
3745 cfg->dig_out_pins[cfg->dig_outs] = nid;
3746 cfg->dig_out_type[cfg->dig_outs] =
3747 (loc == AC_JACK_LOC_HDMI) ?
3748 HDA_PCM_TYPE_HDMI : HDA_PCM_TYPE_SPDIF;
3749 cfg->dig_outs++;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003750 break;
3751 case AC_JACK_SPDIF_IN:
Takashi Iwai1b52ae72009-01-20 17:17:29 +01003752 case AC_JACK_DIG_OTHER_IN:
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003753 cfg->dig_in_pin = nid;
Takashi Iwai2297bd62009-01-20 18:24:13 +01003754 if (loc == AC_JACK_LOC_HDMI)
3755 cfg->dig_in_type = HDA_PCM_TYPE_HDMI;
3756 else
3757 cfg->dig_in_type = HDA_PCM_TYPE_SPDIF;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003758 break;
3759 }
3760 }
3761
Takashi Iwai5832fcf2008-02-12 18:30:12 +01003762 /* FIX-UP:
3763 * If no line-out is defined but multiple HPs are found,
3764 * some of them might be the real line-outs.
3765 */
3766 if (!cfg->line_outs && cfg->hp_outs > 1) {
3767 int i = 0;
3768 while (i < cfg->hp_outs) {
3769 /* The real HPs should have the sequence 0x0f */
3770 if ((sequences_hp[i] & 0x0f) == 0x0f) {
3771 i++;
3772 continue;
3773 }
3774 /* Move it to the line-out table */
3775 cfg->line_out_pins[cfg->line_outs] = cfg->hp_pins[i];
3776 sequences_line_out[cfg->line_outs] = sequences_hp[i];
3777 cfg->line_outs++;
3778 cfg->hp_outs--;
3779 memmove(cfg->hp_pins + i, cfg->hp_pins + i + 1,
3780 sizeof(cfg->hp_pins[0]) * (cfg->hp_outs - i));
3781 memmove(sequences_hp + i - 1, sequences_hp + i,
3782 sizeof(sequences_hp[0]) * (cfg->hp_outs - i));
3783 }
3784 }
3785
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003786 /* sort by sequence */
Steve Longerbeam81937d32007-05-08 15:33:03 +02003787 sort_pins_by_sequence(cfg->line_out_pins, sequences_line_out,
3788 cfg->line_outs);
3789 sort_pins_by_sequence(cfg->speaker_pins, sequences_speaker,
3790 cfg->speaker_outs);
Takashi Iwaif889fa92007-10-31 15:49:32 +01003791 sort_pins_by_sequence(cfg->hp_pins, sequences_hp,
3792 cfg->hp_outs);
Steve Longerbeam81937d32007-05-08 15:33:03 +02003793
Takashi Iwaif889fa92007-10-31 15:49:32 +01003794 /* if we have only one mic, make it AUTO_PIN_MIC */
3795 if (!cfg->input_pins[AUTO_PIN_MIC] &&
3796 cfg->input_pins[AUTO_PIN_FRONT_MIC]) {
3797 cfg->input_pins[AUTO_PIN_MIC] =
3798 cfg->input_pins[AUTO_PIN_FRONT_MIC];
3799 cfg->input_pins[AUTO_PIN_FRONT_MIC] = 0;
3800 }
3801 /* ditto for line-in */
3802 if (!cfg->input_pins[AUTO_PIN_LINE] &&
3803 cfg->input_pins[AUTO_PIN_FRONT_LINE]) {
3804 cfg->input_pins[AUTO_PIN_LINE] =
3805 cfg->input_pins[AUTO_PIN_FRONT_LINE];
3806 cfg->input_pins[AUTO_PIN_FRONT_LINE] = 0;
3807 }
3808
Steve Longerbeam81937d32007-05-08 15:33:03 +02003809 /*
3810 * FIX-UP: if no line-outs are detected, try to use speaker or HP pin
3811 * as a primary output
3812 */
3813 if (!cfg->line_outs) {
3814 if (cfg->speaker_outs) {
3815 cfg->line_outs = cfg->speaker_outs;
3816 memcpy(cfg->line_out_pins, cfg->speaker_pins,
3817 sizeof(cfg->speaker_pins));
3818 cfg->speaker_outs = 0;
3819 memset(cfg->speaker_pins, 0, sizeof(cfg->speaker_pins));
3820 cfg->line_out_type = AUTO_PIN_SPEAKER_OUT;
3821 } else if (cfg->hp_outs) {
3822 cfg->line_outs = cfg->hp_outs;
3823 memcpy(cfg->line_out_pins, cfg->hp_pins,
3824 sizeof(cfg->hp_pins));
3825 cfg->hp_outs = 0;
3826 memset(cfg->hp_pins, 0, sizeof(cfg->hp_pins));
3827 cfg->line_out_type = AUTO_PIN_HP_OUT;
3828 }
3829 }
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003830
Takashi Iwaicb8e2f82005-07-29 11:54:32 +02003831 /* Reorder the surround channels
3832 * ALSA sequence is front/surr/clfe/side
3833 * HDA sequence is:
3834 * 4-ch: front/surr => OK as it is
3835 * 6-ch: front/clfe/surr
Takashi Iwai9422db42007-04-20 16:11:43 +02003836 * 8-ch: front/clfe/rear/side|fc
Takashi Iwaicb8e2f82005-07-29 11:54:32 +02003837 */
3838 switch (cfg->line_outs) {
3839 case 3:
Takashi Iwaicb8e2f82005-07-29 11:54:32 +02003840 case 4:
3841 nid = cfg->line_out_pins[1];
Takashi Iwai9422db42007-04-20 16:11:43 +02003842 cfg->line_out_pins[1] = cfg->line_out_pins[2];
Takashi Iwaicb8e2f82005-07-29 11:54:32 +02003843 cfg->line_out_pins[2] = nid;
3844 break;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003845 }
3846
Takashi Iwai82bc9552006-03-21 11:24:42 +01003847 /*
3848 * debug prints of the parsed results
3849 */
3850 snd_printd("autoconfig: line_outs=%d (0x%x/0x%x/0x%x/0x%x/0x%x)\n",
3851 cfg->line_outs, cfg->line_out_pins[0], cfg->line_out_pins[1],
3852 cfg->line_out_pins[2], cfg->line_out_pins[3],
3853 cfg->line_out_pins[4]);
3854 snd_printd(" speaker_outs=%d (0x%x/0x%x/0x%x/0x%x/0x%x)\n",
3855 cfg->speaker_outs, cfg->speaker_pins[0],
3856 cfg->speaker_pins[1], cfg->speaker_pins[2],
3857 cfg->speaker_pins[3], cfg->speaker_pins[4]);
Takashi Iwaieb06ed82006-09-20 17:10:27 +02003858 snd_printd(" hp_outs=%d (0x%x/0x%x/0x%x/0x%x/0x%x)\n",
3859 cfg->hp_outs, cfg->hp_pins[0],
3860 cfg->hp_pins[1], cfg->hp_pins[2],
3861 cfg->hp_pins[3], cfg->hp_pins[4]);
Matthew Ranostay90da78b2008-01-24 11:48:01 +01003862 snd_printd(" mono: mono_out=0x%x\n", cfg->mono_out_pin);
Takashi Iwai0852d7a2009-02-11 11:35:15 +01003863 if (cfg->dig_outs)
3864 snd_printd(" dig-out=0x%x/0x%x\n",
3865 cfg->dig_out_pins[0], cfg->dig_out_pins[1]);
Takashi Iwai82bc9552006-03-21 11:24:42 +01003866 snd_printd(" inputs: mic=0x%x, fmic=0x%x, line=0x%x, fline=0x%x,"
3867 " cd=0x%x, aux=0x%x\n",
3868 cfg->input_pins[AUTO_PIN_MIC],
3869 cfg->input_pins[AUTO_PIN_FRONT_MIC],
3870 cfg->input_pins[AUTO_PIN_LINE],
3871 cfg->input_pins[AUTO_PIN_FRONT_LINE],
3872 cfg->input_pins[AUTO_PIN_CD],
3873 cfg->input_pins[AUTO_PIN_AUX]);
Takashi Iwai32d2c7f2009-02-11 11:33:13 +01003874 if (cfg->dig_in_pin)
Takashi Iwai89ce9e82009-01-20 17:15:57 +01003875 snd_printd(" dig-in=0x%x\n", cfg->dig_in_pin);
Takashi Iwai82bc9552006-03-21 11:24:42 +01003876
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003877 return 0;
3878}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003879EXPORT_SYMBOL_HDA(snd_hda_parse_pin_def_config);
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003880
Takashi Iwai4a471b72005-12-07 13:56:29 +01003881/* labels for input pins */
3882const char *auto_pin_cfg_labels[AUTO_PIN_LAST] = {
3883 "Mic", "Front Mic", "Line", "Front Line", "CD", "Aux"
3884};
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003885EXPORT_SYMBOL_HDA(auto_pin_cfg_labels);
Takashi Iwai4a471b72005-12-07 13:56:29 +01003886
3887
Linus Torvalds1da177e2005-04-16 15:20:36 -07003888#ifdef CONFIG_PM
3889/*
3890 * power management
3891 */
3892
3893/**
3894 * snd_hda_suspend - suspend the codecs
3895 * @bus: the HDA bus
Linus Torvalds1da177e2005-04-16 15:20:36 -07003896 *
3897 * Returns 0 if successful.
3898 */
Takashi Iwai8dd78332009-06-02 01:16:07 +02003899int snd_hda_suspend(struct hda_bus *bus)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003900{
Takashi Iwai0ba21762007-04-16 11:29:14 +02003901 struct hda_codec *codec;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003902
Takashi Iwai0ba21762007-04-16 11:29:14 +02003903 list_for_each_entry(codec, &bus->codec_list, list) {
Takashi Iwai0b7a2e92007-08-14 15:18:26 +02003904#ifdef CONFIG_SND_HDA_POWER_SAVE
3905 if (!codec->power_on)
3906 continue;
3907#endif
Takashi Iwaicb53c622007-08-10 17:21:45 +02003908 hda_call_codec_suspend(codec);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003909 }
3910 return 0;
3911}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003912EXPORT_SYMBOL_HDA(snd_hda_suspend);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003913
3914/**
3915 * snd_hda_resume - resume the codecs
3916 * @bus: the HDA bus
Linus Torvalds1da177e2005-04-16 15:20:36 -07003917 *
3918 * Returns 0 if successful.
Takashi Iwaicb53c622007-08-10 17:21:45 +02003919 *
3920 * This fucntion is defined only when POWER_SAVE isn't set.
3921 * In the power-save mode, the codec is resumed dynamically.
Linus Torvalds1da177e2005-04-16 15:20:36 -07003922 */
3923int snd_hda_resume(struct hda_bus *bus)
3924{
Takashi Iwai0ba21762007-04-16 11:29:14 +02003925 struct hda_codec *codec;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003926
Takashi Iwai0ba21762007-04-16 11:29:14 +02003927 list_for_each_entry(codec, &bus->codec_list, list) {
Maxim Levitskyd804ad92007-09-03 15:28:04 +02003928 if (snd_hda_codec_needs_resume(codec))
3929 hda_call_codec_resume(codec);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003930 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003931 return 0;
3932}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003933EXPORT_SYMBOL_HDA(snd_hda_resume);
Takashi Iwai1289e9e2008-11-27 15:47:11 +01003934#endif /* CONFIG_PM */
Takashi Iwaib2e18592008-07-30 15:01:44 +02003935
3936/*
3937 * generic arrays
3938 */
3939
3940/* get a new element from the given array
3941 * if it exceeds the pre-allocated array size, re-allocate the array
3942 */
3943void *snd_array_new(struct snd_array *array)
3944{
3945 if (array->used >= array->alloced) {
3946 int num = array->alloced + array->alloc_align;
Takashi Iwaib910d9a2008-11-07 00:26:52 +01003947 void *nlist;
3948 if (snd_BUG_ON(num >= 4096))
3949 return NULL;
3950 nlist = kcalloc(num + 1, array->elem_size, GFP_KERNEL);
Takashi Iwaib2e18592008-07-30 15:01:44 +02003951 if (!nlist)
3952 return NULL;
3953 if (array->list) {
3954 memcpy(nlist, array->list,
3955 array->elem_size * array->alloced);
3956 kfree(array->list);
3957 }
3958 array->list = nlist;
3959 array->alloced = num;
3960 }
Takashi Iwaif43aa022008-11-10 16:24:26 +01003961 return snd_array_elem(array, array->used++);
Takashi Iwaib2e18592008-07-30 15:01:44 +02003962}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003963EXPORT_SYMBOL_HDA(snd_array_new);
Takashi Iwaib2e18592008-07-30 15:01:44 +02003964
3965/* free the given array elements */
3966void snd_array_free(struct snd_array *array)
3967{
3968 kfree(array->list);
3969 array->used = 0;
3970 array->alloced = 0;
3971 array->list = NULL;
3972}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003973EXPORT_SYMBOL_HDA(snd_array_free);
Takashi Iwaib2022262008-11-21 21:24:03 +01003974
3975/*
3976 * used by hda_proc.c and hda_eld.c
3977 */
3978void snd_print_pcm_rates(int pcm, char *buf, int buflen)
3979{
3980 static unsigned int rates[] = {
3981 8000, 11025, 16000, 22050, 32000, 44100, 48000, 88200,
3982 96000, 176400, 192000, 384000
3983 };
3984 int i, j;
3985
3986 for (i = 0, j = 0; i < ARRAY_SIZE(rates); i++)
3987 if (pcm & (1 << i))
3988 j += snprintf(buf + j, buflen - j, " %d", rates[i]);
3989
3990 buf[j] = '\0'; /* necessary when j == 0 */
3991}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003992EXPORT_SYMBOL_HDA(snd_print_pcm_rates);
Takashi Iwaib2022262008-11-21 21:24:03 +01003993
3994void snd_print_pcm_bits(int pcm, char *buf, int buflen)
3995{
3996 static unsigned int bits[] = { 8, 16, 20, 24, 32 };
3997 int i, j;
3998
3999 for (i = 0, j = 0; i < ARRAY_SIZE(bits); i++)
4000 if (pcm & (AC_SUPPCM_BITS_8 << i))
4001 j += snprintf(buf + j, buflen - j, " %d", bits[i]);
4002
4003 buf[j] = '\0'; /* necessary when j == 0 */
4004}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01004005EXPORT_SYMBOL_HDA(snd_print_pcm_bits);
Takashi Iwai1289e9e2008-11-27 15:47:11 +01004006
4007MODULE_DESCRIPTION("HDA codec core");
4008MODULE_LICENSE("GPL");