blob: 9c1af0101dde7c9f12aa6ac495cee339b6b600cf [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" },
49 { 0x10ec, "Realtek" },
Joseph Chanc577b8a2006-11-29 15:29:40 +010050 { 0x1106, "VIA" },
Matthew Ranostay7f168592007-10-18 17:38:17 +020051 { 0x111d, "IDT" },
Takashi Iwaic8cd1282008-02-13 16:59:29 +010052 { 0x11c1, "LSI" },
Takashi Iwai54b903e2005-05-15 14:30:10 +020053 { 0x11d4, "Analog Devices" },
Linus Torvalds1da177e2005-04-16 15:20:36 -070054 { 0x13f6, "C-Media" },
Takashi Iwaia9226252006-09-17 22:05:54 +020055 { 0x14f1, "Conexant" },
Takashi Iwaic8cd1282008-02-13 16:59:29 +010056 { 0x17e8, "Chrontel" },
57 { 0x1854, "LG" },
Mark Brown8199de32008-10-28 14:50:13 +000058 { 0x1aec, "Wolfson Microelectronics" },
Linus Torvalds1da177e2005-04-16 15:20:36 -070059 { 0x434d, "C-Media" },
Matt2f2f4252005-04-13 14:45:30 +020060 { 0x8384, "SigmaTel" },
Linus Torvalds1da177e2005-04-16 15:20:36 -070061 {} /* terminator */
62};
63
Takashi Iwai1289e9e2008-11-27 15:47:11 +010064static DEFINE_MUTEX(preset_mutex);
65static LIST_HEAD(hda_preset_tables);
66
67int snd_hda_add_codec_preset(struct hda_codec_preset_list *preset)
68{
69 mutex_lock(&preset_mutex);
70 list_add_tail(&preset->list, &hda_preset_tables);
71 mutex_unlock(&preset_mutex);
72 return 0;
73}
Takashi Iwaiff7a3262008-11-28 15:17:06 +010074EXPORT_SYMBOL_HDA(snd_hda_add_codec_preset);
Takashi Iwai1289e9e2008-11-27 15:47:11 +010075
76int snd_hda_delete_codec_preset(struct hda_codec_preset_list *preset)
77{
78 mutex_lock(&preset_mutex);
79 list_del(&preset->list);
80 mutex_unlock(&preset_mutex);
81 return 0;
82}
Takashi Iwaiff7a3262008-11-28 15:17:06 +010083EXPORT_SYMBOL_HDA(snd_hda_delete_codec_preset);
Linus Torvalds1da177e2005-04-16 15:20:36 -070084
Takashi Iwaicb53c622007-08-10 17:21:45 +020085#ifdef CONFIG_SND_HDA_POWER_SAVE
86static void hda_power_work(struct work_struct *work);
87static void hda_keep_power_on(struct hda_codec *codec);
88#else
89static inline void hda_keep_power_on(struct hda_codec *codec) {}
90#endif
91
Matthew Ranostay50a9f792008-10-25 01:05:45 -040092const char *snd_hda_get_jack_location(u32 cfg)
93{
94 static char *bases[7] = {
95 "N/A", "Rear", "Front", "Left", "Right", "Top", "Bottom",
96 };
97 static unsigned char specials_idx[] = {
98 0x07, 0x08,
99 0x17, 0x18, 0x19,
100 0x37, 0x38
101 };
102 static char *specials[] = {
103 "Rear Panel", "Drive Bar",
104 "Riser", "HDMI", "ATAPI",
105 "Mobile-In", "Mobile-Out"
106 };
107 int i;
108 cfg = (cfg & AC_DEFCFG_LOCATION) >> AC_DEFCFG_LOCATION_SHIFT;
109 if ((cfg & 0x0f) < 7)
110 return bases[cfg & 0x0f];
111 for (i = 0; i < ARRAY_SIZE(specials_idx); i++) {
112 if (cfg == specials_idx[i])
113 return specials[i];
114 }
115 return "UNKNOWN";
116}
Takashi Iwaiff7a3262008-11-28 15:17:06 +0100117EXPORT_SYMBOL_HDA(snd_hda_get_jack_location);
Matthew Ranostay50a9f792008-10-25 01:05:45 -0400118
119const char *snd_hda_get_jack_connectivity(u32 cfg)
120{
121 static char *jack_locations[4] = { "Ext", "Int", "Sep", "Oth" };
122
123 return jack_locations[(cfg >> (AC_DEFCFG_LOCATION_SHIFT + 4)) & 3];
124}
Takashi Iwaiff7a3262008-11-28 15:17:06 +0100125EXPORT_SYMBOL_HDA(snd_hda_get_jack_connectivity);
Matthew Ranostay50a9f792008-10-25 01:05:45 -0400126
127const char *snd_hda_get_jack_type(u32 cfg)
128{
129 static char *jack_types[16] = {
130 "Line Out", "Speaker", "HP Out", "CD",
131 "SPDIF Out", "Digital Out", "Modem Line", "Modem Hand",
132 "Line In", "Aux", "Mic", "Telephony",
133 "SPDIF In", "Digitial In", "Reserved", "Other"
134 };
135
136 return jack_types[(cfg & AC_DEFCFG_DEVICE)
137 >> AC_DEFCFG_DEVICE_SHIFT];
138}
Takashi Iwaiff7a3262008-11-28 15:17:06 +0100139EXPORT_SYMBOL_HDA(snd_hda_get_jack_type);
Matthew Ranostay50a9f792008-10-25 01:05:45 -0400140
Takashi Iwai33fa35e2008-11-06 16:50:40 +0100141/*
142 * Compose a 32bit command word to be sent to the HD-audio controller
143 */
144static inline unsigned int
145make_codec_cmd(struct hda_codec *codec, hda_nid_t nid, int direct,
146 unsigned int verb, unsigned int parm)
147{
148 u32 val;
149
150 val = (u32)(codec->addr & 0x0f) << 28;
151 val |= (u32)direct << 27;
152 val |= (u32)nid << 20;
153 val |= verb << 8;
154 val |= parm;
155 return val;
156}
157
Linus Torvalds1da177e2005-04-16 15:20:36 -0700158/**
159 * snd_hda_codec_read - send a command and get the response
160 * @codec: the HDA codec
161 * @nid: NID to send the command
162 * @direct: direct flag
163 * @verb: the verb to send
164 * @parm: the parameter for the verb
165 *
166 * Send a single command and read the corresponding response.
167 *
168 * Returns the obtained response value, or -1 for an error.
169 */
Takashi Iwai0ba21762007-04-16 11:29:14 +0200170unsigned int snd_hda_codec_read(struct hda_codec *codec, hda_nid_t nid,
171 int direct,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700172 unsigned int verb, unsigned int parm)
173{
Takashi Iwai33fa35e2008-11-06 16:50:40 +0100174 struct hda_bus *bus = codec->bus;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700175 unsigned int res;
Takashi Iwai33fa35e2008-11-06 16:50:40 +0100176
177 res = make_codec_cmd(codec, nid, direct, verb, parm);
Takashi Iwaicb53c622007-08-10 17:21:45 +0200178 snd_hda_power_up(codec);
Takashi Iwai33fa35e2008-11-06 16:50:40 +0100179 mutex_lock(&bus->cmd_mutex);
180 if (!bus->ops.command(bus, res))
181 res = bus->ops.get_response(bus);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700182 else
183 res = (unsigned int)-1;
Takashi Iwai33fa35e2008-11-06 16:50:40 +0100184 mutex_unlock(&bus->cmd_mutex);
Takashi Iwaicb53c622007-08-10 17:21:45 +0200185 snd_hda_power_down(codec);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700186 return res;
187}
Takashi Iwaiff7a3262008-11-28 15:17:06 +0100188EXPORT_SYMBOL_HDA(snd_hda_codec_read);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700189
190/**
191 * snd_hda_codec_write - send a single command without waiting for response
192 * @codec: the HDA codec
193 * @nid: NID to send the command
194 * @direct: direct flag
195 * @verb: the verb to send
196 * @parm: the parameter for the verb
197 *
198 * Send a single command without waiting for response.
199 *
200 * Returns 0 if successful, or a negative error code.
201 */
202int snd_hda_codec_write(struct hda_codec *codec, hda_nid_t nid, int direct,
203 unsigned int verb, unsigned int parm)
204{
Takashi Iwai33fa35e2008-11-06 16:50:40 +0100205 struct hda_bus *bus = codec->bus;
206 unsigned int res;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700207 int err;
Takashi Iwai33fa35e2008-11-06 16:50:40 +0100208
209 res = make_codec_cmd(codec, nid, direct, verb, parm);
Takashi Iwaicb53c622007-08-10 17:21:45 +0200210 snd_hda_power_up(codec);
Takashi Iwai33fa35e2008-11-06 16:50:40 +0100211 mutex_lock(&bus->cmd_mutex);
212 err = bus->ops.command(bus, res);
213 mutex_unlock(&bus->cmd_mutex);
Takashi Iwaicb53c622007-08-10 17:21:45 +0200214 snd_hda_power_down(codec);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700215 return err;
216}
Takashi Iwaiff7a3262008-11-28 15:17:06 +0100217EXPORT_SYMBOL_HDA(snd_hda_codec_write);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700218
219/**
220 * snd_hda_sequence_write - sequence writes
221 * @codec: the HDA codec
222 * @seq: VERB array to send
223 *
224 * Send the commands sequentially from the given array.
225 * The array must be terminated with NID=0.
226 */
227void snd_hda_sequence_write(struct hda_codec *codec, const struct hda_verb *seq)
228{
229 for (; seq->nid; seq++)
230 snd_hda_codec_write(codec, seq->nid, 0, seq->verb, seq->param);
231}
Takashi Iwaiff7a3262008-11-28 15:17:06 +0100232EXPORT_SYMBOL_HDA(snd_hda_sequence_write);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700233
234/**
235 * snd_hda_get_sub_nodes - get the range of sub nodes
236 * @codec: the HDA codec
237 * @nid: NID to parse
238 * @start_id: the pointer to store the start NID
239 *
240 * Parse the NID and store the start NID of its sub-nodes.
241 * Returns the number of sub-nodes.
242 */
Takashi Iwai0ba21762007-04-16 11:29:14 +0200243int snd_hda_get_sub_nodes(struct hda_codec *codec, hda_nid_t nid,
244 hda_nid_t *start_id)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700245{
246 unsigned int parm;
247
248 parm = snd_hda_param_read(codec, nid, AC_PAR_NODE_COUNT);
Danny Tholene8a7f132007-09-11 21:41:56 +0200249 if (parm == -1)
250 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700251 *start_id = (parm >> 16) & 0x7fff;
252 return (int)(parm & 0x7fff);
253}
Takashi Iwaiff7a3262008-11-28 15:17:06 +0100254EXPORT_SYMBOL_HDA(snd_hda_get_sub_nodes);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700255
256/**
257 * snd_hda_get_connections - get connection list
258 * @codec: the HDA codec
259 * @nid: NID to parse
260 * @conn_list: connection list array
261 * @max_conns: max. number of connections to store
262 *
263 * Parses the connection list of the given widget and stores the list
264 * of NIDs.
265 *
266 * Returns the number of connections, or a negative error code.
267 */
268int snd_hda_get_connections(struct hda_codec *codec, hda_nid_t nid,
269 hda_nid_t *conn_list, int max_conns)
270{
271 unsigned int parm;
Takashi Iwai54d17402005-11-21 16:33:22 +0100272 int i, conn_len, conns;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700273 unsigned int shift, num_elems, mask;
Takashi Iwai54d17402005-11-21 16:33:22 +0100274 hda_nid_t prev_nid;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700275
Takashi Iwaida3cec32008-08-08 17:12:14 +0200276 if (snd_BUG_ON(!conn_list || max_conns <= 0))
277 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700278
279 parm = snd_hda_param_read(codec, nid, AC_PAR_CONNLIST_LEN);
280 if (parm & AC_CLIST_LONG) {
281 /* long form */
282 shift = 16;
283 num_elems = 2;
284 } else {
285 /* short form */
286 shift = 8;
287 num_elems = 4;
288 }
289 conn_len = parm & AC_CLIST_LENGTH;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700290 mask = (1 << (shift-1)) - 1;
291
Takashi Iwai0ba21762007-04-16 11:29:14 +0200292 if (!conn_len)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700293 return 0; /* no connection */
294
295 if (conn_len == 1) {
296 /* single connection */
Takashi Iwai0ba21762007-04-16 11:29:14 +0200297 parm = snd_hda_codec_read(codec, nid, 0,
298 AC_VERB_GET_CONNECT_LIST, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700299 conn_list[0] = parm & mask;
300 return 1;
301 }
302
303 /* multi connection */
304 conns = 0;
Takashi Iwai54d17402005-11-21 16:33:22 +0100305 prev_nid = 0;
306 for (i = 0; i < conn_len; i++) {
307 int range_val;
308 hda_nid_t val, n;
309
310 if (i % num_elems == 0)
311 parm = snd_hda_codec_read(codec, nid, 0,
312 AC_VERB_GET_CONNECT_LIST, i);
Takashi Iwai0ba21762007-04-16 11:29:14 +0200313 range_val = !!(parm & (1 << (shift-1))); /* ranges */
Takashi Iwai54d17402005-11-21 16:33:22 +0100314 val = parm & mask;
315 parm >>= shift;
316 if (range_val) {
317 /* ranges between the previous and this one */
Takashi Iwai0ba21762007-04-16 11:29:14 +0200318 if (!prev_nid || prev_nid >= val) {
319 snd_printk(KERN_WARNING "hda_codec: "
320 "invalid dep_range_val %x:%x\n",
321 prev_nid, val);
Takashi Iwai54d17402005-11-21 16:33:22 +0100322 continue;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700323 }
Takashi Iwai54d17402005-11-21 16:33:22 +0100324 for (n = prev_nid + 1; n <= val; n++) {
325 if (conns >= max_conns) {
Takashi Iwai0ba21762007-04-16 11:29:14 +0200326 snd_printk(KERN_ERR
327 "Too many connections\n");
Takashi Iwai54d17402005-11-21 16:33:22 +0100328 return -EINVAL;
329 }
330 conn_list[conns++] = n;
331 }
332 } else {
333 if (conns >= max_conns) {
334 snd_printk(KERN_ERR "Too many connections\n");
335 return -EINVAL;
336 }
337 conn_list[conns++] = val;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700338 }
Takashi Iwai54d17402005-11-21 16:33:22 +0100339 prev_nid = val;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700340 }
341 return conns;
342}
Takashi Iwaiff7a3262008-11-28 15:17:06 +0100343EXPORT_SYMBOL_HDA(snd_hda_get_connections);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700344
345
346/**
347 * snd_hda_queue_unsol_event - add an unsolicited event to queue
348 * @bus: the BUS
349 * @res: unsolicited event (lower 32bit of RIRB entry)
350 * @res_ex: codec addr and flags (upper 32bit or RIRB entry)
351 *
352 * Adds the given event to the queue. The events are processed in
353 * the workqueue asynchronously. Call this function in the interrupt
354 * hanlder when RIRB receives an unsolicited event.
355 *
356 * Returns 0 if successful, or a negative error code.
357 */
358int snd_hda_queue_unsol_event(struct hda_bus *bus, u32 res, u32 res_ex)
359{
360 struct hda_bus_unsolicited *unsol;
361 unsigned int wp;
362
Takashi Iwai0ba21762007-04-16 11:29:14 +0200363 unsol = bus->unsol;
364 if (!unsol)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700365 return 0;
366
367 wp = (unsol->wp + 1) % HDA_UNSOL_QUEUE_SIZE;
368 unsol->wp = wp;
369
370 wp <<= 1;
371 unsol->queue[wp] = res;
372 unsol->queue[wp + 1] = res_ex;
373
Takashi Iwaie250af22006-12-19 17:08:52 +0100374 schedule_work(&unsol->work);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700375
376 return 0;
377}
Takashi Iwaiff7a3262008-11-28 15:17:06 +0100378EXPORT_SYMBOL_HDA(snd_hda_queue_unsol_event);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700379
380/*
Wu Fengguang5c1d1a92008-10-07 14:17:53 +0800381 * process queued unsolicited events
Linus Torvalds1da177e2005-04-16 15:20:36 -0700382 */
David Howellsc4028952006-11-22 14:57:56 +0000383static void process_unsol_events(struct work_struct *work)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700384{
David Howellsc4028952006-11-22 14:57:56 +0000385 struct hda_bus_unsolicited *unsol =
386 container_of(work, struct hda_bus_unsolicited, work);
387 struct hda_bus *bus = unsol->bus;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700388 struct hda_codec *codec;
389 unsigned int rp, caddr, res;
390
391 while (unsol->rp != unsol->wp) {
392 rp = (unsol->rp + 1) % HDA_UNSOL_QUEUE_SIZE;
393 unsol->rp = rp;
394 rp <<= 1;
395 res = unsol->queue[rp];
396 caddr = unsol->queue[rp + 1];
Takashi Iwai0ba21762007-04-16 11:29:14 +0200397 if (!(caddr & (1 << 4))) /* no unsolicited event? */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700398 continue;
399 codec = bus->caddr_tbl[caddr & 0x0f];
400 if (codec && codec->patch_ops.unsol_event)
401 codec->patch_ops.unsol_event(codec, res);
402 }
403}
404
405/*
406 * initialize unsolicited queue
407 */
Takashi Iwai6c1f45e2008-07-30 15:01:45 +0200408static int init_unsol_queue(struct hda_bus *bus)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700409{
410 struct hda_bus_unsolicited *unsol;
411
Takashi Iwai9f146bb2005-11-17 11:07:49 +0100412 if (bus->unsol) /* already initialized */
413 return 0;
414
Takashi Iwaie560d8d2005-09-09 14:21:46 +0200415 unsol = kzalloc(sizeof(*unsol), GFP_KERNEL);
Takashi Iwai0ba21762007-04-16 11:29:14 +0200416 if (!unsol) {
417 snd_printk(KERN_ERR "hda_codec: "
418 "can't allocate unsolicited queue\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700419 return -ENOMEM;
420 }
David Howellsc4028952006-11-22 14:57:56 +0000421 INIT_WORK(&unsol->work, process_unsol_events);
422 unsol->bus = bus;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700423 bus->unsol = unsol;
424 return 0;
425}
426
427/*
428 * destructor
429 */
430static void snd_hda_codec_free(struct hda_codec *codec);
431
432static int snd_hda_bus_free(struct hda_bus *bus)
433{
Takashi Iwai0ba21762007-04-16 11:29:14 +0200434 struct hda_codec *codec, *n;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700435
Takashi Iwai0ba21762007-04-16 11:29:14 +0200436 if (!bus)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700437 return 0;
438 if (bus->unsol) {
Takashi Iwaie250af22006-12-19 17:08:52 +0100439 flush_scheduled_work();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700440 kfree(bus->unsol);
441 }
Takashi Iwai0ba21762007-04-16 11:29:14 +0200442 list_for_each_entry_safe(codec, n, &bus->codec_list, list) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700443 snd_hda_codec_free(codec);
444 }
445 if (bus->ops.private_free)
446 bus->ops.private_free(bus);
447 kfree(bus);
448 return 0;
449}
450
Takashi Iwaic8b6bf92005-11-17 14:57:47 +0100451static int snd_hda_bus_dev_free(struct snd_device *device)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700452{
453 struct hda_bus *bus = device->device_data;
Takashi Iwaib94d35392008-11-21 09:08:06 +0100454 bus->shutdown = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700455 return snd_hda_bus_free(bus);
456}
457
Takashi Iwaid7ffba12008-07-30 15:01:46 +0200458#ifdef CONFIG_SND_HDA_HWDEP
459static int snd_hda_bus_dev_register(struct snd_device *device)
460{
461 struct hda_bus *bus = device->device_data;
462 struct hda_codec *codec;
463 list_for_each_entry(codec, &bus->codec_list, list) {
464 snd_hda_hwdep_add_sysfs(codec);
465 }
466 return 0;
467}
468#else
469#define snd_hda_bus_dev_register NULL
470#endif
471
Linus Torvalds1da177e2005-04-16 15:20:36 -0700472/**
473 * snd_hda_bus_new - create a HDA bus
474 * @card: the card entry
475 * @temp: the template for hda_bus information
476 * @busp: the pointer to store the created bus instance
477 *
478 * Returns 0 if successful, or a negative error code.
479 */
Takashi Iwai1289e9e2008-11-27 15:47:11 +0100480int /*__devinit*/ snd_hda_bus_new(struct snd_card *card,
Takashi Iwai756e2b02007-04-16 11:27:07 +0200481 const struct hda_bus_template *temp,
482 struct hda_bus **busp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700483{
484 struct hda_bus *bus;
485 int err;
Takashi Iwaic8b6bf92005-11-17 14:57:47 +0100486 static struct snd_device_ops dev_ops = {
Takashi Iwaid7ffba12008-07-30 15:01:46 +0200487 .dev_register = snd_hda_bus_dev_register,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700488 .dev_free = snd_hda_bus_dev_free,
489 };
490
Takashi Iwaida3cec32008-08-08 17:12:14 +0200491 if (snd_BUG_ON(!temp))
492 return -EINVAL;
493 if (snd_BUG_ON(!temp->ops.command || !temp->ops.get_response))
494 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700495
496 if (busp)
497 *busp = NULL;
498
Takashi Iwaie560d8d2005-09-09 14:21:46 +0200499 bus = kzalloc(sizeof(*bus), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700500 if (bus == NULL) {
501 snd_printk(KERN_ERR "can't allocate struct hda_bus\n");
502 return -ENOMEM;
503 }
504
505 bus->card = card;
506 bus->private_data = temp->private_data;
507 bus->pci = temp->pci;
508 bus->modelname = temp->modelname;
Takashi Iwaifee2fba2008-11-27 12:43:28 +0100509 bus->power_save = temp->power_save;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700510 bus->ops = temp->ops;
511
Ingo Molnar62932df2006-01-16 16:34:20 +0100512 mutex_init(&bus->cmd_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700513 INIT_LIST_HEAD(&bus->codec_list);
514
Takashi Iwai0ba21762007-04-16 11:29:14 +0200515 err = snd_device_new(card, SNDRV_DEV_BUS, bus, &dev_ops);
516 if (err < 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700517 snd_hda_bus_free(bus);
518 return err;
519 }
520 if (busp)
521 *busp = bus;
522 return 0;
523}
Takashi Iwaiff7a3262008-11-28 15:17:06 +0100524EXPORT_SYMBOL_HDA(snd_hda_bus_new);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700525
Takashi Iwai82467612007-07-27 19:15:54 +0200526#ifdef CONFIG_SND_HDA_GENERIC
527#define is_generic_config(codec) \
Takashi Iwaif44ac832008-07-30 15:01:45 +0200528 (codec->modelname && !strcmp(codec->modelname, "generic"))
Takashi Iwai82467612007-07-27 19:15:54 +0200529#else
530#define is_generic_config(codec) 0
531#endif
532
Takashi Iwai645f10c2008-11-28 15:07:37 +0100533#ifdef MODULE
Takashi Iwai1289e9e2008-11-27 15:47:11 +0100534#define HDA_MODREQ_MAX_COUNT 2 /* two request_modules()'s */
535#else
Takashi Iwai645f10c2008-11-28 15:07:37 +0100536#define HDA_MODREQ_MAX_COUNT 0 /* all presets are statically linked */
Takashi Iwai1289e9e2008-11-27 15:47:11 +0100537#endif
538
Linus Torvalds1da177e2005-04-16 15:20:36 -0700539/*
540 * find a matching codec preset
541 */
Takashi Iwai6c1f45e2008-07-30 15:01:45 +0200542static const struct hda_codec_preset *
Takashi Iwai756e2b02007-04-16 11:27:07 +0200543find_codec_preset(struct hda_codec *codec)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700544{
Takashi Iwai1289e9e2008-11-27 15:47:11 +0100545 struct hda_codec_preset_list *tbl;
546 const struct hda_codec_preset *preset;
547 int mod_requested = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700548
Takashi Iwai82467612007-07-27 19:15:54 +0200549 if (is_generic_config(codec))
Takashi Iwaid5ad6302007-03-07 15:55:59 +0100550 return NULL; /* use the generic parser */
551
Takashi Iwai1289e9e2008-11-27 15:47:11 +0100552 again:
553 mutex_lock(&preset_mutex);
554 list_for_each_entry(tbl, &hda_preset_tables, list) {
555 if (!try_module_get(tbl->owner)) {
556 snd_printk(KERN_ERR "hda_codec: cannot module_get\n");
557 continue;
558 }
559 for (preset = tbl->preset; preset->id; preset++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700560 u32 mask = preset->mask;
Marc Boucherca7cfae2008-01-22 15:32:25 +0100561 if (preset->afg && preset->afg != codec->afg)
562 continue;
563 if (preset->mfg && preset->mfg != codec->mfg)
564 continue;
Takashi Iwai0ba21762007-04-16 11:29:14 +0200565 if (!mask)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700566 mask = ~0;
Takashi Iwai9c7f8522006-06-28 15:08:22 +0200567 if (preset->id == (codec->vendor_id & mask) &&
Takashi Iwai0ba21762007-04-16 11:29:14 +0200568 (!preset->rev ||
Takashi Iwai1289e9e2008-11-27 15:47:11 +0100569 preset->rev == codec->revision_id)) {
570 mutex_unlock(&preset_mutex);
571 codec->owner = tbl->owner;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700572 return preset;
Takashi Iwai1289e9e2008-11-27 15:47:11 +0100573 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700574 }
Takashi Iwai1289e9e2008-11-27 15:47:11 +0100575 module_put(tbl->owner);
576 }
577 mutex_unlock(&preset_mutex);
578
579 if (mod_requested < HDA_MODREQ_MAX_COUNT) {
580 char name[32];
581 if (!mod_requested)
582 snprintf(name, sizeof(name), "snd-hda-codec-id:%08x",
583 codec->vendor_id);
584 else
585 snprintf(name, sizeof(name), "snd-hda-codec-id:%04x*",
586 (codec->vendor_id >> 16) & 0xffff);
587 request_module(name);
588 mod_requested++;
589 goto again;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700590 }
591 return NULL;
592}
593
594/*
Takashi Iwaif44ac832008-07-30 15:01:45 +0200595 * get_codec_name - store the codec name
Linus Torvalds1da177e2005-04-16 15:20:36 -0700596 */
Takashi Iwaif44ac832008-07-30 15:01:45 +0200597static int get_codec_name(struct hda_codec *codec)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700598{
599 const struct hda_vendor_id *c;
600 const char *vendor = NULL;
601 u16 vendor_id = codec->vendor_id >> 16;
Takashi Iwaif44ac832008-07-30 15:01:45 +0200602 char tmp[16], name[32];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700603
604 for (c = hda_vendor_ids; c->id; c++) {
605 if (c->id == vendor_id) {
606 vendor = c->name;
607 break;
608 }
609 }
Takashi Iwai0ba21762007-04-16 11:29:14 +0200610 if (!vendor) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700611 sprintf(tmp, "Generic %04x", vendor_id);
612 vendor = tmp;
613 }
614 if (codec->preset && codec->preset->name)
Takashi Iwaif44ac832008-07-30 15:01:45 +0200615 snprintf(name, sizeof(name), "%s %s", vendor,
616 codec->preset->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700617 else
Takashi Iwaif44ac832008-07-30 15:01:45 +0200618 snprintf(name, sizeof(name), "%s ID %x", vendor,
Takashi Iwai0ba21762007-04-16 11:29:14 +0200619 codec->vendor_id & 0xffff);
Takashi Iwaif44ac832008-07-30 15:01:45 +0200620 codec->name = kstrdup(name, GFP_KERNEL);
621 if (!codec->name)
622 return -ENOMEM;
623 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700624}
625
626/*
Sasha Khapyorsky673b6832005-08-11 11:00:16 +0200627 * look for an AFG and MFG nodes
Linus Torvalds1da177e2005-04-16 15:20:36 -0700628 */
Takashi Iwai1289e9e2008-11-27 15:47:11 +0100629static void /*__devinit*/ setup_fg_nodes(struct hda_codec *codec)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700630{
631 int i, total_nodes;
632 hda_nid_t nid;
633
634 total_nodes = snd_hda_get_sub_nodes(codec, AC_NODE_ROOT, &nid);
635 for (i = 0; i < total_nodes; i++, nid++) {
Takashi Iwai0ba21762007-04-16 11:29:14 +0200636 unsigned int func;
637 func = snd_hda_param_read(codec, nid, AC_PAR_FUNCTION_TYPE);
638 switch (func & 0xff) {
Sasha Khapyorsky673b6832005-08-11 11:00:16 +0200639 case AC_GRP_AUDIO_FUNCTION:
640 codec->afg = nid;
641 break;
642 case AC_GRP_MODEM_FUNCTION:
643 codec->mfg = nid;
644 break;
645 default:
646 break;
647 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700648 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700649}
650
651/*
Takashi Iwai54d17402005-11-21 16:33:22 +0100652 * read widget caps for each widget and store in cache
653 */
654static int read_widget_caps(struct hda_codec *codec, hda_nid_t fg_node)
655{
656 int i;
657 hda_nid_t nid;
658
659 codec->num_nodes = snd_hda_get_sub_nodes(codec, fg_node,
660 &codec->start_nid);
661 codec->wcaps = kmalloc(codec->num_nodes * 4, GFP_KERNEL);
Takashi Iwai0ba21762007-04-16 11:29:14 +0200662 if (!codec->wcaps)
Takashi Iwai54d17402005-11-21 16:33:22 +0100663 return -ENOMEM;
664 nid = codec->start_nid;
665 for (i = 0; i < codec->num_nodes; i++, nid++)
666 codec->wcaps[i] = snd_hda_param_read(codec, nid,
667 AC_PAR_AUDIO_WIDGET_CAP);
668 return 0;
669}
670
671
Takashi Iwai01751f52007-08-10 16:59:39 +0200672static void init_hda_cache(struct hda_cache_rec *cache,
673 unsigned int record_size);
Takashi Iwai1fcaee62007-08-23 00:01:09 +0200674static void free_hda_cache(struct hda_cache_rec *cache);
Takashi Iwai01751f52007-08-10 16:59:39 +0200675
Takashi Iwai54d17402005-11-21 16:33:22 +0100676/*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700677 * codec destructor
678 */
679static void snd_hda_codec_free(struct hda_codec *codec)
680{
Takashi Iwai0ba21762007-04-16 11:29:14 +0200681 if (!codec)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700682 return;
Takashi Iwaicb53c622007-08-10 17:21:45 +0200683#ifdef CONFIG_SND_HDA_POWER_SAVE
684 cancel_delayed_work(&codec->power_work);
Takashi Iwai2525fdc2007-08-15 22:18:22 +0200685 flush_scheduled_work();
Takashi Iwaicb53c622007-08-10 17:21:45 +0200686#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700687 list_del(&codec->list);
Takashi Iwaid13bd412008-07-30 15:01:45 +0200688 snd_array_free(&codec->mixers);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700689 codec->bus->caddr_tbl[codec->addr] = NULL;
690 if (codec->patch_ops.free)
691 codec->patch_ops.free(codec);
Takashi Iwai1289e9e2008-11-27 15:47:11 +0100692 module_put(codec->owner);
Takashi Iwai01751f52007-08-10 16:59:39 +0200693 free_hda_cache(&codec->amp_cache);
Takashi Iwaib3ac5632007-08-10 17:03:40 +0200694 free_hda_cache(&codec->cmd_cache);
Takashi Iwaif44ac832008-07-30 15:01:45 +0200695 kfree(codec->name);
696 kfree(codec->modelname);
Takashi Iwai54d17402005-11-21 16:33:22 +0100697 kfree(codec->wcaps);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700698 kfree(codec);
699}
700
Linus Torvalds1da177e2005-04-16 15:20:36 -0700701/**
702 * snd_hda_codec_new - create a HDA codec
703 * @bus: the bus to assign
704 * @codec_addr: the codec address
705 * @codecp: the pointer to store the generated codec
706 *
707 * Returns 0 if successful, or a negative error code.
708 */
Takashi Iwai1289e9e2008-11-27 15:47:11 +0100709int /*__devinit*/ snd_hda_codec_new(struct hda_bus *bus, unsigned int codec_addr,
Takashi Iwai756e2b02007-04-16 11:27:07 +0200710 struct hda_codec **codecp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700711{
712 struct hda_codec *codec;
Jaroslav Kyselaba443682008-08-13 20:55:32 +0200713 char component[31];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700714 int err;
715
Takashi Iwaida3cec32008-08-08 17:12:14 +0200716 if (snd_BUG_ON(!bus))
717 return -EINVAL;
718 if (snd_BUG_ON(codec_addr > HDA_MAX_CODEC_ADDRESS))
719 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700720
721 if (bus->caddr_tbl[codec_addr]) {
Takashi Iwai0ba21762007-04-16 11:29:14 +0200722 snd_printk(KERN_ERR "hda_codec: "
723 "address 0x%x is already occupied\n", codec_addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700724 return -EBUSY;
725 }
726
Takashi Iwaie560d8d2005-09-09 14:21:46 +0200727 codec = kzalloc(sizeof(*codec), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700728 if (codec == NULL) {
729 snd_printk(KERN_ERR "can't allocate struct hda_codec\n");
730 return -ENOMEM;
731 }
732
733 codec->bus = bus;
734 codec->addr = codec_addr;
Ingo Molnar62932df2006-01-16 16:34:20 +0100735 mutex_init(&codec->spdif_mutex);
Takashi Iwai01751f52007-08-10 16:59:39 +0200736 init_hda_cache(&codec->amp_cache, sizeof(struct hda_amp_info));
Takashi Iwaib3ac5632007-08-10 17:03:40 +0200737 init_hda_cache(&codec->cmd_cache, sizeof(struct hda_cache_head));
Takashi Iwaid13bd412008-07-30 15:01:45 +0200738 snd_array_init(&codec->mixers, sizeof(struct snd_kcontrol *), 32);
Takashi Iwai6c1f45e2008-07-30 15:01:45 +0200739 if (codec->bus->modelname) {
740 codec->modelname = kstrdup(codec->bus->modelname, GFP_KERNEL);
741 if (!codec->modelname) {
742 snd_hda_codec_free(codec);
743 return -ENODEV;
744 }
745 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700746
Takashi Iwaicb53c622007-08-10 17:21:45 +0200747#ifdef CONFIG_SND_HDA_POWER_SAVE
748 INIT_DELAYED_WORK(&codec->power_work, hda_power_work);
749 /* snd_hda_codec_new() marks the codec as power-up, and leave it as is.
750 * the caller has to power down appropriatley after initialization
751 * phase.
752 */
753 hda_keep_power_on(codec);
754#endif
755
Linus Torvalds1da177e2005-04-16 15:20:36 -0700756 list_add_tail(&codec->list, &bus->codec_list);
757 bus->caddr_tbl[codec_addr] = codec;
758
Takashi Iwai0ba21762007-04-16 11:29:14 +0200759 codec->vendor_id = snd_hda_param_read(codec, AC_NODE_ROOT,
760 AC_PAR_VENDOR_ID);
Takashi Iwai111d3af2006-02-16 18:17:58 +0100761 if (codec->vendor_id == -1)
762 /* read again, hopefully the access method was corrected
763 * in the last read...
764 */
765 codec->vendor_id = snd_hda_param_read(codec, AC_NODE_ROOT,
766 AC_PAR_VENDOR_ID);
Takashi Iwai0ba21762007-04-16 11:29:14 +0200767 codec->subsystem_id = snd_hda_param_read(codec, AC_NODE_ROOT,
768 AC_PAR_SUBSYSTEM_ID);
769 codec->revision_id = snd_hda_param_read(codec, AC_NODE_ROOT,
770 AC_PAR_REV_ID);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700771
Sasha Khapyorsky673b6832005-08-11 11:00:16 +0200772 setup_fg_nodes(codec);
Takashi Iwai0ba21762007-04-16 11:29:14 +0200773 if (!codec->afg && !codec->mfg) {
Sasha Khapyorsky673b6832005-08-11 11:00:16 +0200774 snd_printdd("hda_codec: no AFG or MFG node found\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700775 snd_hda_codec_free(codec);
776 return -ENODEV;
777 }
778
Takashi Iwai54d17402005-11-21 16:33:22 +0100779 if (read_widget_caps(codec, codec->afg ? codec->afg : codec->mfg) < 0) {
780 snd_printk(KERN_ERR "hda_codec: cannot malloc\n");
781 snd_hda_codec_free(codec);
782 return -ENOMEM;
783 }
784
Takashi Iwai0ba21762007-04-16 11:29:14 +0200785 if (!codec->subsystem_id) {
Takashi Iwai86284e42005-10-11 15:05:54 +0200786 hda_nid_t nid = codec->afg ? codec->afg : codec->mfg;
Takashi Iwai0ba21762007-04-16 11:29:14 +0200787 codec->subsystem_id =
788 snd_hda_codec_read(codec, nid, 0,
789 AC_VERB_GET_SUBSYSTEM_ID, 0);
Takashi Iwai86284e42005-10-11 15:05:54 +0200790 }
Takashi Iwaif44ac832008-07-30 15:01:45 +0200791 if (bus->modelname)
792 codec->modelname = kstrdup(bus->modelname, GFP_KERNEL);
Takashi Iwai86284e42005-10-11 15:05:54 +0200793
Takashi Iwai6c1f45e2008-07-30 15:01:45 +0200794 err = snd_hda_codec_configure(codec);
795 if (err < 0) {
796 snd_hda_codec_free(codec);
797 return err;
798 }
799 snd_hda_codec_proc_new(codec);
800
Takashi Iwai6c1f45e2008-07-30 15:01:45 +0200801 snd_hda_create_hwdep(codec);
Takashi Iwai6c1f45e2008-07-30 15:01:45 +0200802
803 sprintf(component, "HDA:%08x,%08x,%08x", codec->vendor_id,
804 codec->subsystem_id, codec->revision_id);
805 snd_component_add(codec->bus->card, component);
806
807 if (codecp)
808 *codecp = codec;
809 return 0;
810}
Takashi Iwaiff7a3262008-11-28 15:17:06 +0100811EXPORT_SYMBOL_HDA(snd_hda_codec_new);
Takashi Iwai6c1f45e2008-07-30 15:01:45 +0200812
813int snd_hda_codec_configure(struct hda_codec *codec)
814{
815 int err;
816
Takashi Iwaid5ad6302007-03-07 15:55:59 +0100817 codec->preset = find_codec_preset(codec);
Takashi Iwaif44ac832008-07-30 15:01:45 +0200818 if (!codec->name) {
819 err = get_codec_name(codec);
820 if (err < 0)
821 return err;
822 }
Takashi Iwai43ea1d42007-04-26 19:12:08 +0200823 /* audio codec should override the mixer name */
Takashi Iwaif44ac832008-07-30 15:01:45 +0200824 if (codec->afg || !*codec->bus->card->mixername)
825 strlcpy(codec->bus->card->mixername, codec->name,
826 sizeof(codec->bus->card->mixername));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700827
Takashi Iwai82467612007-07-27 19:15:54 +0200828 if (is_generic_config(codec)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700829 err = snd_hda_parse_generic_codec(codec);
Takashi Iwai82467612007-07-27 19:15:54 +0200830 goto patched;
831 }
Takashi Iwai82467612007-07-27 19:15:54 +0200832 if (codec->preset && codec->preset->patch) {
833 err = codec->preset->patch(codec);
834 goto patched;
835 }
836
837 /* call the default parser */
Takashi Iwai82467612007-07-27 19:15:54 +0200838 err = snd_hda_parse_generic_codec(codec);
Takashi Iwai35a1e0c2007-10-19 08:13:40 +0200839 if (err < 0)
840 printk(KERN_ERR "hda-codec: No codec parser is available\n");
Takashi Iwai82467612007-07-27 19:15:54 +0200841
842 patched:
Takashi Iwai6c1f45e2008-07-30 15:01:45 +0200843 if (!err && codec->patch_ops.unsol_event)
844 err = init_unsol_queue(codec->bus);
845 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700846}
847
848/**
849 * snd_hda_codec_setup_stream - set up the codec for streaming
850 * @codec: the CODEC to set up
851 * @nid: the NID to set up
852 * @stream_tag: stream tag to pass, it's between 0x1 and 0xf.
853 * @channel_id: channel id to pass, zero based.
854 * @format: stream format.
855 */
Takashi Iwai0ba21762007-04-16 11:29:14 +0200856void snd_hda_codec_setup_stream(struct hda_codec *codec, hda_nid_t nid,
857 u32 stream_tag,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700858 int channel_id, int format)
859{
Takashi Iwai0ba21762007-04-16 11:29:14 +0200860 if (!nid)
Takashi Iwaid21b37e2005-04-20 13:45:55 +0200861 return;
862
Takashi Iwai0ba21762007-04-16 11:29:14 +0200863 snd_printdd("hda_codec_setup_stream: "
864 "NID=0x%x, stream=0x%x, channel=%d, format=0x%x\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700865 nid, stream_tag, channel_id, format);
866 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CHANNEL_STREAMID,
867 (stream_tag << 4) | channel_id);
868 msleep(1);
869 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_STREAM_FORMAT, format);
870}
Takashi Iwaiff7a3262008-11-28 15:17:06 +0100871EXPORT_SYMBOL_HDA(snd_hda_codec_setup_stream);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700872
Takashi Iwai888afa12008-03-18 09:57:50 +0100873void snd_hda_codec_cleanup_stream(struct hda_codec *codec, hda_nid_t nid)
874{
875 if (!nid)
876 return;
877
878 snd_printdd("hda_codec_cleanup_stream: NID=0x%x\n", nid);
879 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CHANNEL_STREAMID, 0);
880#if 0 /* keep the format */
881 msleep(1);
882 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_STREAM_FORMAT, 0);
883#endif
884}
Takashi Iwaiff7a3262008-11-28 15:17:06 +0100885EXPORT_SYMBOL_HDA(snd_hda_codec_cleanup_stream);
Takashi Iwai888afa12008-03-18 09:57:50 +0100886
Linus Torvalds1da177e2005-04-16 15:20:36 -0700887/*
888 * amp access functions
889 */
890
Takashi Iwai4a19fae2005-06-08 14:43:58 +0200891/* FIXME: more better hash key? */
892#define HDA_HASH_KEY(nid,dir,idx) (u32)((nid) + ((idx) << 16) + ((dir) << 24))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700893#define INFO_AMP_CAPS (1<<0)
Takashi Iwai4a19fae2005-06-08 14:43:58 +0200894#define INFO_AMP_VOL(ch) (1 << (1 + (ch)))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700895
896/* initialize the hash table */
Takashi Iwai1289e9e2008-11-27 15:47:11 +0100897static void /*__devinit*/ init_hda_cache(struct hda_cache_rec *cache,
Takashi Iwai01751f52007-08-10 16:59:39 +0200898 unsigned int record_size)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700899{
Takashi Iwai01751f52007-08-10 16:59:39 +0200900 memset(cache, 0, sizeof(*cache));
901 memset(cache->hash, 0xff, sizeof(cache->hash));
Takashi Iwai603c4012008-07-30 15:01:44 +0200902 snd_array_init(&cache->buf, record_size, 64);
Takashi Iwai01751f52007-08-10 16:59:39 +0200903}
904
Takashi Iwai1fcaee62007-08-23 00:01:09 +0200905static void free_hda_cache(struct hda_cache_rec *cache)
Takashi Iwai01751f52007-08-10 16:59:39 +0200906{
Takashi Iwai603c4012008-07-30 15:01:44 +0200907 snd_array_free(&cache->buf);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700908}
909
910/* query the hash. allocate an entry if not found. */
Takashi Iwai01751f52007-08-10 16:59:39 +0200911static struct hda_cache_head *get_alloc_hash(struct hda_cache_rec *cache,
912 u32 key)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700913{
Takashi Iwai01751f52007-08-10 16:59:39 +0200914 u16 idx = key % (u16)ARRAY_SIZE(cache->hash);
915 u16 cur = cache->hash[idx];
916 struct hda_cache_head *info;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700917
918 while (cur != 0xffff) {
Takashi Iwaif43aa022008-11-10 16:24:26 +0100919 info = snd_array_elem(&cache->buf, cur);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700920 if (info->key == key)
921 return info;
922 cur = info->next;
923 }
924
925 /* add a new hash entry */
Takashi Iwai603c4012008-07-30 15:01:44 +0200926 info = snd_array_new(&cache->buf);
Takashi Iwaic2174292008-11-07 00:23:30 +0100927 if (!info)
928 return NULL;
Takashi Iwaif43aa022008-11-10 16:24:26 +0100929 cur = snd_array_index(&cache->buf, info);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700930 info->key = key;
Takashi Iwai01751f52007-08-10 16:59:39 +0200931 info->val = 0;
932 info->next = cache->hash[idx];
933 cache->hash[idx] = cur;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700934
935 return info;
936}
937
Takashi Iwai01751f52007-08-10 16:59:39 +0200938/* query and allocate an amp hash entry */
939static inline struct hda_amp_info *
940get_alloc_amp_hash(struct hda_codec *codec, u32 key)
941{
942 return (struct hda_amp_info *)get_alloc_hash(&codec->amp_cache, key);
943}
944
Linus Torvalds1da177e2005-04-16 15:20:36 -0700945/*
946 * query AMP capabilities for the given widget and direction
947 */
Matthew Ranostay09a99952008-01-24 11:49:21 +0100948u32 query_amp_caps(struct hda_codec *codec, hda_nid_t nid, int direction)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700949{
Takashi Iwai0ba21762007-04-16 11:29:14 +0200950 struct hda_amp_info *info;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700951
Takashi Iwai0ba21762007-04-16 11:29:14 +0200952 info = get_alloc_amp_hash(codec, HDA_HASH_KEY(nid, direction, 0));
953 if (!info)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700954 return 0;
Takashi Iwai01751f52007-08-10 16:59:39 +0200955 if (!(info->head.val & INFO_AMP_CAPS)) {
Takashi Iwai0ba21762007-04-16 11:29:14 +0200956 if (!(get_wcaps(codec, nid) & AC_WCAP_AMP_OVRD))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700957 nid = codec->afg;
Takashi Iwai0ba21762007-04-16 11:29:14 +0200958 info->amp_caps = snd_hda_param_read(codec, nid,
959 direction == HDA_OUTPUT ?
960 AC_PAR_AMP_OUT_CAP :
961 AC_PAR_AMP_IN_CAP);
Takashi Iwaib75e53f2007-05-10 16:56:09 +0200962 if (info->amp_caps)
Takashi Iwai01751f52007-08-10 16:59:39 +0200963 info->head.val |= INFO_AMP_CAPS;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700964 }
965 return info->amp_caps;
966}
Takashi Iwaiff7a3262008-11-28 15:17:06 +0100967EXPORT_SYMBOL_HDA(query_amp_caps);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700968
Takashi Iwai897cc182007-05-29 19:01:37 +0200969int snd_hda_override_amp_caps(struct hda_codec *codec, hda_nid_t nid, int dir,
970 unsigned int caps)
971{
972 struct hda_amp_info *info;
973
974 info = get_alloc_amp_hash(codec, HDA_HASH_KEY(nid, dir, 0));
975 if (!info)
976 return -EINVAL;
977 info->amp_caps = caps;
Takashi Iwai01751f52007-08-10 16:59:39 +0200978 info->head.val |= INFO_AMP_CAPS;
Takashi Iwai897cc182007-05-29 19:01:37 +0200979 return 0;
980}
Takashi Iwaiff7a3262008-11-28 15:17:06 +0100981EXPORT_SYMBOL_HDA(snd_hda_override_amp_caps);
Takashi Iwai897cc182007-05-29 19:01:37 +0200982
Linus Torvalds1da177e2005-04-16 15:20:36 -0700983/*
984 * read the current volume to info
Takashi Iwai4a19fae2005-06-08 14:43:58 +0200985 * if the cache exists, read the cache value.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700986 */
Takashi Iwai0ba21762007-04-16 11:29:14 +0200987static unsigned int get_vol_mute(struct hda_codec *codec,
988 struct hda_amp_info *info, hda_nid_t nid,
989 int ch, int direction, int index)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700990{
991 u32 val, parm;
992
Takashi Iwai01751f52007-08-10 16:59:39 +0200993 if (info->head.val & INFO_AMP_VOL(ch))
Takashi Iwai4a19fae2005-06-08 14:43:58 +0200994 return info->vol[ch];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700995
996 parm = ch ? AC_AMP_GET_RIGHT : AC_AMP_GET_LEFT;
997 parm |= direction == HDA_OUTPUT ? AC_AMP_GET_OUTPUT : AC_AMP_GET_INPUT;
998 parm |= index;
Takashi Iwai0ba21762007-04-16 11:29:14 +0200999 val = snd_hda_codec_read(codec, nid, 0,
1000 AC_VERB_GET_AMP_GAIN_MUTE, parm);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001001 info->vol[ch] = val & 0xff;
Takashi Iwai01751f52007-08-10 16:59:39 +02001002 info->head.val |= INFO_AMP_VOL(ch);
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001003 return info->vol[ch];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001004}
1005
1006/*
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001007 * write the current volume in info to the h/w and update the cache
Linus Torvalds1da177e2005-04-16 15:20:36 -07001008 */
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001009static void put_vol_mute(struct hda_codec *codec, struct hda_amp_info *info,
Takashi Iwai0ba21762007-04-16 11:29:14 +02001010 hda_nid_t nid, int ch, int direction, int index,
1011 int val)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001012{
1013 u32 parm;
1014
1015 parm = ch ? AC_AMP_SET_RIGHT : AC_AMP_SET_LEFT;
1016 parm |= direction == HDA_OUTPUT ? AC_AMP_SET_OUTPUT : AC_AMP_SET_INPUT;
1017 parm |= index << AC_AMP_SET_INDEX_SHIFT;
1018 parm |= val;
1019 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, parm);
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001020 info->vol[ch] = val;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001021}
1022
1023/*
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001024 * read AMP value. The volume is between 0 to 0x7f, 0x80 = mute bit.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001025 */
Takashi Iwai834be882006-03-01 14:16:17 +01001026int snd_hda_codec_amp_read(struct hda_codec *codec, hda_nid_t nid, int ch,
1027 int direction, int index)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001028{
Takashi Iwai0ba21762007-04-16 11:29:14 +02001029 struct hda_amp_info *info;
1030 info = get_alloc_amp_hash(codec, HDA_HASH_KEY(nid, direction, index));
1031 if (!info)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001032 return 0;
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001033 return get_vol_mute(codec, info, nid, ch, direction, index);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001034}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001035EXPORT_SYMBOL_HDA(snd_hda_codec_amp_read);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001036
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001037/*
1038 * update the AMP value, mask = bit mask to set, val = the value
1039 */
Takashi Iwai834be882006-03-01 14:16:17 +01001040int snd_hda_codec_amp_update(struct hda_codec *codec, hda_nid_t nid, int ch,
1041 int direction, int idx, int mask, int val)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001042{
Takashi Iwai0ba21762007-04-16 11:29:14 +02001043 struct hda_amp_info *info;
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001044
Takashi Iwai0ba21762007-04-16 11:29:14 +02001045 info = get_alloc_amp_hash(codec, HDA_HASH_KEY(nid, direction, idx));
1046 if (!info)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001047 return 0;
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001048 val &= mask;
1049 val |= get_vol_mute(codec, info, nid, ch, direction, idx) & ~mask;
Takashi Iwai82beb8f2007-08-10 17:09:26 +02001050 if (info->vol[ch] == val)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001051 return 0;
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001052 put_vol_mute(codec, info, nid, ch, direction, idx, val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001053 return 1;
1054}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001055EXPORT_SYMBOL_HDA(snd_hda_codec_amp_update);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001056
Takashi Iwai47fd8302007-08-10 17:11:07 +02001057/*
1058 * update the AMP stereo with the same mask and value
1059 */
1060int snd_hda_codec_amp_stereo(struct hda_codec *codec, hda_nid_t nid,
1061 int direction, int idx, int mask, int val)
1062{
1063 int ch, ret = 0;
1064 for (ch = 0; ch < 2; ch++)
1065 ret |= snd_hda_codec_amp_update(codec, nid, ch, direction,
1066 idx, mask, val);
1067 return ret;
1068}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001069EXPORT_SYMBOL_HDA(snd_hda_codec_amp_stereo);
Takashi Iwai47fd8302007-08-10 17:11:07 +02001070
Takashi Iwaicb53c622007-08-10 17:21:45 +02001071#ifdef SND_HDA_NEEDS_RESUME
Takashi Iwaib3ac5632007-08-10 17:03:40 +02001072/* resume the all amp commands from the cache */
1073void snd_hda_codec_resume_amp(struct hda_codec *codec)
1074{
Takashi Iwai603c4012008-07-30 15:01:44 +02001075 struct hda_amp_info *buffer = codec->amp_cache.buf.list;
Takashi Iwaib3ac5632007-08-10 17:03:40 +02001076 int i;
1077
Takashi Iwai603c4012008-07-30 15:01:44 +02001078 for (i = 0; i < codec->amp_cache.buf.used; i++, buffer++) {
Takashi Iwaib3ac5632007-08-10 17:03:40 +02001079 u32 key = buffer->head.key;
1080 hda_nid_t nid;
1081 unsigned int idx, dir, ch;
1082 if (!key)
1083 continue;
1084 nid = key & 0xff;
1085 idx = (key >> 16) & 0xff;
1086 dir = (key >> 24) & 0xff;
1087 for (ch = 0; ch < 2; ch++) {
1088 if (!(buffer->head.val & INFO_AMP_VOL(ch)))
1089 continue;
1090 put_vol_mute(codec, buffer, nid, ch, dir, idx,
1091 buffer->vol[ch]);
1092 }
1093 }
1094}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001095EXPORT_SYMBOL_HDA(snd_hda_codec_resume_amp);
Takashi Iwaicb53c622007-08-10 17:21:45 +02001096#endif /* SND_HDA_NEEDS_RESUME */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001097
Linus Torvalds1da177e2005-04-16 15:20:36 -07001098/* volume */
Takashi Iwai0ba21762007-04-16 11:29:14 +02001099int snd_hda_mixer_amp_volume_info(struct snd_kcontrol *kcontrol,
1100 struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001101{
1102 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1103 u16 nid = get_amp_nid(kcontrol);
1104 u8 chs = get_amp_channels(kcontrol);
1105 int dir = get_amp_direction(kcontrol);
1106 u32 caps;
1107
1108 caps = query_amp_caps(codec, nid, dir);
Takashi Iwai0ba21762007-04-16 11:29:14 +02001109 /* num steps */
1110 caps = (caps & AC_AMPCAP_NUM_STEPS) >> AC_AMPCAP_NUM_STEPS_SHIFT;
1111 if (!caps) {
1112 printk(KERN_WARNING "hda_codec: "
Takashi Iwai9c8f2ab2008-01-11 16:12:23 +01001113 "num_steps = 0 for NID=0x%x (ctl = %s)\n", nid,
1114 kcontrol->id.name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001115 return -EINVAL;
1116 }
1117 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
1118 uinfo->count = chs == 3 ? 2 : 1;
1119 uinfo->value.integer.min = 0;
1120 uinfo->value.integer.max = caps;
1121 return 0;
1122}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001123EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_volume_info);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001124
Takashi Iwai0ba21762007-04-16 11:29:14 +02001125int snd_hda_mixer_amp_volume_get(struct snd_kcontrol *kcontrol,
1126 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001127{
1128 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1129 hda_nid_t nid = get_amp_nid(kcontrol);
1130 int chs = get_amp_channels(kcontrol);
1131 int dir = get_amp_direction(kcontrol);
1132 int idx = get_amp_index(kcontrol);
1133 long *valp = ucontrol->value.integer.value;
1134
1135 if (chs & 1)
Takashi Iwai47fd8302007-08-10 17:11:07 +02001136 *valp++ = snd_hda_codec_amp_read(codec, nid, 0, dir, idx)
1137 & HDA_AMP_VOLMASK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001138 if (chs & 2)
Takashi Iwai47fd8302007-08-10 17:11:07 +02001139 *valp = snd_hda_codec_amp_read(codec, nid, 1, dir, idx)
1140 & HDA_AMP_VOLMASK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001141 return 0;
1142}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001143EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_volume_get);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001144
Takashi Iwai0ba21762007-04-16 11:29:14 +02001145int snd_hda_mixer_amp_volume_put(struct snd_kcontrol *kcontrol,
1146 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001147{
1148 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1149 hda_nid_t nid = get_amp_nid(kcontrol);
1150 int chs = get_amp_channels(kcontrol);
1151 int dir = get_amp_direction(kcontrol);
1152 int idx = get_amp_index(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001153 long *valp = ucontrol->value.integer.value;
1154 int change = 0;
1155
Takashi Iwaicb53c622007-08-10 17:21:45 +02001156 snd_hda_power_up(codec);
Nicolas Grazianob9f5a892005-07-29 12:17:20 +02001157 if (chs & 1) {
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001158 change = snd_hda_codec_amp_update(codec, nid, 0, dir, idx,
1159 0x7f, *valp);
Nicolas Grazianob9f5a892005-07-29 12:17:20 +02001160 valp++;
1161 }
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001162 if (chs & 2)
1163 change |= snd_hda_codec_amp_update(codec, nid, 1, dir, idx,
Nicolas Grazianob9f5a892005-07-29 12:17:20 +02001164 0x7f, *valp);
Takashi Iwaicb53c622007-08-10 17:21:45 +02001165 snd_hda_power_down(codec);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001166 return change;
1167}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001168EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_volume_put);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001169
Jaroslav Kysela302e9c52006-07-05 17:39:49 +02001170int snd_hda_mixer_amp_tlv(struct snd_kcontrol *kcontrol, int op_flag,
1171 unsigned int size, unsigned int __user *_tlv)
1172{
1173 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1174 hda_nid_t nid = get_amp_nid(kcontrol);
1175 int dir = get_amp_direction(kcontrol);
1176 u32 caps, val1, val2;
1177
1178 if (size < 4 * sizeof(unsigned int))
1179 return -ENOMEM;
1180 caps = query_amp_caps(codec, nid, dir);
Takashi Iwai0ba21762007-04-16 11:29:14 +02001181 val2 = (caps & AC_AMPCAP_STEP_SIZE) >> AC_AMPCAP_STEP_SIZE_SHIFT;
1182 val2 = (val2 + 1) * 25;
Jaroslav Kysela302e9c52006-07-05 17:39:49 +02001183 val1 = -((caps & AC_AMPCAP_OFFSET) >> AC_AMPCAP_OFFSET_SHIFT);
1184 val1 = ((int)val1) * ((int)val2);
Jaroslav Kysela302e9c52006-07-05 17:39:49 +02001185 if (put_user(SNDRV_CTL_TLVT_DB_SCALE, _tlv))
1186 return -EFAULT;
1187 if (put_user(2 * sizeof(unsigned int), _tlv + 1))
1188 return -EFAULT;
1189 if (put_user(val1, _tlv + 2))
1190 return -EFAULT;
1191 if (put_user(val2, _tlv + 3))
1192 return -EFAULT;
1193 return 0;
1194}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001195EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_tlv);
Jaroslav Kysela302e9c52006-07-05 17:39:49 +02001196
Takashi Iwai2134ea42008-01-10 16:53:55 +01001197/*
1198 * set (static) TLV for virtual master volume; recalculated as max 0dB
1199 */
1200void snd_hda_set_vmaster_tlv(struct hda_codec *codec, hda_nid_t nid, int dir,
1201 unsigned int *tlv)
1202{
1203 u32 caps;
1204 int nums, step;
1205
1206 caps = query_amp_caps(codec, nid, dir);
1207 nums = (caps & AC_AMPCAP_NUM_STEPS) >> AC_AMPCAP_NUM_STEPS_SHIFT;
1208 step = (caps & AC_AMPCAP_STEP_SIZE) >> AC_AMPCAP_STEP_SIZE_SHIFT;
1209 step = (step + 1) * 25;
1210 tlv[0] = SNDRV_CTL_TLVT_DB_SCALE;
1211 tlv[1] = 2 * sizeof(unsigned int);
1212 tlv[2] = -nums * step;
1213 tlv[3] = step;
1214}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001215EXPORT_SYMBOL_HDA(snd_hda_set_vmaster_tlv);
Takashi Iwai2134ea42008-01-10 16:53:55 +01001216
1217/* find a mixer control element with the given name */
Takashi Iwai09f99702008-02-04 12:31:13 +01001218static struct snd_kcontrol *
1219_snd_hda_find_mixer_ctl(struct hda_codec *codec,
1220 const char *name, int idx)
Takashi Iwai2134ea42008-01-10 16:53:55 +01001221{
1222 struct snd_ctl_elem_id id;
1223 memset(&id, 0, sizeof(id));
1224 id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
Takashi Iwai09f99702008-02-04 12:31:13 +01001225 id.index = idx;
Takashi Iwai2134ea42008-01-10 16:53:55 +01001226 strcpy(id.name, name);
1227 return snd_ctl_find_id(codec->bus->card, &id);
1228}
1229
Takashi Iwai09f99702008-02-04 12:31:13 +01001230struct snd_kcontrol *snd_hda_find_mixer_ctl(struct hda_codec *codec,
1231 const char *name)
1232{
1233 return _snd_hda_find_mixer_ctl(codec, name, 0);
1234}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001235EXPORT_SYMBOL_HDA(snd_hda_find_mixer_ctl);
Takashi Iwai09f99702008-02-04 12:31:13 +01001236
Takashi Iwaid13bd412008-07-30 15:01:45 +02001237/* Add a control element and assign to the codec */
1238int snd_hda_ctl_add(struct hda_codec *codec, struct snd_kcontrol *kctl)
1239{
1240 int err;
1241 struct snd_kcontrol **knewp;
1242
1243 err = snd_ctl_add(codec->bus->card, kctl);
1244 if (err < 0)
1245 return err;
1246 knewp = snd_array_new(&codec->mixers);
1247 if (!knewp)
1248 return -ENOMEM;
1249 *knewp = kctl;
1250 return 0;
1251}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001252EXPORT_SYMBOL_HDA(snd_hda_ctl_add);
Takashi Iwaid13bd412008-07-30 15:01:45 +02001253
Takashi Iwai529bd6c2008-11-27 14:17:01 +01001254#ifdef CONFIG_SND_HDA_RECONFIG
Takashi Iwaid13bd412008-07-30 15:01:45 +02001255/* Clear all controls assigned to the given codec */
1256void snd_hda_ctls_clear(struct hda_codec *codec)
1257{
1258 int i;
1259 struct snd_kcontrol **kctls = codec->mixers.list;
1260 for (i = 0; i < codec->mixers.used; i++)
1261 snd_ctl_remove(codec->bus->card, kctls[i]);
1262 snd_array_free(&codec->mixers);
1263}
1264
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001265void snd_hda_codec_reset(struct hda_codec *codec)
1266{
1267 int i;
1268
1269#ifdef CONFIG_SND_HDA_POWER_SAVE
1270 cancel_delayed_work(&codec->power_work);
1271 flush_scheduled_work();
1272#endif
1273 snd_hda_ctls_clear(codec);
1274 /* relase PCMs */
1275 for (i = 0; i < codec->num_pcms; i++) {
Takashi Iwai529bd6c2008-11-27 14:17:01 +01001276 if (codec->pcm_info[i].pcm) {
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001277 snd_device_free(codec->bus->card,
1278 codec->pcm_info[i].pcm);
Takashi Iwai529bd6c2008-11-27 14:17:01 +01001279 clear_bit(codec->pcm_info[i].device,
1280 codec->bus->pcm_dev_bits);
1281 }
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001282 }
1283 if (codec->patch_ops.free)
1284 codec->patch_ops.free(codec);
1285 codec->spec = NULL;
1286 free_hda_cache(&codec->amp_cache);
1287 free_hda_cache(&codec->cmd_cache);
1288 codec->num_pcms = 0;
1289 codec->pcm_info = NULL;
1290 codec->preset = NULL;
Takashi Iwai1289e9e2008-11-27 15:47:11 +01001291 module_put(codec->owner);
1292 codec->owner = NULL;
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001293}
Takashi Iwai529bd6c2008-11-27 14:17:01 +01001294#endif /* CONFIG_SND_HDA_RECONFIG */
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02001295
Takashi Iwai2134ea42008-01-10 16:53:55 +01001296/* create a virtual master control and add slaves */
1297int snd_hda_add_vmaster(struct hda_codec *codec, char *name,
1298 unsigned int *tlv, const char **slaves)
1299{
1300 struct snd_kcontrol *kctl;
1301 const char **s;
1302 int err;
1303
Takashi Iwai2f085542008-02-22 18:43:50 +01001304 for (s = slaves; *s && !snd_hda_find_mixer_ctl(codec, *s); s++)
1305 ;
1306 if (!*s) {
1307 snd_printdd("No slave found for %s\n", name);
1308 return 0;
1309 }
Takashi Iwai2134ea42008-01-10 16:53:55 +01001310 kctl = snd_ctl_make_virtual_master(name, tlv);
1311 if (!kctl)
1312 return -ENOMEM;
Takashi Iwaid13bd412008-07-30 15:01:45 +02001313 err = snd_hda_ctl_add(codec, kctl);
Takashi Iwai2134ea42008-01-10 16:53:55 +01001314 if (err < 0)
1315 return err;
1316
1317 for (s = slaves; *s; s++) {
1318 struct snd_kcontrol *sctl;
1319
1320 sctl = snd_hda_find_mixer_ctl(codec, *s);
1321 if (!sctl) {
1322 snd_printdd("Cannot find slave %s, skipped\n", *s);
1323 continue;
1324 }
1325 err = snd_ctl_add_slave(kctl, sctl);
1326 if (err < 0)
1327 return err;
1328 }
1329 return 0;
1330}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001331EXPORT_SYMBOL_HDA(snd_hda_add_vmaster);
Takashi Iwai2134ea42008-01-10 16:53:55 +01001332
Linus Torvalds1da177e2005-04-16 15:20:36 -07001333/* switch */
Takashi Iwai0ba21762007-04-16 11:29:14 +02001334int snd_hda_mixer_amp_switch_info(struct snd_kcontrol *kcontrol,
1335 struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001336{
1337 int chs = get_amp_channels(kcontrol);
1338
1339 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
1340 uinfo->count = chs == 3 ? 2 : 1;
1341 uinfo->value.integer.min = 0;
1342 uinfo->value.integer.max = 1;
1343 return 0;
1344}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001345EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_switch_info);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001346
Takashi Iwai0ba21762007-04-16 11:29:14 +02001347int snd_hda_mixer_amp_switch_get(struct snd_kcontrol *kcontrol,
1348 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001349{
1350 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1351 hda_nid_t nid = get_amp_nid(kcontrol);
1352 int chs = get_amp_channels(kcontrol);
1353 int dir = get_amp_direction(kcontrol);
1354 int idx = get_amp_index(kcontrol);
1355 long *valp = ucontrol->value.integer.value;
1356
1357 if (chs & 1)
Takashi Iwai0ba21762007-04-16 11:29:14 +02001358 *valp++ = (snd_hda_codec_amp_read(codec, nid, 0, dir, idx) &
Takashi Iwai47fd8302007-08-10 17:11:07 +02001359 HDA_AMP_MUTE) ? 0 : 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001360 if (chs & 2)
Takashi Iwai0ba21762007-04-16 11:29:14 +02001361 *valp = (snd_hda_codec_amp_read(codec, nid, 1, dir, idx) &
Takashi Iwai47fd8302007-08-10 17:11:07 +02001362 HDA_AMP_MUTE) ? 0 : 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001363 return 0;
1364}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001365EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_switch_get);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001366
Takashi Iwai0ba21762007-04-16 11:29:14 +02001367int snd_hda_mixer_amp_switch_put(struct snd_kcontrol *kcontrol,
1368 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001369{
1370 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1371 hda_nid_t nid = get_amp_nid(kcontrol);
1372 int chs = get_amp_channels(kcontrol);
1373 int dir = get_amp_direction(kcontrol);
1374 int idx = get_amp_index(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001375 long *valp = ucontrol->value.integer.value;
1376 int change = 0;
1377
Takashi Iwaicb53c622007-08-10 17:21:45 +02001378 snd_hda_power_up(codec);
Nicolas Grazianob9f5a892005-07-29 12:17:20 +02001379 if (chs & 1) {
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001380 change = snd_hda_codec_amp_update(codec, nid, 0, dir, idx,
Takashi Iwai47fd8302007-08-10 17:11:07 +02001381 HDA_AMP_MUTE,
1382 *valp ? 0 : HDA_AMP_MUTE);
Nicolas Grazianob9f5a892005-07-29 12:17:20 +02001383 valp++;
1384 }
Takashi Iwai4a19fae2005-06-08 14:43:58 +02001385 if (chs & 2)
1386 change |= snd_hda_codec_amp_update(codec, nid, 1, dir, idx,
Takashi Iwai47fd8302007-08-10 17:11:07 +02001387 HDA_AMP_MUTE,
1388 *valp ? 0 : HDA_AMP_MUTE);
Takashi Iwaicb53c622007-08-10 17:21:45 +02001389#ifdef CONFIG_SND_HDA_POWER_SAVE
1390 if (codec->patch_ops.check_power_status)
1391 codec->patch_ops.check_power_status(codec, nid);
1392#endif
1393 snd_hda_power_down(codec);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001394 return change;
1395}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001396EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_switch_put);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001397
1398/*
Takashi Iwai985be542005-11-02 18:26:49 +01001399 * bound volume controls
1400 *
1401 * bind multiple volumes (# indices, from 0)
1402 */
1403
1404#define AMP_VAL_IDX_SHIFT 19
1405#define AMP_VAL_IDX_MASK (0x0f<<19)
1406
Takashi Iwai0ba21762007-04-16 11:29:14 +02001407int snd_hda_mixer_bind_switch_get(struct snd_kcontrol *kcontrol,
1408 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai985be542005-11-02 18:26:49 +01001409{
1410 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1411 unsigned long pval;
1412 int err;
1413
Ingo Molnar62932df2006-01-16 16:34:20 +01001414 mutex_lock(&codec->spdif_mutex); /* reuse spdif_mutex */
Takashi Iwai985be542005-11-02 18:26:49 +01001415 pval = kcontrol->private_value;
1416 kcontrol->private_value = pval & ~AMP_VAL_IDX_MASK; /* index 0 */
1417 err = snd_hda_mixer_amp_switch_get(kcontrol, ucontrol);
1418 kcontrol->private_value = pval;
Ingo Molnar62932df2006-01-16 16:34:20 +01001419 mutex_unlock(&codec->spdif_mutex);
Takashi Iwai985be542005-11-02 18:26:49 +01001420 return err;
1421}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001422EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_switch_get);
Takashi Iwai985be542005-11-02 18:26:49 +01001423
Takashi Iwai0ba21762007-04-16 11:29:14 +02001424int snd_hda_mixer_bind_switch_put(struct snd_kcontrol *kcontrol,
1425 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai985be542005-11-02 18:26:49 +01001426{
1427 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1428 unsigned long pval;
1429 int i, indices, err = 0, change = 0;
1430
Ingo Molnar62932df2006-01-16 16:34:20 +01001431 mutex_lock(&codec->spdif_mutex); /* reuse spdif_mutex */
Takashi Iwai985be542005-11-02 18:26:49 +01001432 pval = kcontrol->private_value;
1433 indices = (pval & AMP_VAL_IDX_MASK) >> AMP_VAL_IDX_SHIFT;
1434 for (i = 0; i < indices; i++) {
Takashi Iwai0ba21762007-04-16 11:29:14 +02001435 kcontrol->private_value = (pval & ~AMP_VAL_IDX_MASK) |
1436 (i << AMP_VAL_IDX_SHIFT);
Takashi Iwai985be542005-11-02 18:26:49 +01001437 err = snd_hda_mixer_amp_switch_put(kcontrol, ucontrol);
1438 if (err < 0)
1439 break;
1440 change |= err;
1441 }
1442 kcontrol->private_value = pval;
Ingo Molnar62932df2006-01-16 16:34:20 +01001443 mutex_unlock(&codec->spdif_mutex);
Takashi Iwai985be542005-11-02 18:26:49 +01001444 return err < 0 ? err : change;
1445}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001446EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_switch_put);
Takashi Iwai985be542005-11-02 18:26:49 +01001447
1448/*
Takashi Iwai532d5382007-07-27 19:02:40 +02001449 * generic bound volume/swtich controls
1450 */
1451int snd_hda_mixer_bind_ctls_info(struct snd_kcontrol *kcontrol,
1452 struct snd_ctl_elem_info *uinfo)
1453{
1454 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1455 struct hda_bind_ctls *c;
1456 int err;
1457
Takashi Iwai532d5382007-07-27 19:02:40 +02001458 mutex_lock(&codec->spdif_mutex); /* reuse spdif_mutex */
Serge A. Suchkov14c65f92008-02-22 18:43:16 +01001459 c = (struct hda_bind_ctls *)kcontrol->private_value;
Takashi Iwai532d5382007-07-27 19:02:40 +02001460 kcontrol->private_value = *c->values;
1461 err = c->ops->info(kcontrol, uinfo);
1462 kcontrol->private_value = (long)c;
1463 mutex_unlock(&codec->spdif_mutex);
1464 return err;
1465}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001466EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_ctls_info);
Takashi Iwai532d5382007-07-27 19:02:40 +02001467
1468int snd_hda_mixer_bind_ctls_get(struct snd_kcontrol *kcontrol,
1469 struct snd_ctl_elem_value *ucontrol)
1470{
1471 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1472 struct hda_bind_ctls *c;
1473 int err;
1474
Takashi Iwai532d5382007-07-27 19:02:40 +02001475 mutex_lock(&codec->spdif_mutex); /* reuse spdif_mutex */
Serge A. Suchkov14c65f92008-02-22 18:43:16 +01001476 c = (struct hda_bind_ctls *)kcontrol->private_value;
Takashi Iwai532d5382007-07-27 19:02:40 +02001477 kcontrol->private_value = *c->values;
1478 err = c->ops->get(kcontrol, ucontrol);
1479 kcontrol->private_value = (long)c;
1480 mutex_unlock(&codec->spdif_mutex);
1481 return err;
1482}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001483EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_ctls_get);
Takashi Iwai532d5382007-07-27 19:02:40 +02001484
1485int snd_hda_mixer_bind_ctls_put(struct snd_kcontrol *kcontrol,
1486 struct snd_ctl_elem_value *ucontrol)
1487{
1488 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1489 struct hda_bind_ctls *c;
1490 unsigned long *vals;
1491 int err = 0, change = 0;
1492
Takashi Iwai532d5382007-07-27 19:02:40 +02001493 mutex_lock(&codec->spdif_mutex); /* reuse spdif_mutex */
Serge A. Suchkov14c65f92008-02-22 18:43:16 +01001494 c = (struct hda_bind_ctls *)kcontrol->private_value;
Takashi Iwai532d5382007-07-27 19:02:40 +02001495 for (vals = c->values; *vals; vals++) {
1496 kcontrol->private_value = *vals;
1497 err = c->ops->put(kcontrol, ucontrol);
1498 if (err < 0)
1499 break;
1500 change |= err;
1501 }
1502 kcontrol->private_value = (long)c;
1503 mutex_unlock(&codec->spdif_mutex);
1504 return err < 0 ? err : change;
1505}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001506EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_ctls_put);
Takashi Iwai532d5382007-07-27 19:02:40 +02001507
1508int snd_hda_mixer_bind_tlv(struct snd_kcontrol *kcontrol, int op_flag,
1509 unsigned int size, unsigned int __user *tlv)
1510{
1511 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1512 struct hda_bind_ctls *c;
1513 int err;
1514
Takashi Iwai532d5382007-07-27 19:02:40 +02001515 mutex_lock(&codec->spdif_mutex); /* reuse spdif_mutex */
Serge A. Suchkov14c65f92008-02-22 18:43:16 +01001516 c = (struct hda_bind_ctls *)kcontrol->private_value;
Takashi Iwai532d5382007-07-27 19:02:40 +02001517 kcontrol->private_value = *c->values;
1518 err = c->ops->tlv(kcontrol, op_flag, size, tlv);
1519 kcontrol->private_value = (long)c;
1520 mutex_unlock(&codec->spdif_mutex);
1521 return err;
1522}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001523EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_tlv);
Takashi Iwai532d5382007-07-27 19:02:40 +02001524
1525struct hda_ctl_ops snd_hda_bind_vol = {
1526 .info = snd_hda_mixer_amp_volume_info,
1527 .get = snd_hda_mixer_amp_volume_get,
1528 .put = snd_hda_mixer_amp_volume_put,
1529 .tlv = snd_hda_mixer_amp_tlv
1530};
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001531EXPORT_SYMBOL_HDA(snd_hda_bind_vol);
Takashi Iwai532d5382007-07-27 19:02:40 +02001532
1533struct hda_ctl_ops snd_hda_bind_sw = {
1534 .info = snd_hda_mixer_amp_switch_info,
1535 .get = snd_hda_mixer_amp_switch_get,
1536 .put = snd_hda_mixer_amp_switch_put,
1537 .tlv = snd_hda_mixer_amp_tlv
1538};
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001539EXPORT_SYMBOL_HDA(snd_hda_bind_sw);
Takashi Iwai532d5382007-07-27 19:02:40 +02001540
1541/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07001542 * SPDIF out controls
1543 */
1544
Takashi Iwai0ba21762007-04-16 11:29:14 +02001545static int snd_hda_spdif_mask_info(struct snd_kcontrol *kcontrol,
1546 struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001547{
1548 uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
1549 uinfo->count = 1;
1550 return 0;
1551}
1552
Takashi Iwai0ba21762007-04-16 11:29:14 +02001553static int snd_hda_spdif_cmask_get(struct snd_kcontrol *kcontrol,
1554 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001555{
1556 ucontrol->value.iec958.status[0] = IEC958_AES0_PROFESSIONAL |
1557 IEC958_AES0_NONAUDIO |
1558 IEC958_AES0_CON_EMPHASIS_5015 |
1559 IEC958_AES0_CON_NOT_COPYRIGHT;
1560 ucontrol->value.iec958.status[1] = IEC958_AES1_CON_CATEGORY |
1561 IEC958_AES1_CON_ORIGINAL;
1562 return 0;
1563}
1564
Takashi Iwai0ba21762007-04-16 11:29:14 +02001565static int snd_hda_spdif_pmask_get(struct snd_kcontrol *kcontrol,
1566 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001567{
1568 ucontrol->value.iec958.status[0] = IEC958_AES0_PROFESSIONAL |
1569 IEC958_AES0_NONAUDIO |
1570 IEC958_AES0_PRO_EMPHASIS_5015;
1571 return 0;
1572}
1573
Takashi Iwai0ba21762007-04-16 11:29:14 +02001574static int snd_hda_spdif_default_get(struct snd_kcontrol *kcontrol,
1575 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001576{
1577 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1578
1579 ucontrol->value.iec958.status[0] = codec->spdif_status & 0xff;
1580 ucontrol->value.iec958.status[1] = (codec->spdif_status >> 8) & 0xff;
1581 ucontrol->value.iec958.status[2] = (codec->spdif_status >> 16) & 0xff;
1582 ucontrol->value.iec958.status[3] = (codec->spdif_status >> 24) & 0xff;
1583
1584 return 0;
1585}
1586
1587/* convert from SPDIF status bits to HDA SPDIF bits
1588 * bit 0 (DigEn) is always set zero (to be filled later)
1589 */
1590static unsigned short convert_from_spdif_status(unsigned int sbits)
1591{
1592 unsigned short val = 0;
1593
1594 if (sbits & IEC958_AES0_PROFESSIONAL)
Takashi Iwai0ba21762007-04-16 11:29:14 +02001595 val |= AC_DIG1_PROFESSIONAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001596 if (sbits & IEC958_AES0_NONAUDIO)
Takashi Iwai0ba21762007-04-16 11:29:14 +02001597 val |= AC_DIG1_NONAUDIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001598 if (sbits & IEC958_AES0_PROFESSIONAL) {
Takashi Iwai0ba21762007-04-16 11:29:14 +02001599 if ((sbits & IEC958_AES0_PRO_EMPHASIS) ==
1600 IEC958_AES0_PRO_EMPHASIS_5015)
1601 val |= AC_DIG1_EMPHASIS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001602 } else {
Takashi Iwai0ba21762007-04-16 11:29:14 +02001603 if ((sbits & IEC958_AES0_CON_EMPHASIS) ==
1604 IEC958_AES0_CON_EMPHASIS_5015)
1605 val |= AC_DIG1_EMPHASIS;
1606 if (!(sbits & IEC958_AES0_CON_NOT_COPYRIGHT))
1607 val |= AC_DIG1_COPYRIGHT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001608 if (sbits & (IEC958_AES1_CON_ORIGINAL << 8))
Takashi Iwai0ba21762007-04-16 11:29:14 +02001609 val |= AC_DIG1_LEVEL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001610 val |= sbits & (IEC958_AES1_CON_CATEGORY << 8);
1611 }
1612 return val;
1613}
1614
1615/* convert to SPDIF status bits from HDA SPDIF bits
1616 */
1617static unsigned int convert_to_spdif_status(unsigned short val)
1618{
1619 unsigned int sbits = 0;
1620
Takashi Iwai0ba21762007-04-16 11:29:14 +02001621 if (val & AC_DIG1_NONAUDIO)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001622 sbits |= IEC958_AES0_NONAUDIO;
Takashi Iwai0ba21762007-04-16 11:29:14 +02001623 if (val & AC_DIG1_PROFESSIONAL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001624 sbits |= IEC958_AES0_PROFESSIONAL;
1625 if (sbits & IEC958_AES0_PROFESSIONAL) {
Takashi Iwai0ba21762007-04-16 11:29:14 +02001626 if (sbits & AC_DIG1_EMPHASIS)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001627 sbits |= IEC958_AES0_PRO_EMPHASIS_5015;
1628 } else {
Takashi Iwai0ba21762007-04-16 11:29:14 +02001629 if (val & AC_DIG1_EMPHASIS)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001630 sbits |= IEC958_AES0_CON_EMPHASIS_5015;
Takashi Iwai0ba21762007-04-16 11:29:14 +02001631 if (!(val & AC_DIG1_COPYRIGHT))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001632 sbits |= IEC958_AES0_CON_NOT_COPYRIGHT;
Takashi Iwai0ba21762007-04-16 11:29:14 +02001633 if (val & AC_DIG1_LEVEL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001634 sbits |= (IEC958_AES1_CON_ORIGINAL << 8);
1635 sbits |= val & (0x7f << 8);
1636 }
1637 return sbits;
1638}
1639
Takashi Iwai2f728532008-09-25 16:32:41 +02001640/* set digital convert verbs both for the given NID and its slaves */
1641static void set_dig_out(struct hda_codec *codec, hda_nid_t nid,
1642 int verb, int val)
1643{
1644 hda_nid_t *d;
1645
Takashi Iwai9e976972008-11-25 08:17:20 +01001646 snd_hda_codec_write_cache(codec, nid, 0, verb, val);
Takashi Iwai2f728532008-09-25 16:32:41 +02001647 d = codec->slave_dig_outs;
1648 if (!d)
1649 return;
1650 for (; *d; d++)
Takashi Iwai9e976972008-11-25 08:17:20 +01001651 snd_hda_codec_write_cache(codec, *d, 0, verb, val);
Takashi Iwai2f728532008-09-25 16:32:41 +02001652}
1653
1654static inline void set_dig_out_convert(struct hda_codec *codec, hda_nid_t nid,
1655 int dig1, int dig2)
1656{
1657 if (dig1 != -1)
1658 set_dig_out(codec, nid, AC_VERB_SET_DIGI_CONVERT_1, dig1);
1659 if (dig2 != -1)
1660 set_dig_out(codec, nid, AC_VERB_SET_DIGI_CONVERT_2, dig2);
1661}
1662
Takashi Iwai0ba21762007-04-16 11:29:14 +02001663static int snd_hda_spdif_default_put(struct snd_kcontrol *kcontrol,
1664 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001665{
1666 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1667 hda_nid_t nid = kcontrol->private_value;
1668 unsigned short val;
1669 int change;
1670
Ingo Molnar62932df2006-01-16 16:34:20 +01001671 mutex_lock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001672 codec->spdif_status = ucontrol->value.iec958.status[0] |
1673 ((unsigned int)ucontrol->value.iec958.status[1] << 8) |
1674 ((unsigned int)ucontrol->value.iec958.status[2] << 16) |
1675 ((unsigned int)ucontrol->value.iec958.status[3] << 24);
1676 val = convert_from_spdif_status(codec->spdif_status);
1677 val |= codec->spdif_ctls & 1;
1678 change = codec->spdif_ctls != val;
1679 codec->spdif_ctls = val;
1680
Takashi Iwai2f728532008-09-25 16:32:41 +02001681 if (change)
1682 set_dig_out_convert(codec, nid, val & 0xff, (val >> 8) & 0xff);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001683
Ingo Molnar62932df2006-01-16 16:34:20 +01001684 mutex_unlock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001685 return change;
1686}
1687
Takashi Iwaia5ce8892007-07-23 15:42:26 +02001688#define snd_hda_spdif_out_switch_info snd_ctl_boolean_mono_info
Linus Torvalds1da177e2005-04-16 15:20:36 -07001689
Takashi Iwai0ba21762007-04-16 11:29:14 +02001690static int snd_hda_spdif_out_switch_get(struct snd_kcontrol *kcontrol,
1691 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001692{
1693 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1694
Takashi Iwai0ba21762007-04-16 11:29:14 +02001695 ucontrol->value.integer.value[0] = codec->spdif_ctls & AC_DIG1_ENABLE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001696 return 0;
1697}
1698
Takashi Iwai0ba21762007-04-16 11:29:14 +02001699static int snd_hda_spdif_out_switch_put(struct snd_kcontrol *kcontrol,
1700 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001701{
1702 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1703 hda_nid_t nid = kcontrol->private_value;
1704 unsigned short val;
1705 int change;
1706
Ingo Molnar62932df2006-01-16 16:34:20 +01001707 mutex_lock(&codec->spdif_mutex);
Takashi Iwai0ba21762007-04-16 11:29:14 +02001708 val = codec->spdif_ctls & ~AC_DIG1_ENABLE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001709 if (ucontrol->value.integer.value[0])
Takashi Iwai0ba21762007-04-16 11:29:14 +02001710 val |= AC_DIG1_ENABLE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001711 change = codec->spdif_ctls != val;
Takashi Iwai82beb8f2007-08-10 17:09:26 +02001712 if (change) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001713 codec->spdif_ctls = val;
Takashi Iwai2f728532008-09-25 16:32:41 +02001714 set_dig_out_convert(codec, nid, val & 0xff, -1);
Takashi Iwai0ba21762007-04-16 11:29:14 +02001715 /* unmute amp switch (if any) */
1716 if ((get_wcaps(codec, nid) & AC_WCAP_OUT_AMP) &&
Takashi Iwai47fd8302007-08-10 17:11:07 +02001717 (val & AC_DIG1_ENABLE))
1718 snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0,
1719 HDA_AMP_MUTE, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001720 }
Ingo Molnar62932df2006-01-16 16:34:20 +01001721 mutex_unlock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001722 return change;
1723}
1724
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01001725static struct snd_kcontrol_new dig_mixes[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001726 {
1727 .access = SNDRV_CTL_ELEM_ACCESS_READ,
1728 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1729 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,CON_MASK),
1730 .info = snd_hda_spdif_mask_info,
1731 .get = snd_hda_spdif_cmask_get,
1732 },
1733 {
1734 .access = SNDRV_CTL_ELEM_ACCESS_READ,
1735 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1736 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,PRO_MASK),
1737 .info = snd_hda_spdif_mask_info,
1738 .get = snd_hda_spdif_pmask_get,
1739 },
1740 {
1741 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1742 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT),
1743 .info = snd_hda_spdif_mask_info,
1744 .get = snd_hda_spdif_default_get,
1745 .put = snd_hda_spdif_default_put,
1746 },
1747 {
1748 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1749 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,SWITCH),
1750 .info = snd_hda_spdif_out_switch_info,
1751 .get = snd_hda_spdif_out_switch_get,
1752 .put = snd_hda_spdif_out_switch_put,
1753 },
1754 { } /* end */
1755};
1756
Takashi Iwai09f99702008-02-04 12:31:13 +01001757#define SPDIF_MAX_IDX 4 /* 4 instances should be enough to probe */
1758
Linus Torvalds1da177e2005-04-16 15:20:36 -07001759/**
1760 * snd_hda_create_spdif_out_ctls - create Output SPDIF-related controls
1761 * @codec: the HDA codec
1762 * @nid: audio out widget NID
1763 *
1764 * Creates controls related with the SPDIF output.
1765 * Called from each patch supporting the SPDIF out.
1766 *
1767 * Returns 0 if successful, or a negative error code.
1768 */
Takashi Iwai12f288b2007-08-02 15:51:59 +02001769int snd_hda_create_spdif_out_ctls(struct hda_codec *codec, hda_nid_t nid)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001770{
1771 int err;
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01001772 struct snd_kcontrol *kctl;
1773 struct snd_kcontrol_new *dig_mix;
Takashi Iwai09f99702008-02-04 12:31:13 +01001774 int idx;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001775
Takashi Iwai09f99702008-02-04 12:31:13 +01001776 for (idx = 0; idx < SPDIF_MAX_IDX; idx++) {
1777 if (!_snd_hda_find_mixer_ctl(codec, "IEC958 Playback Switch",
1778 idx))
1779 break;
1780 }
1781 if (idx >= SPDIF_MAX_IDX) {
1782 printk(KERN_ERR "hda_codec: too many IEC958 outputs\n");
1783 return -EBUSY;
1784 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001785 for (dig_mix = dig_mixes; dig_mix->name; dig_mix++) {
1786 kctl = snd_ctl_new1(dig_mix, codec);
Takashi Iwaib91f0802008-11-04 08:43:08 +01001787 if (!kctl)
1788 return -ENOMEM;
Takashi Iwai09f99702008-02-04 12:31:13 +01001789 kctl->id.index = idx;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001790 kctl->private_value = nid;
Takashi Iwaid13bd412008-07-30 15:01:45 +02001791 err = snd_hda_ctl_add(codec, kctl);
Takashi Iwai0ba21762007-04-16 11:29:14 +02001792 if (err < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001793 return err;
1794 }
Takashi Iwai0ba21762007-04-16 11:29:14 +02001795 codec->spdif_ctls =
Andrew Paprocki3982d172007-12-19 12:13:44 +01001796 snd_hda_codec_read(codec, nid, 0,
1797 AC_VERB_GET_DIGI_CONVERT_1, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001798 codec->spdif_status = convert_to_spdif_status(codec->spdif_ctls);
1799 return 0;
1800}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001801EXPORT_SYMBOL_HDA(snd_hda_create_spdif_out_ctls);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001802
1803/*
Takashi Iwai9a081602008-02-12 18:37:26 +01001804 * SPDIF sharing with analog output
1805 */
1806static int spdif_share_sw_get(struct snd_kcontrol *kcontrol,
1807 struct snd_ctl_elem_value *ucontrol)
1808{
1809 struct hda_multi_out *mout = snd_kcontrol_chip(kcontrol);
1810 ucontrol->value.integer.value[0] = mout->share_spdif;
1811 return 0;
1812}
1813
1814static int spdif_share_sw_put(struct snd_kcontrol *kcontrol,
1815 struct snd_ctl_elem_value *ucontrol)
1816{
1817 struct hda_multi_out *mout = snd_kcontrol_chip(kcontrol);
1818 mout->share_spdif = !!ucontrol->value.integer.value[0];
1819 return 0;
1820}
1821
1822static struct snd_kcontrol_new spdif_share_sw = {
1823 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1824 .name = "IEC958 Default PCM Playback Switch",
1825 .info = snd_ctl_boolean_mono_info,
1826 .get = spdif_share_sw_get,
1827 .put = spdif_share_sw_put,
1828};
1829
1830int snd_hda_create_spdif_share_sw(struct hda_codec *codec,
1831 struct hda_multi_out *mout)
1832{
1833 if (!mout->dig_out_nid)
1834 return 0;
1835 /* ATTENTION: here mout is passed as private_data, instead of codec */
Takashi Iwaid13bd412008-07-30 15:01:45 +02001836 return snd_hda_ctl_add(codec,
Takashi Iwai9a081602008-02-12 18:37:26 +01001837 snd_ctl_new1(&spdif_share_sw, mout));
1838}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001839EXPORT_SYMBOL_HDA(snd_hda_create_spdif_share_sw);
Takashi Iwai9a081602008-02-12 18:37:26 +01001840
1841/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07001842 * SPDIF input
1843 */
1844
1845#define snd_hda_spdif_in_switch_info snd_hda_spdif_out_switch_info
1846
Takashi Iwai0ba21762007-04-16 11:29:14 +02001847static int snd_hda_spdif_in_switch_get(struct snd_kcontrol *kcontrol,
1848 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001849{
1850 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1851
1852 ucontrol->value.integer.value[0] = codec->spdif_in_enable;
1853 return 0;
1854}
1855
Takashi Iwai0ba21762007-04-16 11:29:14 +02001856static int snd_hda_spdif_in_switch_put(struct snd_kcontrol *kcontrol,
1857 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001858{
1859 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1860 hda_nid_t nid = kcontrol->private_value;
1861 unsigned int val = !!ucontrol->value.integer.value[0];
1862 int change;
1863
Ingo Molnar62932df2006-01-16 16:34:20 +01001864 mutex_lock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001865 change = codec->spdif_in_enable != val;
Takashi Iwai82beb8f2007-08-10 17:09:26 +02001866 if (change) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001867 codec->spdif_in_enable = val;
Takashi Iwai82beb8f2007-08-10 17:09:26 +02001868 snd_hda_codec_write_cache(codec, nid, 0,
1869 AC_VERB_SET_DIGI_CONVERT_1, val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001870 }
Ingo Molnar62932df2006-01-16 16:34:20 +01001871 mutex_unlock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001872 return change;
1873}
1874
Takashi Iwai0ba21762007-04-16 11:29:14 +02001875static int snd_hda_spdif_in_status_get(struct snd_kcontrol *kcontrol,
1876 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001877{
1878 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1879 hda_nid_t nid = kcontrol->private_value;
1880 unsigned short val;
1881 unsigned int sbits;
1882
Andrew Paprocki3982d172007-12-19 12:13:44 +01001883 val = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_DIGI_CONVERT_1, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001884 sbits = convert_to_spdif_status(val);
1885 ucontrol->value.iec958.status[0] = sbits;
1886 ucontrol->value.iec958.status[1] = sbits >> 8;
1887 ucontrol->value.iec958.status[2] = sbits >> 16;
1888 ucontrol->value.iec958.status[3] = sbits >> 24;
1889 return 0;
1890}
1891
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01001892static struct snd_kcontrol_new dig_in_ctls[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001893 {
1894 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1895 .name = SNDRV_CTL_NAME_IEC958("",CAPTURE,SWITCH),
1896 .info = snd_hda_spdif_in_switch_info,
1897 .get = snd_hda_spdif_in_switch_get,
1898 .put = snd_hda_spdif_in_switch_put,
1899 },
1900 {
1901 .access = SNDRV_CTL_ELEM_ACCESS_READ,
1902 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1903 .name = SNDRV_CTL_NAME_IEC958("",CAPTURE,DEFAULT),
1904 .info = snd_hda_spdif_mask_info,
1905 .get = snd_hda_spdif_in_status_get,
1906 },
1907 { } /* end */
1908};
1909
1910/**
1911 * snd_hda_create_spdif_in_ctls - create Input SPDIF-related controls
1912 * @codec: the HDA codec
1913 * @nid: audio in widget NID
1914 *
1915 * Creates controls related with the SPDIF input.
1916 * Called from each patch supporting the SPDIF in.
1917 *
1918 * Returns 0 if successful, or a negative error code.
1919 */
Takashi Iwai12f288b2007-08-02 15:51:59 +02001920int snd_hda_create_spdif_in_ctls(struct hda_codec *codec, hda_nid_t nid)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001921{
1922 int err;
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01001923 struct snd_kcontrol *kctl;
1924 struct snd_kcontrol_new *dig_mix;
Takashi Iwai09f99702008-02-04 12:31:13 +01001925 int idx;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001926
Takashi Iwai09f99702008-02-04 12:31:13 +01001927 for (idx = 0; idx < SPDIF_MAX_IDX; idx++) {
1928 if (!_snd_hda_find_mixer_ctl(codec, "IEC958 Capture Switch",
1929 idx))
1930 break;
1931 }
1932 if (idx >= SPDIF_MAX_IDX) {
1933 printk(KERN_ERR "hda_codec: too many IEC958 inputs\n");
1934 return -EBUSY;
1935 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001936 for (dig_mix = dig_in_ctls; dig_mix->name; dig_mix++) {
1937 kctl = snd_ctl_new1(dig_mix, codec);
1938 kctl->private_value = nid;
Takashi Iwaid13bd412008-07-30 15:01:45 +02001939 err = snd_hda_ctl_add(codec, kctl);
Takashi Iwai0ba21762007-04-16 11:29:14 +02001940 if (err < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001941 return err;
1942 }
Takashi Iwai0ba21762007-04-16 11:29:14 +02001943 codec->spdif_in_enable =
Andrew Paprocki3982d172007-12-19 12:13:44 +01001944 snd_hda_codec_read(codec, nid, 0,
1945 AC_VERB_GET_DIGI_CONVERT_1, 0) &
Takashi Iwai0ba21762007-04-16 11:29:14 +02001946 AC_DIG1_ENABLE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001947 return 0;
1948}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001949EXPORT_SYMBOL_HDA(snd_hda_create_spdif_in_ctls);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001950
Takashi Iwaicb53c622007-08-10 17:21:45 +02001951#ifdef SND_HDA_NEEDS_RESUME
Takashi Iwai82beb8f2007-08-10 17:09:26 +02001952/*
1953 * command cache
1954 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001955
Takashi Iwaib3ac5632007-08-10 17:03:40 +02001956/* build a 32bit cache key with the widget id and the command parameter */
1957#define build_cmd_cache_key(nid, verb) ((verb << 8) | nid)
1958#define get_cmd_cache_nid(key) ((key) & 0xff)
1959#define get_cmd_cache_cmd(key) (((key) >> 8) & 0xffff)
1960
1961/**
1962 * snd_hda_codec_write_cache - send a single command with caching
1963 * @codec: the HDA codec
1964 * @nid: NID to send the command
1965 * @direct: direct flag
1966 * @verb: the verb to send
1967 * @parm: the parameter for the verb
1968 *
1969 * Send a single command without waiting for response.
1970 *
1971 * Returns 0 if successful, or a negative error code.
1972 */
1973int snd_hda_codec_write_cache(struct hda_codec *codec, hda_nid_t nid,
1974 int direct, unsigned int verb, unsigned int parm)
1975{
Takashi Iwai33fa35e2008-11-06 16:50:40 +01001976 struct hda_bus *bus = codec->bus;
1977 unsigned int res;
Takashi Iwaib3ac5632007-08-10 17:03:40 +02001978 int err;
Takashi Iwai33fa35e2008-11-06 16:50:40 +01001979
1980 res = make_codec_cmd(codec, nid, direct, verb, parm);
Takashi Iwaicb53c622007-08-10 17:21:45 +02001981 snd_hda_power_up(codec);
Takashi Iwai33fa35e2008-11-06 16:50:40 +01001982 mutex_lock(&bus->cmd_mutex);
1983 err = bus->ops.command(bus, res);
Takashi Iwaib3ac5632007-08-10 17:03:40 +02001984 if (!err) {
1985 struct hda_cache_head *c;
1986 u32 key = build_cmd_cache_key(nid, verb);
1987 c = get_alloc_hash(&codec->cmd_cache, key);
1988 if (c)
1989 c->val = parm;
1990 }
Takashi Iwai33fa35e2008-11-06 16:50:40 +01001991 mutex_unlock(&bus->cmd_mutex);
Takashi Iwaicb53c622007-08-10 17:21:45 +02001992 snd_hda_power_down(codec);
Takashi Iwaib3ac5632007-08-10 17:03:40 +02001993 return err;
1994}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01001995EXPORT_SYMBOL_HDA(snd_hda_codec_write_cache);
Takashi Iwaib3ac5632007-08-10 17:03:40 +02001996
1997/* resume the all commands from the cache */
1998void snd_hda_codec_resume_cache(struct hda_codec *codec)
1999{
Takashi Iwai603c4012008-07-30 15:01:44 +02002000 struct hda_cache_head *buffer = codec->cmd_cache.buf.list;
Takashi Iwaib3ac5632007-08-10 17:03:40 +02002001 int i;
2002
Takashi Iwai603c4012008-07-30 15:01:44 +02002003 for (i = 0; i < codec->cmd_cache.buf.used; i++, buffer++) {
Takashi Iwaib3ac5632007-08-10 17:03:40 +02002004 u32 key = buffer->key;
2005 if (!key)
2006 continue;
2007 snd_hda_codec_write(codec, get_cmd_cache_nid(key), 0,
2008 get_cmd_cache_cmd(key), buffer->val);
2009 }
2010}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002011EXPORT_SYMBOL_HDA(snd_hda_codec_resume_cache);
Takashi Iwaib3ac5632007-08-10 17:03:40 +02002012
2013/**
2014 * snd_hda_sequence_write_cache - sequence writes with caching
2015 * @codec: the HDA codec
2016 * @seq: VERB array to send
2017 *
2018 * Send the commands sequentially from the given array.
2019 * Thte commands are recorded on cache for power-save and resume.
2020 * The array must be terminated with NID=0.
2021 */
2022void snd_hda_sequence_write_cache(struct hda_codec *codec,
2023 const struct hda_verb *seq)
2024{
2025 for (; seq->nid; seq++)
2026 snd_hda_codec_write_cache(codec, seq->nid, 0, seq->verb,
2027 seq->param);
2028}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002029EXPORT_SYMBOL_HDA(snd_hda_sequence_write_cache);
Takashi Iwaicb53c622007-08-10 17:21:45 +02002030#endif /* SND_HDA_NEEDS_RESUME */
Takashi Iwaib3ac5632007-08-10 17:03:40 +02002031
Takashi Iwai54d17402005-11-21 16:33:22 +01002032/*
2033 * set power state of the codec
2034 */
2035static void hda_set_power_state(struct hda_codec *codec, hda_nid_t fg,
2036 unsigned int power_state)
2037{
Takashi Iwaicb53c622007-08-10 17:21:45 +02002038 hda_nid_t nid;
2039 int i;
Takashi Iwai54d17402005-11-21 16:33:22 +01002040
2041 snd_hda_codec_write(codec, fg, 0, AC_VERB_SET_POWER_STATE,
2042 power_state);
Marc Boucherd2595d82008-01-22 15:23:30 +01002043 msleep(10); /* partial workaround for "azx_get_response timeout" */
Takashi Iwai54d17402005-11-21 16:33:22 +01002044
Takashi Iwaicb53c622007-08-10 17:21:45 +02002045 nid = codec->start_nid;
2046 for (i = 0; i < codec->num_nodes; i++, nid++) {
Takashi Iwai7eba5c92007-11-14 14:53:42 +01002047 unsigned int wcaps = get_wcaps(codec, nid);
2048 if (wcaps & AC_WCAP_POWER) {
2049 unsigned int wid_type = (wcaps & AC_WCAP_TYPE) >>
2050 AC_WCAP_TYPE_SHIFT;
2051 if (wid_type == AC_WID_PIN) {
2052 unsigned int pincap;
2053 /*
2054 * don't power down the widget if it controls
2055 * eapd and EAPD_BTLENABLE is set.
2056 */
2057 pincap = snd_hda_param_read(codec, nid,
2058 AC_PAR_PIN_CAP);
2059 if (pincap & AC_PINCAP_EAPD) {
2060 int eapd = snd_hda_codec_read(codec,
2061 nid, 0,
2062 AC_VERB_GET_EAPD_BTLENABLE, 0);
2063 eapd &= 0x02;
2064 if (power_state == AC_PWRST_D3 && eapd)
2065 continue;
2066 }
Takashi Iwai1194b5b2007-10-10 10:04:26 +02002067 }
Takashi Iwai54d17402005-11-21 16:33:22 +01002068 snd_hda_codec_write(codec, nid, 0,
2069 AC_VERB_SET_POWER_STATE,
2070 power_state);
Takashi Iwai1194b5b2007-10-10 10:04:26 +02002071 }
Takashi Iwai54d17402005-11-21 16:33:22 +01002072 }
2073
Takashi Iwaicb53c622007-08-10 17:21:45 +02002074 if (power_state == AC_PWRST_D0) {
2075 unsigned long end_time;
2076 int state;
Takashi Iwai54d17402005-11-21 16:33:22 +01002077 msleep(10);
Takashi Iwaicb53c622007-08-10 17:21:45 +02002078 /* wait until the codec reachs to D0 */
2079 end_time = jiffies + msecs_to_jiffies(500);
2080 do {
2081 state = snd_hda_codec_read(codec, fg, 0,
2082 AC_VERB_GET_POWER_STATE, 0);
2083 if (state == power_state)
2084 break;
2085 msleep(1);
2086 } while (time_after_eq(end_time, jiffies));
2087 }
Takashi Iwai54d17402005-11-21 16:33:22 +01002088}
2089
Takashi Iwai11aeff02008-07-30 15:01:46 +02002090#ifdef CONFIG_SND_HDA_HWDEP
2091/* execute additional init verbs */
2092static void hda_exec_init_verbs(struct hda_codec *codec)
2093{
2094 if (codec->init_verbs.list)
2095 snd_hda_sequence_write(codec, codec->init_verbs.list);
2096}
2097#else
2098static inline void hda_exec_init_verbs(struct hda_codec *codec) {}
2099#endif
2100
Takashi Iwaicb53c622007-08-10 17:21:45 +02002101#ifdef SND_HDA_NEEDS_RESUME
2102/*
2103 * call suspend and power-down; used both from PM and power-save
2104 */
2105static void hda_call_codec_suspend(struct hda_codec *codec)
2106{
2107 if (codec->patch_ops.suspend)
2108 codec->patch_ops.suspend(codec, PMSG_SUSPEND);
2109 hda_set_power_state(codec,
2110 codec->afg ? codec->afg : codec->mfg,
2111 AC_PWRST_D3);
2112#ifdef CONFIG_SND_HDA_POWER_SAVE
2113 cancel_delayed_work(&codec->power_work);
Takashi Iwai95e99fd2007-08-13 15:29:04 +02002114 codec->power_on = 0;
Takashi Iwaia221e282007-08-16 16:35:33 +02002115 codec->power_transition = 0;
Takashi Iwaicb53c622007-08-10 17:21:45 +02002116#endif
2117}
2118
2119/*
2120 * kick up codec; used both from PM and power-save
2121 */
2122static void hda_call_codec_resume(struct hda_codec *codec)
2123{
2124 hda_set_power_state(codec,
2125 codec->afg ? codec->afg : codec->mfg,
2126 AC_PWRST_D0);
Takashi Iwai11aeff02008-07-30 15:01:46 +02002127 hda_exec_init_verbs(codec);
Takashi Iwaicb53c622007-08-10 17:21:45 +02002128 if (codec->patch_ops.resume)
2129 codec->patch_ops.resume(codec);
2130 else {
Takashi Iwai9d99f312007-08-14 15:15:52 +02002131 if (codec->patch_ops.init)
2132 codec->patch_ops.init(codec);
Takashi Iwaicb53c622007-08-10 17:21:45 +02002133 snd_hda_codec_resume_amp(codec);
2134 snd_hda_codec_resume_cache(codec);
2135 }
2136}
2137#endif /* SND_HDA_NEEDS_RESUME */
2138
Takashi Iwai54d17402005-11-21 16:33:22 +01002139
Linus Torvalds1da177e2005-04-16 15:20:36 -07002140/**
2141 * snd_hda_build_controls - build mixer controls
2142 * @bus: the BUS
2143 *
2144 * Creates mixer controls for each codec included in the bus.
2145 *
2146 * Returns 0 if successful, otherwise a negative error code.
2147 */
Takashi Iwai1289e9e2008-11-27 15:47:11 +01002148int /*__devinit*/ snd_hda_build_controls(struct hda_bus *bus)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002149{
Takashi Iwai0ba21762007-04-16 11:29:14 +02002150 struct hda_codec *codec;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002151
Takashi Iwai0ba21762007-04-16 11:29:14 +02002152 list_for_each_entry(codec, &bus->codec_list, list) {
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02002153 int err = snd_hda_codec_build_controls(codec);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002154 if (err < 0)
2155 return err;
2156 }
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02002157 return 0;
2158}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002159EXPORT_SYMBOL_HDA(snd_hda_build_controls);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002160
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02002161int snd_hda_codec_build_controls(struct hda_codec *codec)
2162{
2163 int err = 0;
2164 /* fake as if already powered-on */
2165 hda_keep_power_on(codec);
2166 /* then fire up */
2167 hda_set_power_state(codec,
2168 codec->afg ? codec->afg : codec->mfg,
2169 AC_PWRST_D0);
Takashi Iwai11aeff02008-07-30 15:01:46 +02002170 hda_exec_init_verbs(codec);
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02002171 /* continue to initialize... */
2172 if (codec->patch_ops.init)
2173 err = codec->patch_ops.init(codec);
2174 if (!err && codec->patch_ops.build_controls)
2175 err = codec->patch_ops.build_controls(codec);
2176 snd_hda_power_down(codec);
2177 if (err < 0)
2178 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002179 return 0;
2180}
2181
Linus Torvalds1da177e2005-04-16 15:20:36 -07002182/*
2183 * stream formats
2184 */
Takashi Iwaibefdf312005-08-22 13:57:55 +02002185struct hda_rate_tbl {
2186 unsigned int hz;
2187 unsigned int alsa_bits;
2188 unsigned int hda_fmt;
2189};
2190
2191static struct hda_rate_tbl rate_bits[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002192 /* rate in Hz, ALSA rate bitmask, HDA format value */
Nicolas Graziano9d8f53f2005-08-22 13:47:16 +02002193
2194 /* autodetected value used in snd_hda_query_supported_pcm */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002195 { 8000, SNDRV_PCM_RATE_8000, 0x0500 }, /* 1/6 x 48 */
2196 { 11025, SNDRV_PCM_RATE_11025, 0x4300 }, /* 1/4 x 44 */
2197 { 16000, SNDRV_PCM_RATE_16000, 0x0200 }, /* 1/3 x 48 */
2198 { 22050, SNDRV_PCM_RATE_22050, 0x4100 }, /* 1/2 x 44 */
2199 { 32000, SNDRV_PCM_RATE_32000, 0x0a00 }, /* 2/3 x 48 */
2200 { 44100, SNDRV_PCM_RATE_44100, 0x4000 }, /* 44 */
2201 { 48000, SNDRV_PCM_RATE_48000, 0x0000 }, /* 48 */
2202 { 88200, SNDRV_PCM_RATE_88200, 0x4800 }, /* 2 x 44 */
2203 { 96000, SNDRV_PCM_RATE_96000, 0x0800 }, /* 2 x 48 */
2204 { 176400, SNDRV_PCM_RATE_176400, 0x5800 },/* 4 x 44 */
2205 { 192000, SNDRV_PCM_RATE_192000, 0x1800 }, /* 4 x 48 */
Takashi Iwaia961f9f2007-04-12 13:08:09 +02002206#define AC_PAR_PCM_RATE_BITS 11
2207 /* up to bits 10, 384kHZ isn't supported properly */
2208
2209 /* not autodetected value */
2210 { 9600, SNDRV_PCM_RATE_KNOT, 0x0400 }, /* 1/5 x 48 */
Nicolas Graziano9d8f53f2005-08-22 13:47:16 +02002211
Takashi Iwaibefdf312005-08-22 13:57:55 +02002212 { 0 } /* terminator */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002213};
2214
2215/**
2216 * snd_hda_calc_stream_format - calculate format bitset
2217 * @rate: the sample rate
2218 * @channels: the number of channels
2219 * @format: the PCM format (SNDRV_PCM_FORMAT_XXX)
2220 * @maxbps: the max. bps
2221 *
2222 * Calculate the format bitset from the given rate, channels and th PCM format.
2223 *
2224 * Return zero if invalid.
2225 */
2226unsigned int snd_hda_calc_stream_format(unsigned int rate,
2227 unsigned int channels,
2228 unsigned int format,
2229 unsigned int maxbps)
2230{
2231 int i;
2232 unsigned int val = 0;
2233
Takashi Iwaibefdf312005-08-22 13:57:55 +02002234 for (i = 0; rate_bits[i].hz; i++)
2235 if (rate_bits[i].hz == rate) {
2236 val = rate_bits[i].hda_fmt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002237 break;
2238 }
Takashi Iwai0ba21762007-04-16 11:29:14 +02002239 if (!rate_bits[i].hz) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002240 snd_printdd("invalid rate %d\n", rate);
2241 return 0;
2242 }
2243
2244 if (channels == 0 || channels > 8) {
2245 snd_printdd("invalid channels %d\n", channels);
2246 return 0;
2247 }
2248 val |= channels - 1;
2249
2250 switch (snd_pcm_format_width(format)) {
2251 case 8: val |= 0x00; break;
2252 case 16: val |= 0x10; break;
2253 case 20:
2254 case 24:
2255 case 32:
2256 if (maxbps >= 32)
2257 val |= 0x40;
2258 else if (maxbps >= 24)
2259 val |= 0x30;
2260 else
2261 val |= 0x20;
2262 break;
2263 default:
Takashi Iwai0ba21762007-04-16 11:29:14 +02002264 snd_printdd("invalid format width %d\n",
2265 snd_pcm_format_width(format));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002266 return 0;
2267 }
2268
2269 return val;
2270}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002271EXPORT_SYMBOL_HDA(snd_hda_calc_stream_format);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002272
2273/**
2274 * snd_hda_query_supported_pcm - query the supported PCM rates and formats
2275 * @codec: the HDA codec
2276 * @nid: NID to query
2277 * @ratesp: the pointer to store the detected rate bitflags
2278 * @formatsp: the pointer to store the detected formats
2279 * @bpsp: the pointer to store the detected format widths
2280 *
2281 * Queries the supported PCM rates and formats. The NULL @ratesp, @formatsp
2282 * or @bsps argument is ignored.
2283 *
2284 * Returns 0 if successful, otherwise a negative error code.
2285 */
Takashi Iwai986862bd2008-11-27 12:40:13 +01002286static int snd_hda_query_supported_pcm(struct hda_codec *codec, hda_nid_t nid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002287 u32 *ratesp, u64 *formatsp, unsigned int *bpsp)
2288{
2289 int i;
2290 unsigned int val, streams;
2291
2292 val = 0;
2293 if (nid != codec->afg &&
Takashi Iwai54d17402005-11-21 16:33:22 +01002294 (get_wcaps(codec, nid) & AC_WCAP_FORMAT_OVRD)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002295 val = snd_hda_param_read(codec, nid, AC_PAR_PCM);
2296 if (val == -1)
2297 return -EIO;
2298 }
Takashi Iwai0ba21762007-04-16 11:29:14 +02002299 if (!val)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002300 val = snd_hda_param_read(codec, codec->afg, AC_PAR_PCM);
2301
2302 if (ratesp) {
2303 u32 rates = 0;
Takashi Iwaia961f9f2007-04-12 13:08:09 +02002304 for (i = 0; i < AC_PAR_PCM_RATE_BITS; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002305 if (val & (1 << i))
Takashi Iwaibefdf312005-08-22 13:57:55 +02002306 rates |= rate_bits[i].alsa_bits;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002307 }
2308 *ratesp = rates;
2309 }
2310
2311 if (formatsp || bpsp) {
2312 u64 formats = 0;
2313 unsigned int bps;
2314 unsigned int wcaps;
2315
Takashi Iwai54d17402005-11-21 16:33:22 +01002316 wcaps = get_wcaps(codec, nid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002317 streams = snd_hda_param_read(codec, nid, AC_PAR_STREAM);
2318 if (streams == -1)
2319 return -EIO;
Takashi Iwai0ba21762007-04-16 11:29:14 +02002320 if (!streams) {
2321 streams = snd_hda_param_read(codec, codec->afg,
2322 AC_PAR_STREAM);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002323 if (streams == -1)
2324 return -EIO;
2325 }
2326
2327 bps = 0;
2328 if (streams & AC_SUPFMT_PCM) {
2329 if (val & AC_SUPPCM_BITS_8) {
2330 formats |= SNDRV_PCM_FMTBIT_U8;
2331 bps = 8;
2332 }
2333 if (val & AC_SUPPCM_BITS_16) {
2334 formats |= SNDRV_PCM_FMTBIT_S16_LE;
2335 bps = 16;
2336 }
2337 if (wcaps & AC_WCAP_DIGITAL) {
2338 if (val & AC_SUPPCM_BITS_32)
2339 formats |= SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_LE;
2340 if (val & (AC_SUPPCM_BITS_20|AC_SUPPCM_BITS_24))
2341 formats |= SNDRV_PCM_FMTBIT_S32_LE;
2342 if (val & AC_SUPPCM_BITS_24)
2343 bps = 24;
2344 else if (val & AC_SUPPCM_BITS_20)
2345 bps = 20;
Takashi Iwai0ba21762007-04-16 11:29:14 +02002346 } else if (val & (AC_SUPPCM_BITS_20|AC_SUPPCM_BITS_24|
2347 AC_SUPPCM_BITS_32)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002348 formats |= SNDRV_PCM_FMTBIT_S32_LE;
2349 if (val & AC_SUPPCM_BITS_32)
2350 bps = 32;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002351 else if (val & AC_SUPPCM_BITS_24)
2352 bps = 24;
Nicolas Graziano33ef76512006-09-19 14:23:14 +02002353 else if (val & AC_SUPPCM_BITS_20)
2354 bps = 20;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002355 }
2356 }
Takashi Iwai0ba21762007-04-16 11:29:14 +02002357 else if (streams == AC_SUPFMT_FLOAT32) {
2358 /* should be exclusive */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002359 formats |= SNDRV_PCM_FMTBIT_FLOAT_LE;
2360 bps = 32;
Takashi Iwai0ba21762007-04-16 11:29:14 +02002361 } else if (streams == AC_SUPFMT_AC3) {
2362 /* should be exclusive */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002363 /* temporary hack: we have still no proper support
2364 * for the direct AC3 stream...
2365 */
2366 formats |= SNDRV_PCM_FMTBIT_U8;
2367 bps = 8;
2368 }
2369 if (formatsp)
2370 *formatsp = formats;
2371 if (bpsp)
2372 *bpsp = bps;
2373 }
2374
2375 return 0;
2376}
2377
2378/**
Takashi Iwai0ba21762007-04-16 11:29:14 +02002379 * snd_hda_is_supported_format - check whether the given node supports
2380 * the format val
Linus Torvalds1da177e2005-04-16 15:20:36 -07002381 *
2382 * Returns 1 if supported, 0 if not.
2383 */
2384int snd_hda_is_supported_format(struct hda_codec *codec, hda_nid_t nid,
2385 unsigned int format)
2386{
2387 int i;
2388 unsigned int val = 0, rate, stream;
2389
2390 if (nid != codec->afg &&
Takashi Iwai54d17402005-11-21 16:33:22 +01002391 (get_wcaps(codec, nid) & AC_WCAP_FORMAT_OVRD)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002392 val = snd_hda_param_read(codec, nid, AC_PAR_PCM);
2393 if (val == -1)
2394 return 0;
2395 }
Takashi Iwai0ba21762007-04-16 11:29:14 +02002396 if (!val) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002397 val = snd_hda_param_read(codec, codec->afg, AC_PAR_PCM);
2398 if (val == -1)
2399 return 0;
2400 }
2401
2402 rate = format & 0xff00;
Takashi Iwaia961f9f2007-04-12 13:08:09 +02002403 for (i = 0; i < AC_PAR_PCM_RATE_BITS; i++)
Takashi Iwaibefdf312005-08-22 13:57:55 +02002404 if (rate_bits[i].hda_fmt == rate) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002405 if (val & (1 << i))
2406 break;
2407 return 0;
2408 }
Takashi Iwaia961f9f2007-04-12 13:08:09 +02002409 if (i >= AC_PAR_PCM_RATE_BITS)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002410 return 0;
2411
2412 stream = snd_hda_param_read(codec, nid, AC_PAR_STREAM);
2413 if (stream == -1)
2414 return 0;
Takashi Iwai0ba21762007-04-16 11:29:14 +02002415 if (!stream && nid != codec->afg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002416 stream = snd_hda_param_read(codec, codec->afg, AC_PAR_STREAM);
Takashi Iwai0ba21762007-04-16 11:29:14 +02002417 if (!stream || stream == -1)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002418 return 0;
2419
2420 if (stream & AC_SUPFMT_PCM) {
2421 switch (format & 0xf0) {
2422 case 0x00:
Takashi Iwai0ba21762007-04-16 11:29:14 +02002423 if (!(val & AC_SUPPCM_BITS_8))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002424 return 0;
2425 break;
2426 case 0x10:
Takashi Iwai0ba21762007-04-16 11:29:14 +02002427 if (!(val & AC_SUPPCM_BITS_16))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002428 return 0;
2429 break;
2430 case 0x20:
Takashi Iwai0ba21762007-04-16 11:29:14 +02002431 if (!(val & AC_SUPPCM_BITS_20))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002432 return 0;
2433 break;
2434 case 0x30:
Takashi Iwai0ba21762007-04-16 11:29:14 +02002435 if (!(val & AC_SUPPCM_BITS_24))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002436 return 0;
2437 break;
2438 case 0x40:
Takashi Iwai0ba21762007-04-16 11:29:14 +02002439 if (!(val & AC_SUPPCM_BITS_32))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002440 return 0;
2441 break;
2442 default:
2443 return 0;
2444 }
2445 } else {
2446 /* FIXME: check for float32 and AC3? */
2447 }
2448
2449 return 1;
2450}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002451EXPORT_SYMBOL_HDA(snd_hda_is_supported_format);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002452
2453/*
2454 * PCM stuff
2455 */
2456static int hda_pcm_default_open_close(struct hda_pcm_stream *hinfo,
2457 struct hda_codec *codec,
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01002458 struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002459{
2460 return 0;
2461}
2462
2463static int hda_pcm_default_prepare(struct hda_pcm_stream *hinfo,
2464 struct hda_codec *codec,
2465 unsigned int stream_tag,
2466 unsigned int format,
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01002467 struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002468{
2469 snd_hda_codec_setup_stream(codec, hinfo->nid, stream_tag, 0, format);
2470 return 0;
2471}
2472
2473static int hda_pcm_default_cleanup(struct hda_pcm_stream *hinfo,
2474 struct hda_codec *codec,
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01002475 struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002476{
Takashi Iwai888afa12008-03-18 09:57:50 +01002477 snd_hda_codec_cleanup_stream(codec, hinfo->nid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002478 return 0;
2479}
2480
Takashi Iwai6c1f45e2008-07-30 15:01:45 +02002481static int set_pcm_default_values(struct hda_codec *codec,
2482 struct hda_pcm_stream *info)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002483{
Takashi Iwai0ba21762007-04-16 11:29:14 +02002484 /* query support PCM information from the given NID */
2485 if (info->nid && (!info->rates || !info->formats)) {
2486 snd_hda_query_supported_pcm(codec, info->nid,
2487 info->rates ? NULL : &info->rates,
2488 info->formats ? NULL : &info->formats,
2489 info->maxbps ? NULL : &info->maxbps);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002490 }
2491 if (info->ops.open == NULL)
2492 info->ops.open = hda_pcm_default_open_close;
2493 if (info->ops.close == NULL)
2494 info->ops.close = hda_pcm_default_open_close;
2495 if (info->ops.prepare == NULL) {
Takashi Iwaida3cec32008-08-08 17:12:14 +02002496 if (snd_BUG_ON(!info->nid))
2497 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002498 info->ops.prepare = hda_pcm_default_prepare;
2499 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002500 if (info->ops.cleanup == NULL) {
Takashi Iwaida3cec32008-08-08 17:12:14 +02002501 if (snd_BUG_ON(!info->nid))
2502 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002503 info->ops.cleanup = hda_pcm_default_cleanup;
2504 }
2505 return 0;
2506}
2507
Takashi Iwai176d5332008-07-30 15:01:44 +02002508/*
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002509 * get the empty PCM device number to assign
2510 */
2511static int get_empty_pcm_device(struct hda_bus *bus, int type)
2512{
2513 static const char *dev_name[HDA_PCM_NTYPES] = {
2514 "Audio", "SPDIF", "HDMI", "Modem"
2515 };
2516 /* starting device index for each PCM type */
2517 static int dev_idx[HDA_PCM_NTYPES] = {
2518 [HDA_PCM_TYPE_AUDIO] = 0,
2519 [HDA_PCM_TYPE_SPDIF] = 1,
2520 [HDA_PCM_TYPE_HDMI] = 3,
2521 [HDA_PCM_TYPE_MODEM] = 6
2522 };
2523 /* normal audio device indices; not linear to keep compatibility */
2524 static int audio_idx[4] = { 0, 2, 4, 5 };
2525 int i, dev;
2526
2527 switch (type) {
2528 case HDA_PCM_TYPE_AUDIO:
2529 for (i = 0; i < ARRAY_SIZE(audio_idx); i++) {
2530 dev = audio_idx[i];
2531 if (!test_bit(dev, bus->pcm_dev_bits))
2532 break;
2533 }
2534 if (i >= ARRAY_SIZE(audio_idx)) {
2535 snd_printk(KERN_WARNING "Too many audio devices\n");
2536 return -EAGAIN;
2537 }
2538 break;
2539 case HDA_PCM_TYPE_SPDIF:
2540 case HDA_PCM_TYPE_HDMI:
2541 case HDA_PCM_TYPE_MODEM:
2542 dev = dev_idx[type];
2543 if (test_bit(dev, bus->pcm_dev_bits)) {
2544 snd_printk(KERN_WARNING "%s already defined\n",
2545 dev_name[type]);
2546 return -EAGAIN;
2547 }
2548 break;
2549 default:
2550 snd_printk(KERN_WARNING "Invalid PCM type %d\n", type);
2551 return -EINVAL;
2552 }
2553 set_bit(dev, bus->pcm_dev_bits);
2554 return dev;
2555}
2556
2557/*
Takashi Iwai176d5332008-07-30 15:01:44 +02002558 * attach a new PCM stream
2559 */
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002560static int snd_hda_attach_pcm(struct hda_codec *codec, struct hda_pcm *pcm)
Takashi Iwai176d5332008-07-30 15:01:44 +02002561{
Takashi Iwai33fa35e2008-11-06 16:50:40 +01002562 struct hda_bus *bus = codec->bus;
Takashi Iwai176d5332008-07-30 15:01:44 +02002563 struct hda_pcm_stream *info;
2564 int stream, err;
2565
Takashi Iwaib91f0802008-11-04 08:43:08 +01002566 if (snd_BUG_ON(!pcm->name))
Takashi Iwai176d5332008-07-30 15:01:44 +02002567 return -EINVAL;
2568 for (stream = 0; stream < 2; stream++) {
2569 info = &pcm->stream[stream];
2570 if (info->substreams) {
2571 err = set_pcm_default_values(codec, info);
2572 if (err < 0)
2573 return err;
2574 }
2575 }
Takashi Iwai33fa35e2008-11-06 16:50:40 +01002576 return bus->ops.attach_pcm(bus, codec, pcm);
Takashi Iwai176d5332008-07-30 15:01:44 +02002577}
2578
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002579/* assign all PCMs of the given codec */
2580int snd_hda_codec_build_pcms(struct hda_codec *codec)
2581{
2582 unsigned int pcm;
2583 int err;
2584
2585 if (!codec->num_pcms) {
2586 if (!codec->patch_ops.build_pcms)
2587 return 0;
2588 err = codec->patch_ops.build_pcms(codec);
2589 if (err < 0)
2590 return err;
2591 }
2592 for (pcm = 0; pcm < codec->num_pcms; pcm++) {
2593 struct hda_pcm *cpcm = &codec->pcm_info[pcm];
2594 int dev;
2595
2596 if (!cpcm->stream[0].substreams && !cpcm->stream[1].substreams)
2597 return 0; /* no substreams assigned */
2598
2599 if (!cpcm->pcm) {
2600 dev = get_empty_pcm_device(codec->bus, cpcm->pcm_type);
2601 if (dev < 0)
2602 return 0;
2603 cpcm->device = dev;
2604 err = snd_hda_attach_pcm(codec, cpcm);
2605 if (err < 0)
2606 return err;
2607 }
2608 }
2609 return 0;
2610}
2611
Linus Torvalds1da177e2005-04-16 15:20:36 -07002612/**
2613 * snd_hda_build_pcms - build PCM information
2614 * @bus: the BUS
2615 *
2616 * Create PCM information for each codec included in the bus.
2617 *
2618 * The build_pcms codec patch is requested to set up codec->num_pcms and
2619 * codec->pcm_info properly. The array is referred by the top-level driver
2620 * to create its PCM instances.
2621 * The allocated codec->pcm_info should be released in codec->patch_ops.free
2622 * callback.
2623 *
2624 * At least, substreams, channels_min and channels_max must be filled for
2625 * each stream. substreams = 0 indicates that the stream doesn't exist.
2626 * When rates and/or formats are zero, the supported values are queried
2627 * from the given nid. The nid is used also by the default ops.prepare
2628 * and ops.cleanup callbacks.
2629 *
2630 * The driver needs to call ops.open in its open callback. Similarly,
2631 * ops.close is supposed to be called in the close callback.
2632 * ops.prepare should be called in the prepare or hw_params callback
2633 * with the proper parameters for set up.
2634 * ops.cleanup should be called in hw_free for clean up of streams.
2635 *
2636 * This function returns 0 if successfull, or a negative error code.
2637 */
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002638int __devinit snd_hda_build_pcms(struct hda_bus *bus)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002639{
Takashi Iwai0ba21762007-04-16 11:29:14 +02002640 struct hda_codec *codec;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002641
Takashi Iwai0ba21762007-04-16 11:29:14 +02002642 list_for_each_entry(codec, &bus->codec_list, list) {
Takashi Iwai529bd6c2008-11-27 14:17:01 +01002643 int err = snd_hda_codec_build_pcms(codec);
2644 if (err < 0)
2645 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002646 }
2647 return 0;
2648}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002649EXPORT_SYMBOL_HDA(snd_hda_build_pcms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002650
Linus Torvalds1da177e2005-04-16 15:20:36 -07002651/**
2652 * snd_hda_check_board_config - compare the current codec with the config table
2653 * @codec: the HDA codec
Takashi Iwaif5fcc132006-11-24 17:07:44 +01002654 * @num_configs: number of config enums
2655 * @models: array of model name strings
Linus Torvalds1da177e2005-04-16 15:20:36 -07002656 * @tbl: configuration table, terminated by null entries
2657 *
2658 * Compares the modelname or PCI subsystem id of the current codec with the
2659 * given configuration table. If a matching entry is found, returns its
2660 * config value (supposed to be 0 or positive).
2661 *
2662 * If no entries are matching, the function returns a negative value.
2663 */
Takashi Iwai12f288b2007-08-02 15:51:59 +02002664int snd_hda_check_board_config(struct hda_codec *codec,
2665 int num_configs, const char **models,
2666 const struct snd_pci_quirk *tbl)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002667{
Takashi Iwaif44ac832008-07-30 15:01:45 +02002668 if (codec->modelname && models) {
Takashi Iwaif5fcc132006-11-24 17:07:44 +01002669 int i;
2670 for (i = 0; i < num_configs; i++) {
2671 if (models[i] &&
Takashi Iwaif44ac832008-07-30 15:01:45 +02002672 !strcmp(codec->modelname, models[i])) {
Takashi Iwaif5fcc132006-11-24 17:07:44 +01002673 snd_printd(KERN_INFO "hda_codec: model '%s' is "
2674 "selected\n", models[i]);
2675 return i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002676 }
2677 }
2678 }
2679
Takashi Iwaif5fcc132006-11-24 17:07:44 +01002680 if (!codec->bus->pci || !tbl)
2681 return -1;
2682
2683 tbl = snd_pci_quirk_lookup(codec->bus->pci, tbl);
2684 if (!tbl)
2685 return -1;
2686 if (tbl->value >= 0 && tbl->value < num_configs) {
Takashi Iwai62cf8722008-05-20 12:15:15 +02002687#ifdef CONFIG_SND_DEBUG_VERBOSE
Takashi Iwaif5fcc132006-11-24 17:07:44 +01002688 char tmp[10];
2689 const char *model = NULL;
2690 if (models)
2691 model = models[tbl->value];
2692 if (!model) {
2693 sprintf(tmp, "#%d", tbl->value);
2694 model = tmp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002695 }
Takashi Iwaif5fcc132006-11-24 17:07:44 +01002696 snd_printdd(KERN_INFO "hda_codec: model '%s' is selected "
2697 "for config %x:%x (%s)\n",
2698 model, tbl->subvendor, tbl->subdevice,
2699 (tbl->name ? tbl->name : "Unknown device"));
2700#endif
2701 return tbl->value;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002702 }
2703 return -1;
2704}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002705EXPORT_SYMBOL_HDA(snd_hda_check_board_config);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002706
2707/**
Mauro Carvalho Chehab2eda3442008-08-11 10:18:39 +02002708 * snd_hda_check_board_codec_sid_config - compare the current codec
2709 subsystem ID with the
2710 config table
2711
2712 This is important for Gateway notebooks with SB450 HDA Audio
2713 where the vendor ID of the PCI device is:
2714 ATI Technologies Inc SB450 HDA Audio [1002:437b]
2715 and the vendor/subvendor are found only at the codec.
2716
2717 * @codec: the HDA codec
2718 * @num_configs: number of config enums
2719 * @models: array of model name strings
2720 * @tbl: configuration table, terminated by null entries
2721 *
2722 * Compares the modelname or PCI subsystem id of the current codec with the
2723 * given configuration table. If a matching entry is found, returns its
2724 * config value (supposed to be 0 or positive).
2725 *
2726 * If no entries are matching, the function returns a negative value.
2727 */
2728int snd_hda_check_board_codec_sid_config(struct hda_codec *codec,
2729 int num_configs, const char **models,
2730 const struct snd_pci_quirk *tbl)
2731{
2732 const struct snd_pci_quirk *q;
2733
2734 /* Search for codec ID */
2735 for (q = tbl; q->subvendor; q++) {
2736 unsigned long vendorid = (q->subdevice) | (q->subvendor << 16);
2737
2738 if (vendorid == codec->subsystem_id)
2739 break;
2740 }
2741
2742 if (!q->subvendor)
2743 return -1;
2744
2745 tbl = q;
2746
2747 if (tbl->value >= 0 && tbl->value < num_configs) {
2748#ifdef CONFIG_SND_DEBUG_DETECT
2749 char tmp[10];
2750 const char *model = NULL;
2751 if (models)
2752 model = models[tbl->value];
2753 if (!model) {
2754 sprintf(tmp, "#%d", tbl->value);
2755 model = tmp;
2756 }
2757 snd_printdd(KERN_INFO "hda_codec: model '%s' is selected "
2758 "for config %x:%x (%s)\n",
2759 model, tbl->subvendor, tbl->subdevice,
2760 (tbl->name ? tbl->name : "Unknown device"));
2761#endif
2762 return tbl->value;
2763 }
2764 return -1;
2765}
2766EXPORT_SYMBOL_HDA(snd_hda_check_board_codec_sid_config);
2767
2768/**
Linus Torvalds1da177e2005-04-16 15:20:36 -07002769 * snd_hda_add_new_ctls - create controls from the array
2770 * @codec: the HDA codec
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01002771 * @knew: the array of struct snd_kcontrol_new
Linus Torvalds1da177e2005-04-16 15:20:36 -07002772 *
2773 * This helper function creates and add new controls in the given array.
2774 * The array must be terminated with an empty entry as terminator.
2775 *
2776 * Returns 0 if successful, or a negative error code.
2777 */
Takashi Iwai12f288b2007-08-02 15:51:59 +02002778int snd_hda_add_new_ctls(struct hda_codec *codec, struct snd_kcontrol_new *knew)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002779{
Takashi Iwaicb53c622007-08-10 17:21:45 +02002780 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002781
2782 for (; knew->name; knew++) {
Takashi Iwai54d17402005-11-21 16:33:22 +01002783 struct snd_kcontrol *kctl;
2784 kctl = snd_ctl_new1(knew, codec);
Takashi Iwai0ba21762007-04-16 11:29:14 +02002785 if (!kctl)
Takashi Iwai54d17402005-11-21 16:33:22 +01002786 return -ENOMEM;
Takashi Iwaid13bd412008-07-30 15:01:45 +02002787 err = snd_hda_ctl_add(codec, kctl);
Takashi Iwai54d17402005-11-21 16:33:22 +01002788 if (err < 0) {
Takashi Iwai0ba21762007-04-16 11:29:14 +02002789 if (!codec->addr)
Takashi Iwai54d17402005-11-21 16:33:22 +01002790 return err;
2791 kctl = snd_ctl_new1(knew, codec);
Takashi Iwai0ba21762007-04-16 11:29:14 +02002792 if (!kctl)
Takashi Iwai54d17402005-11-21 16:33:22 +01002793 return -ENOMEM;
2794 kctl->id.device = codec->addr;
Takashi Iwaid13bd412008-07-30 15:01:45 +02002795 err = snd_hda_ctl_add(codec, kctl);
Takashi Iwai0ba21762007-04-16 11:29:14 +02002796 if (err < 0)
Takashi Iwai54d17402005-11-21 16:33:22 +01002797 return err;
2798 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002799 }
2800 return 0;
2801}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002802EXPORT_SYMBOL_HDA(snd_hda_add_new_ctls);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002803
Takashi Iwaicb53c622007-08-10 17:21:45 +02002804#ifdef CONFIG_SND_HDA_POWER_SAVE
2805static void hda_set_power_state(struct hda_codec *codec, hda_nid_t fg,
2806 unsigned int power_state);
2807
2808static void hda_power_work(struct work_struct *work)
2809{
2810 struct hda_codec *codec =
2811 container_of(work, struct hda_codec, power_work.work);
Takashi Iwai33fa35e2008-11-06 16:50:40 +01002812 struct hda_bus *bus = codec->bus;
Takashi Iwaicb53c622007-08-10 17:21:45 +02002813
Maxim Levitsky2e492462007-09-03 15:26:57 +02002814 if (!codec->power_on || codec->power_count) {
2815 codec->power_transition = 0;
Takashi Iwaicb53c622007-08-10 17:21:45 +02002816 return;
Maxim Levitsky2e492462007-09-03 15:26:57 +02002817 }
Takashi Iwaicb53c622007-08-10 17:21:45 +02002818
2819 hda_call_codec_suspend(codec);
Takashi Iwai33fa35e2008-11-06 16:50:40 +01002820 if (bus->ops.pm_notify)
2821 bus->ops.pm_notify(bus);
Takashi Iwaicb53c622007-08-10 17:21:45 +02002822}
2823
2824static void hda_keep_power_on(struct hda_codec *codec)
2825{
2826 codec->power_count++;
2827 codec->power_on = 1;
2828}
2829
2830void snd_hda_power_up(struct hda_codec *codec)
2831{
Takashi Iwai33fa35e2008-11-06 16:50:40 +01002832 struct hda_bus *bus = codec->bus;
2833
Takashi Iwaicb53c622007-08-10 17:21:45 +02002834 codec->power_count++;
Takashi Iwaia221e282007-08-16 16:35:33 +02002835 if (codec->power_on || codec->power_transition)
Takashi Iwaicb53c622007-08-10 17:21:45 +02002836 return;
2837
2838 codec->power_on = 1;
Takashi Iwai33fa35e2008-11-06 16:50:40 +01002839 if (bus->ops.pm_notify)
2840 bus->ops.pm_notify(bus);
Takashi Iwaicb53c622007-08-10 17:21:45 +02002841 hda_call_codec_resume(codec);
2842 cancel_delayed_work(&codec->power_work);
Takashi Iwaia221e282007-08-16 16:35:33 +02002843 codec->power_transition = 0;
Takashi Iwaicb53c622007-08-10 17:21:45 +02002844}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002845EXPORT_SYMBOL_HDA(snd_hda_power_up);
Takashi Iwai1289e9e2008-11-27 15:47:11 +01002846
2847#define power_save(codec) \
2848 ((codec)->bus->power_save ? *(codec)->bus->power_save : 0)
Takashi Iwaicb53c622007-08-10 17:21:45 +02002849
Takashi Iwaifee2fba2008-11-27 12:43:28 +01002850#define power_save(codec) \
2851 ((codec)->bus->power_save ? *(codec)->bus->power_save : 0)
2852
Takashi Iwaicb53c622007-08-10 17:21:45 +02002853void snd_hda_power_down(struct hda_codec *codec)
2854{
2855 --codec->power_count;
Takashi Iwaia221e282007-08-16 16:35:33 +02002856 if (!codec->power_on || codec->power_count || codec->power_transition)
Takashi Iwaicb53c622007-08-10 17:21:45 +02002857 return;
Takashi Iwaifee2fba2008-11-27 12:43:28 +01002858 if (power_save(codec)) {
Takashi Iwaia221e282007-08-16 16:35:33 +02002859 codec->power_transition = 1; /* avoid reentrance */
Takashi Iwaicb53c622007-08-10 17:21:45 +02002860 schedule_delayed_work(&codec->power_work,
Takashi Iwaifee2fba2008-11-27 12:43:28 +01002861 msecs_to_jiffies(power_save(codec) * 1000));
Takashi Iwaia221e282007-08-16 16:35:33 +02002862 }
Takashi Iwaicb53c622007-08-10 17:21:45 +02002863}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002864EXPORT_SYMBOL_HDA(snd_hda_power_down);
Takashi Iwaicb53c622007-08-10 17:21:45 +02002865
2866int snd_hda_check_amp_list_power(struct hda_codec *codec,
2867 struct hda_loopback_check *check,
2868 hda_nid_t nid)
2869{
2870 struct hda_amp_list *p;
2871 int ch, v;
2872
2873 if (!check->amplist)
2874 return 0;
2875 for (p = check->amplist; p->nid; p++) {
2876 if (p->nid == nid)
2877 break;
2878 }
2879 if (!p->nid)
2880 return 0; /* nothing changed */
2881
2882 for (p = check->amplist; p->nid; p++) {
2883 for (ch = 0; ch < 2; ch++) {
2884 v = snd_hda_codec_amp_read(codec, p->nid, ch, p->dir,
2885 p->idx);
2886 if (!(v & HDA_AMP_MUTE) && v > 0) {
2887 if (!check->power_on) {
2888 check->power_on = 1;
2889 snd_hda_power_up(codec);
2890 }
2891 return 1;
2892 }
2893 }
2894 }
2895 if (check->power_on) {
2896 check->power_on = 0;
2897 snd_hda_power_down(codec);
2898 }
2899 return 0;
2900}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002901EXPORT_SYMBOL_HDA(snd_hda_check_amp_list_power);
Takashi Iwaicb53c622007-08-10 17:21:45 +02002902#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07002903
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01002904/*
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01002905 * Channel mode helper
2906 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02002907int snd_hda_ch_mode_info(struct hda_codec *codec,
2908 struct snd_ctl_elem_info *uinfo,
2909 const struct hda_channel_mode *chmode,
2910 int num_chmodes)
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01002911{
2912 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2913 uinfo->count = 1;
2914 uinfo->value.enumerated.items = num_chmodes;
2915 if (uinfo->value.enumerated.item >= num_chmodes)
2916 uinfo->value.enumerated.item = num_chmodes - 1;
2917 sprintf(uinfo->value.enumerated.name, "%dch",
2918 chmode[uinfo->value.enumerated.item].channels);
2919 return 0;
2920}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002921EXPORT_SYMBOL_HDA(snd_hda_ch_mode_info);
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01002922
Takashi Iwai0ba21762007-04-16 11:29:14 +02002923int snd_hda_ch_mode_get(struct hda_codec *codec,
2924 struct snd_ctl_elem_value *ucontrol,
2925 const struct hda_channel_mode *chmode,
2926 int num_chmodes,
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01002927 int max_channels)
2928{
2929 int i;
2930
2931 for (i = 0; i < num_chmodes; i++) {
2932 if (max_channels == chmode[i].channels) {
2933 ucontrol->value.enumerated.item[0] = i;
2934 break;
2935 }
2936 }
2937 return 0;
2938}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002939EXPORT_SYMBOL_HDA(snd_hda_ch_mode_get);
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01002940
Takashi Iwai0ba21762007-04-16 11:29:14 +02002941int snd_hda_ch_mode_put(struct hda_codec *codec,
2942 struct snd_ctl_elem_value *ucontrol,
2943 const struct hda_channel_mode *chmode,
2944 int num_chmodes,
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01002945 int *max_channelsp)
2946{
2947 unsigned int mode;
2948
2949 mode = ucontrol->value.enumerated.item[0];
Takashi Iwai68ea7b22007-11-15 15:54:38 +01002950 if (mode >= num_chmodes)
2951 return -EINVAL;
Takashi Iwai82beb8f2007-08-10 17:09:26 +02002952 if (*max_channelsp == chmode[mode].channels)
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01002953 return 0;
2954 /* change the current channel setting */
2955 *max_channelsp = chmode[mode].channels;
2956 if (chmode[mode].sequence)
Takashi Iwai82beb8f2007-08-10 17:09:26 +02002957 snd_hda_sequence_write_cache(codec, chmode[mode].sequence);
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01002958 return 1;
2959}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002960EXPORT_SYMBOL_HDA(snd_hda_ch_mode_put);
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01002961
Linus Torvalds1da177e2005-04-16 15:20:36 -07002962/*
2963 * input MUX helper
2964 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02002965int snd_hda_input_mux_info(const struct hda_input_mux *imux,
2966 struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002967{
2968 unsigned int index;
2969
2970 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2971 uinfo->count = 1;
2972 uinfo->value.enumerated.items = imux->num_items;
Takashi Iwai5513b0c2007-10-09 11:58:41 +02002973 if (!imux->num_items)
2974 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002975 index = uinfo->value.enumerated.item;
2976 if (index >= imux->num_items)
2977 index = imux->num_items - 1;
2978 strcpy(uinfo->value.enumerated.name, imux->items[index].label);
2979 return 0;
2980}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01002981EXPORT_SYMBOL_HDA(snd_hda_input_mux_info);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002982
Takashi Iwai0ba21762007-04-16 11:29:14 +02002983int snd_hda_input_mux_put(struct hda_codec *codec,
2984 const struct hda_input_mux *imux,
2985 struct snd_ctl_elem_value *ucontrol,
2986 hda_nid_t nid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002987 unsigned int *cur_val)
2988{
2989 unsigned int idx;
2990
Takashi Iwai5513b0c2007-10-09 11:58:41 +02002991 if (!imux->num_items)
2992 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002993 idx = ucontrol->value.enumerated.item[0];
2994 if (idx >= imux->num_items)
2995 idx = imux->num_items - 1;
Takashi Iwai82beb8f2007-08-10 17:09:26 +02002996 if (*cur_val == idx)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002997 return 0;
Takashi Iwai82beb8f2007-08-10 17:09:26 +02002998 snd_hda_codec_write_cache(codec, nid, 0, AC_VERB_SET_CONNECT_SEL,
2999 imux->items[idx].index);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003000 *cur_val = idx;
3001 return 1;
3002}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003003EXPORT_SYMBOL_HDA(snd_hda_input_mux_put);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003004
3005
3006/*
3007 * Multi-channel / digital-out PCM helper functions
3008 */
3009
Takashi Iwai6b97eb42007-04-05 14:51:48 +02003010/* setup SPDIF output stream */
3011static void setup_dig_out_stream(struct hda_codec *codec, hda_nid_t nid,
3012 unsigned int stream_tag, unsigned int format)
3013{
3014 /* turn off SPDIF once; otherwise the IEC958 bits won't be updated */
Takashi Iwai2f728532008-09-25 16:32:41 +02003015 if (codec->spdif_status_reset && (codec->spdif_ctls & AC_DIG1_ENABLE))
3016 set_dig_out_convert(codec, nid,
3017 codec->spdif_ctls & ~AC_DIG1_ENABLE & 0xff,
3018 -1);
Takashi Iwai6b97eb42007-04-05 14:51:48 +02003019 snd_hda_codec_setup_stream(codec, nid, stream_tag, 0, format);
Takashi Iwai2f728532008-09-25 16:32:41 +02003020 if (codec->slave_dig_outs) {
3021 hda_nid_t *d;
3022 for (d = codec->slave_dig_outs; *d; d++)
3023 snd_hda_codec_setup_stream(codec, *d, stream_tag, 0,
3024 format);
Matthew Ranostayde51ca12008-09-07 14:31:40 -04003025 }
Takashi Iwai2f728532008-09-25 16:32:41 +02003026 /* turn on again (if needed) */
3027 if (codec->spdif_status_reset && (codec->spdif_ctls & AC_DIG1_ENABLE))
3028 set_dig_out_convert(codec, nid,
3029 codec->spdif_ctls & 0xff, -1);
3030}
Matthew Ranostayde51ca12008-09-07 14:31:40 -04003031
Takashi Iwai2f728532008-09-25 16:32:41 +02003032static void cleanup_dig_out_stream(struct hda_codec *codec, hda_nid_t nid)
3033{
3034 snd_hda_codec_cleanup_stream(codec, nid);
3035 if (codec->slave_dig_outs) {
3036 hda_nid_t *d;
3037 for (d = codec->slave_dig_outs; *d; d++)
3038 snd_hda_codec_cleanup_stream(codec, *d);
3039 }
Takashi Iwai6b97eb42007-04-05 14:51:48 +02003040}
3041
Linus Torvalds1da177e2005-04-16 15:20:36 -07003042/*
3043 * open the digital out in the exclusive mode
3044 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003045int snd_hda_multi_out_dig_open(struct hda_codec *codec,
3046 struct hda_multi_out *mout)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003047{
Ingo Molnar62932df2006-01-16 16:34:20 +01003048 mutex_lock(&codec->spdif_mutex);
Takashi Iwai5930ca42007-04-16 11:23:56 +02003049 if (mout->dig_out_used == HDA_DIG_ANALOG_DUP)
3050 /* already opened as analog dup; reset it once */
Takashi Iwai2f728532008-09-25 16:32:41 +02003051 cleanup_dig_out_stream(codec, mout->dig_out_nid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003052 mout->dig_out_used = HDA_DIG_EXCLUSIVE;
Ingo Molnar62932df2006-01-16 16:34:20 +01003053 mutex_unlock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003054 return 0;
3055}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003056EXPORT_SYMBOL_HDA(snd_hda_multi_out_dig_open);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003057
Takashi Iwai6b97eb42007-04-05 14:51:48 +02003058int snd_hda_multi_out_dig_prepare(struct hda_codec *codec,
3059 struct hda_multi_out *mout,
3060 unsigned int stream_tag,
3061 unsigned int format,
3062 struct snd_pcm_substream *substream)
3063{
3064 mutex_lock(&codec->spdif_mutex);
3065 setup_dig_out_stream(codec, mout->dig_out_nid, stream_tag, format);
3066 mutex_unlock(&codec->spdif_mutex);
3067 return 0;
3068}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003069EXPORT_SYMBOL_HDA(snd_hda_multi_out_dig_prepare);
Takashi Iwai6b97eb42007-04-05 14:51:48 +02003070
Linus Torvalds1da177e2005-04-16 15:20:36 -07003071/*
3072 * release the digital out
3073 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003074int snd_hda_multi_out_dig_close(struct hda_codec *codec,
3075 struct hda_multi_out *mout)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003076{
Ingo Molnar62932df2006-01-16 16:34:20 +01003077 mutex_lock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003078 mout->dig_out_used = 0;
Ingo Molnar62932df2006-01-16 16:34:20 +01003079 mutex_unlock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003080 return 0;
3081}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003082EXPORT_SYMBOL_HDA(snd_hda_multi_out_dig_close);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003083
3084/*
3085 * set up more restrictions for analog out
3086 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003087int snd_hda_multi_out_analog_open(struct hda_codec *codec,
3088 struct hda_multi_out *mout,
Takashi Iwai9a081602008-02-12 18:37:26 +01003089 struct snd_pcm_substream *substream,
3090 struct hda_pcm_stream *hinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003091{
Takashi Iwai9a081602008-02-12 18:37:26 +01003092 struct snd_pcm_runtime *runtime = substream->runtime;
3093 runtime->hw.channels_max = mout->max_channels;
3094 if (mout->dig_out_nid) {
3095 if (!mout->analog_rates) {
3096 mout->analog_rates = hinfo->rates;
3097 mout->analog_formats = hinfo->formats;
3098 mout->analog_maxbps = hinfo->maxbps;
3099 } else {
3100 runtime->hw.rates = mout->analog_rates;
3101 runtime->hw.formats = mout->analog_formats;
3102 hinfo->maxbps = mout->analog_maxbps;
3103 }
3104 if (!mout->spdif_rates) {
3105 snd_hda_query_supported_pcm(codec, mout->dig_out_nid,
3106 &mout->spdif_rates,
3107 &mout->spdif_formats,
3108 &mout->spdif_maxbps);
3109 }
3110 mutex_lock(&codec->spdif_mutex);
3111 if (mout->share_spdif) {
3112 runtime->hw.rates &= mout->spdif_rates;
3113 runtime->hw.formats &= mout->spdif_formats;
3114 if (mout->spdif_maxbps < hinfo->maxbps)
3115 hinfo->maxbps = mout->spdif_maxbps;
3116 }
Frederik Deweerdteaa99852008-04-14 13:11:44 +02003117 mutex_unlock(&codec->spdif_mutex);
Takashi Iwai9a081602008-02-12 18:37:26 +01003118 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003119 return snd_pcm_hw_constraint_step(substream->runtime, 0,
3120 SNDRV_PCM_HW_PARAM_CHANNELS, 2);
3121}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003122EXPORT_SYMBOL_HDA(snd_hda_multi_out_analog_open);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003123
3124/*
3125 * set up the i/o for analog out
3126 * when the digital out is available, copy the front out to digital out, too.
3127 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003128int snd_hda_multi_out_analog_prepare(struct hda_codec *codec,
3129 struct hda_multi_out *mout,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003130 unsigned int stream_tag,
3131 unsigned int format,
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01003132 struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003133{
3134 hda_nid_t *nids = mout->dac_nids;
3135 int chs = substream->runtime->channels;
3136 int i;
3137
Ingo Molnar62932df2006-01-16 16:34:20 +01003138 mutex_lock(&codec->spdif_mutex);
Takashi Iwai9a081602008-02-12 18:37:26 +01003139 if (mout->dig_out_nid && mout->share_spdif &&
3140 mout->dig_out_used != HDA_DIG_EXCLUSIVE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003141 if (chs == 2 &&
Takashi Iwai0ba21762007-04-16 11:29:14 +02003142 snd_hda_is_supported_format(codec, mout->dig_out_nid,
3143 format) &&
3144 !(codec->spdif_status & IEC958_AES0_NONAUDIO)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003145 mout->dig_out_used = HDA_DIG_ANALOG_DUP;
Takashi Iwai6b97eb42007-04-05 14:51:48 +02003146 setup_dig_out_stream(codec, mout->dig_out_nid,
3147 stream_tag, format);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003148 } else {
3149 mout->dig_out_used = 0;
Takashi Iwai2f728532008-09-25 16:32:41 +02003150 cleanup_dig_out_stream(codec, mout->dig_out_nid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003151 }
3152 }
Ingo Molnar62932df2006-01-16 16:34:20 +01003153 mutex_unlock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003154
3155 /* front */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003156 snd_hda_codec_setup_stream(codec, nids[HDA_FRONT], stream_tag,
3157 0, format);
Takashi Iwaid29240c2007-10-26 12:35:56 +02003158 if (!mout->no_share_stream &&
3159 mout->hp_nid && mout->hp_nid != nids[HDA_FRONT])
Linus Torvalds1da177e2005-04-16 15:20:36 -07003160 /* headphone out will just decode front left/right (stereo) */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003161 snd_hda_codec_setup_stream(codec, mout->hp_nid, stream_tag,
3162 0, format);
Takashi Iwai82bc9552006-03-21 11:24:42 +01003163 /* extra outputs copied from front */
3164 for (i = 0; i < ARRAY_SIZE(mout->extra_out_nid); i++)
Takashi Iwaid29240c2007-10-26 12:35:56 +02003165 if (!mout->no_share_stream && mout->extra_out_nid[i])
Takashi Iwai82bc9552006-03-21 11:24:42 +01003166 snd_hda_codec_setup_stream(codec,
3167 mout->extra_out_nid[i],
3168 stream_tag, 0, format);
3169
Linus Torvalds1da177e2005-04-16 15:20:36 -07003170 /* surrounds */
3171 for (i = 1; i < mout->num_dacs; i++) {
Takashi Iwai4b3acaf2005-06-10 19:48:10 +02003172 if (chs >= (i + 1) * 2) /* independent out */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003173 snd_hda_codec_setup_stream(codec, nids[i], stream_tag,
3174 i * 2, format);
Takashi Iwaid29240c2007-10-26 12:35:56 +02003175 else if (!mout->no_share_stream) /* copy front */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003176 snd_hda_codec_setup_stream(codec, nids[i], stream_tag,
3177 0, format);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003178 }
3179 return 0;
3180}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003181EXPORT_SYMBOL_HDA(snd_hda_multi_out_analog_prepare);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003182
3183/*
3184 * clean up the setting for analog out
3185 */
Takashi Iwai0ba21762007-04-16 11:29:14 +02003186int snd_hda_multi_out_analog_cleanup(struct hda_codec *codec,
3187 struct hda_multi_out *mout)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003188{
3189 hda_nid_t *nids = mout->dac_nids;
3190 int i;
3191
3192 for (i = 0; i < mout->num_dacs; i++)
Takashi Iwai888afa12008-03-18 09:57:50 +01003193 snd_hda_codec_cleanup_stream(codec, nids[i]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003194 if (mout->hp_nid)
Takashi Iwai888afa12008-03-18 09:57:50 +01003195 snd_hda_codec_cleanup_stream(codec, mout->hp_nid);
Takashi Iwai82bc9552006-03-21 11:24:42 +01003196 for (i = 0; i < ARRAY_SIZE(mout->extra_out_nid); i++)
3197 if (mout->extra_out_nid[i])
Takashi Iwai888afa12008-03-18 09:57:50 +01003198 snd_hda_codec_cleanup_stream(codec,
3199 mout->extra_out_nid[i]);
Ingo Molnar62932df2006-01-16 16:34:20 +01003200 mutex_lock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003201 if (mout->dig_out_nid && mout->dig_out_used == HDA_DIG_ANALOG_DUP) {
Takashi Iwai2f728532008-09-25 16:32:41 +02003202 cleanup_dig_out_stream(codec, mout->dig_out_nid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003203 mout->dig_out_used = 0;
3204 }
Ingo Molnar62932df2006-01-16 16:34:20 +01003205 mutex_unlock(&codec->spdif_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003206 return 0;
3207}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003208EXPORT_SYMBOL_HDA(snd_hda_multi_out_analog_cleanup);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003209
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003210/*
Wu Fengguang6b345002008-10-07 14:21:41 +08003211 * Helper for automatic pin configuration
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003212 */
Kailang Yangdf694da2005-12-05 19:42:22 +01003213
Takashi Iwai12f288b2007-08-02 15:51:59 +02003214static int is_in_nid_list(hda_nid_t nid, hda_nid_t *list)
Kailang Yangdf694da2005-12-05 19:42:22 +01003215{
3216 for (; *list; list++)
3217 if (*list == nid)
3218 return 1;
3219 return 0;
3220}
3221
Steve Longerbeam81937d32007-05-08 15:33:03 +02003222
3223/*
3224 * Sort an associated group of pins according to their sequence numbers.
3225 */
3226static void sort_pins_by_sequence(hda_nid_t * pins, short * sequences,
3227 int num_pins)
3228{
3229 int i, j;
3230 short seq;
3231 hda_nid_t nid;
3232
3233 for (i = 0; i < num_pins; i++) {
3234 for (j = i + 1; j < num_pins; j++) {
3235 if (sequences[i] > sequences[j]) {
3236 seq = sequences[i];
3237 sequences[i] = sequences[j];
3238 sequences[j] = seq;
3239 nid = pins[i];
3240 pins[i] = pins[j];
3241 pins[j] = nid;
3242 }
3243 }
3244 }
3245}
3246
3247
Takashi Iwai82bc9552006-03-21 11:24:42 +01003248/*
3249 * Parse all pin widgets and store the useful pin nids to cfg
3250 *
3251 * The number of line-outs or any primary output is stored in line_outs,
3252 * and the corresponding output pins are assigned to line_out_pins[],
3253 * in the order of front, rear, CLFE, side, ...
3254 *
3255 * If more extra outputs (speaker and headphone) are found, the pins are
Takashi Iwaieb06ed82006-09-20 17:10:27 +02003256 * assisnged to hp_pins[] and speaker_pins[], respectively. If no line-out jack
Takashi Iwai82bc9552006-03-21 11:24:42 +01003257 * is detected, one of speaker of HP pins is assigned as the primary
3258 * output, i.e. to line_out_pins[0]. So, line_outs is always positive
3259 * if any analog output exists.
3260 *
3261 * The analog input pins are assigned to input_pins array.
3262 * The digital input/output pins are assigned to dig_in_pin and dig_out_pin,
3263 * respectively.
3264 */
Takashi Iwai12f288b2007-08-02 15:51:59 +02003265int snd_hda_parse_pin_def_config(struct hda_codec *codec,
3266 struct auto_pin_cfg *cfg,
3267 hda_nid_t *ignore_nids)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003268{
Takashi Iwai0ef6ce72008-01-22 15:35:37 +01003269 hda_nid_t nid, end_nid;
Steve Longerbeam81937d32007-05-08 15:33:03 +02003270 short seq, assoc_line_out, assoc_speaker;
3271 short sequences_line_out[ARRAY_SIZE(cfg->line_out_pins)];
3272 short sequences_speaker[ARRAY_SIZE(cfg->speaker_pins)];
Takashi Iwaif889fa92007-10-31 15:49:32 +01003273 short sequences_hp[ARRAY_SIZE(cfg->hp_pins)];
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003274
3275 memset(cfg, 0, sizeof(*cfg));
3276
Steve Longerbeam81937d32007-05-08 15:33:03 +02003277 memset(sequences_line_out, 0, sizeof(sequences_line_out));
3278 memset(sequences_speaker, 0, sizeof(sequences_speaker));
Takashi Iwaif889fa92007-10-31 15:49:32 +01003279 memset(sequences_hp, 0, sizeof(sequences_hp));
Steve Longerbeam81937d32007-05-08 15:33:03 +02003280 assoc_line_out = assoc_speaker = 0;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003281
Takashi Iwai0ef6ce72008-01-22 15:35:37 +01003282 end_nid = codec->start_nid + codec->num_nodes;
3283 for (nid = codec->start_nid; nid < end_nid; nid++) {
Takashi Iwai54d17402005-11-21 16:33:22 +01003284 unsigned int wid_caps = get_wcaps(codec, nid);
Takashi Iwai0ba21762007-04-16 11:29:14 +02003285 unsigned int wid_type =
3286 (wid_caps & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003287 unsigned int def_conf;
3288 short assoc, loc;
3289
3290 /* read all default configuration for pin complex */
3291 if (wid_type != AC_WID_PIN)
3292 continue;
Kailang Yangdf694da2005-12-05 19:42:22 +01003293 /* ignore the given nids (e.g. pc-beep returns error) */
3294 if (ignore_nids && is_in_nid_list(nid, ignore_nids))
3295 continue;
3296
Takashi Iwai0ba21762007-04-16 11:29:14 +02003297 def_conf = snd_hda_codec_read(codec, nid, 0,
3298 AC_VERB_GET_CONFIG_DEFAULT, 0);
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003299 if (get_defcfg_connect(def_conf) == AC_JACK_PORT_NONE)
3300 continue;
3301 loc = get_defcfg_location(def_conf);
3302 switch (get_defcfg_device(def_conf)) {
3303 case AC_JACK_LINE_OUT:
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003304 seq = get_defcfg_sequence(def_conf);
3305 assoc = get_defcfg_association(def_conf);
Matthew Ranostay90da78b2008-01-24 11:48:01 +01003306
3307 if (!(wid_caps & AC_WCAP_STEREO))
3308 if (!cfg->mono_out_pin)
3309 cfg->mono_out_pin = nid;
Takashi Iwai0ba21762007-04-16 11:29:14 +02003310 if (!assoc)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003311 continue;
Takashi Iwai0ba21762007-04-16 11:29:14 +02003312 if (!assoc_line_out)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003313 assoc_line_out = assoc;
3314 else if (assoc_line_out != assoc)
3315 continue;
3316 if (cfg->line_outs >= ARRAY_SIZE(cfg->line_out_pins))
3317 continue;
3318 cfg->line_out_pins[cfg->line_outs] = nid;
Steve Longerbeam81937d32007-05-08 15:33:03 +02003319 sequences_line_out[cfg->line_outs] = seq;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003320 cfg->line_outs++;
3321 break;
Takashi Iwai8d88bc32005-11-17 11:09:23 +01003322 case AC_JACK_SPEAKER:
Steve Longerbeam81937d32007-05-08 15:33:03 +02003323 seq = get_defcfg_sequence(def_conf);
3324 assoc = get_defcfg_association(def_conf);
3325 if (! assoc)
3326 continue;
3327 if (! assoc_speaker)
3328 assoc_speaker = assoc;
3329 else if (assoc_speaker != assoc)
3330 continue;
Takashi Iwai82bc9552006-03-21 11:24:42 +01003331 if (cfg->speaker_outs >= ARRAY_SIZE(cfg->speaker_pins))
3332 continue;
3333 cfg->speaker_pins[cfg->speaker_outs] = nid;
Steve Longerbeam81937d32007-05-08 15:33:03 +02003334 sequences_speaker[cfg->speaker_outs] = seq;
Takashi Iwai82bc9552006-03-21 11:24:42 +01003335 cfg->speaker_outs++;
Takashi Iwai8d88bc32005-11-17 11:09:23 +01003336 break;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003337 case AC_JACK_HP_OUT:
Takashi Iwaif889fa92007-10-31 15:49:32 +01003338 seq = get_defcfg_sequence(def_conf);
3339 assoc = get_defcfg_association(def_conf);
Takashi Iwaieb06ed82006-09-20 17:10:27 +02003340 if (cfg->hp_outs >= ARRAY_SIZE(cfg->hp_pins))
3341 continue;
3342 cfg->hp_pins[cfg->hp_outs] = nid;
Takashi Iwaif889fa92007-10-31 15:49:32 +01003343 sequences_hp[cfg->hp_outs] = (assoc << 4) | seq;
Takashi Iwaieb06ed82006-09-20 17:10:27 +02003344 cfg->hp_outs++;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003345 break;
Takashi Iwai314634b2006-09-21 11:56:18 +02003346 case AC_JACK_MIC_IN: {
3347 int preferred, alt;
3348 if (loc == AC_JACK_LOC_FRONT) {
3349 preferred = AUTO_PIN_FRONT_MIC;
3350 alt = AUTO_PIN_MIC;
3351 } else {
3352 preferred = AUTO_PIN_MIC;
3353 alt = AUTO_PIN_FRONT_MIC;
3354 }
3355 if (!cfg->input_pins[preferred])
3356 cfg->input_pins[preferred] = nid;
3357 else if (!cfg->input_pins[alt])
3358 cfg->input_pins[alt] = nid;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003359 break;
Takashi Iwai314634b2006-09-21 11:56:18 +02003360 }
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003361 case AC_JACK_LINE_IN:
3362 if (loc == AC_JACK_LOC_FRONT)
3363 cfg->input_pins[AUTO_PIN_FRONT_LINE] = nid;
3364 else
3365 cfg->input_pins[AUTO_PIN_LINE] = nid;
3366 break;
3367 case AC_JACK_CD:
3368 cfg->input_pins[AUTO_PIN_CD] = nid;
3369 break;
3370 case AC_JACK_AUX:
3371 cfg->input_pins[AUTO_PIN_AUX] = nid;
3372 break;
3373 case AC_JACK_SPDIF_OUT:
3374 cfg->dig_out_pin = nid;
3375 break;
3376 case AC_JACK_SPDIF_IN:
3377 cfg->dig_in_pin = nid;
3378 break;
3379 }
3380 }
3381
Takashi Iwai5832fcf2008-02-12 18:30:12 +01003382 /* FIX-UP:
3383 * If no line-out is defined but multiple HPs are found,
3384 * some of them might be the real line-outs.
3385 */
3386 if (!cfg->line_outs && cfg->hp_outs > 1) {
3387 int i = 0;
3388 while (i < cfg->hp_outs) {
3389 /* The real HPs should have the sequence 0x0f */
3390 if ((sequences_hp[i] & 0x0f) == 0x0f) {
3391 i++;
3392 continue;
3393 }
3394 /* Move it to the line-out table */
3395 cfg->line_out_pins[cfg->line_outs] = cfg->hp_pins[i];
3396 sequences_line_out[cfg->line_outs] = sequences_hp[i];
3397 cfg->line_outs++;
3398 cfg->hp_outs--;
3399 memmove(cfg->hp_pins + i, cfg->hp_pins + i + 1,
3400 sizeof(cfg->hp_pins[0]) * (cfg->hp_outs - i));
3401 memmove(sequences_hp + i - 1, sequences_hp + i,
3402 sizeof(sequences_hp[0]) * (cfg->hp_outs - i));
3403 }
3404 }
3405
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003406 /* sort by sequence */
Steve Longerbeam81937d32007-05-08 15:33:03 +02003407 sort_pins_by_sequence(cfg->line_out_pins, sequences_line_out,
3408 cfg->line_outs);
3409 sort_pins_by_sequence(cfg->speaker_pins, sequences_speaker,
3410 cfg->speaker_outs);
Takashi Iwaif889fa92007-10-31 15:49:32 +01003411 sort_pins_by_sequence(cfg->hp_pins, sequences_hp,
3412 cfg->hp_outs);
Steve Longerbeam81937d32007-05-08 15:33:03 +02003413
Takashi Iwaif889fa92007-10-31 15:49:32 +01003414 /* if we have only one mic, make it AUTO_PIN_MIC */
3415 if (!cfg->input_pins[AUTO_PIN_MIC] &&
3416 cfg->input_pins[AUTO_PIN_FRONT_MIC]) {
3417 cfg->input_pins[AUTO_PIN_MIC] =
3418 cfg->input_pins[AUTO_PIN_FRONT_MIC];
3419 cfg->input_pins[AUTO_PIN_FRONT_MIC] = 0;
3420 }
3421 /* ditto for line-in */
3422 if (!cfg->input_pins[AUTO_PIN_LINE] &&
3423 cfg->input_pins[AUTO_PIN_FRONT_LINE]) {
3424 cfg->input_pins[AUTO_PIN_LINE] =
3425 cfg->input_pins[AUTO_PIN_FRONT_LINE];
3426 cfg->input_pins[AUTO_PIN_FRONT_LINE] = 0;
3427 }
3428
Steve Longerbeam81937d32007-05-08 15:33:03 +02003429 /*
3430 * FIX-UP: if no line-outs are detected, try to use speaker or HP pin
3431 * as a primary output
3432 */
3433 if (!cfg->line_outs) {
3434 if (cfg->speaker_outs) {
3435 cfg->line_outs = cfg->speaker_outs;
3436 memcpy(cfg->line_out_pins, cfg->speaker_pins,
3437 sizeof(cfg->speaker_pins));
3438 cfg->speaker_outs = 0;
3439 memset(cfg->speaker_pins, 0, sizeof(cfg->speaker_pins));
3440 cfg->line_out_type = AUTO_PIN_SPEAKER_OUT;
3441 } else if (cfg->hp_outs) {
3442 cfg->line_outs = cfg->hp_outs;
3443 memcpy(cfg->line_out_pins, cfg->hp_pins,
3444 sizeof(cfg->hp_pins));
3445 cfg->hp_outs = 0;
3446 memset(cfg->hp_pins, 0, sizeof(cfg->hp_pins));
3447 cfg->line_out_type = AUTO_PIN_HP_OUT;
3448 }
3449 }
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003450
Takashi Iwaicb8e2f82005-07-29 11:54:32 +02003451 /* Reorder the surround channels
3452 * ALSA sequence is front/surr/clfe/side
3453 * HDA sequence is:
3454 * 4-ch: front/surr => OK as it is
3455 * 6-ch: front/clfe/surr
Takashi Iwai9422db42007-04-20 16:11:43 +02003456 * 8-ch: front/clfe/rear/side|fc
Takashi Iwaicb8e2f82005-07-29 11:54:32 +02003457 */
3458 switch (cfg->line_outs) {
3459 case 3:
Takashi Iwaicb8e2f82005-07-29 11:54:32 +02003460 case 4:
3461 nid = cfg->line_out_pins[1];
Takashi Iwai9422db42007-04-20 16:11:43 +02003462 cfg->line_out_pins[1] = cfg->line_out_pins[2];
Takashi Iwaicb8e2f82005-07-29 11:54:32 +02003463 cfg->line_out_pins[2] = nid;
3464 break;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003465 }
3466
Takashi Iwai82bc9552006-03-21 11:24:42 +01003467 /*
3468 * debug prints of the parsed results
3469 */
3470 snd_printd("autoconfig: line_outs=%d (0x%x/0x%x/0x%x/0x%x/0x%x)\n",
3471 cfg->line_outs, cfg->line_out_pins[0], cfg->line_out_pins[1],
3472 cfg->line_out_pins[2], cfg->line_out_pins[3],
3473 cfg->line_out_pins[4]);
3474 snd_printd(" speaker_outs=%d (0x%x/0x%x/0x%x/0x%x/0x%x)\n",
3475 cfg->speaker_outs, cfg->speaker_pins[0],
3476 cfg->speaker_pins[1], cfg->speaker_pins[2],
3477 cfg->speaker_pins[3], cfg->speaker_pins[4]);
Takashi Iwaieb06ed82006-09-20 17:10:27 +02003478 snd_printd(" hp_outs=%d (0x%x/0x%x/0x%x/0x%x/0x%x)\n",
3479 cfg->hp_outs, cfg->hp_pins[0],
3480 cfg->hp_pins[1], cfg->hp_pins[2],
3481 cfg->hp_pins[3], cfg->hp_pins[4]);
Matthew Ranostay90da78b2008-01-24 11:48:01 +01003482 snd_printd(" mono: mono_out=0x%x\n", cfg->mono_out_pin);
Takashi Iwai82bc9552006-03-21 11:24:42 +01003483 snd_printd(" inputs: mic=0x%x, fmic=0x%x, line=0x%x, fline=0x%x,"
3484 " cd=0x%x, aux=0x%x\n",
3485 cfg->input_pins[AUTO_PIN_MIC],
3486 cfg->input_pins[AUTO_PIN_FRONT_MIC],
3487 cfg->input_pins[AUTO_PIN_LINE],
3488 cfg->input_pins[AUTO_PIN_FRONT_LINE],
3489 cfg->input_pins[AUTO_PIN_CD],
3490 cfg->input_pins[AUTO_PIN_AUX]);
3491
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003492 return 0;
3493}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003494EXPORT_SYMBOL_HDA(snd_hda_parse_pin_def_config);
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003495
Takashi Iwai4a471b72005-12-07 13:56:29 +01003496/* labels for input pins */
3497const char *auto_pin_cfg_labels[AUTO_PIN_LAST] = {
3498 "Mic", "Front Mic", "Line", "Front Line", "CD", "Aux"
3499};
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003500EXPORT_SYMBOL_HDA(auto_pin_cfg_labels);
Takashi Iwai4a471b72005-12-07 13:56:29 +01003501
3502
Linus Torvalds1da177e2005-04-16 15:20:36 -07003503#ifdef CONFIG_PM
3504/*
3505 * power management
3506 */
3507
3508/**
3509 * snd_hda_suspend - suspend the codecs
3510 * @bus: the HDA bus
3511 * @state: suspsend state
3512 *
3513 * Returns 0 if successful.
3514 */
3515int snd_hda_suspend(struct hda_bus *bus, pm_message_t state)
3516{
Takashi Iwai0ba21762007-04-16 11:29:14 +02003517 struct hda_codec *codec;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003518
Takashi Iwai0ba21762007-04-16 11:29:14 +02003519 list_for_each_entry(codec, &bus->codec_list, list) {
Takashi Iwai0b7a2e92007-08-14 15:18:26 +02003520#ifdef CONFIG_SND_HDA_POWER_SAVE
3521 if (!codec->power_on)
3522 continue;
3523#endif
Takashi Iwaicb53c622007-08-10 17:21:45 +02003524 hda_call_codec_suspend(codec);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003525 }
3526 return 0;
3527}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003528EXPORT_SYMBOL_HDA(snd_hda_suspend);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003529
3530/**
3531 * snd_hda_resume - resume the codecs
3532 * @bus: the HDA bus
Linus Torvalds1da177e2005-04-16 15:20:36 -07003533 *
3534 * Returns 0 if successful.
Takashi Iwaicb53c622007-08-10 17:21:45 +02003535 *
3536 * This fucntion is defined only when POWER_SAVE isn't set.
3537 * In the power-save mode, the codec is resumed dynamically.
Linus Torvalds1da177e2005-04-16 15:20:36 -07003538 */
3539int snd_hda_resume(struct hda_bus *bus)
3540{
Takashi Iwai0ba21762007-04-16 11:29:14 +02003541 struct hda_codec *codec;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003542
Takashi Iwai0ba21762007-04-16 11:29:14 +02003543 list_for_each_entry(codec, &bus->codec_list, list) {
Maxim Levitskyd804ad92007-09-03 15:28:04 +02003544 if (snd_hda_codec_needs_resume(codec))
3545 hda_call_codec_resume(codec);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003546 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003547 return 0;
3548}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003549EXPORT_SYMBOL_HDA(snd_hda_resume);
Takashi Iwai1289e9e2008-11-27 15:47:11 +01003550#endif /* CONFIG_PM */
Takashi Iwaib2e18592008-07-30 15:01:44 +02003551
3552/*
3553 * generic arrays
3554 */
3555
3556/* get a new element from the given array
3557 * if it exceeds the pre-allocated array size, re-allocate the array
3558 */
3559void *snd_array_new(struct snd_array *array)
3560{
3561 if (array->used >= array->alloced) {
3562 int num = array->alloced + array->alloc_align;
Takashi Iwaib910d9a2008-11-07 00:26:52 +01003563 void *nlist;
3564 if (snd_BUG_ON(num >= 4096))
3565 return NULL;
3566 nlist = kcalloc(num + 1, array->elem_size, GFP_KERNEL);
Takashi Iwaib2e18592008-07-30 15:01:44 +02003567 if (!nlist)
3568 return NULL;
3569 if (array->list) {
3570 memcpy(nlist, array->list,
3571 array->elem_size * array->alloced);
3572 kfree(array->list);
3573 }
3574 array->list = nlist;
3575 array->alloced = num;
3576 }
Takashi Iwaif43aa022008-11-10 16:24:26 +01003577 return snd_array_elem(array, array->used++);
Takashi Iwaib2e18592008-07-30 15:01:44 +02003578}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003579EXPORT_SYMBOL_HDA(snd_array_new);
Takashi Iwaib2e18592008-07-30 15:01:44 +02003580
3581/* free the given array elements */
3582void snd_array_free(struct snd_array *array)
3583{
3584 kfree(array->list);
3585 array->used = 0;
3586 array->alloced = 0;
3587 array->list = NULL;
3588}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003589EXPORT_SYMBOL_HDA(snd_array_free);
Takashi Iwaib2022262008-11-21 21:24:03 +01003590
3591/*
3592 * used by hda_proc.c and hda_eld.c
3593 */
3594void snd_print_pcm_rates(int pcm, char *buf, int buflen)
3595{
3596 static unsigned int rates[] = {
3597 8000, 11025, 16000, 22050, 32000, 44100, 48000, 88200,
3598 96000, 176400, 192000, 384000
3599 };
3600 int i, j;
3601
3602 for (i = 0, j = 0; i < ARRAY_SIZE(rates); i++)
3603 if (pcm & (1 << i))
3604 j += snprintf(buf + j, buflen - j, " %d", rates[i]);
3605
3606 buf[j] = '\0'; /* necessary when j == 0 */
3607}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003608EXPORT_SYMBOL_HDA(snd_print_pcm_rates);
Takashi Iwaib2022262008-11-21 21:24:03 +01003609
3610void snd_print_pcm_bits(int pcm, char *buf, int buflen)
3611{
3612 static unsigned int bits[] = { 8, 16, 20, 24, 32 };
3613 int i, j;
3614
3615 for (i = 0, j = 0; i < ARRAY_SIZE(bits); i++)
3616 if (pcm & (AC_SUPPCM_BITS_8 << i))
3617 j += snprintf(buf + j, buflen - j, " %d", bits[i]);
3618
3619 buf[j] = '\0'; /* necessary when j == 0 */
3620}
Takashi Iwaiff7a3262008-11-28 15:17:06 +01003621EXPORT_SYMBOL_HDA(snd_print_pcm_bits);
Takashi Iwai1289e9e2008-11-27 15:47:11 +01003622
3623MODULE_DESCRIPTION("HDA codec core");
3624MODULE_LICENSE("GPL");