xref: /openbmc/linux/sound/pci/hda/hda_codec.c (revision 4eea30914facd2c99061cd70e5b05d3c76c743a2)
11da177e4SLinus Torvalds /*
21da177e4SLinus Torvalds  * Universal Interface for Intel High Definition Audio Codec
31da177e4SLinus Torvalds  *
41da177e4SLinus Torvalds  * Copyright (c) 2004 Takashi Iwai <tiwai@suse.de>
51da177e4SLinus Torvalds  *
61da177e4SLinus Torvalds  *
71da177e4SLinus Torvalds  *  This driver is free software; you can redistribute it and/or modify
81da177e4SLinus Torvalds  *  it under the terms of the GNU General Public License as published by
91da177e4SLinus Torvalds  *  the Free Software Foundation; either version 2 of the License, or
101da177e4SLinus Torvalds  *  (at your option) any later version.
111da177e4SLinus Torvalds  *
121da177e4SLinus Torvalds  *  This driver is distributed in the hope that it will be useful,
131da177e4SLinus Torvalds  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
141da177e4SLinus Torvalds  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
151da177e4SLinus Torvalds  *  GNU General Public License for more details.
161da177e4SLinus Torvalds  *
171da177e4SLinus Torvalds  *  You should have received a copy of the GNU General Public License
181da177e4SLinus Torvalds  *  along with this program; if not, write to the Free Software
191da177e4SLinus Torvalds  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
201da177e4SLinus Torvalds  */
211da177e4SLinus Torvalds 
2218478e8bSTakashi Iwai #include <linux/mm.h>
231da177e4SLinus Torvalds #include <linux/init.h>
241da177e4SLinus Torvalds #include <linux/delay.h>
251da177e4SLinus Torvalds #include <linux/slab.h>
261da177e4SLinus Torvalds #include <linux/pci.h>
2762932df8SIngo Molnar #include <linux/mutex.h>
28da155d5bSPaul Gortmaker #include <linux/module.h>
291da177e4SLinus Torvalds #include <sound/core.h>
301da177e4SLinus Torvalds #include "hda_codec.h"
311da177e4SLinus Torvalds #include <sound/asoundef.h>
32302e9c5aSJaroslav Kysela #include <sound/tlv.h>
331da177e4SLinus Torvalds #include <sound/initval.h>
34cd372fb3STakashi Iwai #include <sound/jack.h>
351da177e4SLinus Torvalds #include "hda_local.h"
36123c07aeSJaroslav Kysela #include "hda_beep.h"
371835a0f9STakashi Iwai #include "hda_jack.h"
382807314dSTakashi Iwai #include <sound/hda_hwdep.h>
391da177e4SLinus Torvalds 
40d66fee5dSTakashi Iwai #define CREATE_TRACE_POINTS
41d66fee5dSTakashi Iwai #include "hda_trace.h"
42d66fee5dSTakashi Iwai 
431da177e4SLinus Torvalds /*
441da177e4SLinus Torvalds  * vendor / preset table
451da177e4SLinus Torvalds  */
461da177e4SLinus Torvalds 
471da177e4SLinus Torvalds struct hda_vendor_id {
481da177e4SLinus Torvalds 	unsigned int id;
491da177e4SLinus Torvalds 	const char *name;
501da177e4SLinus Torvalds };
511da177e4SLinus Torvalds 
521da177e4SLinus Torvalds /* codec vendor labels */
531da177e4SLinus Torvalds static struct hda_vendor_id hda_vendor_ids[] = {
54c8cd1281STakashi Iwai 	{ 0x1002, "ATI" },
55e5f14248STakashi Iwai 	{ 0x1013, "Cirrus Logic" },
56a9226251STakashi Iwai 	{ 0x1057, "Motorola" },
57c8cd1281STakashi Iwai 	{ 0x1095, "Silicon Image" },
5831117b78STakashi Iwai 	{ 0x10de, "Nvidia" },
59c8cd1281STakashi Iwai 	{ 0x10ec, "Realtek" },
604e01f54bSTakashi Iwai 	{ 0x1102, "Creative" },
61c577b8a1SJoseph Chan 	{ 0x1106, "VIA" },
627f16859aSMatthew Ranostay 	{ 0x111d, "IDT" },
63c8cd1281STakashi Iwai 	{ 0x11c1, "LSI" },
6454b903ecSTakashi Iwai 	{ 0x11d4, "Analog Devices" },
651da177e4SLinus Torvalds 	{ 0x13f6, "C-Media" },
66a9226251STakashi Iwai 	{ 0x14f1, "Conexant" },
67c8cd1281STakashi Iwai 	{ 0x17e8, "Chrontel" },
68c8cd1281STakashi Iwai 	{ 0x1854, "LG" },
698199de3bSMark Brown 	{ 0x1aec, "Wolfson Microelectronics" },
701da177e4SLinus Torvalds 	{ 0x434d, "C-Media" },
7174c61133STakashi Iwai 	{ 0x8086, "Intel" },
722f2f4251SMatt 	{ 0x8384, "SigmaTel" },
731da177e4SLinus Torvalds 	{} /* terminator */
741da177e4SLinus Torvalds };
751da177e4SLinus Torvalds 
761289e9e8STakashi Iwai static DEFINE_MUTEX(preset_mutex);
771289e9e8STakashi Iwai static LIST_HEAD(hda_preset_tables);
781289e9e8STakashi Iwai 
791289e9e8STakashi Iwai int snd_hda_add_codec_preset(struct hda_codec_preset_list *preset)
801289e9e8STakashi Iwai {
811289e9e8STakashi Iwai 	mutex_lock(&preset_mutex);
821289e9e8STakashi Iwai 	list_add_tail(&preset->list, &hda_preset_tables);
831289e9e8STakashi Iwai 	mutex_unlock(&preset_mutex);
841289e9e8STakashi Iwai 	return 0;
851289e9e8STakashi Iwai }
86ff7a3267STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_add_codec_preset);
871289e9e8STakashi Iwai 
881289e9e8STakashi Iwai int snd_hda_delete_codec_preset(struct hda_codec_preset_list *preset)
891289e9e8STakashi Iwai {
901289e9e8STakashi Iwai 	mutex_lock(&preset_mutex);
911289e9e8STakashi Iwai 	list_del(&preset->list);
921289e9e8STakashi Iwai 	mutex_unlock(&preset_mutex);
931289e9e8STakashi Iwai 	return 0;
941289e9e8STakashi Iwai }
95ff7a3267STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_delete_codec_preset);
961da177e4SLinus Torvalds 
9783012a7cSTakashi Iwai #ifdef CONFIG_PM
98d846b174STakashi Iwai #define codec_in_pm(codec)	((codec)->in_pm)
99cb53c626STakashi Iwai static void hda_power_work(struct work_struct *work);
100cb53c626STakashi Iwai static void hda_keep_power_on(struct hda_codec *codec);
101e581f3dbSTakashi Iwai #define hda_codec_is_power_on(codec)	((codec)->power_on)
10268467f51STakashi Iwai static inline void hda_call_pm_notify(struct hda_bus *bus, bool power_up)
10368467f51STakashi Iwai {
10468467f51STakashi Iwai 	if (bus->ops.pm_notify)
10568467f51STakashi Iwai 		bus->ops.pm_notify(bus, power_up);
10668467f51STakashi Iwai }
107cb53c626STakashi Iwai #else
108d846b174STakashi Iwai #define codec_in_pm(codec)	0
109cb53c626STakashi Iwai static inline void hda_keep_power_on(struct hda_codec *codec) {}
110e581f3dbSTakashi Iwai #define hda_codec_is_power_on(codec)	1
11168467f51STakashi Iwai #define hda_call_pm_notify(bus, state) {}
112cb53c626STakashi Iwai #endif
113cb53c626STakashi Iwai 
114d5191e50STakashi Iwai /**
115d5191e50STakashi Iwai  * snd_hda_get_jack_location - Give a location string of the jack
116d5191e50STakashi Iwai  * @cfg: pin default config value
117d5191e50STakashi Iwai  *
118d5191e50STakashi Iwai  * Parse the pin default config value and returns the string of the
119d5191e50STakashi Iwai  * jack location, e.g. "Rear", "Front", etc.
120d5191e50STakashi Iwai  */
12150a9f790SMatthew Ranostay const char *snd_hda_get_jack_location(u32 cfg)
12250a9f790SMatthew Ranostay {
12350a9f790SMatthew Ranostay 	static char *bases[7] = {
12450a9f790SMatthew Ranostay 		"N/A", "Rear", "Front", "Left", "Right", "Top", "Bottom",
12550a9f790SMatthew Ranostay 	};
12650a9f790SMatthew Ranostay 	static unsigned char specials_idx[] = {
12750a9f790SMatthew Ranostay 		0x07, 0x08,
12850a9f790SMatthew Ranostay 		0x17, 0x18, 0x19,
12950a9f790SMatthew Ranostay 		0x37, 0x38
13050a9f790SMatthew Ranostay 	};
13150a9f790SMatthew Ranostay 	static char *specials[] = {
13250a9f790SMatthew Ranostay 		"Rear Panel", "Drive Bar",
13350a9f790SMatthew Ranostay 		"Riser", "HDMI", "ATAPI",
13450a9f790SMatthew Ranostay 		"Mobile-In", "Mobile-Out"
13550a9f790SMatthew Ranostay 	};
13650a9f790SMatthew Ranostay 	int i;
13750a9f790SMatthew Ranostay 	cfg = (cfg & AC_DEFCFG_LOCATION) >> AC_DEFCFG_LOCATION_SHIFT;
13850a9f790SMatthew Ranostay 	if ((cfg & 0x0f) < 7)
13950a9f790SMatthew Ranostay 		return bases[cfg & 0x0f];
14050a9f790SMatthew Ranostay 	for (i = 0; i < ARRAY_SIZE(specials_idx); i++) {
14150a9f790SMatthew Ranostay 		if (cfg == specials_idx[i])
14250a9f790SMatthew Ranostay 			return specials[i];
14350a9f790SMatthew Ranostay 	}
14450a9f790SMatthew Ranostay 	return "UNKNOWN";
14550a9f790SMatthew Ranostay }
146ff7a3267STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_get_jack_location);
14750a9f790SMatthew Ranostay 
148d5191e50STakashi Iwai /**
149d5191e50STakashi Iwai  * snd_hda_get_jack_connectivity - Give a connectivity string of the jack
150d5191e50STakashi Iwai  * @cfg: pin default config value
151d5191e50STakashi Iwai  *
152d5191e50STakashi Iwai  * Parse the pin default config value and returns the string of the
153d5191e50STakashi Iwai  * jack connectivity, i.e. external or internal connection.
154d5191e50STakashi Iwai  */
15550a9f790SMatthew Ranostay const char *snd_hda_get_jack_connectivity(u32 cfg)
15650a9f790SMatthew Ranostay {
15750a9f790SMatthew Ranostay 	static char *jack_locations[4] = { "Ext", "Int", "Sep", "Oth" };
15850a9f790SMatthew Ranostay 
15950a9f790SMatthew Ranostay 	return jack_locations[(cfg >> (AC_DEFCFG_LOCATION_SHIFT + 4)) & 3];
16050a9f790SMatthew Ranostay }
161ff7a3267STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_get_jack_connectivity);
16250a9f790SMatthew Ranostay 
163d5191e50STakashi Iwai /**
164d5191e50STakashi Iwai  * snd_hda_get_jack_type - Give a type string of the jack
165d5191e50STakashi Iwai  * @cfg: pin default config value
166d5191e50STakashi Iwai  *
167d5191e50STakashi Iwai  * Parse the pin default config value and returns the string of the
168d5191e50STakashi Iwai  * jack type, i.e. the purpose of the jack, such as Line-Out or CD.
169d5191e50STakashi Iwai  */
17050a9f790SMatthew Ranostay const char *snd_hda_get_jack_type(u32 cfg)
17150a9f790SMatthew Ranostay {
17250a9f790SMatthew Ranostay 	static char *jack_types[16] = {
17350a9f790SMatthew Ranostay 		"Line Out", "Speaker", "HP Out", "CD",
17450a9f790SMatthew Ranostay 		"SPDIF Out", "Digital Out", "Modem Line", "Modem Hand",
17550a9f790SMatthew Ranostay 		"Line In", "Aux", "Mic", "Telephony",
17650a9f790SMatthew Ranostay 		"SPDIF In", "Digitial In", "Reserved", "Other"
17750a9f790SMatthew Ranostay 	};
17850a9f790SMatthew Ranostay 
17950a9f790SMatthew Ranostay 	return jack_types[(cfg & AC_DEFCFG_DEVICE)
18050a9f790SMatthew Ranostay 				>> AC_DEFCFG_DEVICE_SHIFT];
18150a9f790SMatthew Ranostay }
182ff7a3267STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_get_jack_type);
18350a9f790SMatthew Ranostay 
18433fa35edSTakashi Iwai /*
18533fa35edSTakashi Iwai  * Compose a 32bit command word to be sent to the HD-audio controller
18633fa35edSTakashi Iwai  */
18733fa35edSTakashi Iwai static inline unsigned int
18833fa35edSTakashi Iwai make_codec_cmd(struct hda_codec *codec, hda_nid_t nid, int direct,
18933fa35edSTakashi Iwai 	       unsigned int verb, unsigned int parm)
19033fa35edSTakashi Iwai {
19133fa35edSTakashi Iwai 	u32 val;
19233fa35edSTakashi Iwai 
19382e1b804STakashi Iwai 	if ((codec->addr & ~0xf) || (direct & ~1) || (nid & ~0x7f) ||
19482e1b804STakashi Iwai 	    (verb & ~0xfff) || (parm & ~0xffff)) {
1956430aeebSWu Fengguang 		printk(KERN_ERR "hda-codec: out of range cmd %x:%x:%x:%x:%x\n",
1966430aeebSWu Fengguang 		       codec->addr, direct, nid, verb, parm);
1976430aeebSWu Fengguang 		return ~0;
1986430aeebSWu Fengguang 	}
1996430aeebSWu Fengguang 
2006430aeebSWu Fengguang 	val = (u32)codec->addr << 28;
20133fa35edSTakashi Iwai 	val |= (u32)direct << 27;
20233fa35edSTakashi Iwai 	val |= (u32)nid << 20;
20333fa35edSTakashi Iwai 	val |= verb << 8;
20433fa35edSTakashi Iwai 	val |= parm;
20533fa35edSTakashi Iwai 	return val;
20633fa35edSTakashi Iwai }
20733fa35edSTakashi Iwai 
208aa2936f5STakashi Iwai /*
209aa2936f5STakashi Iwai  * Send and receive a verb
210aa2936f5STakashi Iwai  */
211aa2936f5STakashi Iwai static int codec_exec_verb(struct hda_codec *codec, unsigned int cmd,
212aa2936f5STakashi Iwai 			   unsigned int *res)
213aa2936f5STakashi Iwai {
214aa2936f5STakashi Iwai 	struct hda_bus *bus = codec->bus;
2158dd78330STakashi Iwai 	int err;
216aa2936f5STakashi Iwai 
2176430aeebSWu Fengguang 	if (cmd == ~0)
2186430aeebSWu Fengguang 		return -1;
2196430aeebSWu Fengguang 
220aa2936f5STakashi Iwai 	if (res)
221aa2936f5STakashi Iwai 		*res = -1;
2228dd78330STakashi Iwai  again:
223aa2936f5STakashi Iwai 	snd_hda_power_up(codec);
224aa2936f5STakashi Iwai 	mutex_lock(&bus->cmd_mutex);
2253bcce5c0STakashi Iwai 	for (;;) {
226d66fee5dSTakashi Iwai 		trace_hda_send_cmd(codec, cmd);
227aa2936f5STakashi Iwai 		err = bus->ops.command(bus, cmd);
2283bcce5c0STakashi Iwai 		if (err != -EAGAIN)
2293bcce5c0STakashi Iwai 			break;
2303bcce5c0STakashi Iwai 		/* process pending verbs */
2313bcce5c0STakashi Iwai 		bus->ops.get_response(bus, codec->addr);
2323bcce5c0STakashi Iwai 	}
233d66fee5dSTakashi Iwai 	if (!err && res) {
234deadff16SWu Fengguang 		*res = bus->ops.get_response(bus, codec->addr);
235d66fee5dSTakashi Iwai 		trace_hda_get_response(codec, *res);
236d66fee5dSTakashi Iwai 	}
237aa2936f5STakashi Iwai 	mutex_unlock(&bus->cmd_mutex);
238aa2936f5STakashi Iwai 	snd_hda_power_down(codec);
239d846b174STakashi Iwai 	if (!codec_in_pm(codec) && res && *res == -1 && bus->rirb_error) {
2408dd78330STakashi Iwai 		if (bus->response_reset) {
2418dd78330STakashi Iwai 			snd_printd("hda_codec: resetting BUS due to "
2428dd78330STakashi Iwai 				   "fatal communication error\n");
243d66fee5dSTakashi Iwai 			trace_hda_bus_reset(bus);
2448dd78330STakashi Iwai 			bus->ops.bus_reset(bus);
2458dd78330STakashi Iwai 		}
2468dd78330STakashi Iwai 		goto again;
2478dd78330STakashi Iwai 	}
2488dd78330STakashi Iwai 	/* clear reset-flag when the communication gets recovered */
249d846b174STakashi Iwai 	if (!err || codec_in_pm(codec))
2508dd78330STakashi Iwai 		bus->response_reset = 0;
251aa2936f5STakashi Iwai 	return err;
252aa2936f5STakashi Iwai }
253aa2936f5STakashi Iwai 
2541da177e4SLinus Torvalds /**
2551da177e4SLinus Torvalds  * snd_hda_codec_read - send a command and get the response
2561da177e4SLinus Torvalds  * @codec: the HDA codec
2571da177e4SLinus Torvalds  * @nid: NID to send the command
2581da177e4SLinus Torvalds  * @direct: direct flag
2591da177e4SLinus Torvalds  * @verb: the verb to send
2601da177e4SLinus Torvalds  * @parm: the parameter for the verb
2611da177e4SLinus Torvalds  *
2621da177e4SLinus Torvalds  * Send a single command and read the corresponding response.
2631da177e4SLinus Torvalds  *
2641da177e4SLinus Torvalds  * Returns the obtained response value, or -1 for an error.
2651da177e4SLinus Torvalds  */
2660ba21762STakashi Iwai unsigned int snd_hda_codec_read(struct hda_codec *codec, hda_nid_t nid,
2670ba21762STakashi Iwai 				int direct,
2681da177e4SLinus Torvalds 				unsigned int verb, unsigned int parm)
2691da177e4SLinus Torvalds {
270aa2936f5STakashi Iwai 	unsigned cmd = make_codec_cmd(codec, nid, direct, verb, parm);
271aa2936f5STakashi Iwai 	unsigned int res;
2729857edfdSGreg Thelen 	if (codec_exec_verb(codec, cmd, &res))
2739857edfdSGreg Thelen 		return -1;
2741da177e4SLinus Torvalds 	return res;
2751da177e4SLinus Torvalds }
276ff7a3267STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_codec_read);
2771da177e4SLinus Torvalds 
2781da177e4SLinus Torvalds /**
2791da177e4SLinus Torvalds  * snd_hda_codec_write - send a single command without waiting for response
2801da177e4SLinus Torvalds  * @codec: the HDA codec
2811da177e4SLinus Torvalds  * @nid: NID to send the command
2821da177e4SLinus Torvalds  * @direct: direct flag
2831da177e4SLinus Torvalds  * @verb: the verb to send
2841da177e4SLinus Torvalds  * @parm: the parameter for the verb
2851da177e4SLinus Torvalds  *
2861da177e4SLinus Torvalds  * Send a single command without waiting for response.
2871da177e4SLinus Torvalds  *
2881da177e4SLinus Torvalds  * Returns 0 if successful, or a negative error code.
2891da177e4SLinus Torvalds  */
2901da177e4SLinus Torvalds int snd_hda_codec_write(struct hda_codec *codec, hda_nid_t nid, int direct,
2911da177e4SLinus Torvalds 			 unsigned int verb, unsigned int parm)
2921da177e4SLinus Torvalds {
293aa2936f5STakashi Iwai 	unsigned int cmd = make_codec_cmd(codec, nid, direct, verb, parm);
29433fa35edSTakashi Iwai 	unsigned int res;
295b20f3b83STakashi Iwai 	return codec_exec_verb(codec, cmd,
296b20f3b83STakashi Iwai 			       codec->bus->sync_write ? &res : NULL);
2971da177e4SLinus Torvalds }
298ff7a3267STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_codec_write);
2991da177e4SLinus Torvalds 
3001da177e4SLinus Torvalds /**
3011da177e4SLinus Torvalds  * snd_hda_sequence_write - sequence writes
3021da177e4SLinus Torvalds  * @codec: the HDA codec
3031da177e4SLinus Torvalds  * @seq: VERB array to send
3041da177e4SLinus Torvalds  *
3051da177e4SLinus Torvalds  * Send the commands sequentially from the given array.
3061da177e4SLinus Torvalds  * The array must be terminated with NID=0.
3071da177e4SLinus Torvalds  */
3081da177e4SLinus Torvalds void snd_hda_sequence_write(struct hda_codec *codec, const struct hda_verb *seq)
3091da177e4SLinus Torvalds {
3101da177e4SLinus Torvalds 	for (; seq->nid; seq++)
3111da177e4SLinus Torvalds 		snd_hda_codec_write(codec, seq->nid, 0, seq->verb, seq->param);
3121da177e4SLinus Torvalds }
313ff7a3267STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_sequence_write);
3141da177e4SLinus Torvalds 
3151da177e4SLinus Torvalds /**
3161da177e4SLinus Torvalds  * snd_hda_get_sub_nodes - get the range of sub nodes
3171da177e4SLinus Torvalds  * @codec: the HDA codec
3181da177e4SLinus Torvalds  * @nid: NID to parse
3191da177e4SLinus Torvalds  * @start_id: the pointer to store the start NID
3201da177e4SLinus Torvalds  *
3211da177e4SLinus Torvalds  * Parse the NID and store the start NID of its sub-nodes.
3221da177e4SLinus Torvalds  * Returns the number of sub-nodes.
3231da177e4SLinus Torvalds  */
3240ba21762STakashi Iwai int snd_hda_get_sub_nodes(struct hda_codec *codec, hda_nid_t nid,
3250ba21762STakashi Iwai 			  hda_nid_t *start_id)
3261da177e4SLinus Torvalds {
3271da177e4SLinus Torvalds 	unsigned int parm;
3281da177e4SLinus Torvalds 
3291da177e4SLinus Torvalds 	parm = snd_hda_param_read(codec, nid, AC_PAR_NODE_COUNT);
330e8a7f136SDanny Tholen 	if (parm == -1)
331e8a7f136SDanny Tholen 		return 0;
3321da177e4SLinus Torvalds 	*start_id = (parm >> 16) & 0x7fff;
3331da177e4SLinus Torvalds 	return (int)(parm & 0x7fff);
3341da177e4SLinus Torvalds }
335ff7a3267STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_get_sub_nodes);
3361da177e4SLinus Torvalds 
337ee8e765bSTakashi Iwai /* connection list element */
338ee8e765bSTakashi Iwai struct hda_conn_list {
339ee8e765bSTakashi Iwai 	struct list_head list;
340ee8e765bSTakashi Iwai 	int len;
341ee8e765bSTakashi Iwai 	hda_nid_t nid;
342ee8e765bSTakashi Iwai 	hda_nid_t conns[0];
343ee8e765bSTakashi Iwai };
344ee8e765bSTakashi Iwai 
345b2f934a0STakashi Iwai /* look up the cached results */
346ee8e765bSTakashi Iwai static struct hda_conn_list *
347ee8e765bSTakashi Iwai lookup_conn_list(struct hda_codec *codec, hda_nid_t nid)
348b2f934a0STakashi Iwai {
349ee8e765bSTakashi Iwai 	struct hda_conn_list *p;
350ee8e765bSTakashi Iwai 	list_for_each_entry(p, &codec->conn_list, list) {
351ee8e765bSTakashi Iwai 		if (p->nid == nid)
352b2f934a0STakashi Iwai 			return p;
353b2f934a0STakashi Iwai 	}
354b2f934a0STakashi Iwai 	return NULL;
355b2f934a0STakashi Iwai }
356a12d3e1eSTakashi Iwai 
357ee8e765bSTakashi Iwai static int add_conn_list(struct hda_codec *codec, hda_nid_t nid, int len,
358ee8e765bSTakashi Iwai 			 const hda_nid_t *list)
359ee8e765bSTakashi Iwai {
360ee8e765bSTakashi Iwai 	struct hda_conn_list *p;
361ee8e765bSTakashi Iwai 
362ee8e765bSTakashi Iwai 	p = kmalloc(sizeof(*p) + len * sizeof(hda_nid_t), GFP_KERNEL);
363ee8e765bSTakashi Iwai 	if (!p)
364ee8e765bSTakashi Iwai 		return -ENOMEM;
365ee8e765bSTakashi Iwai 	p->len = len;
366ee8e765bSTakashi Iwai 	p->nid = nid;
367ee8e765bSTakashi Iwai 	memcpy(p->conns, list, len * sizeof(hda_nid_t));
368ee8e765bSTakashi Iwai 	list_add(&p->list, &codec->conn_list);
369ee8e765bSTakashi Iwai 	return 0;
370ee8e765bSTakashi Iwai }
371ee8e765bSTakashi Iwai 
372ee8e765bSTakashi Iwai static void remove_conn_list(struct hda_codec *codec)
373ee8e765bSTakashi Iwai {
374ee8e765bSTakashi Iwai 	while (!list_empty(&codec->conn_list)) {
375ee8e765bSTakashi Iwai 		struct hda_conn_list *p;
376ee8e765bSTakashi Iwai 		p = list_first_entry(&codec->conn_list, typeof(*p), list);
377ee8e765bSTakashi Iwai 		list_del(&p->list);
378ee8e765bSTakashi Iwai 		kfree(p);
379ee8e765bSTakashi Iwai 	}
380ee8e765bSTakashi Iwai }
381ee8e765bSTakashi Iwai 
382b2f934a0STakashi Iwai /* read the connection and add to the cache */
38309cf03b8STakashi Iwai static int read_and_add_raw_conns(struct hda_codec *codec, hda_nid_t nid)
38409cf03b8STakashi Iwai {
385*4eea3091STakashi Iwai 	hda_nid_t list[32];
386*4eea3091STakashi Iwai 	hda_nid_t *result = list;
38709cf03b8STakashi Iwai 	int len;
38809cf03b8STakashi Iwai 
38909cf03b8STakashi Iwai 	len = snd_hda_get_raw_connections(codec, nid, list, ARRAY_SIZE(list));
390*4eea3091STakashi Iwai 	if (len == -ENOSPC) {
391*4eea3091STakashi Iwai 		len = snd_hda_get_num_raw_conns(codec, nid);
392*4eea3091STakashi Iwai 		result = kmalloc(sizeof(hda_nid_t) * len, GFP_KERNEL);
393*4eea3091STakashi Iwai 		if (!result)
394*4eea3091STakashi Iwai 			return -ENOMEM;
395*4eea3091STakashi Iwai 		len = snd_hda_get_raw_connections(codec, nid, result, len);
396*4eea3091STakashi Iwai 	}
397*4eea3091STakashi Iwai 	if (len >= 0)
398*4eea3091STakashi Iwai 		len = snd_hda_override_conn_list(codec, nid, len, result);
399*4eea3091STakashi Iwai 	if (result != list)
400*4eea3091STakashi Iwai 		kfree(result);
401a12d3e1eSTakashi Iwai 	return len;
402a12d3e1eSTakashi Iwai }
403dce2079bSTakashi Iwai 
404dce2079bSTakashi Iwai /**
405ee8e765bSTakashi Iwai  * snd_hda_get_conn_list - get connection list
406ee8e765bSTakashi Iwai  * @codec: the HDA codec
407ee8e765bSTakashi Iwai  * @nid: NID to parse
408ee8e765bSTakashi Iwai  * @len: number of connection list entries
409ee8e765bSTakashi Iwai  * @listp: the pointer to store NID list
410ee8e765bSTakashi Iwai  *
411ee8e765bSTakashi Iwai  * Parses the connection list of the given widget and stores the pointer
412ee8e765bSTakashi Iwai  * to the list of NIDs.
413ee8e765bSTakashi Iwai  *
414ee8e765bSTakashi Iwai  * Returns the number of connections, or a negative error code.
415ee8e765bSTakashi Iwai  *
416ee8e765bSTakashi Iwai  * Note that the returned pointer isn't protected against the list
417ee8e765bSTakashi Iwai  * modification.  If snd_hda_override_conn_list() might be called
418ee8e765bSTakashi Iwai  * concurrently, protect with a mutex appropriately.
419ee8e765bSTakashi Iwai  */
420ee8e765bSTakashi Iwai int snd_hda_get_conn_list(struct hda_codec *codec, hda_nid_t nid,
421ee8e765bSTakashi Iwai 			  const hda_nid_t **listp)
422ee8e765bSTakashi Iwai {
423ee8e765bSTakashi Iwai 	bool added = false;
424ee8e765bSTakashi Iwai 
425ee8e765bSTakashi Iwai 	for (;;) {
426ee8e765bSTakashi Iwai 		int err;
427ee8e765bSTakashi Iwai 		const struct hda_conn_list *p;
428ee8e765bSTakashi Iwai 
429ee8e765bSTakashi Iwai 		/* if the connection-list is already cached, read it */
430ee8e765bSTakashi Iwai 		p = lookup_conn_list(codec, nid);
431ee8e765bSTakashi Iwai 		if (p) {
432ee8e765bSTakashi Iwai 			if (listp)
433ee8e765bSTakashi Iwai 				*listp = p->conns;
434ee8e765bSTakashi Iwai 			return p->len;
435ee8e765bSTakashi Iwai 		}
436ee8e765bSTakashi Iwai 		if (snd_BUG_ON(added))
437ee8e765bSTakashi Iwai 			return -EINVAL;
438ee8e765bSTakashi Iwai 
439ee8e765bSTakashi Iwai 		err = read_and_add_raw_conns(codec, nid);
440ee8e765bSTakashi Iwai 		if (err < 0)
441ee8e765bSTakashi Iwai 			return err;
442ee8e765bSTakashi Iwai 		added = true;
443ee8e765bSTakashi Iwai 	}
444ee8e765bSTakashi Iwai }
445ee8e765bSTakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_get_conn_list);
446ee8e765bSTakashi Iwai 
447ee8e765bSTakashi Iwai /**
448dce2079bSTakashi Iwai  * snd_hda_get_connections - copy connection list
4491da177e4SLinus Torvalds  * @codec: the HDA codec
4501da177e4SLinus Torvalds  * @nid: NID to parse
45109cf03b8STakashi Iwai  * @conn_list: connection list array; when NULL, checks only the size
4521da177e4SLinus Torvalds  * @max_conns: max. number of connections to store
4531da177e4SLinus Torvalds  *
4541da177e4SLinus Torvalds  * Parses the connection list of the given widget and stores the list
4551da177e4SLinus Torvalds  * of NIDs.
4561da177e4SLinus Torvalds  *
4571da177e4SLinus Torvalds  * Returns the number of connections, or a negative error code.
4581da177e4SLinus Torvalds  */
4591da177e4SLinus Torvalds int snd_hda_get_connections(struct hda_codec *codec, hda_nid_t nid,
4601da177e4SLinus Torvalds 			    hda_nid_t *conn_list, int max_conns)
4611da177e4SLinus Torvalds {
462ee8e765bSTakashi Iwai 	const hda_nid_t *list;
463ee8e765bSTakashi Iwai 	int len = snd_hda_get_conn_list(codec, nid, &list);
464a12d3e1eSTakashi Iwai 
465ee8e765bSTakashi Iwai 	if (len > 0 && conn_list) {
466ee8e765bSTakashi Iwai 		if (len > max_conns) {
467dce2079bSTakashi Iwai 			snd_printk(KERN_ERR "hda_codec: "
468dce2079bSTakashi Iwai 				   "Too many connections %d for NID 0x%x\n",
469dce2079bSTakashi Iwai 				   len, nid);
470dce2079bSTakashi Iwai 			return -EINVAL;
471dce2079bSTakashi Iwai 		}
472ee8e765bSTakashi Iwai 		memcpy(conn_list, list, len * sizeof(hda_nid_t));
47309cf03b8STakashi Iwai 	}
47409cf03b8STakashi Iwai 
47509cf03b8STakashi Iwai 	return len;
476a12d3e1eSTakashi Iwai }
477a12d3e1eSTakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_get_connections);
478a12d3e1eSTakashi Iwai 
479*4eea3091STakashi Iwai /* return CONNLIST_LEN parameter of the given widget */
480*4eea3091STakashi Iwai static unsigned int get_num_conns(struct hda_codec *codec, hda_nid_t nid)
481*4eea3091STakashi Iwai {
482*4eea3091STakashi Iwai 	unsigned int wcaps = get_wcaps(codec, nid);
483*4eea3091STakashi Iwai 	unsigned int parm;
484*4eea3091STakashi Iwai 
485*4eea3091STakashi Iwai 	if (!(wcaps & AC_WCAP_CONN_LIST) &&
486*4eea3091STakashi Iwai 	    get_wcaps_type(wcaps) != AC_WID_VOL_KNB)
487*4eea3091STakashi Iwai 		return 0;
488*4eea3091STakashi Iwai 
489*4eea3091STakashi Iwai 	parm = snd_hda_param_read(codec, nid, AC_PAR_CONNLIST_LEN);
490*4eea3091STakashi Iwai 	if (parm == -1)
491*4eea3091STakashi Iwai 		parm = 0;
492*4eea3091STakashi Iwai 	return parm;
493*4eea3091STakashi Iwai }
494*4eea3091STakashi Iwai 
495*4eea3091STakashi Iwai int snd_hda_get_num_raw_conns(struct hda_codec *codec, hda_nid_t nid)
496*4eea3091STakashi Iwai {
497*4eea3091STakashi Iwai 	return get_num_conns(codec, nid) & AC_CLIST_LENGTH;
498*4eea3091STakashi Iwai }
499*4eea3091STakashi Iwai 
5009e7717c9STakashi Iwai /**
5019e7717c9STakashi Iwai  * snd_hda_get_raw_connections - copy connection list without cache
5029e7717c9STakashi Iwai  * @codec: the HDA codec
5039e7717c9STakashi Iwai  * @nid: NID to parse
5049e7717c9STakashi Iwai  * @conn_list: connection list array
5059e7717c9STakashi Iwai  * @max_conns: max. number of connections to store
5069e7717c9STakashi Iwai  *
5079e7717c9STakashi Iwai  * Like snd_hda_get_connections(), copy the connection list but without
5089e7717c9STakashi Iwai  * checking through the connection-list cache.
5099e7717c9STakashi Iwai  * Currently called only from hda_proc.c, so not exported.
5109e7717c9STakashi Iwai  */
5119e7717c9STakashi Iwai int snd_hda_get_raw_connections(struct hda_codec *codec, hda_nid_t nid,
512a12d3e1eSTakashi Iwai 				hda_nid_t *conn_list, int max_conns)
513a12d3e1eSTakashi Iwai {
5141da177e4SLinus Torvalds 	unsigned int parm;
51554d17403STakashi Iwai 	int i, conn_len, conns;
5161da177e4SLinus Torvalds 	unsigned int shift, num_elems, mask;
51754d17403STakashi Iwai 	hda_nid_t prev_nid;
5185fdaecdbSTakashi Iwai 	int null_count = 0;
5191da177e4SLinus Torvalds 
520da3cec35STakashi Iwai 	if (snd_BUG_ON(!conn_list || max_conns <= 0))
521da3cec35STakashi Iwai 		return -EINVAL;
5221da177e4SLinus Torvalds 
523*4eea3091STakashi Iwai 	parm = get_num_conns(codec, nid);
524*4eea3091STakashi Iwai 	if (!parm)
5258d087c76STakashi Iwai 		return 0;
52616a433d8SJaroslav Kysela 
5271da177e4SLinus Torvalds 	if (parm & AC_CLIST_LONG) {
5281da177e4SLinus Torvalds 		/* long form */
5291da177e4SLinus Torvalds 		shift = 16;
5301da177e4SLinus Torvalds 		num_elems = 2;
5311da177e4SLinus Torvalds 	} else {
5321da177e4SLinus Torvalds 		/* short form */
5331da177e4SLinus Torvalds 		shift = 8;
5341da177e4SLinus Torvalds 		num_elems = 4;
5351da177e4SLinus Torvalds 	}
5361da177e4SLinus Torvalds 	conn_len = parm & AC_CLIST_LENGTH;
5371da177e4SLinus Torvalds 	mask = (1 << (shift-1)) - 1;
5381da177e4SLinus Torvalds 
5391da177e4SLinus Torvalds 	if (!conn_len)
5401da177e4SLinus Torvalds 		return 0; /* no connection */
5411da177e4SLinus Torvalds 
5421da177e4SLinus Torvalds 	if (conn_len == 1) {
5431da177e4SLinus Torvalds 		/* single connection */
5440ba21762STakashi Iwai 		parm = snd_hda_codec_read(codec, nid, 0,
5450ba21762STakashi Iwai 					  AC_VERB_GET_CONNECT_LIST, 0);
5463c6aae44STakashi Iwai 		if (parm == -1 && codec->bus->rirb_error)
5473c6aae44STakashi Iwai 			return -EIO;
5481da177e4SLinus Torvalds 		conn_list[0] = parm & mask;
5491da177e4SLinus Torvalds 		return 1;
5501da177e4SLinus Torvalds 	}
5511da177e4SLinus Torvalds 
5521da177e4SLinus Torvalds 	/* multi connection */
5531da177e4SLinus Torvalds 	conns = 0;
55454d17403STakashi Iwai 	prev_nid = 0;
55554d17403STakashi Iwai 	for (i = 0; i < conn_len; i++) {
5561da177e4SLinus Torvalds 		int range_val;
55754d17403STakashi Iwai 		hda_nid_t val, n;
55854d17403STakashi Iwai 
5593c6aae44STakashi Iwai 		if (i % num_elems == 0) {
56054d17403STakashi Iwai 			parm = snd_hda_codec_read(codec, nid, 0,
56154d17403STakashi Iwai 						  AC_VERB_GET_CONNECT_LIST, i);
5623c6aae44STakashi Iwai 			if (parm == -1 && codec->bus->rirb_error)
5633c6aae44STakashi Iwai 				return -EIO;
5643c6aae44STakashi Iwai 		}
56554d17403STakashi Iwai 		range_val = !!(parm & (1 << (shift-1))); /* ranges */
56654d17403STakashi Iwai 		val = parm & mask;
5675fdaecdbSTakashi Iwai 		if (val == 0 && null_count++) {  /* no second chance */
5682e9bf247SJaroslav Kysela 			snd_printk(KERN_WARNING "hda_codec: "
5692e9bf247SJaroslav Kysela 				   "invalid CONNECT_LIST verb %x[%i]:%x\n",
5702e9bf247SJaroslav Kysela 				    nid, i, parm);
5712e9bf247SJaroslav Kysela 			return 0;
5722e9bf247SJaroslav Kysela 		}
5731da177e4SLinus Torvalds 		parm >>= shift;
5741da177e4SLinus Torvalds 		if (range_val) {
57554d17403STakashi Iwai 			/* ranges between the previous and this one */
57654d17403STakashi Iwai 			if (!prev_nid || prev_nid >= val) {
5770ba21762STakashi Iwai 				snd_printk(KERN_WARNING "hda_codec: "
5780ba21762STakashi Iwai 					   "invalid dep_range_val %x:%x\n",
5790ba21762STakashi Iwai 					   prev_nid, val);
5801da177e4SLinus Torvalds 				continue;
5811da177e4SLinus Torvalds 			}
58254d17403STakashi Iwai 			for (n = prev_nid + 1; n <= val; n++) {
583*4eea3091STakashi Iwai 				if (conns >= max_conns)
584*4eea3091STakashi Iwai 					return -ENOSPC;
5851da177e4SLinus Torvalds 				conn_list[conns++] = n;
5861da177e4SLinus Torvalds 			}
5871da177e4SLinus Torvalds 		} else {
588*4eea3091STakashi Iwai 			if (conns >= max_conns)
589*4eea3091STakashi Iwai 				return -ENOSPC;
59054d17403STakashi Iwai 			conn_list[conns++] = val;
5911da177e4SLinus Torvalds 		}
59254d17403STakashi Iwai 		prev_nid = val;
5931da177e4SLinus Torvalds 	}
5941da177e4SLinus Torvalds 	return conns;
5951da177e4SLinus Torvalds }
5961da177e4SLinus Torvalds 
5971da177e4SLinus Torvalds /**
598b2f934a0STakashi Iwai  * snd_hda_override_conn_list - add/modify the connection-list to cache
599b2f934a0STakashi Iwai  * @codec: the HDA codec
600b2f934a0STakashi Iwai  * @nid: NID to parse
601b2f934a0STakashi Iwai  * @len: number of connection list entries
602b2f934a0STakashi Iwai  * @list: the list of connection entries
603b2f934a0STakashi Iwai  *
604b2f934a0STakashi Iwai  * Add or modify the given connection-list to the cache.  If the corresponding
605b2f934a0STakashi Iwai  * cache already exists, invalidate it and append a new one.
606b2f934a0STakashi Iwai  *
607b2f934a0STakashi Iwai  * Returns zero or a negative error code.
608b2f934a0STakashi Iwai  */
609b2f934a0STakashi Iwai int snd_hda_override_conn_list(struct hda_codec *codec, hda_nid_t nid, int len,
610b2f934a0STakashi Iwai 			       const hda_nid_t *list)
6111da177e4SLinus Torvalds {
612ee8e765bSTakashi Iwai 	struct hda_conn_list *p;
613b2f934a0STakashi Iwai 
614ee8e765bSTakashi Iwai 	p = lookup_conn_list(codec, nid);
615ee8e765bSTakashi Iwai 	if (p) {
616ee8e765bSTakashi Iwai 		list_del(&p->list);
617ee8e765bSTakashi Iwai 		kfree(p);
618ee8e765bSTakashi Iwai 	}
619b2f934a0STakashi Iwai 
620ee8e765bSTakashi Iwai 	return add_conn_list(codec, nid, len, list);
6211da177e4SLinus Torvalds }
622b2f934a0STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_override_conn_list);
623b2f934a0STakashi Iwai 
624b2f934a0STakashi Iwai /**
6258d087c76STakashi Iwai  * snd_hda_get_conn_index - get the connection index of the given NID
6268d087c76STakashi Iwai  * @codec: the HDA codec
6278d087c76STakashi Iwai  * @mux: NID containing the list
6288d087c76STakashi Iwai  * @nid: NID to select
6298d087c76STakashi Iwai  * @recursive: 1 when searching NID recursively, otherwise 0
6308d087c76STakashi Iwai  *
6318d087c76STakashi Iwai  * Parses the connection list of the widget @mux and checks whether the
6328d087c76STakashi Iwai  * widget @nid is present.  If it is, return the connection index.
6338d087c76STakashi Iwai  * Otherwise it returns -1.
6348d087c76STakashi Iwai  */
6358d087c76STakashi Iwai int snd_hda_get_conn_index(struct hda_codec *codec, hda_nid_t mux,
6368d087c76STakashi Iwai 			   hda_nid_t nid, int recursive)
6378d087c76STakashi Iwai {
638ee8e765bSTakashi Iwai 	const hda_nid_t *conn;
6398d087c76STakashi Iwai 	int i, nums;
6408d087c76STakashi Iwai 
641ee8e765bSTakashi Iwai 	nums = snd_hda_get_conn_list(codec, mux, &conn);
6428d087c76STakashi Iwai 	for (i = 0; i < nums; i++)
6438d087c76STakashi Iwai 		if (conn[i] == nid)
6448d087c76STakashi Iwai 			return i;
6458d087c76STakashi Iwai 	if (!recursive)
6468d087c76STakashi Iwai 		return -1;
647d94ddd85STakashi Iwai 	if (recursive > 10) {
6488d087c76STakashi Iwai 		snd_printd("hda_codec: too deep connection for 0x%x\n", nid);
6498d087c76STakashi Iwai 		return -1;
6501da177e4SLinus Torvalds 	}
6518d087c76STakashi Iwai 	recursive++;
65299e14c9dSTakashi Iwai 	for (i = 0; i < nums; i++) {
65399e14c9dSTakashi Iwai 		unsigned int type = get_wcaps_type(get_wcaps(codec, conn[i]));
65499e14c9dSTakashi Iwai 		if (type == AC_WID_PIN || type == AC_WID_AUD_OUT)
65599e14c9dSTakashi Iwai 			continue;
6568d087c76STakashi Iwai 		if (snd_hda_get_conn_index(codec, conn[i], nid, recursive) >= 0)
6578d087c76STakashi Iwai 			return i;
65899e14c9dSTakashi Iwai 	}
6598d087c76STakashi Iwai 	return -1;
6608d087c76STakashi Iwai }
6618d087c76STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_get_conn_index);
6621da177e4SLinus Torvalds 
6631da177e4SLinus Torvalds /**
6641da177e4SLinus Torvalds  * snd_hda_queue_unsol_event - add an unsolicited event to queue
6651da177e4SLinus Torvalds  * @bus: the BUS
6661da177e4SLinus Torvalds  * @res: unsolicited event (lower 32bit of RIRB entry)
6671da177e4SLinus Torvalds  * @res_ex: codec addr and flags (upper 32bit or RIRB entry)
6681da177e4SLinus Torvalds  *
6691da177e4SLinus Torvalds  * Adds the given event to the queue.  The events are processed in
6701da177e4SLinus Torvalds  * the workqueue asynchronously.  Call this function in the interrupt
6711da177e4SLinus Torvalds  * hanlder when RIRB receives an unsolicited event.
6721da177e4SLinus Torvalds  *
6731da177e4SLinus Torvalds  * Returns 0 if successful, or a negative error code.
6741da177e4SLinus Torvalds  */
6751da177e4SLinus Torvalds int snd_hda_queue_unsol_event(struct hda_bus *bus, u32 res, u32 res_ex)
6761da177e4SLinus Torvalds {
6771da177e4SLinus Torvalds 	struct hda_bus_unsolicited *unsol;
6781da177e4SLinus Torvalds 	unsigned int wp;
6791da177e4SLinus Torvalds 
680ecf726f5STakashi Iwai 	trace_hda_unsol_event(bus, res, res_ex);
6810ba21762STakashi Iwai 	unsol = bus->unsol;
6820ba21762STakashi Iwai 	if (!unsol)
6831da177e4SLinus Torvalds 		return 0;
6841da177e4SLinus Torvalds 
6851da177e4SLinus Torvalds 	wp = (unsol->wp + 1) % HDA_UNSOL_QUEUE_SIZE;
6861da177e4SLinus Torvalds 	unsol->wp = wp;
6871da177e4SLinus Torvalds 
6881da177e4SLinus Torvalds 	wp <<= 1;
6891da177e4SLinus Torvalds 	unsol->queue[wp] = res;
6901da177e4SLinus Torvalds 	unsol->queue[wp + 1] = res_ex;
6911da177e4SLinus Torvalds 
6926acaed38STakashi Iwai 	queue_work(bus->workq, &unsol->work);
6931da177e4SLinus Torvalds 
6941da177e4SLinus Torvalds 	return 0;
6951da177e4SLinus Torvalds }
696ff7a3267STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_queue_unsol_event);
6971da177e4SLinus Torvalds 
6981da177e4SLinus Torvalds /*
6995c1d1a98SWu Fengguang  * process queued unsolicited events
7001da177e4SLinus Torvalds  */
701c4028958SDavid Howells static void process_unsol_events(struct work_struct *work)
7021da177e4SLinus Torvalds {
703c4028958SDavid Howells 	struct hda_bus_unsolicited *unsol =
704c4028958SDavid Howells 		container_of(work, struct hda_bus_unsolicited, work);
705c4028958SDavid Howells 	struct hda_bus *bus = unsol->bus;
7061da177e4SLinus Torvalds 	struct hda_codec *codec;
7071da177e4SLinus Torvalds 	unsigned int rp, caddr, res;
7081da177e4SLinus Torvalds 
7091da177e4SLinus Torvalds 	while (unsol->rp != unsol->wp) {
7101da177e4SLinus Torvalds 		rp = (unsol->rp + 1) % HDA_UNSOL_QUEUE_SIZE;
7111da177e4SLinus Torvalds 		unsol->rp = rp;
7121da177e4SLinus Torvalds 		rp <<= 1;
7131da177e4SLinus Torvalds 		res = unsol->queue[rp];
7141da177e4SLinus Torvalds 		caddr = unsol->queue[rp + 1];
7151da177e4SLinus Torvalds 		if (!(caddr & (1 << 4))) /* no unsolicited event? */
7161da177e4SLinus Torvalds 			continue;
7171da177e4SLinus Torvalds 		codec = bus->caddr_tbl[caddr & 0x0f];
7181da177e4SLinus Torvalds 		if (codec && codec->patch_ops.unsol_event)
7191da177e4SLinus Torvalds 			codec->patch_ops.unsol_event(codec, res);
7201da177e4SLinus Torvalds 	}
7211da177e4SLinus Torvalds }
7221da177e4SLinus Torvalds 
7231da177e4SLinus Torvalds /*
7241da177e4SLinus Torvalds  * initialize unsolicited queue
7251da177e4SLinus Torvalds  */
7266c1f45eaSTakashi Iwai static int init_unsol_queue(struct hda_bus *bus)
7271da177e4SLinus Torvalds {
7281da177e4SLinus Torvalds 	struct hda_bus_unsolicited *unsol;
7291da177e4SLinus Torvalds 
7309f146bb6STakashi Iwai 	if (bus->unsol) /* already initialized */
7319f146bb6STakashi Iwai 		return 0;
7329f146bb6STakashi Iwai 
733e560d8d8STakashi Iwai 	unsol = kzalloc(sizeof(*unsol), GFP_KERNEL);
7341da177e4SLinus Torvalds 	if (!unsol) {
7350ba21762STakashi Iwai 		snd_printk(KERN_ERR "hda_codec: "
7360ba21762STakashi Iwai 			   "can't allocate unsolicited queue\n");
7371da177e4SLinus Torvalds 		return -ENOMEM;
7381da177e4SLinus Torvalds 	}
739c4028958SDavid Howells 	INIT_WORK(&unsol->work, process_unsol_events);
740c4028958SDavid Howells 	unsol->bus = bus;
7411da177e4SLinus Torvalds 	bus->unsol = unsol;
7421da177e4SLinus Torvalds 	return 0;
7431da177e4SLinus Torvalds }
7441da177e4SLinus Torvalds 
7451da177e4SLinus Torvalds /*
7461da177e4SLinus Torvalds  * destructor
7471da177e4SLinus Torvalds  */
7481da177e4SLinus Torvalds static void snd_hda_codec_free(struct hda_codec *codec);
7491da177e4SLinus Torvalds 
7501da177e4SLinus Torvalds static int snd_hda_bus_free(struct hda_bus *bus)
7511da177e4SLinus Torvalds {
7520ba21762STakashi Iwai 	struct hda_codec *codec, *n;
7531da177e4SLinus Torvalds 
7541da177e4SLinus Torvalds 	if (!bus)
7551da177e4SLinus Torvalds 		return 0;
7566acaed38STakashi Iwai 	if (bus->workq)
7576acaed38STakashi Iwai 		flush_workqueue(bus->workq);
7586acaed38STakashi Iwai 	if (bus->unsol)
7591da177e4SLinus Torvalds 		kfree(bus->unsol);
7600ba21762STakashi Iwai 	list_for_each_entry_safe(codec, n, &bus->codec_list, list) {
7611da177e4SLinus Torvalds 		snd_hda_codec_free(codec);
7621da177e4SLinus Torvalds 	}
7631da177e4SLinus Torvalds 	if (bus->ops.private_free)
7641da177e4SLinus Torvalds 		bus->ops.private_free(bus);
7656acaed38STakashi Iwai 	if (bus->workq)
7666acaed38STakashi Iwai 		destroy_workqueue(bus->workq);
7671da177e4SLinus Torvalds 	kfree(bus);
7681da177e4SLinus Torvalds 	return 0;
7691da177e4SLinus Torvalds }
7701da177e4SLinus Torvalds 
771c8b6bf9bSTakashi Iwai static int snd_hda_bus_dev_free(struct snd_device *device)
7721da177e4SLinus Torvalds {
7731da177e4SLinus Torvalds 	struct hda_bus *bus = device->device_data;
774b94d3539STakashi Iwai 	bus->shutdown = 1;
7751da177e4SLinus Torvalds 	return snd_hda_bus_free(bus);
7761da177e4SLinus Torvalds }
7771da177e4SLinus Torvalds 
778d7ffba19STakashi Iwai #ifdef CONFIG_SND_HDA_HWDEP
779d7ffba19STakashi Iwai static int snd_hda_bus_dev_register(struct snd_device *device)
780d7ffba19STakashi Iwai {
781d7ffba19STakashi Iwai 	struct hda_bus *bus = device->device_data;
782d7ffba19STakashi Iwai 	struct hda_codec *codec;
783d7ffba19STakashi Iwai 	list_for_each_entry(codec, &bus->codec_list, list) {
784d7ffba19STakashi Iwai 		snd_hda_hwdep_add_sysfs(codec);
785a2f6309eSTakashi Iwai 		snd_hda_hwdep_add_power_sysfs(codec);
786d7ffba19STakashi Iwai 	}
787d7ffba19STakashi Iwai 	return 0;
788d7ffba19STakashi Iwai }
789d7ffba19STakashi Iwai #else
790d7ffba19STakashi Iwai #define snd_hda_bus_dev_register	NULL
791d7ffba19STakashi Iwai #endif
792d7ffba19STakashi Iwai 
7931da177e4SLinus Torvalds /**
7941da177e4SLinus Torvalds  * snd_hda_bus_new - create a HDA bus
7951da177e4SLinus Torvalds  * @card: the card entry
7961da177e4SLinus Torvalds  * @temp: the template for hda_bus information
7971da177e4SLinus Torvalds  * @busp: the pointer to store the created bus instance
7981da177e4SLinus Torvalds  *
7991da177e4SLinus Torvalds  * Returns 0 if successful, or a negative error code.
8001da177e4SLinus Torvalds  */
8016a0f56a7STakashi Iwai int snd_hda_bus_new(struct snd_card *card,
802756e2b01STakashi Iwai 			      const struct hda_bus_template *temp,
8031da177e4SLinus Torvalds 			      struct hda_bus **busp)
8041da177e4SLinus Torvalds {
8051da177e4SLinus Torvalds 	struct hda_bus *bus;
8061da177e4SLinus Torvalds 	int err;
807c8b6bf9bSTakashi Iwai 	static struct snd_device_ops dev_ops = {
808d7ffba19STakashi Iwai 		.dev_register = snd_hda_bus_dev_register,
8091da177e4SLinus Torvalds 		.dev_free = snd_hda_bus_dev_free,
8101da177e4SLinus Torvalds 	};
8111da177e4SLinus Torvalds 
812da3cec35STakashi Iwai 	if (snd_BUG_ON(!temp))
813da3cec35STakashi Iwai 		return -EINVAL;
814da3cec35STakashi Iwai 	if (snd_BUG_ON(!temp->ops.command || !temp->ops.get_response))
815da3cec35STakashi Iwai 		return -EINVAL;
8161da177e4SLinus Torvalds 
8171da177e4SLinus Torvalds 	if (busp)
8181da177e4SLinus Torvalds 		*busp = NULL;
8191da177e4SLinus Torvalds 
820e560d8d8STakashi Iwai 	bus = kzalloc(sizeof(*bus), GFP_KERNEL);
8211da177e4SLinus Torvalds 	if (bus == NULL) {
8221da177e4SLinus Torvalds 		snd_printk(KERN_ERR "can't allocate struct hda_bus\n");
8231da177e4SLinus Torvalds 		return -ENOMEM;
8241da177e4SLinus Torvalds 	}
8251da177e4SLinus Torvalds 
8261da177e4SLinus Torvalds 	bus->card = card;
8271da177e4SLinus Torvalds 	bus->private_data = temp->private_data;
8281da177e4SLinus Torvalds 	bus->pci = temp->pci;
8291da177e4SLinus Torvalds 	bus->modelname = temp->modelname;
830fee2fba3STakashi Iwai 	bus->power_save = temp->power_save;
8311da177e4SLinus Torvalds 	bus->ops = temp->ops;
8321da177e4SLinus Torvalds 
83362932df8SIngo Molnar 	mutex_init(&bus->cmd_mutex);
8343f50ac6aSTakashi Iwai 	mutex_init(&bus->prepare_mutex);
8351da177e4SLinus Torvalds 	INIT_LIST_HEAD(&bus->codec_list);
8361da177e4SLinus Torvalds 
837e8c0ee5dSTakashi Iwai 	snprintf(bus->workq_name, sizeof(bus->workq_name),
838e8c0ee5dSTakashi Iwai 		 "hd-audio%d", card->number);
839e8c0ee5dSTakashi Iwai 	bus->workq = create_singlethread_workqueue(bus->workq_name);
8406acaed38STakashi Iwai 	if (!bus->workq) {
841e8c0ee5dSTakashi Iwai 		snd_printk(KERN_ERR "cannot create workqueue %s\n",
842e8c0ee5dSTakashi Iwai 			   bus->workq_name);
8436acaed38STakashi Iwai 		kfree(bus);
8446acaed38STakashi Iwai 		return -ENOMEM;
8456acaed38STakashi Iwai 	}
8466acaed38STakashi Iwai 
8470ba21762STakashi Iwai 	err = snd_device_new(card, SNDRV_DEV_BUS, bus, &dev_ops);
8480ba21762STakashi Iwai 	if (err < 0) {
8491da177e4SLinus Torvalds 		snd_hda_bus_free(bus);
8501da177e4SLinus Torvalds 		return err;
8511da177e4SLinus Torvalds 	}
8521da177e4SLinus Torvalds 	if (busp)
8531da177e4SLinus Torvalds 		*busp = bus;
8541da177e4SLinus Torvalds 	return 0;
8551da177e4SLinus Torvalds }
856ff7a3267STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_bus_new);
8571da177e4SLinus Torvalds 
85882467611STakashi Iwai #ifdef CONFIG_SND_HDA_GENERIC
85982467611STakashi Iwai #define is_generic_config(codec) \
860f44ac837STakashi Iwai 	(codec->modelname && !strcmp(codec->modelname, "generic"))
86182467611STakashi Iwai #else
86282467611STakashi Iwai #define is_generic_config(codec)	0
86382467611STakashi Iwai #endif
86482467611STakashi Iwai 
865645f10c1STakashi Iwai #ifdef MODULE
8661289e9e8STakashi Iwai #define HDA_MODREQ_MAX_COUNT	2	/* two request_modules()'s */
8671289e9e8STakashi Iwai #else
868645f10c1STakashi Iwai #define HDA_MODREQ_MAX_COUNT	0	/* all presets are statically linked */
8691289e9e8STakashi Iwai #endif
8701289e9e8STakashi Iwai 
8711da177e4SLinus Torvalds /*
8721da177e4SLinus Torvalds  * find a matching codec preset
8731da177e4SLinus Torvalds  */
8746c1f45eaSTakashi Iwai static const struct hda_codec_preset *
875756e2b01STakashi Iwai find_codec_preset(struct hda_codec *codec)
8761da177e4SLinus Torvalds {
8771289e9e8STakashi Iwai 	struct hda_codec_preset_list *tbl;
8781289e9e8STakashi Iwai 	const struct hda_codec_preset *preset;
8795d908ab9STakashi Iwai 	unsigned int mod_requested = 0;
8801da177e4SLinus Torvalds 
88182467611STakashi Iwai 	if (is_generic_config(codec))
882d5ad630bSTakashi Iwai 		return NULL; /* use the generic parser */
883d5ad630bSTakashi Iwai 
8841289e9e8STakashi Iwai  again:
8851289e9e8STakashi Iwai 	mutex_lock(&preset_mutex);
8861289e9e8STakashi Iwai 	list_for_each_entry(tbl, &hda_preset_tables, list) {
8871289e9e8STakashi Iwai 		if (!try_module_get(tbl->owner)) {
8881289e9e8STakashi Iwai 			snd_printk(KERN_ERR "hda_codec: cannot module_get\n");
8891289e9e8STakashi Iwai 			continue;
8901289e9e8STakashi Iwai 		}
8911289e9e8STakashi Iwai 		for (preset = tbl->preset; preset->id; preset++) {
8921da177e4SLinus Torvalds 			u32 mask = preset->mask;
893ca7cfae9SMarc Boucher 			if (preset->afg && preset->afg != codec->afg)
894ca7cfae9SMarc Boucher 				continue;
895ca7cfae9SMarc Boucher 			if (preset->mfg && preset->mfg != codec->mfg)
896ca7cfae9SMarc Boucher 				continue;
8971da177e4SLinus Torvalds 			if (!mask)
8981da177e4SLinus Torvalds 				mask = ~0;
8999c7f852eSTakashi Iwai 			if (preset->id == (codec->vendor_id & mask) &&
9009c7f852eSTakashi Iwai 			    (!preset->rev ||
9011289e9e8STakashi Iwai 			     preset->rev == codec->revision_id)) {
9021289e9e8STakashi Iwai 				mutex_unlock(&preset_mutex);
9031289e9e8STakashi Iwai 				codec->owner = tbl->owner;
9041da177e4SLinus Torvalds 				return preset;
9051da177e4SLinus Torvalds 			}
9061da177e4SLinus Torvalds 		}
9071289e9e8STakashi Iwai 		module_put(tbl->owner);
9081289e9e8STakashi Iwai 	}
9091289e9e8STakashi Iwai 	mutex_unlock(&preset_mutex);
9101289e9e8STakashi Iwai 
9111289e9e8STakashi Iwai 	if (mod_requested < HDA_MODREQ_MAX_COUNT) {
9121289e9e8STakashi Iwai 		char name[32];
9131289e9e8STakashi Iwai 		if (!mod_requested)
9141289e9e8STakashi Iwai 			snprintf(name, sizeof(name), "snd-hda-codec-id:%08x",
9151289e9e8STakashi Iwai 				 codec->vendor_id);
9161289e9e8STakashi Iwai 		else
9171289e9e8STakashi Iwai 			snprintf(name, sizeof(name), "snd-hda-codec-id:%04x*",
9181289e9e8STakashi Iwai 				 (codec->vendor_id >> 16) & 0xffff);
9191289e9e8STakashi Iwai 		request_module(name);
9201289e9e8STakashi Iwai 		mod_requested++;
9211289e9e8STakashi Iwai 		goto again;
9221289e9e8STakashi Iwai 	}
9231da177e4SLinus Torvalds 	return NULL;
9241da177e4SLinus Torvalds }
9251da177e4SLinus Torvalds 
9261da177e4SLinus Torvalds /*
927f44ac837STakashi Iwai  * get_codec_name - store the codec name
9281da177e4SLinus Torvalds  */
929f44ac837STakashi Iwai static int get_codec_name(struct hda_codec *codec)
9301da177e4SLinus Torvalds {
9311da177e4SLinus Torvalds 	const struct hda_vendor_id *c;
9321da177e4SLinus Torvalds 	const char *vendor = NULL;
9331da177e4SLinus Torvalds 	u16 vendor_id = codec->vendor_id >> 16;
934812a2ccaSTakashi Iwai 	char tmp[16];
935812a2ccaSTakashi Iwai 
936812a2ccaSTakashi Iwai 	if (codec->vendor_name)
937812a2ccaSTakashi Iwai 		goto get_chip_name;
9381da177e4SLinus Torvalds 
9391da177e4SLinus Torvalds 	for (c = hda_vendor_ids; c->id; c++) {
9401da177e4SLinus Torvalds 		if (c->id == vendor_id) {
9411da177e4SLinus Torvalds 			vendor = c->name;
9421da177e4SLinus Torvalds 			break;
9431da177e4SLinus Torvalds 		}
9441da177e4SLinus Torvalds 	}
9451da177e4SLinus Torvalds 	if (!vendor) {
9461da177e4SLinus Torvalds 		sprintf(tmp, "Generic %04x", vendor_id);
9471da177e4SLinus Torvalds 		vendor = tmp;
9481da177e4SLinus Torvalds 	}
949812a2ccaSTakashi Iwai 	codec->vendor_name = kstrdup(vendor, GFP_KERNEL);
950812a2ccaSTakashi Iwai 	if (!codec->vendor_name)
951812a2ccaSTakashi Iwai 		return -ENOMEM;
952812a2ccaSTakashi Iwai 
953812a2ccaSTakashi Iwai  get_chip_name:
954812a2ccaSTakashi Iwai 	if (codec->chip_name)
955812a2ccaSTakashi Iwai 		return 0;
956812a2ccaSTakashi Iwai 
9571da177e4SLinus Torvalds 	if (codec->preset && codec->preset->name)
958812a2ccaSTakashi Iwai 		codec->chip_name = kstrdup(codec->preset->name, GFP_KERNEL);
959812a2ccaSTakashi Iwai 	else {
960812a2ccaSTakashi Iwai 		sprintf(tmp, "ID %x", codec->vendor_id & 0xffff);
961812a2ccaSTakashi Iwai 		codec->chip_name = kstrdup(tmp, GFP_KERNEL);
962812a2ccaSTakashi Iwai 	}
963812a2ccaSTakashi Iwai 	if (!codec->chip_name)
964f44ac837STakashi Iwai 		return -ENOMEM;
965f44ac837STakashi Iwai 	return 0;
9661da177e4SLinus Torvalds }
9671da177e4SLinus Torvalds 
9681da177e4SLinus Torvalds /*
969673b683aSSasha Khapyorsky  * look for an AFG and MFG nodes
9701da177e4SLinus Torvalds  */
9716a0f56a7STakashi Iwai static void setup_fg_nodes(struct hda_codec *codec)
9721da177e4SLinus Torvalds {
97393e82ae7STakashi Iwai 	int i, total_nodes, function_id;
9741da177e4SLinus Torvalds 	hda_nid_t nid;
9751da177e4SLinus Torvalds 
9761da177e4SLinus Torvalds 	total_nodes = snd_hda_get_sub_nodes(codec, AC_NODE_ROOT, &nid);
9771da177e4SLinus Torvalds 	for (i = 0; i < total_nodes; i++, nid++) {
97893e82ae7STakashi Iwai 		function_id = snd_hda_param_read(codec, nid,
97979c944adSJaroslav Kysela 						AC_PAR_FUNCTION_TYPE);
980cd7643bfSJaroslav Kysela 		switch (function_id & 0xff) {
981673b683aSSasha Khapyorsky 		case AC_GRP_AUDIO_FUNCTION:
982673b683aSSasha Khapyorsky 			codec->afg = nid;
98379c944adSJaroslav Kysela 			codec->afg_function_id = function_id & 0xff;
98479c944adSJaroslav Kysela 			codec->afg_unsol = (function_id >> 8) & 1;
985673b683aSSasha Khapyorsky 			break;
986673b683aSSasha Khapyorsky 		case AC_GRP_MODEM_FUNCTION:
987673b683aSSasha Khapyorsky 			codec->mfg = nid;
98879c944adSJaroslav Kysela 			codec->mfg_function_id = function_id & 0xff;
98979c944adSJaroslav Kysela 			codec->mfg_unsol = (function_id >> 8) & 1;
990673b683aSSasha Khapyorsky 			break;
991673b683aSSasha Khapyorsky 		default:
992673b683aSSasha Khapyorsky 			break;
9931da177e4SLinus Torvalds 		}
994673b683aSSasha Khapyorsky 	}
9951da177e4SLinus Torvalds }
9961da177e4SLinus Torvalds 
9971da177e4SLinus Torvalds /*
99854d17403STakashi Iwai  * read widget caps for each widget and store in cache
99954d17403STakashi Iwai  */
100054d17403STakashi Iwai static int read_widget_caps(struct hda_codec *codec, hda_nid_t fg_node)
100154d17403STakashi Iwai {
100254d17403STakashi Iwai 	int i;
100354d17403STakashi Iwai 	hda_nid_t nid;
100454d17403STakashi Iwai 
100554d17403STakashi Iwai 	codec->num_nodes = snd_hda_get_sub_nodes(codec, fg_node,
100654d17403STakashi Iwai 						 &codec->start_nid);
100754d17403STakashi Iwai 	codec->wcaps = kmalloc(codec->num_nodes * 4, GFP_KERNEL);
100854d17403STakashi Iwai 	if (!codec->wcaps)
100954d17403STakashi Iwai 		return -ENOMEM;
101054d17403STakashi Iwai 	nid = codec->start_nid;
101154d17403STakashi Iwai 	for (i = 0; i < codec->num_nodes; i++, nid++)
101254d17403STakashi Iwai 		codec->wcaps[i] = snd_hda_param_read(codec, nid,
101354d17403STakashi Iwai 						     AC_PAR_AUDIO_WIDGET_CAP);
101454d17403STakashi Iwai 	return 0;
101554d17403STakashi Iwai }
101654d17403STakashi Iwai 
10173be14149STakashi Iwai /* read all pin default configurations and save codec->init_pins */
10183be14149STakashi Iwai static int read_pin_defaults(struct hda_codec *codec)
10193be14149STakashi Iwai {
10203be14149STakashi Iwai 	int i;
10213be14149STakashi Iwai 	hda_nid_t nid = codec->start_nid;
10223be14149STakashi Iwai 
10233be14149STakashi Iwai 	for (i = 0; i < codec->num_nodes; i++, nid++) {
10243be14149STakashi Iwai 		struct hda_pincfg *pin;
10253be14149STakashi Iwai 		unsigned int wcaps = get_wcaps(codec, nid);
1026a22d543aSTakashi Iwai 		unsigned int wid_type = get_wcaps_type(wcaps);
10273be14149STakashi Iwai 		if (wid_type != AC_WID_PIN)
10283be14149STakashi Iwai 			continue;
10293be14149STakashi Iwai 		pin = snd_array_new(&codec->init_pins);
10303be14149STakashi Iwai 		if (!pin)
10313be14149STakashi Iwai 			return -ENOMEM;
10323be14149STakashi Iwai 		pin->nid = nid;
10333be14149STakashi Iwai 		pin->cfg = snd_hda_codec_read(codec, nid, 0,
10343be14149STakashi Iwai 					      AC_VERB_GET_CONFIG_DEFAULT, 0);
1035ac0547dcSTakashi Iwai 		pin->ctrl = snd_hda_codec_read(codec, nid, 0,
1036ac0547dcSTakashi Iwai 					       AC_VERB_GET_PIN_WIDGET_CONTROL,
1037ac0547dcSTakashi Iwai 					       0);
10383be14149STakashi Iwai 	}
10393be14149STakashi Iwai 	return 0;
10403be14149STakashi Iwai }
10413be14149STakashi Iwai 
10423be14149STakashi Iwai /* look up the given pin config list and return the item matching with NID */
10433be14149STakashi Iwai static struct hda_pincfg *look_up_pincfg(struct hda_codec *codec,
10443be14149STakashi Iwai 					 struct snd_array *array,
10453be14149STakashi Iwai 					 hda_nid_t nid)
10463be14149STakashi Iwai {
10473be14149STakashi Iwai 	int i;
10483be14149STakashi Iwai 	for (i = 0; i < array->used; i++) {
10493be14149STakashi Iwai 		struct hda_pincfg *pin = snd_array_elem(array, i);
10503be14149STakashi Iwai 		if (pin->nid == nid)
10513be14149STakashi Iwai 			return pin;
10523be14149STakashi Iwai 	}
10533be14149STakashi Iwai 	return NULL;
10543be14149STakashi Iwai }
10553be14149STakashi Iwai 
10563be14149STakashi Iwai /* set the current pin config value for the given NID.
10573be14149STakashi Iwai  * the value is cached, and read via snd_hda_codec_get_pincfg()
10583be14149STakashi Iwai  */
10593be14149STakashi Iwai int snd_hda_add_pincfg(struct hda_codec *codec, struct snd_array *list,
10603be14149STakashi Iwai 		       hda_nid_t nid, unsigned int cfg)
10613be14149STakashi Iwai {
10623be14149STakashi Iwai 	struct hda_pincfg *pin;
10633be14149STakashi Iwai 
1064b82855a0STakashi Iwai 	if (get_wcaps_type(get_wcaps(codec, nid)) != AC_WID_PIN)
1065b82855a0STakashi Iwai 		return -EINVAL;
1066b82855a0STakashi Iwai 
10673be14149STakashi Iwai 	pin = look_up_pincfg(codec, list, nid);
10683be14149STakashi Iwai 	if (!pin) {
10693be14149STakashi Iwai 		pin = snd_array_new(list);
10703be14149STakashi Iwai 		if (!pin)
10713be14149STakashi Iwai 			return -ENOMEM;
10723be14149STakashi Iwai 		pin->nid = nid;
10733be14149STakashi Iwai 	}
10743be14149STakashi Iwai 	pin->cfg = cfg;
10753be14149STakashi Iwai 	return 0;
10763be14149STakashi Iwai }
10773be14149STakashi Iwai 
1078d5191e50STakashi Iwai /**
1079d5191e50STakashi Iwai  * snd_hda_codec_set_pincfg - Override a pin default configuration
1080d5191e50STakashi Iwai  * @codec: the HDA codec
1081d5191e50STakashi Iwai  * @nid: NID to set the pin config
1082d5191e50STakashi Iwai  * @cfg: the pin default config value
1083d5191e50STakashi Iwai  *
1084d5191e50STakashi Iwai  * Override a pin default configuration value in the cache.
1085d5191e50STakashi Iwai  * This value can be read by snd_hda_codec_get_pincfg() in a higher
1086d5191e50STakashi Iwai  * priority than the real hardware value.
1087d5191e50STakashi Iwai  */
10883be14149STakashi Iwai int snd_hda_codec_set_pincfg(struct hda_codec *codec,
10893be14149STakashi Iwai 			     hda_nid_t nid, unsigned int cfg)
10903be14149STakashi Iwai {
1091346ff70fSTakashi Iwai 	return snd_hda_add_pincfg(codec, &codec->driver_pins, nid, cfg);
10923be14149STakashi Iwai }
10933be14149STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_codec_set_pincfg);
10943be14149STakashi Iwai 
1095d5191e50STakashi Iwai /**
1096d5191e50STakashi Iwai  * snd_hda_codec_get_pincfg - Obtain a pin-default configuration
1097d5191e50STakashi Iwai  * @codec: the HDA codec
1098d5191e50STakashi Iwai  * @nid: NID to get the pin config
1099d5191e50STakashi Iwai  *
1100d5191e50STakashi Iwai  * Get the current pin config value of the given pin NID.
1101d5191e50STakashi Iwai  * If the pincfg value is cached or overridden via sysfs or driver,
1102d5191e50STakashi Iwai  * returns the cached value.
1103d5191e50STakashi Iwai  */
11043be14149STakashi Iwai unsigned int snd_hda_codec_get_pincfg(struct hda_codec *codec, hda_nid_t nid)
11053be14149STakashi Iwai {
11063be14149STakashi Iwai 	struct hda_pincfg *pin;
11073be14149STakashi Iwai 
11083be14149STakashi Iwai #ifdef CONFIG_SND_HDA_HWDEP
110909b70e85STakashi Iwai 	{
111009b70e85STakashi Iwai 		unsigned int cfg = 0;
111109b70e85STakashi Iwai 		mutex_lock(&codec->user_mutex);
1112346ff70fSTakashi Iwai 		pin = look_up_pincfg(codec, &codec->user_pins, nid);
11133be14149STakashi Iwai 		if (pin)
111409b70e85STakashi Iwai 			cfg = pin->cfg;
111509b70e85STakashi Iwai 		mutex_unlock(&codec->user_mutex);
111609b70e85STakashi Iwai 		if (cfg)
111709b70e85STakashi Iwai 			return cfg;
111809b70e85STakashi Iwai 	}
11193be14149STakashi Iwai #endif
11205e7b8e0dSTakashi Iwai 	pin = look_up_pincfg(codec, &codec->driver_pins, nid);
11215e7b8e0dSTakashi Iwai 	if (pin)
11225e7b8e0dSTakashi Iwai 		return pin->cfg;
11233be14149STakashi Iwai 	pin = look_up_pincfg(codec, &codec->init_pins, nid);
11243be14149STakashi Iwai 	if (pin)
11253be14149STakashi Iwai 		return pin->cfg;
11263be14149STakashi Iwai 	return 0;
11273be14149STakashi Iwai }
11283be14149STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_codec_get_pincfg);
11293be14149STakashi Iwai 
1130d7fdc00aSTakashi Iwai /* remember the current pinctl target value */
1131d7fdc00aSTakashi Iwai int snd_hda_codec_set_pin_target(struct hda_codec *codec, hda_nid_t nid,
1132d7fdc00aSTakashi Iwai 				 unsigned int val)
1133d7fdc00aSTakashi Iwai {
1134d7fdc00aSTakashi Iwai 	struct hda_pincfg *pin;
1135d7fdc00aSTakashi Iwai 
1136d7fdc00aSTakashi Iwai 	pin = look_up_pincfg(codec, &codec->init_pins, nid);
1137d7fdc00aSTakashi Iwai 	if (!pin)
1138d7fdc00aSTakashi Iwai 		return -EINVAL;
1139d7fdc00aSTakashi Iwai 	pin->target = val;
1140d7fdc00aSTakashi Iwai 	return 0;
1141d7fdc00aSTakashi Iwai }
1142d7fdc00aSTakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_codec_set_pin_target);
1143d7fdc00aSTakashi Iwai 
1144d7fdc00aSTakashi Iwai /* return the current pinctl target value */
1145d7fdc00aSTakashi Iwai int snd_hda_codec_get_pin_target(struct hda_codec *codec, hda_nid_t nid)
1146d7fdc00aSTakashi Iwai {
1147d7fdc00aSTakashi Iwai 	struct hda_pincfg *pin;
1148d7fdc00aSTakashi Iwai 
1149d7fdc00aSTakashi Iwai 	pin = look_up_pincfg(codec, &codec->init_pins, nid);
1150d7fdc00aSTakashi Iwai 	if (!pin)
1151d7fdc00aSTakashi Iwai 		return 0;
1152d7fdc00aSTakashi Iwai 	return pin->target;
1153d7fdc00aSTakashi Iwai }
1154d7fdc00aSTakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_codec_get_pin_target);
1155d7fdc00aSTakashi Iwai 
115692ee6162STakashi Iwai /**
115792ee6162STakashi Iwai  * snd_hda_shutup_pins - Shut up all pins
115892ee6162STakashi Iwai  * @codec: the HDA codec
115992ee6162STakashi Iwai  *
116092ee6162STakashi Iwai  * Clear all pin controls to shup up before suspend for avoiding click noise.
116192ee6162STakashi Iwai  * The controls aren't cached so that they can be resumed properly.
116292ee6162STakashi Iwai  */
116392ee6162STakashi Iwai void snd_hda_shutup_pins(struct hda_codec *codec)
116492ee6162STakashi Iwai {
116592ee6162STakashi Iwai 	int i;
1166ac0547dcSTakashi Iwai 	/* don't shut up pins when unloading the driver; otherwise it breaks
1167ac0547dcSTakashi Iwai 	 * the default pin setup at the next load of the driver
1168ac0547dcSTakashi Iwai 	 */
1169ac0547dcSTakashi Iwai 	if (codec->bus->shutdown)
1170ac0547dcSTakashi Iwai 		return;
117192ee6162STakashi Iwai 	for (i = 0; i < codec->init_pins.used; i++) {
117292ee6162STakashi Iwai 		struct hda_pincfg *pin = snd_array_elem(&codec->init_pins, i);
117392ee6162STakashi Iwai 		/* use read here for syncing after issuing each verb */
117492ee6162STakashi Iwai 		snd_hda_codec_read(codec, pin->nid, 0,
117592ee6162STakashi Iwai 				   AC_VERB_SET_PIN_WIDGET_CONTROL, 0);
117692ee6162STakashi Iwai 	}
1177ac0547dcSTakashi Iwai 	codec->pins_shutup = 1;
117892ee6162STakashi Iwai }
117992ee6162STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_shutup_pins);
118092ee6162STakashi Iwai 
11812a43952aSTakashi Iwai #ifdef CONFIG_PM
1182ac0547dcSTakashi Iwai /* Restore the pin controls cleared previously via snd_hda_shutup_pins() */
1183ac0547dcSTakashi Iwai static void restore_shutup_pins(struct hda_codec *codec)
1184ac0547dcSTakashi Iwai {
1185ac0547dcSTakashi Iwai 	int i;
1186ac0547dcSTakashi Iwai 	if (!codec->pins_shutup)
1187ac0547dcSTakashi Iwai 		return;
1188ac0547dcSTakashi Iwai 	if (codec->bus->shutdown)
1189ac0547dcSTakashi Iwai 		return;
1190ac0547dcSTakashi Iwai 	for (i = 0; i < codec->init_pins.used; i++) {
1191ac0547dcSTakashi Iwai 		struct hda_pincfg *pin = snd_array_elem(&codec->init_pins, i);
1192ac0547dcSTakashi Iwai 		snd_hda_codec_write(codec, pin->nid, 0,
1193ac0547dcSTakashi Iwai 				    AC_VERB_SET_PIN_WIDGET_CONTROL,
1194ac0547dcSTakashi Iwai 				    pin->ctrl);
1195ac0547dcSTakashi Iwai 	}
1196ac0547dcSTakashi Iwai 	codec->pins_shutup = 0;
1197ac0547dcSTakashi Iwai }
11981c7276cfSMike Waychison #endif
1199ac0547dcSTakashi Iwai 
120026a6cb6cSDavid Henningsson static void hda_jackpoll_work(struct work_struct *work)
120126a6cb6cSDavid Henningsson {
120226a6cb6cSDavid Henningsson 	struct hda_codec *codec =
120326a6cb6cSDavid Henningsson 		container_of(work, struct hda_codec, jackpoll_work.work);
120426a6cb6cSDavid Henningsson 	if (!codec->jackpoll_interval)
120526a6cb6cSDavid Henningsson 		return;
120626a6cb6cSDavid Henningsson 
120726a6cb6cSDavid Henningsson 	snd_hda_jack_set_dirty_all(codec);
120826a6cb6cSDavid Henningsson 	snd_hda_jack_poll_all(codec);
120926a6cb6cSDavid Henningsson 	queue_delayed_work(codec->bus->workq, &codec->jackpoll_work,
121026a6cb6cSDavid Henningsson 			   codec->jackpoll_interval);
121126a6cb6cSDavid Henningsson }
121226a6cb6cSDavid Henningsson 
121301751f54STakashi Iwai static void init_hda_cache(struct hda_cache_rec *cache,
121401751f54STakashi Iwai 			   unsigned int record_size);
12151fcaee6eSTakashi Iwai static void free_hda_cache(struct hda_cache_rec *cache);
121601751f54STakashi Iwai 
12173fdf1469STakashi Iwai /* release all pincfg lists */
12183fdf1469STakashi Iwai static void free_init_pincfgs(struct hda_codec *codec)
12193be14149STakashi Iwai {
1220346ff70fSTakashi Iwai 	snd_array_free(&codec->driver_pins);
12213be14149STakashi Iwai #ifdef CONFIG_SND_HDA_HWDEP
1222346ff70fSTakashi Iwai 	snd_array_free(&codec->user_pins);
12233be14149STakashi Iwai #endif
12243be14149STakashi Iwai 	snd_array_free(&codec->init_pins);
12253be14149STakashi Iwai }
12263be14149STakashi Iwai 
122754d17403STakashi Iwai /*
1228eb541337STakashi Iwai  * audio-converter setup caches
1229eb541337STakashi Iwai  */
1230eb541337STakashi Iwai struct hda_cvt_setup {
1231eb541337STakashi Iwai 	hda_nid_t nid;
1232eb541337STakashi Iwai 	u8 stream_tag;
1233eb541337STakashi Iwai 	u8 channel_id;
1234eb541337STakashi Iwai 	u16 format_id;
1235eb541337STakashi Iwai 	unsigned char active;	/* cvt is currently used */
1236eb541337STakashi Iwai 	unsigned char dirty;	/* setups should be cleared */
1237eb541337STakashi Iwai };
1238eb541337STakashi Iwai 
1239eb541337STakashi Iwai /* get or create a cache entry for the given audio converter NID */
1240eb541337STakashi Iwai static struct hda_cvt_setup *
1241eb541337STakashi Iwai get_hda_cvt_setup(struct hda_codec *codec, hda_nid_t nid)
1242eb541337STakashi Iwai {
1243eb541337STakashi Iwai 	struct hda_cvt_setup *p;
1244eb541337STakashi Iwai 	int i;
1245eb541337STakashi Iwai 
1246eb541337STakashi Iwai 	for (i = 0; i < codec->cvt_setups.used; i++) {
1247eb541337STakashi Iwai 		p = snd_array_elem(&codec->cvt_setups, i);
1248eb541337STakashi Iwai 		if (p->nid == nid)
1249eb541337STakashi Iwai 			return p;
1250eb541337STakashi Iwai 	}
1251eb541337STakashi Iwai 	p = snd_array_new(&codec->cvt_setups);
1252eb541337STakashi Iwai 	if (p)
1253eb541337STakashi Iwai 		p->nid = nid;
1254eb541337STakashi Iwai 	return p;
1255eb541337STakashi Iwai }
1256eb541337STakashi Iwai 
1257eb541337STakashi Iwai /*
12581da177e4SLinus Torvalds  * codec destructor
12591da177e4SLinus Torvalds  */
12601da177e4SLinus Torvalds static void snd_hda_codec_free(struct hda_codec *codec)
12611da177e4SLinus Torvalds {
12621da177e4SLinus Torvalds 	if (!codec)
12631da177e4SLinus Torvalds 		return;
126426a6cb6cSDavid Henningsson 	cancel_delayed_work_sync(&codec->jackpoll_work);
126559cad16bSTakashi Iwai 	snd_hda_jack_tbl_clear(codec);
12663fdf1469STakashi Iwai 	free_init_pincfgs(codec);
126783012a7cSTakashi Iwai #ifdef CONFIG_PM
1268cb53c626STakashi Iwai 	cancel_delayed_work(&codec->power_work);
12696acaed38STakashi Iwai 	flush_workqueue(codec->bus->workq);
1270cb53c626STakashi Iwai #endif
12711da177e4SLinus Torvalds 	list_del(&codec->list);
1272d13bd412STakashi Iwai 	snd_array_free(&codec->mixers);
12735b0cb1d8SJaroslav Kysela 	snd_array_free(&codec->nids);
127459cad16bSTakashi Iwai 	snd_array_free(&codec->cvt_setups);
12757c935976SStephen Warren 	snd_array_free(&codec->spdif_out);
1276ee8e765bSTakashi Iwai 	remove_conn_list(codec);
12771da177e4SLinus Torvalds 	codec->bus->caddr_tbl[codec->addr] = NULL;
12781da177e4SLinus Torvalds 	if (codec->patch_ops.free)
12791da177e4SLinus Torvalds 		codec->patch_ops.free(codec);
128083012a7cSTakashi Iwai #ifdef CONFIG_PM
128108fa20aeSTakashi Iwai 	if (!codec->pm_down_notified) /* cancel leftover refcounts */
128268467f51STakashi Iwai 		hda_call_pm_notify(codec->bus, false);
128368467f51STakashi Iwai #endif
12841289e9e8STakashi Iwai 	module_put(codec->owner);
128501751f54STakashi Iwai 	free_hda_cache(&codec->amp_cache);
1286b3ac5636STakashi Iwai 	free_hda_cache(&codec->cmd_cache);
1287812a2ccaSTakashi Iwai 	kfree(codec->vendor_name);
1288812a2ccaSTakashi Iwai 	kfree(codec->chip_name);
1289f44ac837STakashi Iwai 	kfree(codec->modelname);
129054d17403STakashi Iwai 	kfree(codec->wcaps);
12911da177e4SLinus Torvalds 	kfree(codec);
12921da177e4SLinus Torvalds }
12931da177e4SLinus Torvalds 
1294b8dfc462SMengdong Lin static bool snd_hda_codec_get_supported_ps(struct hda_codec *codec,
1295b8dfc462SMengdong Lin 				hda_nid_t fg, unsigned int power_state);
1296b8dfc462SMengdong Lin 
1297d819387eSTakashi Iwai static unsigned int hda_set_power_state(struct hda_codec *codec,
1298bb6ac72fSTakashi Iwai 				unsigned int power_state);
12999419ab6bSTakashi Iwai static unsigned int default_power_filter(struct hda_codec *codec, hda_nid_t nid,
13009419ab6bSTakashi Iwai 					 unsigned int power_state);
1301bb6ac72fSTakashi Iwai 
13021da177e4SLinus Torvalds /**
13031da177e4SLinus Torvalds  * snd_hda_codec_new - create a HDA codec
13041da177e4SLinus Torvalds  * @bus: the bus to assign
13051da177e4SLinus Torvalds  * @codec_addr: the codec address
13061da177e4SLinus Torvalds  * @codecp: the pointer to store the generated codec
13071da177e4SLinus Torvalds  *
13081da177e4SLinus Torvalds  * Returns 0 if successful, or a negative error code.
13091da177e4SLinus Torvalds  */
13106a0f56a7STakashi Iwai int snd_hda_codec_new(struct hda_bus *bus,
131128aedaf7SNorberto Lopes 				unsigned int codec_addr,
1312a1e21c90STakashi Iwai 				struct hda_codec **codecp)
13131da177e4SLinus Torvalds {
13141da177e4SLinus Torvalds 	struct hda_codec *codec;
1315ba443687SJaroslav Kysela 	char component[31];
1316d819387eSTakashi Iwai 	hda_nid_t fg;
13171da177e4SLinus Torvalds 	int err;
13181da177e4SLinus Torvalds 
1319da3cec35STakashi Iwai 	if (snd_BUG_ON(!bus))
1320da3cec35STakashi Iwai 		return -EINVAL;
1321da3cec35STakashi Iwai 	if (snd_BUG_ON(codec_addr > HDA_MAX_CODEC_ADDRESS))
1322da3cec35STakashi Iwai 		return -EINVAL;
13231da177e4SLinus Torvalds 
13241da177e4SLinus Torvalds 	if (bus->caddr_tbl[codec_addr]) {
13250ba21762STakashi Iwai 		snd_printk(KERN_ERR "hda_codec: "
13260ba21762STakashi Iwai 			   "address 0x%x is already occupied\n", codec_addr);
13271da177e4SLinus Torvalds 		return -EBUSY;
13281da177e4SLinus Torvalds 	}
13291da177e4SLinus Torvalds 
1330e560d8d8STakashi Iwai 	codec = kzalloc(sizeof(*codec), GFP_KERNEL);
13311da177e4SLinus Torvalds 	if (codec == NULL) {
13321da177e4SLinus Torvalds 		snd_printk(KERN_ERR "can't allocate struct hda_codec\n");
13331da177e4SLinus Torvalds 		return -ENOMEM;
13341da177e4SLinus Torvalds 	}
13351da177e4SLinus Torvalds 
13361da177e4SLinus Torvalds 	codec->bus = bus;
13371da177e4SLinus Torvalds 	codec->addr = codec_addr;
133862932df8SIngo Molnar 	mutex_init(&codec->spdif_mutex);
13395a9e02e9SWu Fengguang 	mutex_init(&codec->control_mutex);
1340c3b6bcc2STakashi Iwai 	mutex_init(&codec->hash_mutex);
134101751f54STakashi Iwai 	init_hda_cache(&codec->amp_cache, sizeof(struct hda_amp_info));
1342b3ac5636STakashi Iwai 	init_hda_cache(&codec->cmd_cache, sizeof(struct hda_cache_head));
13435b0cb1d8SJaroslav Kysela 	snd_array_init(&codec->mixers, sizeof(struct hda_nid_item), 32);
13445b0cb1d8SJaroslav Kysela 	snd_array_init(&codec->nids, sizeof(struct hda_nid_item), 32);
13453be14149STakashi Iwai 	snd_array_init(&codec->init_pins, sizeof(struct hda_pincfg), 16);
1346346ff70fSTakashi Iwai 	snd_array_init(&codec->driver_pins, sizeof(struct hda_pincfg), 16);
1347eb541337STakashi Iwai 	snd_array_init(&codec->cvt_setups, sizeof(struct hda_cvt_setup), 8);
13487c935976SStephen Warren 	snd_array_init(&codec->spdif_out, sizeof(struct hda_spdif_out), 16);
1349361dab3eSTakashi Iwai 	snd_array_init(&codec->jacktbl, sizeof(struct hda_jack_tbl), 16);
1350c9ce6b26STakashi Iwai 	snd_array_init(&codec->verbs, sizeof(struct hda_verb *), 8);
1351ee8e765bSTakashi Iwai 	INIT_LIST_HEAD(&codec->conn_list);
1352ee8e765bSTakashi Iwai 
135326a6cb6cSDavid Henningsson 	INIT_DELAYED_WORK(&codec->jackpoll_work, hda_jackpoll_work);
13541da177e4SLinus Torvalds 
135583012a7cSTakashi Iwai #ifdef CONFIG_PM
13565536c6d6STakashi Iwai 	spin_lock_init(&codec->power_lock);
1357cb53c626STakashi Iwai 	INIT_DELAYED_WORK(&codec->power_work, hda_power_work);
1358cb53c626STakashi Iwai 	/* snd_hda_codec_new() marks the codec as power-up, and leave it as is.
1359cb53c626STakashi Iwai 	 * the caller has to power down appropriatley after initialization
1360cb53c626STakashi Iwai 	 * phase.
1361cb53c626STakashi Iwai 	 */
1362cb53c626STakashi Iwai 	hda_keep_power_on(codec);
136368467f51STakashi Iwai 	hda_call_pm_notify(bus, true);
1364cb53c626STakashi Iwai #endif
1365cb53c626STakashi Iwai 
1366c382a9f0STakashi Iwai 	if (codec->bus->modelname) {
1367c382a9f0STakashi Iwai 		codec->modelname = kstrdup(codec->bus->modelname, GFP_KERNEL);
1368c382a9f0STakashi Iwai 		if (!codec->modelname) {
1369c382a9f0STakashi Iwai 			snd_hda_codec_free(codec);
1370c382a9f0STakashi Iwai 			return -ENODEV;
1371c382a9f0STakashi Iwai 		}
1372c382a9f0STakashi Iwai 	}
1373c382a9f0STakashi Iwai 
13741da177e4SLinus Torvalds 	list_add_tail(&codec->list, &bus->codec_list);
13751da177e4SLinus Torvalds 	bus->caddr_tbl[codec_addr] = codec;
13761da177e4SLinus Torvalds 
13770ba21762STakashi Iwai 	codec->vendor_id = snd_hda_param_read(codec, AC_NODE_ROOT,
13780ba21762STakashi Iwai 					      AC_PAR_VENDOR_ID);
1379111d3af5STakashi Iwai 	if (codec->vendor_id == -1)
1380111d3af5STakashi Iwai 		/* read again, hopefully the access method was corrected
1381111d3af5STakashi Iwai 		 * in the last read...
1382111d3af5STakashi Iwai 		 */
1383111d3af5STakashi Iwai 		codec->vendor_id = snd_hda_param_read(codec, AC_NODE_ROOT,
1384111d3af5STakashi Iwai 						      AC_PAR_VENDOR_ID);
13850ba21762STakashi Iwai 	codec->subsystem_id = snd_hda_param_read(codec, AC_NODE_ROOT,
13860ba21762STakashi Iwai 						 AC_PAR_SUBSYSTEM_ID);
13870ba21762STakashi Iwai 	codec->revision_id = snd_hda_param_read(codec, AC_NODE_ROOT,
13880ba21762STakashi Iwai 						AC_PAR_REV_ID);
13891da177e4SLinus Torvalds 
1390673b683aSSasha Khapyorsky 	setup_fg_nodes(codec);
1391673b683aSSasha Khapyorsky 	if (!codec->afg && !codec->mfg) {
1392673b683aSSasha Khapyorsky 		snd_printdd("hda_codec: no AFG or MFG node found\n");
13933be14149STakashi Iwai 		err = -ENODEV;
13943be14149STakashi Iwai 		goto error;
13951da177e4SLinus Torvalds 	}
13961da177e4SLinus Torvalds 
1397d819387eSTakashi Iwai 	fg = codec->afg ? codec->afg : codec->mfg;
1398d819387eSTakashi Iwai 	err = read_widget_caps(codec, fg);
13993be14149STakashi Iwai 	if (err < 0) {
140054d17403STakashi Iwai 		snd_printk(KERN_ERR "hda_codec: cannot malloc\n");
14013be14149STakashi Iwai 		goto error;
140254d17403STakashi Iwai 	}
14033be14149STakashi Iwai 	err = read_pin_defaults(codec);
14043be14149STakashi Iwai 	if (err < 0)
14053be14149STakashi Iwai 		goto error;
140654d17403STakashi Iwai 
140786284e45STakashi Iwai 	if (!codec->subsystem_id) {
14080ba21762STakashi Iwai 		codec->subsystem_id =
1409d819387eSTakashi Iwai 			snd_hda_codec_read(codec, fg, 0,
14100ba21762STakashi Iwai 					   AC_VERB_GET_SUBSYSTEM_ID, 0);
141186284e45STakashi Iwai 	}
141286284e45STakashi Iwai 
141383012a7cSTakashi Iwai #ifdef CONFIG_PM
1414d819387eSTakashi Iwai 	codec->d3_stop_clk = snd_hda_codec_get_supported_ps(codec, fg,
1415b8dfc462SMengdong Lin 					AC_PWRST_CLKSTOP);
1416b8dfc462SMengdong Lin 	if (!codec->d3_stop_clk)
1417b8dfc462SMengdong Lin 		bus->power_keep_link_on = 1;
14185d6147f1SMengdong Lin #endif
1419d819387eSTakashi Iwai 	codec->epss = snd_hda_codec_get_supported_ps(codec, fg,
1420983f6b93STakashi Iwai 					AC_PWRST_EPSS);
14219419ab6bSTakashi Iwai 	codec->power_filter = default_power_filter;
1422b8dfc462SMengdong Lin 
1423bb6ac72fSTakashi Iwai 	/* power-up all before initialization */
1424d819387eSTakashi Iwai 	hda_set_power_state(codec, AC_PWRST_D0);
1425bb6ac72fSTakashi Iwai 
14266c1f45eaSTakashi Iwai 	snd_hda_codec_proc_new(codec);
14276c1f45eaSTakashi Iwai 
14286c1f45eaSTakashi Iwai 	snd_hda_create_hwdep(codec);
14296c1f45eaSTakashi Iwai 
14306c1f45eaSTakashi Iwai 	sprintf(component, "HDA:%08x,%08x,%08x", codec->vendor_id,
14316c1f45eaSTakashi Iwai 		codec->subsystem_id, codec->revision_id);
14326c1f45eaSTakashi Iwai 	snd_component_add(codec->bus->card, component);
14336c1f45eaSTakashi Iwai 
14346c1f45eaSTakashi Iwai 	if (codecp)
14356c1f45eaSTakashi Iwai 		*codecp = codec;
14366c1f45eaSTakashi Iwai 	return 0;
14373be14149STakashi Iwai 
14383be14149STakashi Iwai  error:
14393be14149STakashi Iwai 	snd_hda_codec_free(codec);
14403be14149STakashi Iwai 	return err;
14416c1f45eaSTakashi Iwai }
1442ff7a3267STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_codec_new);
14436c1f45eaSTakashi Iwai 
1444d5191e50STakashi Iwai /**
1445d5191e50STakashi Iwai  * snd_hda_codec_configure - (Re-)configure the HD-audio codec
1446d5191e50STakashi Iwai  * @codec: the HDA codec
1447d5191e50STakashi Iwai  *
1448d5191e50STakashi Iwai  * Start parsing of the given codec tree and (re-)initialize the whole
1449d5191e50STakashi Iwai  * patch instance.
1450d5191e50STakashi Iwai  *
1451d5191e50STakashi Iwai  * Returns 0 if successful or a negative error code.
1452d5191e50STakashi Iwai  */
14536c1f45eaSTakashi Iwai int snd_hda_codec_configure(struct hda_codec *codec)
14546c1f45eaSTakashi Iwai {
14556c1f45eaSTakashi Iwai 	int err;
14566c1f45eaSTakashi Iwai 
14571da177e4SLinus Torvalds 	codec->preset = find_codec_preset(codec);
1458812a2ccaSTakashi Iwai 	if (!codec->vendor_name || !codec->chip_name) {
1459f44ac837STakashi Iwai 		err = get_codec_name(codec);
1460f44ac837STakashi Iwai 		if (err < 0)
1461f44ac837STakashi Iwai 			return err;
1462f44ac837STakashi Iwai 	}
14631da177e4SLinus Torvalds 
146482467611STakashi Iwai 	if (is_generic_config(codec)) {
14651da177e4SLinus Torvalds 		err = snd_hda_parse_generic_codec(codec);
146682467611STakashi Iwai 		goto patched;
146782467611STakashi Iwai 	}
146882467611STakashi Iwai 	if (codec->preset && codec->preset->patch) {
146982467611STakashi Iwai 		err = codec->preset->patch(codec);
147082467611STakashi Iwai 		goto patched;
147182467611STakashi Iwai 	}
147282467611STakashi Iwai 
147382467611STakashi Iwai 	/* call the default parser */
147482467611STakashi Iwai 	err = snd_hda_parse_generic_codec(codec);
147535a1e0ccSTakashi Iwai 	if (err < 0)
147682467611STakashi Iwai 		printk(KERN_ERR "hda-codec: No codec parser is available\n");
147782467611STakashi Iwai 
147882467611STakashi Iwai  patched:
14796c1f45eaSTakashi Iwai 	if (!err && codec->patch_ops.unsol_event)
14806c1f45eaSTakashi Iwai 		err = init_unsol_queue(codec->bus);
1481f62faedbSTakashi Iwai 	/* audio codec should override the mixer name */
1482f62faedbSTakashi Iwai 	if (!err && (codec->afg || !*codec->bus->card->mixername))
1483f62faedbSTakashi Iwai 		snprintf(codec->bus->card->mixername,
1484f62faedbSTakashi Iwai 			 sizeof(codec->bus->card->mixername),
1485f62faedbSTakashi Iwai 			 "%s %s", codec->vendor_name, codec->chip_name);
14861da177e4SLinus Torvalds 	return err;
14871da177e4SLinus Torvalds }
1488a1e21c90STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_codec_configure);
14891da177e4SLinus Torvalds 
1490ed360813STakashi Iwai /* update the stream-id if changed */
1491ed360813STakashi Iwai static void update_pcm_stream_id(struct hda_codec *codec,
1492ed360813STakashi Iwai 				 struct hda_cvt_setup *p, hda_nid_t nid,
1493ed360813STakashi Iwai 				 u32 stream_tag, int channel_id)
1494ed360813STakashi Iwai {
1495ed360813STakashi Iwai 	unsigned int oldval, newval;
1496ed360813STakashi Iwai 
1497ed360813STakashi Iwai 	if (p->stream_tag != stream_tag || p->channel_id != channel_id) {
1498ed360813STakashi Iwai 		oldval = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONV, 0);
1499ed360813STakashi Iwai 		newval = (stream_tag << 4) | channel_id;
1500ed360813STakashi Iwai 		if (oldval != newval)
1501ed360813STakashi Iwai 			snd_hda_codec_write(codec, nid, 0,
1502ed360813STakashi Iwai 					    AC_VERB_SET_CHANNEL_STREAMID,
1503ed360813STakashi Iwai 					    newval);
1504ed360813STakashi Iwai 		p->stream_tag = stream_tag;
1505ed360813STakashi Iwai 		p->channel_id = channel_id;
1506ed360813STakashi Iwai 	}
1507ed360813STakashi Iwai }
1508ed360813STakashi Iwai 
1509ed360813STakashi Iwai /* update the format-id if changed */
1510ed360813STakashi Iwai static void update_pcm_format(struct hda_codec *codec, struct hda_cvt_setup *p,
1511ed360813STakashi Iwai 			      hda_nid_t nid, int format)
1512ed360813STakashi Iwai {
1513ed360813STakashi Iwai 	unsigned int oldval;
1514ed360813STakashi Iwai 
1515ed360813STakashi Iwai 	if (p->format_id != format) {
1516ed360813STakashi Iwai 		oldval = snd_hda_codec_read(codec, nid, 0,
1517ed360813STakashi Iwai 					    AC_VERB_GET_STREAM_FORMAT, 0);
1518ed360813STakashi Iwai 		if (oldval != format) {
1519ed360813STakashi Iwai 			msleep(1);
1520ed360813STakashi Iwai 			snd_hda_codec_write(codec, nid, 0,
1521ed360813STakashi Iwai 					    AC_VERB_SET_STREAM_FORMAT,
1522ed360813STakashi Iwai 					    format);
1523ed360813STakashi Iwai 		}
1524ed360813STakashi Iwai 		p->format_id = format;
1525ed360813STakashi Iwai 	}
1526ed360813STakashi Iwai }
1527ed360813STakashi Iwai 
15281da177e4SLinus Torvalds /**
15291da177e4SLinus Torvalds  * snd_hda_codec_setup_stream - set up the codec for streaming
15301da177e4SLinus Torvalds  * @codec: the CODEC to set up
15311da177e4SLinus Torvalds  * @nid: the NID to set up
15321da177e4SLinus Torvalds  * @stream_tag: stream tag to pass, it's between 0x1 and 0xf.
15331da177e4SLinus Torvalds  * @channel_id: channel id to pass, zero based.
15341da177e4SLinus Torvalds  * @format: stream format.
15351da177e4SLinus Torvalds  */
15360ba21762STakashi Iwai void snd_hda_codec_setup_stream(struct hda_codec *codec, hda_nid_t nid,
15370ba21762STakashi Iwai 				u32 stream_tag,
15381da177e4SLinus Torvalds 				int channel_id, int format)
15391da177e4SLinus Torvalds {
15403f50ac6aSTakashi Iwai 	struct hda_codec *c;
1541eb541337STakashi Iwai 	struct hda_cvt_setup *p;
154262b7e5e0STakashi Iwai 	int type;
1543eb541337STakashi Iwai 	int i;
1544eb541337STakashi Iwai 
1545d21b37eaSTakashi Iwai 	if (!nid)
1546d21b37eaSTakashi Iwai 		return;
1547d21b37eaSTakashi Iwai 
15480ba21762STakashi Iwai 	snd_printdd("hda_codec_setup_stream: "
15490ba21762STakashi Iwai 		    "NID=0x%x, stream=0x%x, channel=%d, format=0x%x\n",
15501da177e4SLinus Torvalds 		    nid, stream_tag, channel_id, format);
1551eb541337STakashi Iwai 	p = get_hda_cvt_setup(codec, nid);
1552affdb62bSTakashi Iwai 	if (!p || p->active)
1553eb541337STakashi Iwai 		return;
1554ed360813STakashi Iwai 
1555ed360813STakashi Iwai 	if (codec->pcm_format_first)
1556ed360813STakashi Iwai 		update_pcm_format(codec, p, nid, format);
1557ed360813STakashi Iwai 	update_pcm_stream_id(codec, p, nid, stream_tag, channel_id);
1558ed360813STakashi Iwai 	if (!codec->pcm_format_first)
1559ed360813STakashi Iwai 		update_pcm_format(codec, p, nid, format);
1560ed360813STakashi Iwai 
1561eb541337STakashi Iwai 	p->active = 1;
1562eb541337STakashi Iwai 	p->dirty = 0;
1563eb541337STakashi Iwai 
1564eb541337STakashi Iwai 	/* make other inactive cvts with the same stream-tag dirty */
156562b7e5e0STakashi Iwai 	type = get_wcaps_type(get_wcaps(codec, nid));
15663f50ac6aSTakashi Iwai 	list_for_each_entry(c, &codec->bus->codec_list, list) {
15673f50ac6aSTakashi Iwai 		for (i = 0; i < c->cvt_setups.used; i++) {
15683f50ac6aSTakashi Iwai 			p = snd_array_elem(&c->cvt_setups, i);
156962b7e5e0STakashi Iwai 			if (!p->active && p->stream_tag == stream_tag &&
157054c2a89fSDavid Henningsson 			    get_wcaps_type(get_wcaps(c, p->nid)) == type)
1571eb541337STakashi Iwai 				p->dirty = 1;
1572eb541337STakashi Iwai 		}
15731da177e4SLinus Torvalds 	}
15743f50ac6aSTakashi Iwai }
1575ff7a3267STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_codec_setup_stream);
15761da177e4SLinus Torvalds 
1577f0cea797STakashi Iwai static void really_cleanup_stream(struct hda_codec *codec,
1578f0cea797STakashi Iwai 				  struct hda_cvt_setup *q);
1579f0cea797STakashi Iwai 
1580d5191e50STakashi Iwai /**
1581f0cea797STakashi Iwai  * __snd_hda_codec_cleanup_stream - clean up the codec for closing
1582d5191e50STakashi Iwai  * @codec: the CODEC to clean up
1583d5191e50STakashi Iwai  * @nid: the NID to clean up
1584f0cea797STakashi Iwai  * @do_now: really clean up the stream instead of clearing the active flag
1585d5191e50STakashi Iwai  */
1586f0cea797STakashi Iwai void __snd_hda_codec_cleanup_stream(struct hda_codec *codec, hda_nid_t nid,
1587f0cea797STakashi Iwai 				    int do_now)
1588888afa15STakashi Iwai {
1589eb541337STakashi Iwai 	struct hda_cvt_setup *p;
1590eb541337STakashi Iwai 
1591888afa15STakashi Iwai 	if (!nid)
1592888afa15STakashi Iwai 		return;
1593888afa15STakashi Iwai 
15940e7adbe2STakashi Iwai 	if (codec->no_sticky_stream)
15950e7adbe2STakashi Iwai 		do_now = 1;
15960e7adbe2STakashi Iwai 
1597888afa15STakashi Iwai 	snd_printdd("hda_codec_cleanup_stream: NID=0x%x\n", nid);
1598eb541337STakashi Iwai 	p = get_hda_cvt_setup(codec, nid);
1599affdb62bSTakashi Iwai 	if (p && p->active) {
1600f0cea797STakashi Iwai 		/* here we just clear the active flag when do_now isn't set;
1601f0cea797STakashi Iwai 		 * actual clean-ups will be done later in
1602f0cea797STakashi Iwai 		 * purify_inactive_streams() called from snd_hda_codec_prpapre()
1603f0cea797STakashi Iwai 		 */
1604f0cea797STakashi Iwai 		if (do_now)
1605f0cea797STakashi Iwai 			really_cleanup_stream(codec, p);
1606f0cea797STakashi Iwai 		else
1607eb541337STakashi Iwai 			p->active = 0;
1608888afa15STakashi Iwai 	}
1609f0cea797STakashi Iwai }
1610f0cea797STakashi Iwai EXPORT_SYMBOL_HDA(__snd_hda_codec_cleanup_stream);
1611888afa15STakashi Iwai 
1612eb541337STakashi Iwai static void really_cleanup_stream(struct hda_codec *codec,
1613eb541337STakashi Iwai 				  struct hda_cvt_setup *q)
1614eb541337STakashi Iwai {
1615eb541337STakashi Iwai 	hda_nid_t nid = q->nid;
1616218264aeSTakashi Iwai 	if (q->stream_tag || q->channel_id)
1617eb541337STakashi Iwai 		snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CHANNEL_STREAMID, 0);
1618218264aeSTakashi Iwai 	if (q->format_id)
1619218264aeSTakashi Iwai 		snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_STREAM_FORMAT, 0
1620218264aeSTakashi Iwai );
1621eb541337STakashi Iwai 	memset(q, 0, sizeof(*q));
1622eb541337STakashi Iwai 	q->nid = nid;
1623eb541337STakashi Iwai }
1624eb541337STakashi Iwai 
1625eb541337STakashi Iwai /* clean up the all conflicting obsolete streams */
1626eb541337STakashi Iwai static void purify_inactive_streams(struct hda_codec *codec)
1627eb541337STakashi Iwai {
16283f50ac6aSTakashi Iwai 	struct hda_codec *c;
1629eb541337STakashi Iwai 	int i;
1630eb541337STakashi Iwai 
16313f50ac6aSTakashi Iwai 	list_for_each_entry(c, &codec->bus->codec_list, list) {
16323f50ac6aSTakashi Iwai 		for (i = 0; i < c->cvt_setups.used; i++) {
16333f50ac6aSTakashi Iwai 			struct hda_cvt_setup *p;
16343f50ac6aSTakashi Iwai 			p = snd_array_elem(&c->cvt_setups, i);
1635eb541337STakashi Iwai 			if (p->dirty)
16363f50ac6aSTakashi Iwai 				really_cleanup_stream(c, p);
16373f50ac6aSTakashi Iwai 		}
1638eb541337STakashi Iwai 	}
1639eb541337STakashi Iwai }
1640eb541337STakashi Iwai 
16412a43952aSTakashi Iwai #ifdef CONFIG_PM
1642eb541337STakashi Iwai /* clean up all streams; called from suspend */
1643eb541337STakashi Iwai static void hda_cleanup_all_streams(struct hda_codec *codec)
1644eb541337STakashi Iwai {
1645eb541337STakashi Iwai 	int i;
1646eb541337STakashi Iwai 
1647eb541337STakashi Iwai 	for (i = 0; i < codec->cvt_setups.used; i++) {
1648eb541337STakashi Iwai 		struct hda_cvt_setup *p = snd_array_elem(&codec->cvt_setups, i);
1649eb541337STakashi Iwai 		if (p->stream_tag)
1650eb541337STakashi Iwai 			really_cleanup_stream(codec, p);
1651eb541337STakashi Iwai 	}
1652eb541337STakashi Iwai }
16531c7276cfSMike Waychison #endif
1654eb541337STakashi Iwai 
16551da177e4SLinus Torvalds /*
16561da177e4SLinus Torvalds  * amp access functions
16571da177e4SLinus Torvalds  */
16581da177e4SLinus Torvalds 
16594a19faeeSTakashi Iwai /* FIXME: more better hash key? */
16604a19faeeSTakashi Iwai #define HDA_HASH_KEY(nid, dir, idx) (u32)((nid) + ((idx) << 16) + ((dir) << 24))
16611327a32bSTakashi Iwai #define HDA_HASH_PINCAP_KEY(nid) (u32)((nid) + (0x02 << 24))
166292c7c8a7STakashi Iwai #define HDA_HASH_PARPCM_KEY(nid) (u32)((nid) + (0x03 << 24))
166392c7c8a7STakashi Iwai #define HDA_HASH_PARSTR_KEY(nid) (u32)((nid) + (0x04 << 24))
16641da177e4SLinus Torvalds #define INFO_AMP_CAPS	(1<<0)
16654a19faeeSTakashi Iwai #define INFO_AMP_VOL(ch)	(1 << (1 + (ch)))
16661da177e4SLinus Torvalds 
16671da177e4SLinus Torvalds /* initialize the hash table */
16686a0f56a7STakashi Iwai static void init_hda_cache(struct hda_cache_rec *cache,
166901751f54STakashi Iwai 				     unsigned int record_size)
16701da177e4SLinus Torvalds {
167101751f54STakashi Iwai 	memset(cache, 0, sizeof(*cache));
167201751f54STakashi Iwai 	memset(cache->hash, 0xff, sizeof(cache->hash));
1673603c4019STakashi Iwai 	snd_array_init(&cache->buf, record_size, 64);
167401751f54STakashi Iwai }
167501751f54STakashi Iwai 
16761fcaee6eSTakashi Iwai static void free_hda_cache(struct hda_cache_rec *cache)
167701751f54STakashi Iwai {
1678603c4019STakashi Iwai 	snd_array_free(&cache->buf);
16791da177e4SLinus Torvalds }
16801da177e4SLinus Torvalds 
16811da177e4SLinus Torvalds /* query the hash.  allocate an entry if not found. */
1682a68d5a54STakashi Iwai static struct hda_cache_head  *get_hash(struct hda_cache_rec *cache, u32 key)
16831da177e4SLinus Torvalds {
168401751f54STakashi Iwai 	u16 idx = key % (u16)ARRAY_SIZE(cache->hash);
168501751f54STakashi Iwai 	u16 cur = cache->hash[idx];
168601751f54STakashi Iwai 	struct hda_cache_head *info;
16871da177e4SLinus Torvalds 
16881da177e4SLinus Torvalds 	while (cur != 0xffff) {
1689f43aa025STakashi Iwai 		info = snd_array_elem(&cache->buf, cur);
16901da177e4SLinus Torvalds 		if (info->key == key)
16911da177e4SLinus Torvalds 			return info;
16921da177e4SLinus Torvalds 		cur = info->next;
16931da177e4SLinus Torvalds 	}
1694a68d5a54STakashi Iwai 	return NULL;
1695a68d5a54STakashi Iwai }
16961da177e4SLinus Torvalds 
1697a68d5a54STakashi Iwai /* query the hash.  allocate an entry if not found. */
1698a68d5a54STakashi Iwai static struct hda_cache_head  *get_alloc_hash(struct hda_cache_rec *cache,
1699a68d5a54STakashi Iwai 					      u32 key)
1700a68d5a54STakashi Iwai {
1701a68d5a54STakashi Iwai 	struct hda_cache_head *info = get_hash(cache, key);
1702a68d5a54STakashi Iwai 	if (!info) {
1703a68d5a54STakashi Iwai 		u16 idx, cur;
17041da177e4SLinus Torvalds 		/* add a new hash entry */
1705603c4019STakashi Iwai 		info = snd_array_new(&cache->buf);
1706c217429bSTakashi Iwai 		if (!info)
1707c217429bSTakashi Iwai 			return NULL;
1708f43aa025STakashi Iwai 		cur = snd_array_index(&cache->buf, info);
17091da177e4SLinus Torvalds 		info->key = key;
171001751f54STakashi Iwai 		info->val = 0;
1711c370dd6eSTakashi Iwai 		info->dirty = 0;
1712a68d5a54STakashi Iwai 		idx = key % (u16)ARRAY_SIZE(cache->hash);
171301751f54STakashi Iwai 		info->next = cache->hash[idx];
171401751f54STakashi Iwai 		cache->hash[idx] = cur;
1715a68d5a54STakashi Iwai 	}
17161da177e4SLinus Torvalds 	return info;
17171da177e4SLinus Torvalds }
17181da177e4SLinus Torvalds 
171901751f54STakashi Iwai /* query and allocate an amp hash entry */
172001751f54STakashi Iwai static inline struct hda_amp_info *
172101751f54STakashi Iwai get_alloc_amp_hash(struct hda_codec *codec, u32 key)
172201751f54STakashi Iwai {
172301751f54STakashi Iwai 	return (struct hda_amp_info *)get_alloc_hash(&codec->amp_cache, key);
172401751f54STakashi Iwai }
172501751f54STakashi Iwai 
1726c3b6bcc2STakashi Iwai /* overwrite the value with the key in the caps hash */
1727c3b6bcc2STakashi Iwai static int write_caps_hash(struct hda_codec *codec, u32 key, unsigned int val)
1728c3b6bcc2STakashi Iwai {
1729c3b6bcc2STakashi Iwai 	struct hda_amp_info *info;
1730c3b6bcc2STakashi Iwai 
1731c3b6bcc2STakashi Iwai 	mutex_lock(&codec->hash_mutex);
1732c3b6bcc2STakashi Iwai 	info = get_alloc_amp_hash(codec, key);
1733c3b6bcc2STakashi Iwai 	if (!info) {
1734c3b6bcc2STakashi Iwai 		mutex_unlock(&codec->hash_mutex);
1735c3b6bcc2STakashi Iwai 		return -EINVAL;
1736c3b6bcc2STakashi Iwai 	}
1737c3b6bcc2STakashi Iwai 	info->amp_caps = val;
1738c3b6bcc2STakashi Iwai 	info->head.val |= INFO_AMP_CAPS;
1739c3b6bcc2STakashi Iwai 	mutex_unlock(&codec->hash_mutex);
1740c3b6bcc2STakashi Iwai 	return 0;
1741c3b6bcc2STakashi Iwai }
1742c3b6bcc2STakashi Iwai 
1743c3b6bcc2STakashi Iwai /* query the value from the caps hash; if not found, fetch the current
1744c3b6bcc2STakashi Iwai  * value from the given function and store in the hash
1745c3b6bcc2STakashi Iwai  */
1746c3b6bcc2STakashi Iwai static unsigned int
1747c3b6bcc2STakashi Iwai query_caps_hash(struct hda_codec *codec, hda_nid_t nid, int dir, u32 key,
1748c3b6bcc2STakashi Iwai 		unsigned int (*func)(struct hda_codec *, hda_nid_t, int))
1749c3b6bcc2STakashi Iwai {
1750c3b6bcc2STakashi Iwai 	struct hda_amp_info *info;
1751c3b6bcc2STakashi Iwai 	unsigned int val;
1752c3b6bcc2STakashi Iwai 
1753c3b6bcc2STakashi Iwai 	mutex_lock(&codec->hash_mutex);
1754c3b6bcc2STakashi Iwai 	info = get_alloc_amp_hash(codec, key);
1755c3b6bcc2STakashi Iwai 	if (!info) {
1756c3b6bcc2STakashi Iwai 		mutex_unlock(&codec->hash_mutex);
1757c3b6bcc2STakashi Iwai 		return 0;
1758c3b6bcc2STakashi Iwai 	}
1759c3b6bcc2STakashi Iwai 	if (!(info->head.val & INFO_AMP_CAPS)) {
1760c3b6bcc2STakashi Iwai 		mutex_unlock(&codec->hash_mutex); /* for reentrance */
1761c3b6bcc2STakashi Iwai 		val = func(codec, nid, dir);
1762c3b6bcc2STakashi Iwai 		write_caps_hash(codec, key, val);
1763c3b6bcc2STakashi Iwai 	} else {
1764c3b6bcc2STakashi Iwai 		val = info->amp_caps;
1765c3b6bcc2STakashi Iwai 		mutex_unlock(&codec->hash_mutex);
1766c3b6bcc2STakashi Iwai 	}
1767c3b6bcc2STakashi Iwai 	return val;
1768c3b6bcc2STakashi Iwai }
1769c3b6bcc2STakashi Iwai 
1770c3b6bcc2STakashi Iwai static unsigned int read_amp_cap(struct hda_codec *codec, hda_nid_t nid,
1771c3b6bcc2STakashi Iwai 				 int direction)
1772c3b6bcc2STakashi Iwai {
1773c3b6bcc2STakashi Iwai 	if (!(get_wcaps(codec, nid) & AC_WCAP_AMP_OVRD))
1774c3b6bcc2STakashi Iwai 		nid = codec->afg;
1775c3b6bcc2STakashi Iwai 	return snd_hda_param_read(codec, nid,
1776c3b6bcc2STakashi Iwai 				  direction == HDA_OUTPUT ?
1777c3b6bcc2STakashi Iwai 				  AC_PAR_AMP_OUT_CAP : AC_PAR_AMP_IN_CAP);
1778c3b6bcc2STakashi Iwai }
1779c3b6bcc2STakashi Iwai 
1780d5191e50STakashi Iwai /**
1781d5191e50STakashi Iwai  * query_amp_caps - query AMP capabilities
1782d5191e50STakashi Iwai  * @codec: the HD-auio codec
1783d5191e50STakashi Iwai  * @nid: the NID to query
1784d5191e50STakashi Iwai  * @direction: either #HDA_INPUT or #HDA_OUTPUT
1785d5191e50STakashi Iwai  *
1786d5191e50STakashi Iwai  * Query AMP capabilities for the given widget and direction.
1787d5191e50STakashi Iwai  * Returns the obtained capability bits.
1788d5191e50STakashi Iwai  *
1789d5191e50STakashi Iwai  * When cap bits have been already read, this doesn't read again but
1790d5191e50STakashi Iwai  * returns the cached value.
17911da177e4SLinus Torvalds  */
179209a99959SMatthew Ranostay u32 query_amp_caps(struct hda_codec *codec, hda_nid_t nid, int direction)
17931da177e4SLinus Torvalds {
1794c3b6bcc2STakashi Iwai 	return query_caps_hash(codec, nid, direction,
1795c3b6bcc2STakashi Iwai 			       HDA_HASH_KEY(nid, direction, 0),
1796c3b6bcc2STakashi Iwai 			       read_amp_cap);
17971da177e4SLinus Torvalds }
1798ff7a3267STakashi Iwai EXPORT_SYMBOL_HDA(query_amp_caps);
17991da177e4SLinus Torvalds 
1800d5191e50STakashi Iwai /**
1801d5191e50STakashi Iwai  * snd_hda_override_amp_caps - Override the AMP capabilities
1802d5191e50STakashi Iwai  * @codec: the CODEC to clean up
1803d5191e50STakashi Iwai  * @nid: the NID to clean up
1804d5191e50STakashi Iwai  * @direction: either #HDA_INPUT or #HDA_OUTPUT
1805d5191e50STakashi Iwai  * @caps: the capability bits to set
1806d5191e50STakashi Iwai  *
1807d5191e50STakashi Iwai  * Override the cached AMP caps bits value by the given one.
1808d5191e50STakashi Iwai  * This function is useful if the driver needs to adjust the AMP ranges,
1809d5191e50STakashi Iwai  * e.g. limit to 0dB, etc.
1810d5191e50STakashi Iwai  *
1811d5191e50STakashi Iwai  * Returns zero if successful or a negative error code.
1812d5191e50STakashi Iwai  */
1813897cc188STakashi Iwai int snd_hda_override_amp_caps(struct hda_codec *codec, hda_nid_t nid, int dir,
1814897cc188STakashi Iwai 			      unsigned int caps)
1815897cc188STakashi Iwai {
1816c3b6bcc2STakashi Iwai 	return write_caps_hash(codec, HDA_HASH_KEY(nid, dir, 0), caps);
1817897cc188STakashi Iwai }
1818ff7a3267STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_override_amp_caps);
1819897cc188STakashi Iwai 
1820c3b6bcc2STakashi Iwai static unsigned int read_pin_cap(struct hda_codec *codec, hda_nid_t nid,
1821c3b6bcc2STakashi Iwai 				 int dir)
182292c7c8a7STakashi Iwai {
182392c7c8a7STakashi Iwai 	return snd_hda_param_read(codec, nid, AC_PAR_PIN_CAP);
182492c7c8a7STakashi Iwai }
182592c7c8a7STakashi Iwai 
1826d5191e50STakashi Iwai /**
1827d5191e50STakashi Iwai  * snd_hda_query_pin_caps - Query PIN capabilities
1828d5191e50STakashi Iwai  * @codec: the HD-auio codec
1829d5191e50STakashi Iwai  * @nid: the NID to query
1830d5191e50STakashi Iwai  *
1831d5191e50STakashi Iwai  * Query PIN capabilities for the given widget.
1832d5191e50STakashi Iwai  * Returns the obtained capability bits.
1833d5191e50STakashi Iwai  *
1834d5191e50STakashi Iwai  * When cap bits have been already read, this doesn't read again but
1835d5191e50STakashi Iwai  * returns the cached value.
1836d5191e50STakashi Iwai  */
183792c7c8a7STakashi Iwai u32 snd_hda_query_pin_caps(struct hda_codec *codec, hda_nid_t nid)
183892c7c8a7STakashi Iwai {
1839c3b6bcc2STakashi Iwai 	return query_caps_hash(codec, nid, 0, HDA_HASH_PINCAP_KEY(nid),
184092c7c8a7STakashi Iwai 			       read_pin_cap);
184192c7c8a7STakashi Iwai }
18421327a32bSTakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_query_pin_caps);
18431327a32bSTakashi Iwai 
1844864f92beSWu Fengguang /**
1845f57c2565STakashi Iwai  * snd_hda_override_pin_caps - Override the pin capabilities
1846f57c2565STakashi Iwai  * @codec: the CODEC
1847f57c2565STakashi Iwai  * @nid: the NID to override
1848f57c2565STakashi Iwai  * @caps: the capability bits to set
1849f57c2565STakashi Iwai  *
1850f57c2565STakashi Iwai  * Override the cached PIN capabilitiy bits value by the given one.
1851f57c2565STakashi Iwai  *
1852f57c2565STakashi Iwai  * Returns zero if successful or a negative error code.
1853f57c2565STakashi Iwai  */
1854f57c2565STakashi Iwai int snd_hda_override_pin_caps(struct hda_codec *codec, hda_nid_t nid,
1855f57c2565STakashi Iwai 			      unsigned int caps)
1856f57c2565STakashi Iwai {
1857c3b6bcc2STakashi Iwai 	return write_caps_hash(codec, HDA_HASH_PINCAP_KEY(nid), caps);
1858f57c2565STakashi Iwai }
1859f57c2565STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_override_pin_caps);
1860f57c2565STakashi Iwai 
1861c3b6bcc2STakashi Iwai /* read or sync the hash value with the current value;
1862c3b6bcc2STakashi Iwai  * call within hash_mutex
18631da177e4SLinus Torvalds  */
1864c3b6bcc2STakashi Iwai static struct hda_amp_info *
1865c3b6bcc2STakashi Iwai update_amp_hash(struct hda_codec *codec, hda_nid_t nid, int ch,
1866280e57d5STakashi Iwai 		int direction, int index, bool init_only)
18671da177e4SLinus Torvalds {
1868c3b6bcc2STakashi Iwai 	struct hda_amp_info *info;
1869c3b6bcc2STakashi Iwai 	unsigned int parm, val = 0;
1870c3b6bcc2STakashi Iwai 	bool val_read = false;
18711da177e4SLinus Torvalds 
1872c3b6bcc2STakashi Iwai  retry:
1873c3b6bcc2STakashi Iwai 	info = get_alloc_amp_hash(codec, HDA_HASH_KEY(nid, direction, index));
1874c3b6bcc2STakashi Iwai 	if (!info)
1875c3b6bcc2STakashi Iwai 		return NULL;
1876c3b6bcc2STakashi Iwai 	if (!(info->head.val & INFO_AMP_VOL(ch))) {
1877c3b6bcc2STakashi Iwai 		if (!val_read) {
1878c3b6bcc2STakashi Iwai 			mutex_unlock(&codec->hash_mutex);
18791da177e4SLinus Torvalds 			parm = ch ? AC_AMP_GET_RIGHT : AC_AMP_GET_LEFT;
1880c3b6bcc2STakashi Iwai 			parm |= direction == HDA_OUTPUT ?
1881c3b6bcc2STakashi Iwai 				AC_AMP_GET_OUTPUT : AC_AMP_GET_INPUT;
18821da177e4SLinus Torvalds 			parm |= index;
18830ba21762STakashi Iwai 			val = snd_hda_codec_read(codec, nid, 0,
18840ba21762STakashi Iwai 				 AC_VERB_GET_AMP_GAIN_MUTE, parm);
1885c3b6bcc2STakashi Iwai 			val &= 0xff;
1886c3b6bcc2STakashi Iwai 			val_read = true;
1887c3b6bcc2STakashi Iwai 			mutex_lock(&codec->hash_mutex);
1888c3b6bcc2STakashi Iwai 			goto retry;
1889c3b6bcc2STakashi Iwai 		}
1890c3b6bcc2STakashi Iwai 		info->vol[ch] = val;
189101751f54STakashi Iwai 		info->head.val |= INFO_AMP_VOL(ch);
1892280e57d5STakashi Iwai 	} else if (init_only)
1893280e57d5STakashi Iwai 		return NULL;
1894c3b6bcc2STakashi Iwai 	return info;
18951da177e4SLinus Torvalds }
18961da177e4SLinus Torvalds 
18971da177e4SLinus Torvalds /*
1898c3b6bcc2STakashi Iwai  * write the current volume in info to the h/w
18991da177e4SLinus Torvalds  */
19002ce4886aSTakashi Iwai static void put_vol_mute(struct hda_codec *codec, unsigned int amp_caps,
19010ba21762STakashi Iwai 			 hda_nid_t nid, int ch, int direction, int index,
19020ba21762STakashi Iwai 			 int val)
19031da177e4SLinus Torvalds {
19041da177e4SLinus Torvalds 	u32 parm;
19051da177e4SLinus Torvalds 
19061da177e4SLinus Torvalds 	parm = ch ? AC_AMP_SET_RIGHT : AC_AMP_SET_LEFT;
19071da177e4SLinus Torvalds 	parm |= direction == HDA_OUTPUT ? AC_AMP_SET_OUTPUT : AC_AMP_SET_INPUT;
19081da177e4SLinus Torvalds 	parm |= index << AC_AMP_SET_INDEX_SHIFT;
19092ce4886aSTakashi Iwai 	if ((val & HDA_AMP_MUTE) && !(amp_caps & AC_AMPCAP_MUTE) &&
19102ce4886aSTakashi Iwai 	    (amp_caps & AC_AMPCAP_MIN_MUTE))
19113868137eSTakashi Iwai 		; /* set the zero value as a fake mute */
19123868137eSTakashi Iwai 	else
19131da177e4SLinus Torvalds 		parm |= val;
19141da177e4SLinus Torvalds 	snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, parm);
19151da177e4SLinus Torvalds }
19161da177e4SLinus Torvalds 
1917d5191e50STakashi Iwai /**
1918d5191e50STakashi Iwai  * snd_hda_codec_amp_read - Read AMP value
1919d5191e50STakashi Iwai  * @codec: HD-audio codec
1920d5191e50STakashi Iwai  * @nid: NID to read the AMP value
1921d5191e50STakashi Iwai  * @ch: channel (left=0 or right=1)
1922d5191e50STakashi Iwai  * @direction: #HDA_INPUT or #HDA_OUTPUT
1923d5191e50STakashi Iwai  * @index: the index value (only for input direction)
1924d5191e50STakashi Iwai  *
1925d5191e50STakashi Iwai  * Read AMP value.  The volume is between 0 to 0x7f, 0x80 = mute bit.
19261da177e4SLinus Torvalds  */
1927834be88dSTakashi Iwai int snd_hda_codec_amp_read(struct hda_codec *codec, hda_nid_t nid, int ch,
1928834be88dSTakashi Iwai 			   int direction, int index)
19291da177e4SLinus Torvalds {
19300ba21762STakashi Iwai 	struct hda_amp_info *info;
1931c3b6bcc2STakashi Iwai 	unsigned int val = 0;
1932c3b6bcc2STakashi Iwai 
1933c3b6bcc2STakashi Iwai 	mutex_lock(&codec->hash_mutex);
1934280e57d5STakashi Iwai 	info = update_amp_hash(codec, nid, ch, direction, index, false);
1935c3b6bcc2STakashi Iwai 	if (info)
1936c3b6bcc2STakashi Iwai 		val = info->vol[ch];
1937c3b6bcc2STakashi Iwai 	mutex_unlock(&codec->hash_mutex);
1938c3b6bcc2STakashi Iwai 	return val;
19391da177e4SLinus Torvalds }
1940ff7a3267STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_codec_amp_read);
19411da177e4SLinus Torvalds 
1942280e57d5STakashi Iwai static int codec_amp_update(struct hda_codec *codec, hda_nid_t nid, int ch,
1943280e57d5STakashi Iwai 			    int direction, int idx, int mask, int val,
1944280e57d5STakashi Iwai 			    bool init_only)
1945280e57d5STakashi Iwai {
1946280e57d5STakashi Iwai 	struct hda_amp_info *info;
19472ce4886aSTakashi Iwai 	unsigned int caps;
1948de1e37b7STakashi Iwai 	unsigned int cache_only;
1949280e57d5STakashi Iwai 
1950280e57d5STakashi Iwai 	if (snd_BUG_ON(mask & ~0xff))
1951280e57d5STakashi Iwai 		mask &= 0xff;
1952280e57d5STakashi Iwai 	val &= mask;
1953280e57d5STakashi Iwai 
1954280e57d5STakashi Iwai 	mutex_lock(&codec->hash_mutex);
1955280e57d5STakashi Iwai 	info = update_amp_hash(codec, nid, ch, direction, idx, init_only);
1956280e57d5STakashi Iwai 	if (!info) {
1957280e57d5STakashi Iwai 		mutex_unlock(&codec->hash_mutex);
1958280e57d5STakashi Iwai 		return 0;
1959280e57d5STakashi Iwai 	}
1960280e57d5STakashi Iwai 	val |= info->vol[ch] & ~mask;
1961280e57d5STakashi Iwai 	if (info->vol[ch] == val) {
1962280e57d5STakashi Iwai 		mutex_unlock(&codec->hash_mutex);
1963280e57d5STakashi Iwai 		return 0;
1964280e57d5STakashi Iwai 	}
1965280e57d5STakashi Iwai 	info->vol[ch] = val;
1966de1e37b7STakashi Iwai 	cache_only = info->head.dirty = codec->cached_write;
19672ce4886aSTakashi Iwai 	caps = info->amp_caps;
1968280e57d5STakashi Iwai 	mutex_unlock(&codec->hash_mutex);
1969de1e37b7STakashi Iwai 	if (!cache_only)
19702ce4886aSTakashi Iwai 		put_vol_mute(codec, caps, nid, ch, direction, idx, val);
1971280e57d5STakashi Iwai 	return 1;
1972280e57d5STakashi Iwai }
1973280e57d5STakashi Iwai 
1974d5191e50STakashi Iwai /**
1975d5191e50STakashi Iwai  * snd_hda_codec_amp_update - update the AMP value
1976d5191e50STakashi Iwai  * @codec: HD-audio codec
1977d5191e50STakashi Iwai  * @nid: NID to read the AMP value
1978d5191e50STakashi Iwai  * @ch: channel (left=0 or right=1)
1979d5191e50STakashi Iwai  * @direction: #HDA_INPUT or #HDA_OUTPUT
1980d5191e50STakashi Iwai  * @idx: the index value (only for input direction)
1981d5191e50STakashi Iwai  * @mask: bit mask to set
1982d5191e50STakashi Iwai  * @val: the bits value to set
1983d5191e50STakashi Iwai  *
1984d5191e50STakashi Iwai  * Update the AMP value with a bit mask.
1985d5191e50STakashi Iwai  * Returns 0 if the value is unchanged, 1 if changed.
19864a19faeeSTakashi Iwai  */
1987834be88dSTakashi Iwai int snd_hda_codec_amp_update(struct hda_codec *codec, hda_nid_t nid, int ch,
1988834be88dSTakashi Iwai 			     int direction, int idx, int mask, int val)
19891da177e4SLinus Torvalds {
1990280e57d5STakashi Iwai 	return codec_amp_update(codec, nid, ch, direction, idx, mask, val, false);
19911da177e4SLinus Torvalds }
1992ff7a3267STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_codec_amp_update);
19931da177e4SLinus Torvalds 
1994d5191e50STakashi Iwai /**
1995d5191e50STakashi Iwai  * snd_hda_codec_amp_stereo - update the AMP stereo values
1996d5191e50STakashi Iwai  * @codec: HD-audio codec
1997d5191e50STakashi Iwai  * @nid: NID to read the AMP value
1998d5191e50STakashi Iwai  * @direction: #HDA_INPUT or #HDA_OUTPUT
1999d5191e50STakashi Iwai  * @idx: the index value (only for input direction)
2000d5191e50STakashi Iwai  * @mask: bit mask to set
2001d5191e50STakashi Iwai  * @val: the bits value to set
2002d5191e50STakashi Iwai  *
2003d5191e50STakashi Iwai  * Update the AMP values like snd_hda_codec_amp_update(), but for a
2004d5191e50STakashi Iwai  * stereo widget with the same mask and value.
200547fd830aSTakashi Iwai  */
200647fd830aSTakashi Iwai int snd_hda_codec_amp_stereo(struct hda_codec *codec, hda_nid_t nid,
200747fd830aSTakashi Iwai 			     int direction, int idx, int mask, int val)
200847fd830aSTakashi Iwai {
200947fd830aSTakashi Iwai 	int ch, ret = 0;
201046712646STakashi Iwai 
201146712646STakashi Iwai 	if (snd_BUG_ON(mask & ~0xff))
201246712646STakashi Iwai 		mask &= 0xff;
201347fd830aSTakashi Iwai 	for (ch = 0; ch < 2; ch++)
201447fd830aSTakashi Iwai 		ret |= snd_hda_codec_amp_update(codec, nid, ch, direction,
201547fd830aSTakashi Iwai 						idx, mask, val);
201647fd830aSTakashi Iwai 	return ret;
201747fd830aSTakashi Iwai }
2018ff7a3267STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_codec_amp_stereo);
201947fd830aSTakashi Iwai 
2020280e57d5STakashi Iwai /* Works like snd_hda_codec_amp_update() but it writes the value only at
2021280e57d5STakashi Iwai  * the first access.  If the amp was already initialized / updated beforehand,
2022280e57d5STakashi Iwai  * this does nothing.
2023280e57d5STakashi Iwai  */
2024280e57d5STakashi Iwai int snd_hda_codec_amp_init(struct hda_codec *codec, hda_nid_t nid, int ch,
2025280e57d5STakashi Iwai 			   int dir, int idx, int mask, int val)
2026280e57d5STakashi Iwai {
2027280e57d5STakashi Iwai 	return codec_amp_update(codec, nid, ch, dir, idx, mask, val, true);
2028280e57d5STakashi Iwai }
2029280e57d5STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_codec_amp_init);
2030280e57d5STakashi Iwai 
2031280e57d5STakashi Iwai int snd_hda_codec_amp_init_stereo(struct hda_codec *codec, hda_nid_t nid,
2032280e57d5STakashi Iwai 				  int dir, int idx, int mask, int val)
2033280e57d5STakashi Iwai {
2034280e57d5STakashi Iwai 	int ch, ret = 0;
2035280e57d5STakashi Iwai 
2036280e57d5STakashi Iwai 	if (snd_BUG_ON(mask & ~0xff))
2037280e57d5STakashi Iwai 		mask &= 0xff;
2038280e57d5STakashi Iwai 	for (ch = 0; ch < 2; ch++)
2039280e57d5STakashi Iwai 		ret |= snd_hda_codec_amp_init(codec, nid, ch, dir,
2040280e57d5STakashi Iwai 					      idx, mask, val);
2041280e57d5STakashi Iwai 	return ret;
2042280e57d5STakashi Iwai }
2043280e57d5STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_codec_amp_init_stereo);
2044280e57d5STakashi Iwai 
2045d5191e50STakashi Iwai /**
2046d5191e50STakashi Iwai  * snd_hda_codec_resume_amp - Resume all AMP commands from the cache
2047d5191e50STakashi Iwai  * @codec: HD-audio codec
2048d5191e50STakashi Iwai  *
2049d5191e50STakashi Iwai  * Resume the all amp commands from the cache.
2050d5191e50STakashi Iwai  */
2051b3ac5636STakashi Iwai void snd_hda_codec_resume_amp(struct hda_codec *codec)
2052b3ac5636STakashi Iwai {
2053b3ac5636STakashi Iwai 	int i;
2054b3ac5636STakashi Iwai 
2055c370dd6eSTakashi Iwai 	mutex_lock(&codec->hash_mutex);
2056aa88a355STakashi Iwai 	codec->cached_write = 0;
2057c370dd6eSTakashi Iwai 	for (i = 0; i < codec->amp_cache.buf.used; i++) {
2058c370dd6eSTakashi Iwai 		struct hda_amp_info *buffer;
2059c370dd6eSTakashi Iwai 		u32 key;
2060b3ac5636STakashi Iwai 		hda_nid_t nid;
2061b3ac5636STakashi Iwai 		unsigned int idx, dir, ch;
20622ce4886aSTakashi Iwai 		struct hda_amp_info info;
2063c370dd6eSTakashi Iwai 
2064c370dd6eSTakashi Iwai 		buffer = snd_array_elem(&codec->amp_cache.buf, i);
20658565f052STakashi Iwai 		if (!buffer->head.dirty)
20668565f052STakashi Iwai 			continue;
20678565f052STakashi Iwai 		buffer->head.dirty = 0;
20682ce4886aSTakashi Iwai 		info = *buffer;
20692ce4886aSTakashi Iwai 		key = info.head.key;
2070b3ac5636STakashi Iwai 		if (!key)
2071b3ac5636STakashi Iwai 			continue;
2072b3ac5636STakashi Iwai 		nid = key & 0xff;
2073b3ac5636STakashi Iwai 		idx = (key >> 16) & 0xff;
2074b3ac5636STakashi Iwai 		dir = (key >> 24) & 0xff;
2075b3ac5636STakashi Iwai 		for (ch = 0; ch < 2; ch++) {
20762ce4886aSTakashi Iwai 			if (!(info.head.val & INFO_AMP_VOL(ch)))
2077b3ac5636STakashi Iwai 				continue;
2078c370dd6eSTakashi Iwai 			mutex_unlock(&codec->hash_mutex);
20792ce4886aSTakashi Iwai 			put_vol_mute(codec, info.amp_caps, nid, ch, dir, idx,
20802ce4886aSTakashi Iwai 				     info.vol[ch]);
2081c370dd6eSTakashi Iwai 			mutex_lock(&codec->hash_mutex);
2082b3ac5636STakashi Iwai 		}
2083b3ac5636STakashi Iwai 	}
2084c370dd6eSTakashi Iwai 	mutex_unlock(&codec->hash_mutex);
2085b3ac5636STakashi Iwai }
2086ff7a3267STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_codec_resume_amp);
20871da177e4SLinus Torvalds 
2088afbd9b84STakashi Iwai static u32 get_amp_max_value(struct hda_codec *codec, hda_nid_t nid, int dir,
2089afbd9b84STakashi Iwai 			     unsigned int ofs)
2090afbd9b84STakashi Iwai {
2091afbd9b84STakashi Iwai 	u32 caps = query_amp_caps(codec, nid, dir);
2092afbd9b84STakashi Iwai 	/* get num steps */
2093afbd9b84STakashi Iwai 	caps = (caps & AC_AMPCAP_NUM_STEPS) >> AC_AMPCAP_NUM_STEPS_SHIFT;
2094afbd9b84STakashi Iwai 	if (ofs < caps)
2095afbd9b84STakashi Iwai 		caps -= ofs;
2096afbd9b84STakashi Iwai 	return caps;
2097afbd9b84STakashi Iwai }
2098afbd9b84STakashi Iwai 
2099d5191e50STakashi Iwai /**
2100d5191e50STakashi Iwai  * snd_hda_mixer_amp_volume_info - Info callback for a standard AMP mixer
2101d5191e50STakashi Iwai  *
2102d5191e50STakashi Iwai  * The control element is supposed to have the private_value field
2103d5191e50STakashi Iwai  * set up via HDA_COMPOSE_AMP_VAL*() or related macros.
2104d5191e50STakashi Iwai  */
21050ba21762STakashi Iwai int snd_hda_mixer_amp_volume_info(struct snd_kcontrol *kcontrol,
21060ba21762STakashi Iwai 				  struct snd_ctl_elem_info *uinfo)
21071da177e4SLinus Torvalds {
21081da177e4SLinus Torvalds 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
21091da177e4SLinus Torvalds 	u16 nid = get_amp_nid(kcontrol);
21101da177e4SLinus Torvalds 	u8 chs = get_amp_channels(kcontrol);
21111da177e4SLinus Torvalds 	int dir = get_amp_direction(kcontrol);
211229fdbec2STakashi Iwai 	unsigned int ofs = get_amp_offset(kcontrol);
21131da177e4SLinus Torvalds 
2114afbd9b84STakashi Iwai 	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
2115afbd9b84STakashi Iwai 	uinfo->count = chs == 3 ? 2 : 1;
2116afbd9b84STakashi Iwai 	uinfo->value.integer.min = 0;
2117afbd9b84STakashi Iwai 	uinfo->value.integer.max = get_amp_max_value(codec, nid, dir, ofs);
2118afbd9b84STakashi Iwai 	if (!uinfo->value.integer.max) {
21190ba21762STakashi Iwai 		printk(KERN_WARNING "hda_codec: "
21209c8f2abdSTakashi Iwai 		       "num_steps = 0 for NID=0x%x (ctl = %s)\n", nid,
21219c8f2abdSTakashi Iwai 		       kcontrol->id.name);
21221da177e4SLinus Torvalds 		return -EINVAL;
21231da177e4SLinus Torvalds 	}
21241da177e4SLinus Torvalds 	return 0;
21251da177e4SLinus Torvalds }
2126ff7a3267STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_volume_info);
21271da177e4SLinus Torvalds 
212829fdbec2STakashi Iwai 
212929fdbec2STakashi Iwai static inline unsigned int
213029fdbec2STakashi Iwai read_amp_value(struct hda_codec *codec, hda_nid_t nid,
213129fdbec2STakashi Iwai 	       int ch, int dir, int idx, unsigned int ofs)
213229fdbec2STakashi Iwai {
213329fdbec2STakashi Iwai 	unsigned int val;
213429fdbec2STakashi Iwai 	val = snd_hda_codec_amp_read(codec, nid, ch, dir, idx);
213529fdbec2STakashi Iwai 	val &= HDA_AMP_VOLMASK;
213629fdbec2STakashi Iwai 	if (val >= ofs)
213729fdbec2STakashi Iwai 		val -= ofs;
213829fdbec2STakashi Iwai 	else
213929fdbec2STakashi Iwai 		val = 0;
214029fdbec2STakashi Iwai 	return val;
214129fdbec2STakashi Iwai }
214229fdbec2STakashi Iwai 
214329fdbec2STakashi Iwai static inline int
214429fdbec2STakashi Iwai update_amp_value(struct hda_codec *codec, hda_nid_t nid,
214529fdbec2STakashi Iwai 		 int ch, int dir, int idx, unsigned int ofs,
214629fdbec2STakashi Iwai 		 unsigned int val)
214729fdbec2STakashi Iwai {
2148afbd9b84STakashi Iwai 	unsigned int maxval;
2149afbd9b84STakashi Iwai 
215029fdbec2STakashi Iwai 	if (val > 0)
215129fdbec2STakashi Iwai 		val += ofs;
21527ccc3efaSTakashi Iwai 	/* ofs = 0: raw max value */
21537ccc3efaSTakashi Iwai 	maxval = get_amp_max_value(codec, nid, dir, 0);
2154afbd9b84STakashi Iwai 	if (val > maxval)
2155afbd9b84STakashi Iwai 		val = maxval;
215629fdbec2STakashi Iwai 	return snd_hda_codec_amp_update(codec, nid, ch, dir, idx,
215729fdbec2STakashi Iwai 					HDA_AMP_VOLMASK, val);
215829fdbec2STakashi Iwai }
215929fdbec2STakashi Iwai 
2160d5191e50STakashi Iwai /**
2161d5191e50STakashi Iwai  * snd_hda_mixer_amp_volume_get - Get callback for a standard AMP mixer volume
2162d5191e50STakashi Iwai  *
2163d5191e50STakashi Iwai  * The control element is supposed to have the private_value field
2164d5191e50STakashi Iwai  * set up via HDA_COMPOSE_AMP_VAL*() or related macros.
2165d5191e50STakashi Iwai  */
21660ba21762STakashi Iwai int snd_hda_mixer_amp_volume_get(struct snd_kcontrol *kcontrol,
21670ba21762STakashi Iwai 				 struct snd_ctl_elem_value *ucontrol)
21681da177e4SLinus Torvalds {
21691da177e4SLinus Torvalds 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
21701da177e4SLinus Torvalds 	hda_nid_t nid = get_amp_nid(kcontrol);
21711da177e4SLinus Torvalds 	int chs = get_amp_channels(kcontrol);
21721da177e4SLinus Torvalds 	int dir = get_amp_direction(kcontrol);
21731da177e4SLinus Torvalds 	int idx = get_amp_index(kcontrol);
217429fdbec2STakashi Iwai 	unsigned int ofs = get_amp_offset(kcontrol);
21751da177e4SLinus Torvalds 	long *valp = ucontrol->value.integer.value;
21761da177e4SLinus Torvalds 
21771da177e4SLinus Torvalds 	if (chs & 1)
217829fdbec2STakashi Iwai 		*valp++ = read_amp_value(codec, nid, 0, dir, idx, ofs);
21791da177e4SLinus Torvalds 	if (chs & 2)
218029fdbec2STakashi Iwai 		*valp = read_amp_value(codec, nid, 1, dir, idx, ofs);
21811da177e4SLinus Torvalds 	return 0;
21821da177e4SLinus Torvalds }
2183ff7a3267STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_volume_get);
21841da177e4SLinus Torvalds 
2185d5191e50STakashi Iwai /**
2186d5191e50STakashi Iwai  * snd_hda_mixer_amp_volume_put - Put callback for a standard AMP mixer volume
2187d5191e50STakashi Iwai  *
2188d5191e50STakashi Iwai  * The control element is supposed to have the private_value field
2189d5191e50STakashi Iwai  * set up via HDA_COMPOSE_AMP_VAL*() or related macros.
2190d5191e50STakashi Iwai  */
21910ba21762STakashi Iwai int snd_hda_mixer_amp_volume_put(struct snd_kcontrol *kcontrol,
21920ba21762STakashi Iwai 				 struct snd_ctl_elem_value *ucontrol)
21931da177e4SLinus Torvalds {
21941da177e4SLinus Torvalds 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
21951da177e4SLinus Torvalds 	hda_nid_t nid = get_amp_nid(kcontrol);
21961da177e4SLinus Torvalds 	int chs = get_amp_channels(kcontrol);
21971da177e4SLinus Torvalds 	int dir = get_amp_direction(kcontrol);
21981da177e4SLinus Torvalds 	int idx = get_amp_index(kcontrol);
219929fdbec2STakashi Iwai 	unsigned int ofs = get_amp_offset(kcontrol);
22001da177e4SLinus Torvalds 	long *valp = ucontrol->value.integer.value;
22011da177e4SLinus Torvalds 	int change = 0;
22021da177e4SLinus Torvalds 
2203cb53c626STakashi Iwai 	snd_hda_power_up(codec);
2204b9f5a89cSNicolas Graziano 	if (chs & 1) {
220529fdbec2STakashi Iwai 		change = update_amp_value(codec, nid, 0, dir, idx, ofs, *valp);
2206b9f5a89cSNicolas Graziano 		valp++;
2207b9f5a89cSNicolas Graziano 	}
22084a19faeeSTakashi Iwai 	if (chs & 2)
220929fdbec2STakashi Iwai 		change |= update_amp_value(codec, nid, 1, dir, idx, ofs, *valp);
2210cb53c626STakashi Iwai 	snd_hda_power_down(codec);
22111da177e4SLinus Torvalds 	return change;
22121da177e4SLinus Torvalds }
2213ff7a3267STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_volume_put);
22141da177e4SLinus Torvalds 
2215d5191e50STakashi Iwai /**
2216d5191e50STakashi Iwai  * snd_hda_mixer_amp_volume_put - TLV callback for a standard AMP mixer volume
2217d5191e50STakashi Iwai  *
2218d5191e50STakashi Iwai  * The control element is supposed to have the private_value field
2219d5191e50STakashi Iwai  * set up via HDA_COMPOSE_AMP_VAL*() or related macros.
2220d5191e50STakashi Iwai  */
2221302e9c5aSJaroslav Kysela int snd_hda_mixer_amp_tlv(struct snd_kcontrol *kcontrol, int op_flag,
2222302e9c5aSJaroslav Kysela 			  unsigned int size, unsigned int __user *_tlv)
2223302e9c5aSJaroslav Kysela {
2224302e9c5aSJaroslav Kysela 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2225302e9c5aSJaroslav Kysela 	hda_nid_t nid = get_amp_nid(kcontrol);
2226302e9c5aSJaroslav Kysela 	int dir = get_amp_direction(kcontrol);
222729fdbec2STakashi Iwai 	unsigned int ofs = get_amp_offset(kcontrol);
2228de8c85f7SClemens Ladisch 	bool min_mute = get_amp_min_mute(kcontrol);
2229302e9c5aSJaroslav Kysela 	u32 caps, val1, val2;
2230302e9c5aSJaroslav Kysela 
2231302e9c5aSJaroslav Kysela 	if (size < 4 * sizeof(unsigned int))
2232302e9c5aSJaroslav Kysela 		return -ENOMEM;
2233302e9c5aSJaroslav Kysela 	caps = query_amp_caps(codec, nid, dir);
22340ba21762STakashi Iwai 	val2 = (caps & AC_AMPCAP_STEP_SIZE) >> AC_AMPCAP_STEP_SIZE_SHIFT;
22350ba21762STakashi Iwai 	val2 = (val2 + 1) * 25;
2236302e9c5aSJaroslav Kysela 	val1 = -((caps & AC_AMPCAP_OFFSET) >> AC_AMPCAP_OFFSET_SHIFT);
223729fdbec2STakashi Iwai 	val1 += ofs;
2238302e9c5aSJaroslav Kysela 	val1 = ((int)val1) * ((int)val2);
22393868137eSTakashi Iwai 	if (min_mute || (caps & AC_AMPCAP_MIN_MUTE))
2240c08d9169STakashi Iwai 		val2 |= TLV_DB_SCALE_MUTE;
2241302e9c5aSJaroslav Kysela 	if (put_user(SNDRV_CTL_TLVT_DB_SCALE, _tlv))
2242302e9c5aSJaroslav Kysela 		return -EFAULT;
2243302e9c5aSJaroslav Kysela 	if (put_user(2 * sizeof(unsigned int), _tlv + 1))
2244302e9c5aSJaroslav Kysela 		return -EFAULT;
2245302e9c5aSJaroslav Kysela 	if (put_user(val1, _tlv + 2))
2246302e9c5aSJaroslav Kysela 		return -EFAULT;
2247302e9c5aSJaroslav Kysela 	if (put_user(val2, _tlv + 3))
2248302e9c5aSJaroslav Kysela 		return -EFAULT;
2249302e9c5aSJaroslav Kysela 	return 0;
2250302e9c5aSJaroslav Kysela }
2251ff7a3267STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_tlv);
2252302e9c5aSJaroslav Kysela 
2253d5191e50STakashi Iwai /**
2254d5191e50STakashi Iwai  * snd_hda_set_vmaster_tlv - Set TLV for a virtual master control
2255d5191e50STakashi Iwai  * @codec: HD-audio codec
2256d5191e50STakashi Iwai  * @nid: NID of a reference widget
2257d5191e50STakashi Iwai  * @dir: #HDA_INPUT or #HDA_OUTPUT
2258d5191e50STakashi Iwai  * @tlv: TLV data to be stored, at least 4 elements
2259d5191e50STakashi Iwai  *
2260d5191e50STakashi Iwai  * Set (static) TLV data for a virtual master volume using the AMP caps
2261d5191e50STakashi Iwai  * obtained from the reference NID.
2262d5191e50STakashi Iwai  * The volume range is recalculated as if the max volume is 0dB.
22632134ea4fSTakashi Iwai  */
22642134ea4fSTakashi Iwai void snd_hda_set_vmaster_tlv(struct hda_codec *codec, hda_nid_t nid, int dir,
22652134ea4fSTakashi Iwai 			     unsigned int *tlv)
22662134ea4fSTakashi Iwai {
22672134ea4fSTakashi Iwai 	u32 caps;
22682134ea4fSTakashi Iwai 	int nums, step;
22692134ea4fSTakashi Iwai 
22702134ea4fSTakashi Iwai 	caps = query_amp_caps(codec, nid, dir);
22712134ea4fSTakashi Iwai 	nums = (caps & AC_AMPCAP_NUM_STEPS) >> AC_AMPCAP_NUM_STEPS_SHIFT;
22722134ea4fSTakashi Iwai 	step = (caps & AC_AMPCAP_STEP_SIZE) >> AC_AMPCAP_STEP_SIZE_SHIFT;
22732134ea4fSTakashi Iwai 	step = (step + 1) * 25;
22742134ea4fSTakashi Iwai 	tlv[0] = SNDRV_CTL_TLVT_DB_SCALE;
22752134ea4fSTakashi Iwai 	tlv[1] = 2 * sizeof(unsigned int);
22762134ea4fSTakashi Iwai 	tlv[2] = -nums * step;
22772134ea4fSTakashi Iwai 	tlv[3] = step;
22782134ea4fSTakashi Iwai }
2279ff7a3267STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_set_vmaster_tlv);
22802134ea4fSTakashi Iwai 
22812134ea4fSTakashi Iwai /* find a mixer control element with the given name */
228209f99701STakashi Iwai static struct snd_kcontrol *
2283dcda5806STakashi Iwai find_mixer_ctl(struct hda_codec *codec, const char *name, int dev, int idx)
22842134ea4fSTakashi Iwai {
22852134ea4fSTakashi Iwai 	struct snd_ctl_elem_id id;
22862134ea4fSTakashi Iwai 	memset(&id, 0, sizeof(id));
22872134ea4fSTakashi Iwai 	id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
2288dcda5806STakashi Iwai 	id.device = dev;
228909f99701STakashi Iwai 	id.index = idx;
229018cb7109STakashi Iwai 	if (snd_BUG_ON(strlen(name) >= sizeof(id.name)))
229118cb7109STakashi Iwai 		return NULL;
22922134ea4fSTakashi Iwai 	strcpy(id.name, name);
22932134ea4fSTakashi Iwai 	return snd_ctl_find_id(codec->bus->card, &id);
22942134ea4fSTakashi Iwai }
22952134ea4fSTakashi Iwai 
2296d5191e50STakashi Iwai /**
2297d5191e50STakashi Iwai  * snd_hda_find_mixer_ctl - Find a mixer control element with the given name
2298d5191e50STakashi Iwai  * @codec: HD-audio codec
2299d5191e50STakashi Iwai  * @name: ctl id name string
2300d5191e50STakashi Iwai  *
2301d5191e50STakashi Iwai  * Get the control element with the given id string and IFACE_MIXER.
2302d5191e50STakashi Iwai  */
230309f99701STakashi Iwai struct snd_kcontrol *snd_hda_find_mixer_ctl(struct hda_codec *codec,
230409f99701STakashi Iwai 					    const char *name)
230509f99701STakashi Iwai {
2306dcda5806STakashi Iwai 	return find_mixer_ctl(codec, name, 0, 0);
230709f99701STakashi Iwai }
2308ff7a3267STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_find_mixer_ctl);
230909f99701STakashi Iwai 
2310dcda5806STakashi Iwai static int find_empty_mixer_ctl_idx(struct hda_codec *codec, const char *name,
2311dcda5806STakashi Iwai 				    int dev)
23121afe206aSTakashi Iwai {
23131afe206aSTakashi Iwai 	int idx;
23141afe206aSTakashi Iwai 	for (idx = 0; idx < 16; idx++) { /* 16 ctlrs should be large enough */
2315dcda5806STakashi Iwai 		if (!find_mixer_ctl(codec, name, dev, idx))
23161afe206aSTakashi Iwai 			return idx;
23171afe206aSTakashi Iwai 	}
23181afe206aSTakashi Iwai 	return -EBUSY;
23191afe206aSTakashi Iwai }
23201afe206aSTakashi Iwai 
2321d5191e50STakashi Iwai /**
23225b0cb1d8SJaroslav Kysela  * snd_hda_ctl_add - Add a control element and assign to the codec
2323d5191e50STakashi Iwai  * @codec: HD-audio codec
2324d5191e50STakashi Iwai  * @nid: corresponding NID (optional)
2325d5191e50STakashi Iwai  * @kctl: the control element to assign
2326d5191e50STakashi Iwai  *
2327d5191e50STakashi Iwai  * Add the given control element to an array inside the codec instance.
2328d5191e50STakashi Iwai  * All control elements belonging to a codec are supposed to be added
2329d5191e50STakashi Iwai  * by this function so that a proper clean-up works at the free or
2330d5191e50STakashi Iwai  * reconfiguration time.
2331d5191e50STakashi Iwai  *
2332d5191e50STakashi Iwai  * If non-zero @nid is passed, the NID is assigned to the control element.
2333d5191e50STakashi Iwai  * The assignment is shown in the codec proc file.
2334d5191e50STakashi Iwai  *
2335d5191e50STakashi Iwai  * snd_hda_ctl_add() checks the control subdev id field whether
2336d5191e50STakashi Iwai  * #HDA_SUBDEV_NID_FLAG bit is set.  If set (and @nid is zero), the lower
23379e3fd871SJaroslav Kysela  * bits value is taken as the NID to assign. The #HDA_NID_ITEM_AMP bit
23389e3fd871SJaroslav Kysela  * specifies if kctl->private_value is a HDA amplifier value.
2339d5191e50STakashi Iwai  */
23403911a4c1SJaroslav Kysela int snd_hda_ctl_add(struct hda_codec *codec, hda_nid_t nid,
23413911a4c1SJaroslav Kysela 		    struct snd_kcontrol *kctl)
2342d13bd412STakashi Iwai {
2343d13bd412STakashi Iwai 	int err;
23449e3fd871SJaroslav Kysela 	unsigned short flags = 0;
23453911a4c1SJaroslav Kysela 	struct hda_nid_item *item;
2346d13bd412STakashi Iwai 
23475e26dfd0SJaroslav Kysela 	if (kctl->id.subdevice & HDA_SUBDEV_AMP_FLAG) {
23489e3fd871SJaroslav Kysela 		flags |= HDA_NID_ITEM_AMP;
23495e26dfd0SJaroslav Kysela 		if (nid == 0)
23505e26dfd0SJaroslav Kysela 			nid = get_amp_nid_(kctl->private_value);
23515e26dfd0SJaroslav Kysela 	}
23529e3fd871SJaroslav Kysela 	if ((kctl->id.subdevice & HDA_SUBDEV_NID_FLAG) != 0 && nid == 0)
23534d02d1b6SJaroslav Kysela 		nid = kctl->id.subdevice & 0xffff;
23545e26dfd0SJaroslav Kysela 	if (kctl->id.subdevice & (HDA_SUBDEV_NID_FLAG|HDA_SUBDEV_AMP_FLAG))
23554d02d1b6SJaroslav Kysela 		kctl->id.subdevice = 0;
2356d13bd412STakashi Iwai 	err = snd_ctl_add(codec->bus->card, kctl);
2357d13bd412STakashi Iwai 	if (err < 0)
2358d13bd412STakashi Iwai 		return err;
23593911a4c1SJaroslav Kysela 	item = snd_array_new(&codec->mixers);
23603911a4c1SJaroslav Kysela 	if (!item)
2361d13bd412STakashi Iwai 		return -ENOMEM;
23623911a4c1SJaroslav Kysela 	item->kctl = kctl;
23633911a4c1SJaroslav Kysela 	item->nid = nid;
23649e3fd871SJaroslav Kysela 	item->flags = flags;
2365d13bd412STakashi Iwai 	return 0;
2366d13bd412STakashi Iwai }
2367ff7a3267STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_ctl_add);
2368d13bd412STakashi Iwai 
2369d5191e50STakashi Iwai /**
23705b0cb1d8SJaroslav Kysela  * snd_hda_add_nid - Assign a NID to a control element
23715b0cb1d8SJaroslav Kysela  * @codec: HD-audio codec
23725b0cb1d8SJaroslav Kysela  * @nid: corresponding NID (optional)
23735b0cb1d8SJaroslav Kysela  * @kctl: the control element to assign
23745b0cb1d8SJaroslav Kysela  * @index: index to kctl
23755b0cb1d8SJaroslav Kysela  *
23765b0cb1d8SJaroslav Kysela  * Add the given control element to an array inside the codec instance.
23775b0cb1d8SJaroslav Kysela  * This function is used when #snd_hda_ctl_add cannot be used for 1:1
23785b0cb1d8SJaroslav Kysela  * NID:KCTL mapping - for example "Capture Source" selector.
23795b0cb1d8SJaroslav Kysela  */
23805b0cb1d8SJaroslav Kysela int snd_hda_add_nid(struct hda_codec *codec, struct snd_kcontrol *kctl,
23815b0cb1d8SJaroslav Kysela 		    unsigned int index, hda_nid_t nid)
23825b0cb1d8SJaroslav Kysela {
23835b0cb1d8SJaroslav Kysela 	struct hda_nid_item *item;
23845b0cb1d8SJaroslav Kysela 
23855b0cb1d8SJaroslav Kysela 	if (nid > 0) {
23865b0cb1d8SJaroslav Kysela 		item = snd_array_new(&codec->nids);
23875b0cb1d8SJaroslav Kysela 		if (!item)
23885b0cb1d8SJaroslav Kysela 			return -ENOMEM;
23895b0cb1d8SJaroslav Kysela 		item->kctl = kctl;
23905b0cb1d8SJaroslav Kysela 		item->index = index;
23915b0cb1d8SJaroslav Kysela 		item->nid = nid;
23925b0cb1d8SJaroslav Kysela 		return 0;
23935b0cb1d8SJaroslav Kysela 	}
239428d1a85eSTakashi Iwai 	printk(KERN_ERR "hda-codec: no NID for mapping control %s:%d:%d\n",
239528d1a85eSTakashi Iwai 	       kctl->id.name, kctl->id.index, index);
23965b0cb1d8SJaroslav Kysela 	return -EINVAL;
23975b0cb1d8SJaroslav Kysela }
23985b0cb1d8SJaroslav Kysela EXPORT_SYMBOL_HDA(snd_hda_add_nid);
23995b0cb1d8SJaroslav Kysela 
24005b0cb1d8SJaroslav Kysela /**
2401d5191e50STakashi Iwai  * snd_hda_ctls_clear - Clear all controls assigned to the given codec
2402d5191e50STakashi Iwai  * @codec: HD-audio codec
2403d5191e50STakashi Iwai  */
2404d13bd412STakashi Iwai void snd_hda_ctls_clear(struct hda_codec *codec)
2405d13bd412STakashi Iwai {
2406d13bd412STakashi Iwai 	int i;
24073911a4c1SJaroslav Kysela 	struct hda_nid_item *items = codec->mixers.list;
2408d13bd412STakashi Iwai 	for (i = 0; i < codec->mixers.used; i++)
24093911a4c1SJaroslav Kysela 		snd_ctl_remove(codec->bus->card, items[i].kctl);
2410d13bd412STakashi Iwai 	snd_array_free(&codec->mixers);
24115b0cb1d8SJaroslav Kysela 	snd_array_free(&codec->nids);
2412d13bd412STakashi Iwai }
2413d13bd412STakashi Iwai 
2414a65d629cSTakashi Iwai /* pseudo device locking
2415a65d629cSTakashi Iwai  * toggle card->shutdown to allow/disallow the device access (as a hack)
2416a65d629cSTakashi Iwai  */
2417d3d020bdSTakashi Iwai int snd_hda_lock_devices(struct hda_bus *bus)
24186c1f45eaSTakashi Iwai {
2419d3d020bdSTakashi Iwai 	struct snd_card *card = bus->card;
2420d3d020bdSTakashi Iwai 	struct hda_codec *codec;
2421d3d020bdSTakashi Iwai 
2422a65d629cSTakashi Iwai 	spin_lock(&card->files_lock);
2423d3d020bdSTakashi Iwai 	if (card->shutdown)
2424d3d020bdSTakashi Iwai 		goto err_unlock;
2425d3d020bdSTakashi Iwai 	card->shutdown = 1;
2426d3d020bdSTakashi Iwai 	if (!list_empty(&card->ctl_files))
2427d3d020bdSTakashi Iwai 		goto err_clear;
2428d3d020bdSTakashi Iwai 
2429d3d020bdSTakashi Iwai 	list_for_each_entry(codec, &bus->codec_list, list) {
2430d3d020bdSTakashi Iwai 		int pcm;
2431d3d020bdSTakashi Iwai 		for (pcm = 0; pcm < codec->num_pcms; pcm++) {
2432d3d020bdSTakashi Iwai 			struct hda_pcm *cpcm = &codec->pcm_info[pcm];
2433d3d020bdSTakashi Iwai 			if (!cpcm->pcm)
2434d3d020bdSTakashi Iwai 				continue;
2435d3d020bdSTakashi Iwai 			if (cpcm->pcm->streams[0].substream_opened ||
2436d3d020bdSTakashi Iwai 			    cpcm->pcm->streams[1].substream_opened)
2437d3d020bdSTakashi Iwai 				goto err_clear;
2438d3d020bdSTakashi Iwai 		}
2439d3d020bdSTakashi Iwai 	}
2440d3d020bdSTakashi Iwai 	spin_unlock(&card->files_lock);
2441d3d020bdSTakashi Iwai 	return 0;
2442d3d020bdSTakashi Iwai 
2443d3d020bdSTakashi Iwai  err_clear:
2444d3d020bdSTakashi Iwai 	card->shutdown = 0;
2445d3d020bdSTakashi Iwai  err_unlock:
2446a65d629cSTakashi Iwai 	spin_unlock(&card->files_lock);
2447a65d629cSTakashi Iwai 	return -EINVAL;
2448a65d629cSTakashi Iwai }
2449d3d020bdSTakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_lock_devices);
2450a65d629cSTakashi Iwai 
2451d3d020bdSTakashi Iwai void snd_hda_unlock_devices(struct hda_bus *bus)
2452a65d629cSTakashi Iwai {
2453d3d020bdSTakashi Iwai 	struct snd_card *card = bus->card;
2454d3d020bdSTakashi Iwai 
2455d3d020bdSTakashi Iwai 	card = bus->card;
2456a65d629cSTakashi Iwai 	spin_lock(&card->files_lock);
2457a65d629cSTakashi Iwai 	card->shutdown = 0;
2458a65d629cSTakashi Iwai 	spin_unlock(&card->files_lock);
2459a65d629cSTakashi Iwai }
2460d3d020bdSTakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_unlock_devices);
2461a65d629cSTakashi Iwai 
2462d5191e50STakashi Iwai /**
2463d5191e50STakashi Iwai  * snd_hda_codec_reset - Clear all objects assigned to the codec
2464d5191e50STakashi Iwai  * @codec: HD-audio codec
2465d5191e50STakashi Iwai  *
2466d5191e50STakashi Iwai  * This frees the all PCM and control elements assigned to the codec, and
2467d5191e50STakashi Iwai  * clears the caches and restores the pin default configurations.
2468d5191e50STakashi Iwai  *
2469d5191e50STakashi Iwai  * When a device is being used, it returns -EBSY.  If successfully freed,
2470d5191e50STakashi Iwai  * returns zero.
2471d5191e50STakashi Iwai  */
2472a65d629cSTakashi Iwai int snd_hda_codec_reset(struct hda_codec *codec)
2473a65d629cSTakashi Iwai {
2474d3d020bdSTakashi Iwai 	struct hda_bus *bus = codec->bus;
2475d3d020bdSTakashi Iwai 	struct snd_card *card = bus->card;
2476d3d020bdSTakashi Iwai 	int i;
2477a65d629cSTakashi Iwai 
2478d3d020bdSTakashi Iwai 	if (snd_hda_lock_devices(bus) < 0)
2479a65d629cSTakashi Iwai 		return -EBUSY;
2480a65d629cSTakashi Iwai 
2481a65d629cSTakashi Iwai 	/* OK, let it free */
248226a6cb6cSDavid Henningsson 	cancel_delayed_work_sync(&codec->jackpoll_work);
248383012a7cSTakashi Iwai #ifdef CONFIG_PM
2484a2d96e77STakashi Iwai 	cancel_delayed_work_sync(&codec->power_work);
2485339876d7STakashi Iwai 	codec->power_on = 0;
2486339876d7STakashi Iwai 	codec->power_transition = 0;
2487339876d7STakashi Iwai 	codec->power_jiffies = jiffies;
2488d3d020bdSTakashi Iwai 	flush_workqueue(bus->workq);
24896c1f45eaSTakashi Iwai #endif
24906c1f45eaSTakashi Iwai 	snd_hda_ctls_clear(codec);
24916c1f45eaSTakashi Iwai 	/* relase PCMs */
24926c1f45eaSTakashi Iwai 	for (i = 0; i < codec->num_pcms; i++) {
2493529bd6c4STakashi Iwai 		if (codec->pcm_info[i].pcm) {
2494a65d629cSTakashi Iwai 			snd_device_free(card, codec->pcm_info[i].pcm);
2495529bd6c4STakashi Iwai 			clear_bit(codec->pcm_info[i].device,
2496d3d020bdSTakashi Iwai 				  bus->pcm_dev_bits);
2497529bd6c4STakashi Iwai 		}
24986c1f45eaSTakashi Iwai 	}
24996c1f45eaSTakashi Iwai 	if (codec->patch_ops.free)
25006c1f45eaSTakashi Iwai 		codec->patch_ops.free(codec);
250107dc59f0STakashi Iwai 	memset(&codec->patch_ops, 0, sizeof(codec->patch_ops));
25021835a0f9STakashi Iwai 	snd_hda_jack_tbl_clear(codec);
250356d17712STakashi Iwai 	codec->proc_widget_hook = NULL;
25046c1f45eaSTakashi Iwai 	codec->spec = NULL;
25056c1f45eaSTakashi Iwai 	free_hda_cache(&codec->amp_cache);
25066c1f45eaSTakashi Iwai 	free_hda_cache(&codec->cmd_cache);
2507827057f5STakashi Iwai 	init_hda_cache(&codec->amp_cache, sizeof(struct hda_amp_info));
2508827057f5STakashi Iwai 	init_hda_cache(&codec->cmd_cache, sizeof(struct hda_cache_head));
2509346ff70fSTakashi Iwai 	/* free only driver_pins so that init_pins + user_pins are restored */
2510346ff70fSTakashi Iwai 	snd_array_free(&codec->driver_pins);
251109a6071bSTakashi Iwai 	snd_array_free(&codec->cvt_setups);
251209a6071bSTakashi Iwai 	snd_array_free(&codec->spdif_out);
2513c9ce6b26STakashi Iwai 	snd_array_free(&codec->verbs);
25146c1f45eaSTakashi Iwai 	codec->num_pcms = 0;
25156c1f45eaSTakashi Iwai 	codec->pcm_info = NULL;
25166c1f45eaSTakashi Iwai 	codec->preset = NULL;
2517d1f1af2dSTakashi Iwai 	codec->slave_dig_outs = NULL;
2518d1f1af2dSTakashi Iwai 	codec->spdif_status_reset = 0;
25191289e9e8STakashi Iwai 	module_put(codec->owner);
25201289e9e8STakashi Iwai 	codec->owner = NULL;
2521a65d629cSTakashi Iwai 
2522a65d629cSTakashi Iwai 	/* allow device access again */
2523d3d020bdSTakashi Iwai 	snd_hda_unlock_devices(bus);
2524a65d629cSTakashi Iwai 	return 0;
25256c1f45eaSTakashi Iwai }
25266c1f45eaSTakashi Iwai 
2527aeb4b88eSTakashi Iwai typedef int (*map_slave_func_t)(void *, struct snd_kcontrol *);
2528aeb4b88eSTakashi Iwai 
2529aeb4b88eSTakashi Iwai /* apply the function to all matching slave ctls in the mixer list */
2530aeb4b88eSTakashi Iwai static int map_slaves(struct hda_codec *codec, const char * const *slaves,
25319322ca54STakashi Iwai 		      const char *suffix, map_slave_func_t func, void *data)
2532aeb4b88eSTakashi Iwai {
2533aeb4b88eSTakashi Iwai 	struct hda_nid_item *items;
2534aeb4b88eSTakashi Iwai 	const char * const *s;
2535aeb4b88eSTakashi Iwai 	int i, err;
2536aeb4b88eSTakashi Iwai 
2537aeb4b88eSTakashi Iwai 	items = codec->mixers.list;
2538aeb4b88eSTakashi Iwai 	for (i = 0; i < codec->mixers.used; i++) {
2539aeb4b88eSTakashi Iwai 		struct snd_kcontrol *sctl = items[i].kctl;
2540aeb4b88eSTakashi Iwai 		if (!sctl || !sctl->id.name ||
2541aeb4b88eSTakashi Iwai 		    sctl->id.iface != SNDRV_CTL_ELEM_IFACE_MIXER)
2542aeb4b88eSTakashi Iwai 			continue;
2543aeb4b88eSTakashi Iwai 		for (s = slaves; *s; s++) {
25449322ca54STakashi Iwai 			char tmpname[sizeof(sctl->id.name)];
25459322ca54STakashi Iwai 			const char *name = *s;
25469322ca54STakashi Iwai 			if (suffix) {
25479322ca54STakashi Iwai 				snprintf(tmpname, sizeof(tmpname), "%s %s",
25489322ca54STakashi Iwai 					 name, suffix);
25499322ca54STakashi Iwai 				name = tmpname;
25509322ca54STakashi Iwai 			}
25519322ca54STakashi Iwai 			if (!strcmp(sctl->id.name, name)) {
2552aeb4b88eSTakashi Iwai 				err = func(data, sctl);
2553aeb4b88eSTakashi Iwai 				if (err)
2554aeb4b88eSTakashi Iwai 					return err;
2555aeb4b88eSTakashi Iwai 				break;
2556aeb4b88eSTakashi Iwai 			}
2557aeb4b88eSTakashi Iwai 		}
2558aeb4b88eSTakashi Iwai 	}
2559aeb4b88eSTakashi Iwai 	return 0;
2560aeb4b88eSTakashi Iwai }
2561aeb4b88eSTakashi Iwai 
2562aeb4b88eSTakashi Iwai static int check_slave_present(void *data, struct snd_kcontrol *sctl)
2563aeb4b88eSTakashi Iwai {
2564aeb4b88eSTakashi Iwai 	return 1;
2565aeb4b88eSTakashi Iwai }
2566aeb4b88eSTakashi Iwai 
256718478e8bSTakashi Iwai /* guess the value corresponding to 0dB */
256818478e8bSTakashi Iwai static int get_kctl_0dB_offset(struct snd_kcontrol *kctl)
256918478e8bSTakashi Iwai {
257018478e8bSTakashi Iwai 	int _tlv[4];
257118478e8bSTakashi Iwai 	const int *tlv = NULL;
257218478e8bSTakashi Iwai 	int val = -1;
257318478e8bSTakashi Iwai 
257418478e8bSTakashi Iwai 	if (kctl->vd[0].access & SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK) {
257518478e8bSTakashi Iwai 		/* FIXME: set_fs() hack for obtaining user-space TLV data */
257618478e8bSTakashi Iwai 		mm_segment_t fs = get_fs();
257718478e8bSTakashi Iwai 		set_fs(get_ds());
257818478e8bSTakashi Iwai 		if (!kctl->tlv.c(kctl, 0, sizeof(_tlv), _tlv))
257918478e8bSTakashi Iwai 			tlv = _tlv;
258018478e8bSTakashi Iwai 		set_fs(fs);
258118478e8bSTakashi Iwai 	} else if (kctl->vd[0].access & SNDRV_CTL_ELEM_ACCESS_TLV_READ)
258218478e8bSTakashi Iwai 		tlv = kctl->tlv.p;
258318478e8bSTakashi Iwai 	if (tlv && tlv[0] == SNDRV_CTL_TLVT_DB_SCALE)
258418478e8bSTakashi Iwai 		val = -tlv[2] / tlv[3];
258518478e8bSTakashi Iwai 	return val;
258618478e8bSTakashi Iwai }
258718478e8bSTakashi Iwai 
258818478e8bSTakashi Iwai /* call kctl->put with the given value(s) */
258918478e8bSTakashi Iwai static int put_kctl_with_value(struct snd_kcontrol *kctl, int val)
259018478e8bSTakashi Iwai {
259118478e8bSTakashi Iwai 	struct snd_ctl_elem_value *ucontrol;
259218478e8bSTakashi Iwai 	ucontrol = kzalloc(sizeof(*ucontrol), GFP_KERNEL);
259318478e8bSTakashi Iwai 	if (!ucontrol)
259418478e8bSTakashi Iwai 		return -ENOMEM;
259518478e8bSTakashi Iwai 	ucontrol->value.integer.value[0] = val;
259618478e8bSTakashi Iwai 	ucontrol->value.integer.value[1] = val;
259718478e8bSTakashi Iwai 	kctl->put(kctl, ucontrol);
259818478e8bSTakashi Iwai 	kfree(ucontrol);
259918478e8bSTakashi Iwai 	return 0;
260018478e8bSTakashi Iwai }
260118478e8bSTakashi Iwai 
260218478e8bSTakashi Iwai /* initialize the slave volume with 0dB */
260318478e8bSTakashi Iwai static int init_slave_0dB(void *data, struct snd_kcontrol *slave)
260418478e8bSTakashi Iwai {
260518478e8bSTakashi Iwai 	int offset = get_kctl_0dB_offset(slave);
260618478e8bSTakashi Iwai 	if (offset > 0)
260718478e8bSTakashi Iwai 		put_kctl_with_value(slave, offset);
260818478e8bSTakashi Iwai 	return 0;
260918478e8bSTakashi Iwai }
261018478e8bSTakashi Iwai 
261118478e8bSTakashi Iwai /* unmute the slave */
261218478e8bSTakashi Iwai static int init_slave_unmute(void *data, struct snd_kcontrol *slave)
261318478e8bSTakashi Iwai {
261418478e8bSTakashi Iwai 	return put_kctl_with_value(slave, 1);
261518478e8bSTakashi Iwai }
261618478e8bSTakashi Iwai 
2617d5191e50STakashi Iwai /**
2618d5191e50STakashi Iwai  * snd_hda_add_vmaster - create a virtual master control and add slaves
2619d5191e50STakashi Iwai  * @codec: HD-audio codec
2620d5191e50STakashi Iwai  * @name: vmaster control name
2621d5191e50STakashi Iwai  * @tlv: TLV data (optional)
2622d5191e50STakashi Iwai  * @slaves: slave control names (optional)
26239322ca54STakashi Iwai  * @suffix: suffix string to each slave name (optional)
262418478e8bSTakashi Iwai  * @init_slave_vol: initialize slaves to unmute/0dB
262529e5853dSTakashi Iwai  * @ctl_ret: store the vmaster kcontrol in return
2626d5191e50STakashi Iwai  *
2627d5191e50STakashi Iwai  * Create a virtual master control with the given name.  The TLV data
2628d5191e50STakashi Iwai  * must be either NULL or a valid data.
2629d5191e50STakashi Iwai  *
2630d5191e50STakashi Iwai  * @slaves is a NULL-terminated array of strings, each of which is a
2631d5191e50STakashi Iwai  * slave control name.  All controls with these names are assigned to
2632d5191e50STakashi Iwai  * the new virtual master control.
2633d5191e50STakashi Iwai  *
2634d5191e50STakashi Iwai  * This function returns zero if successful or a negative error code.
2635d5191e50STakashi Iwai  */
263618478e8bSTakashi Iwai int __snd_hda_add_vmaster(struct hda_codec *codec, char *name,
26379322ca54STakashi Iwai 			unsigned int *tlv, const char * const *slaves,
263829e5853dSTakashi Iwai 			  const char *suffix, bool init_slave_vol,
263929e5853dSTakashi Iwai 			  struct snd_kcontrol **ctl_ret)
26402134ea4fSTakashi Iwai {
26412134ea4fSTakashi Iwai 	struct snd_kcontrol *kctl;
26422134ea4fSTakashi Iwai 	int err;
26432134ea4fSTakashi Iwai 
264429e5853dSTakashi Iwai 	if (ctl_ret)
264529e5853dSTakashi Iwai 		*ctl_ret = NULL;
264629e5853dSTakashi Iwai 
26479322ca54STakashi Iwai 	err = map_slaves(codec, slaves, suffix, check_slave_present, NULL);
2648aeb4b88eSTakashi Iwai 	if (err != 1) {
26492f085549STakashi Iwai 		snd_printdd("No slave found for %s\n", name);
26502f085549STakashi Iwai 		return 0;
26512f085549STakashi Iwai 	}
26522134ea4fSTakashi Iwai 	kctl = snd_ctl_make_virtual_master(name, tlv);
26532134ea4fSTakashi Iwai 	if (!kctl)
26542134ea4fSTakashi Iwai 		return -ENOMEM;
26553911a4c1SJaroslav Kysela 	err = snd_hda_ctl_add(codec, 0, kctl);
26562134ea4fSTakashi Iwai 	if (err < 0)
26572134ea4fSTakashi Iwai 		return err;
26582134ea4fSTakashi Iwai 
26599322ca54STakashi Iwai 	err = map_slaves(codec, slaves, suffix,
26609322ca54STakashi Iwai 			 (map_slave_func_t)snd_ctl_add_slave, kctl);
26612134ea4fSTakashi Iwai 	if (err < 0)
26622134ea4fSTakashi Iwai 		return err;
266318478e8bSTakashi Iwai 
266418478e8bSTakashi Iwai 	/* init with master mute & zero volume */
266518478e8bSTakashi Iwai 	put_kctl_with_value(kctl, 0);
266618478e8bSTakashi Iwai 	if (init_slave_vol)
266718478e8bSTakashi Iwai 		map_slaves(codec, slaves, suffix,
266818478e8bSTakashi Iwai 			   tlv ? init_slave_0dB : init_slave_unmute, kctl);
266918478e8bSTakashi Iwai 
267029e5853dSTakashi Iwai 	if (ctl_ret)
267129e5853dSTakashi Iwai 		*ctl_ret = kctl;
26722134ea4fSTakashi Iwai 	return 0;
26732134ea4fSTakashi Iwai }
267418478e8bSTakashi Iwai EXPORT_SYMBOL_HDA(__snd_hda_add_vmaster);
26752134ea4fSTakashi Iwai 
2676d2f344b5STakashi Iwai /*
2677d2f344b5STakashi Iwai  * mute-LED control using vmaster
2678d2f344b5STakashi Iwai  */
2679d2f344b5STakashi Iwai static int vmaster_mute_mode_info(struct snd_kcontrol *kcontrol,
2680d2f344b5STakashi Iwai 				  struct snd_ctl_elem_info *uinfo)
2681d2f344b5STakashi Iwai {
2682d2f344b5STakashi Iwai 	static const char * const texts[] = {
2683c86c2d44SDavid Henningsson 		"On", "Off", "Follow Master"
2684d2f344b5STakashi Iwai 	};
2685d2f344b5STakashi Iwai 	unsigned int index;
2686d2f344b5STakashi Iwai 
2687d2f344b5STakashi Iwai 	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2688d2f344b5STakashi Iwai 	uinfo->count = 1;
2689d2f344b5STakashi Iwai 	uinfo->value.enumerated.items = 3;
2690d2f344b5STakashi Iwai 	index = uinfo->value.enumerated.item;
2691d2f344b5STakashi Iwai 	if (index >= 3)
2692d2f344b5STakashi Iwai 		index = 2;
2693d2f344b5STakashi Iwai 	strcpy(uinfo->value.enumerated.name, texts[index]);
2694d2f344b5STakashi Iwai 	return 0;
2695d2f344b5STakashi Iwai }
2696d2f344b5STakashi Iwai 
2697d2f344b5STakashi Iwai static int vmaster_mute_mode_get(struct snd_kcontrol *kcontrol,
2698d2f344b5STakashi Iwai 				 struct snd_ctl_elem_value *ucontrol)
2699d2f344b5STakashi Iwai {
2700d2f344b5STakashi Iwai 	struct hda_vmaster_mute_hook *hook = snd_kcontrol_chip(kcontrol);
2701d2f344b5STakashi Iwai 	ucontrol->value.enumerated.item[0] = hook->mute_mode;
2702d2f344b5STakashi Iwai 	return 0;
2703d2f344b5STakashi Iwai }
2704d2f344b5STakashi Iwai 
2705d2f344b5STakashi Iwai static int vmaster_mute_mode_put(struct snd_kcontrol *kcontrol,
2706d2f344b5STakashi Iwai 				 struct snd_ctl_elem_value *ucontrol)
2707d2f344b5STakashi Iwai {
2708d2f344b5STakashi Iwai 	struct hda_vmaster_mute_hook *hook = snd_kcontrol_chip(kcontrol);
2709d2f344b5STakashi Iwai 	unsigned int old_mode = hook->mute_mode;
2710d2f344b5STakashi Iwai 
2711d2f344b5STakashi Iwai 	hook->mute_mode = ucontrol->value.enumerated.item[0];
2712d2f344b5STakashi Iwai 	if (hook->mute_mode > HDA_VMUTE_FOLLOW_MASTER)
2713d2f344b5STakashi Iwai 		hook->mute_mode = HDA_VMUTE_FOLLOW_MASTER;
2714d2f344b5STakashi Iwai 	if (old_mode == hook->mute_mode)
2715d2f344b5STakashi Iwai 		return 0;
2716d2f344b5STakashi Iwai 	snd_hda_sync_vmaster_hook(hook);
2717d2f344b5STakashi Iwai 	return 1;
2718d2f344b5STakashi Iwai }
2719d2f344b5STakashi Iwai 
2720d2f344b5STakashi Iwai static struct snd_kcontrol_new vmaster_mute_mode = {
2721d2f344b5STakashi Iwai 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2722d2f344b5STakashi Iwai 	.name = "Mute-LED Mode",
2723d2f344b5STakashi Iwai 	.info = vmaster_mute_mode_info,
2724d2f344b5STakashi Iwai 	.get = vmaster_mute_mode_get,
2725d2f344b5STakashi Iwai 	.put = vmaster_mute_mode_put,
2726d2f344b5STakashi Iwai };
2727d2f344b5STakashi Iwai 
2728d2f344b5STakashi Iwai /*
2729d2f344b5STakashi Iwai  * Add a mute-LED hook with the given vmaster switch kctl
2730d2f344b5STakashi Iwai  * "Mute-LED Mode" control is automatically created and associated with
2731d2f344b5STakashi Iwai  * the given hook.
2732d2f344b5STakashi Iwai  */
2733d2f344b5STakashi Iwai int snd_hda_add_vmaster_hook(struct hda_codec *codec,
2734f29735cbSTakashi Iwai 			     struct hda_vmaster_mute_hook *hook,
2735f29735cbSTakashi Iwai 			     bool expose_enum_ctl)
2736d2f344b5STakashi Iwai {
2737d2f344b5STakashi Iwai 	struct snd_kcontrol *kctl;
2738d2f344b5STakashi Iwai 
2739d2f344b5STakashi Iwai 	if (!hook->hook || !hook->sw_kctl)
2740d2f344b5STakashi Iwai 		return 0;
2741d2f344b5STakashi Iwai 	snd_ctl_add_vmaster_hook(hook->sw_kctl, hook->hook, codec);
2742d2f344b5STakashi Iwai 	hook->codec = codec;
2743d2f344b5STakashi Iwai 	hook->mute_mode = HDA_VMUTE_FOLLOW_MASTER;
2744f29735cbSTakashi Iwai 	if (!expose_enum_ctl)
2745f29735cbSTakashi Iwai 		return 0;
2746d2f344b5STakashi Iwai 	kctl = snd_ctl_new1(&vmaster_mute_mode, hook);
2747d2f344b5STakashi Iwai 	if (!kctl)
2748d2f344b5STakashi Iwai 		return -ENOMEM;
2749d2f344b5STakashi Iwai 	return snd_hda_ctl_add(codec, 0, kctl);
2750d2f344b5STakashi Iwai }
2751d2f344b5STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_add_vmaster_hook);
2752d2f344b5STakashi Iwai 
2753d2f344b5STakashi Iwai /*
2754d2f344b5STakashi Iwai  * Call the hook with the current value for synchronization
2755d2f344b5STakashi Iwai  * Should be called in init callback
2756d2f344b5STakashi Iwai  */
2757d2f344b5STakashi Iwai void snd_hda_sync_vmaster_hook(struct hda_vmaster_mute_hook *hook)
2758d2f344b5STakashi Iwai {
2759d2f344b5STakashi Iwai 	if (!hook->hook || !hook->codec)
2760d2f344b5STakashi Iwai 		return;
2761d2f344b5STakashi Iwai 	switch (hook->mute_mode) {
2762d2f344b5STakashi Iwai 	case HDA_VMUTE_FOLLOW_MASTER:
2763d2f344b5STakashi Iwai 		snd_ctl_sync_vmaster_hook(hook->sw_kctl);
2764d2f344b5STakashi Iwai 		break;
2765d2f344b5STakashi Iwai 	default:
2766d2f344b5STakashi Iwai 		hook->hook(hook->codec, hook->mute_mode);
2767d2f344b5STakashi Iwai 		break;
2768d2f344b5STakashi Iwai 	}
2769d2f344b5STakashi Iwai }
2770d2f344b5STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_sync_vmaster_hook);
2771d2f344b5STakashi Iwai 
2772d2f344b5STakashi Iwai 
2773d5191e50STakashi Iwai /**
2774d5191e50STakashi Iwai  * snd_hda_mixer_amp_switch_info - Info callback for a standard AMP mixer switch
2775d5191e50STakashi Iwai  *
2776d5191e50STakashi Iwai  * The control element is supposed to have the private_value field
2777d5191e50STakashi Iwai  * set up via HDA_COMPOSE_AMP_VAL*() or related macros.
2778d5191e50STakashi Iwai  */
27790ba21762STakashi Iwai int snd_hda_mixer_amp_switch_info(struct snd_kcontrol *kcontrol,
27800ba21762STakashi Iwai 				  struct snd_ctl_elem_info *uinfo)
27811da177e4SLinus Torvalds {
27821da177e4SLinus Torvalds 	int chs = get_amp_channels(kcontrol);
27831da177e4SLinus Torvalds 
27841da177e4SLinus Torvalds 	uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
27851da177e4SLinus Torvalds 	uinfo->count = chs == 3 ? 2 : 1;
27861da177e4SLinus Torvalds 	uinfo->value.integer.min = 0;
27871da177e4SLinus Torvalds 	uinfo->value.integer.max = 1;
27881da177e4SLinus Torvalds 	return 0;
27891da177e4SLinus Torvalds }
2790ff7a3267STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_switch_info);
27911da177e4SLinus Torvalds 
2792d5191e50STakashi Iwai /**
2793d5191e50STakashi Iwai  * snd_hda_mixer_amp_switch_get - Get callback for a standard AMP mixer switch
2794d5191e50STakashi Iwai  *
2795d5191e50STakashi Iwai  * The control element is supposed to have the private_value field
2796d5191e50STakashi Iwai  * set up via HDA_COMPOSE_AMP_VAL*() or related macros.
2797d5191e50STakashi Iwai  */
27980ba21762STakashi Iwai int snd_hda_mixer_amp_switch_get(struct snd_kcontrol *kcontrol,
27990ba21762STakashi Iwai 				 struct snd_ctl_elem_value *ucontrol)
28001da177e4SLinus Torvalds {
28011da177e4SLinus Torvalds 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
28021da177e4SLinus Torvalds 	hda_nid_t nid = get_amp_nid(kcontrol);
28031da177e4SLinus Torvalds 	int chs = get_amp_channels(kcontrol);
28041da177e4SLinus Torvalds 	int dir = get_amp_direction(kcontrol);
28051da177e4SLinus Torvalds 	int idx = get_amp_index(kcontrol);
28061da177e4SLinus Torvalds 	long *valp = ucontrol->value.integer.value;
28071da177e4SLinus Torvalds 
28081da177e4SLinus Torvalds 	if (chs & 1)
28090ba21762STakashi Iwai 		*valp++ = (snd_hda_codec_amp_read(codec, nid, 0, dir, idx) &
281047fd830aSTakashi Iwai 			   HDA_AMP_MUTE) ? 0 : 1;
28111da177e4SLinus Torvalds 	if (chs & 2)
28120ba21762STakashi Iwai 		*valp = (snd_hda_codec_amp_read(codec, nid, 1, dir, idx) &
281347fd830aSTakashi Iwai 			 HDA_AMP_MUTE) ? 0 : 1;
28141da177e4SLinus Torvalds 	return 0;
28151da177e4SLinus Torvalds }
2816ff7a3267STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_switch_get);
28171da177e4SLinus Torvalds 
2818d5191e50STakashi Iwai /**
2819d5191e50STakashi Iwai  * snd_hda_mixer_amp_switch_put - Put callback for a standard AMP mixer switch
2820d5191e50STakashi Iwai  *
2821d5191e50STakashi Iwai  * The control element is supposed to have the private_value field
2822d5191e50STakashi Iwai  * set up via HDA_COMPOSE_AMP_VAL*() or related macros.
2823d5191e50STakashi Iwai  */
28240ba21762STakashi Iwai int snd_hda_mixer_amp_switch_put(struct snd_kcontrol *kcontrol,
28250ba21762STakashi Iwai 				 struct snd_ctl_elem_value *ucontrol)
28261da177e4SLinus Torvalds {
28271da177e4SLinus Torvalds 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
28281da177e4SLinus Torvalds 	hda_nid_t nid = get_amp_nid(kcontrol);
28291da177e4SLinus Torvalds 	int chs = get_amp_channels(kcontrol);
28301da177e4SLinus Torvalds 	int dir = get_amp_direction(kcontrol);
28311da177e4SLinus Torvalds 	int idx = get_amp_index(kcontrol);
28321da177e4SLinus Torvalds 	long *valp = ucontrol->value.integer.value;
28331da177e4SLinus Torvalds 	int change = 0;
28341da177e4SLinus Torvalds 
2835cb53c626STakashi Iwai 	snd_hda_power_up(codec);
2836b9f5a89cSNicolas Graziano 	if (chs & 1) {
28374a19faeeSTakashi Iwai 		change = snd_hda_codec_amp_update(codec, nid, 0, dir, idx,
283847fd830aSTakashi Iwai 						  HDA_AMP_MUTE,
283947fd830aSTakashi Iwai 						  *valp ? 0 : HDA_AMP_MUTE);
2840b9f5a89cSNicolas Graziano 		valp++;
2841b9f5a89cSNicolas Graziano 	}
28424a19faeeSTakashi Iwai 	if (chs & 2)
28434a19faeeSTakashi Iwai 		change |= snd_hda_codec_amp_update(codec, nid, 1, dir, idx,
284447fd830aSTakashi Iwai 						   HDA_AMP_MUTE,
284547fd830aSTakashi Iwai 						   *valp ? 0 : HDA_AMP_MUTE);
28469e5341b9STakashi Iwai 	hda_call_check_power_status(codec, nid);
2847cb53c626STakashi Iwai 	snd_hda_power_down(codec);
28481da177e4SLinus Torvalds 	return change;
28491da177e4SLinus Torvalds }
2850ff7a3267STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_switch_put);
28511da177e4SLinus Torvalds 
28521da177e4SLinus Torvalds /*
2853985be54bSTakashi Iwai  * bound volume controls
2854985be54bSTakashi Iwai  *
2855985be54bSTakashi Iwai  * bind multiple volumes (# indices, from 0)
2856985be54bSTakashi Iwai  */
2857985be54bSTakashi Iwai 
2858985be54bSTakashi Iwai #define AMP_VAL_IDX_SHIFT	19
2859985be54bSTakashi Iwai #define AMP_VAL_IDX_MASK	(0x0f<<19)
2860985be54bSTakashi Iwai 
2861d5191e50STakashi Iwai /**
2862d5191e50STakashi Iwai  * snd_hda_mixer_bind_switch_get - Get callback for a bound volume control
2863d5191e50STakashi Iwai  *
2864d5191e50STakashi Iwai  * The control element is supposed to have the private_value field
2865d5191e50STakashi Iwai  * set up via HDA_BIND_MUTE*() macros.
2866d5191e50STakashi Iwai  */
28670ba21762STakashi Iwai int snd_hda_mixer_bind_switch_get(struct snd_kcontrol *kcontrol,
28680ba21762STakashi Iwai 				  struct snd_ctl_elem_value *ucontrol)
2869985be54bSTakashi Iwai {
2870985be54bSTakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2871985be54bSTakashi Iwai 	unsigned long pval;
2872985be54bSTakashi Iwai 	int err;
2873985be54bSTakashi Iwai 
28745a9e02e9SWu Fengguang 	mutex_lock(&codec->control_mutex);
2875985be54bSTakashi Iwai 	pval = kcontrol->private_value;
2876985be54bSTakashi Iwai 	kcontrol->private_value = pval & ~AMP_VAL_IDX_MASK; /* index 0 */
2877985be54bSTakashi Iwai 	err = snd_hda_mixer_amp_switch_get(kcontrol, ucontrol);
2878985be54bSTakashi Iwai 	kcontrol->private_value = pval;
28795a9e02e9SWu Fengguang 	mutex_unlock(&codec->control_mutex);
2880985be54bSTakashi Iwai 	return err;
2881985be54bSTakashi Iwai }
2882ff7a3267STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_switch_get);
2883985be54bSTakashi Iwai 
2884d5191e50STakashi Iwai /**
2885d5191e50STakashi Iwai  * snd_hda_mixer_bind_switch_put - Put callback for a bound volume control
2886d5191e50STakashi Iwai  *
2887d5191e50STakashi Iwai  * The control element is supposed to have the private_value field
2888d5191e50STakashi Iwai  * set up via HDA_BIND_MUTE*() macros.
2889d5191e50STakashi Iwai  */
28900ba21762STakashi Iwai int snd_hda_mixer_bind_switch_put(struct snd_kcontrol *kcontrol,
28910ba21762STakashi Iwai 				  struct snd_ctl_elem_value *ucontrol)
2892985be54bSTakashi Iwai {
2893985be54bSTakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2894985be54bSTakashi Iwai 	unsigned long pval;
2895985be54bSTakashi Iwai 	int i, indices, err = 0, change = 0;
2896985be54bSTakashi Iwai 
28975a9e02e9SWu Fengguang 	mutex_lock(&codec->control_mutex);
2898985be54bSTakashi Iwai 	pval = kcontrol->private_value;
2899985be54bSTakashi Iwai 	indices = (pval & AMP_VAL_IDX_MASK) >> AMP_VAL_IDX_SHIFT;
2900985be54bSTakashi Iwai 	for (i = 0; i < indices; i++) {
29010ba21762STakashi Iwai 		kcontrol->private_value = (pval & ~AMP_VAL_IDX_MASK) |
29020ba21762STakashi Iwai 			(i << AMP_VAL_IDX_SHIFT);
2903985be54bSTakashi Iwai 		err = snd_hda_mixer_amp_switch_put(kcontrol, ucontrol);
2904985be54bSTakashi Iwai 		if (err < 0)
2905985be54bSTakashi Iwai 			break;
2906985be54bSTakashi Iwai 		change |= err;
2907985be54bSTakashi Iwai 	}
2908985be54bSTakashi Iwai 	kcontrol->private_value = pval;
29095a9e02e9SWu Fengguang 	mutex_unlock(&codec->control_mutex);
2910985be54bSTakashi Iwai 	return err < 0 ? err : change;
2911985be54bSTakashi Iwai }
2912ff7a3267STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_switch_put);
2913985be54bSTakashi Iwai 
2914d5191e50STakashi Iwai /**
2915d5191e50STakashi Iwai  * snd_hda_mixer_bind_ctls_info - Info callback for a generic bound control
2916d5191e50STakashi Iwai  *
2917d5191e50STakashi Iwai  * The control element is supposed to have the private_value field
2918d5191e50STakashi Iwai  * set up via HDA_BIND_VOL() or HDA_BIND_SW() macros.
2919532d5381STakashi Iwai  */
2920532d5381STakashi Iwai int snd_hda_mixer_bind_ctls_info(struct snd_kcontrol *kcontrol,
2921532d5381STakashi Iwai 				 struct snd_ctl_elem_info *uinfo)
2922532d5381STakashi Iwai {
2923532d5381STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2924532d5381STakashi Iwai 	struct hda_bind_ctls *c;
2925532d5381STakashi Iwai 	int err;
2926532d5381STakashi Iwai 
29275a9e02e9SWu Fengguang 	mutex_lock(&codec->control_mutex);
292814c65f98SSerge A. Suchkov 	c = (struct hda_bind_ctls *)kcontrol->private_value;
2929532d5381STakashi Iwai 	kcontrol->private_value = *c->values;
2930532d5381STakashi Iwai 	err = c->ops->info(kcontrol, uinfo);
2931532d5381STakashi Iwai 	kcontrol->private_value = (long)c;
29325a9e02e9SWu Fengguang 	mutex_unlock(&codec->control_mutex);
2933532d5381STakashi Iwai 	return err;
2934532d5381STakashi Iwai }
2935ff7a3267STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_ctls_info);
2936532d5381STakashi Iwai 
2937d5191e50STakashi Iwai /**
2938d5191e50STakashi Iwai  * snd_hda_mixer_bind_ctls_get - Get callback for a generic bound control
2939d5191e50STakashi Iwai  *
2940d5191e50STakashi Iwai  * The control element is supposed to have the private_value field
2941d5191e50STakashi Iwai  * set up via HDA_BIND_VOL() or HDA_BIND_SW() macros.
2942d5191e50STakashi Iwai  */
2943532d5381STakashi Iwai int snd_hda_mixer_bind_ctls_get(struct snd_kcontrol *kcontrol,
2944532d5381STakashi Iwai 				struct snd_ctl_elem_value *ucontrol)
2945532d5381STakashi Iwai {
2946532d5381STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2947532d5381STakashi Iwai 	struct hda_bind_ctls *c;
2948532d5381STakashi Iwai 	int err;
2949532d5381STakashi Iwai 
29505a9e02e9SWu Fengguang 	mutex_lock(&codec->control_mutex);
295114c65f98SSerge A. Suchkov 	c = (struct hda_bind_ctls *)kcontrol->private_value;
2952532d5381STakashi Iwai 	kcontrol->private_value = *c->values;
2953532d5381STakashi Iwai 	err = c->ops->get(kcontrol, ucontrol);
2954532d5381STakashi Iwai 	kcontrol->private_value = (long)c;
29555a9e02e9SWu Fengguang 	mutex_unlock(&codec->control_mutex);
2956532d5381STakashi Iwai 	return err;
2957532d5381STakashi Iwai }
2958ff7a3267STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_ctls_get);
2959532d5381STakashi Iwai 
2960d5191e50STakashi Iwai /**
2961d5191e50STakashi Iwai  * snd_hda_mixer_bind_ctls_put - Put callback for a generic bound control
2962d5191e50STakashi Iwai  *
2963d5191e50STakashi Iwai  * The control element is supposed to have the private_value field
2964d5191e50STakashi Iwai  * set up via HDA_BIND_VOL() or HDA_BIND_SW() macros.
2965d5191e50STakashi Iwai  */
2966532d5381STakashi Iwai int snd_hda_mixer_bind_ctls_put(struct snd_kcontrol *kcontrol,
2967532d5381STakashi Iwai 				struct snd_ctl_elem_value *ucontrol)
2968532d5381STakashi Iwai {
2969532d5381STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2970532d5381STakashi Iwai 	struct hda_bind_ctls *c;
2971532d5381STakashi Iwai 	unsigned long *vals;
2972532d5381STakashi Iwai 	int err = 0, change = 0;
2973532d5381STakashi Iwai 
29745a9e02e9SWu Fengguang 	mutex_lock(&codec->control_mutex);
297514c65f98SSerge A. Suchkov 	c = (struct hda_bind_ctls *)kcontrol->private_value;
2976532d5381STakashi Iwai 	for (vals = c->values; *vals; vals++) {
2977532d5381STakashi Iwai 		kcontrol->private_value = *vals;
2978532d5381STakashi Iwai 		err = c->ops->put(kcontrol, ucontrol);
2979532d5381STakashi Iwai 		if (err < 0)
2980532d5381STakashi Iwai 			break;
2981532d5381STakashi Iwai 		change |= err;
2982532d5381STakashi Iwai 	}
2983532d5381STakashi Iwai 	kcontrol->private_value = (long)c;
29845a9e02e9SWu Fengguang 	mutex_unlock(&codec->control_mutex);
2985532d5381STakashi Iwai 	return err < 0 ? err : change;
2986532d5381STakashi Iwai }
2987ff7a3267STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_ctls_put);
2988532d5381STakashi Iwai 
2989d5191e50STakashi Iwai /**
2990d5191e50STakashi Iwai  * snd_hda_mixer_bind_tlv - TLV callback for a generic bound control
2991d5191e50STakashi Iwai  *
2992d5191e50STakashi Iwai  * The control element is supposed to have the private_value field
2993d5191e50STakashi Iwai  * set up via HDA_BIND_VOL() macro.
2994d5191e50STakashi Iwai  */
2995532d5381STakashi Iwai int snd_hda_mixer_bind_tlv(struct snd_kcontrol *kcontrol, int op_flag,
2996532d5381STakashi Iwai 			   unsigned int size, unsigned int __user *tlv)
2997532d5381STakashi Iwai {
2998532d5381STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2999532d5381STakashi Iwai 	struct hda_bind_ctls *c;
3000532d5381STakashi Iwai 	int err;
3001532d5381STakashi Iwai 
30025a9e02e9SWu Fengguang 	mutex_lock(&codec->control_mutex);
300314c65f98SSerge A. Suchkov 	c = (struct hda_bind_ctls *)kcontrol->private_value;
3004532d5381STakashi Iwai 	kcontrol->private_value = *c->values;
3005532d5381STakashi Iwai 	err = c->ops->tlv(kcontrol, op_flag, size, tlv);
3006532d5381STakashi Iwai 	kcontrol->private_value = (long)c;
30075a9e02e9SWu Fengguang 	mutex_unlock(&codec->control_mutex);
3008532d5381STakashi Iwai 	return err;
3009532d5381STakashi Iwai }
3010ff7a3267STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_tlv);
3011532d5381STakashi Iwai 
3012532d5381STakashi Iwai struct hda_ctl_ops snd_hda_bind_vol = {
3013532d5381STakashi Iwai 	.info = snd_hda_mixer_amp_volume_info,
3014532d5381STakashi Iwai 	.get = snd_hda_mixer_amp_volume_get,
3015532d5381STakashi Iwai 	.put = snd_hda_mixer_amp_volume_put,
3016532d5381STakashi Iwai 	.tlv = snd_hda_mixer_amp_tlv
3017532d5381STakashi Iwai };
3018ff7a3267STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_bind_vol);
3019532d5381STakashi Iwai 
3020532d5381STakashi Iwai struct hda_ctl_ops snd_hda_bind_sw = {
3021532d5381STakashi Iwai 	.info = snd_hda_mixer_amp_switch_info,
3022532d5381STakashi Iwai 	.get = snd_hda_mixer_amp_switch_get,
3023532d5381STakashi Iwai 	.put = snd_hda_mixer_amp_switch_put,
3024532d5381STakashi Iwai 	.tlv = snd_hda_mixer_amp_tlv
3025532d5381STakashi Iwai };
3026ff7a3267STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_bind_sw);
3027532d5381STakashi Iwai 
3028532d5381STakashi Iwai /*
30291da177e4SLinus Torvalds  * SPDIF out controls
30301da177e4SLinus Torvalds  */
30311da177e4SLinus Torvalds 
30320ba21762STakashi Iwai static int snd_hda_spdif_mask_info(struct snd_kcontrol *kcontrol,
30330ba21762STakashi Iwai 				   struct snd_ctl_elem_info *uinfo)
30341da177e4SLinus Torvalds {
30351da177e4SLinus Torvalds 	uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
30361da177e4SLinus Torvalds 	uinfo->count = 1;
30371da177e4SLinus Torvalds 	return 0;
30381da177e4SLinus Torvalds }
30391da177e4SLinus Torvalds 
30400ba21762STakashi Iwai static int snd_hda_spdif_cmask_get(struct snd_kcontrol *kcontrol,
30410ba21762STakashi Iwai 				   struct snd_ctl_elem_value *ucontrol)
30421da177e4SLinus Torvalds {
30431da177e4SLinus Torvalds 	ucontrol->value.iec958.status[0] = IEC958_AES0_PROFESSIONAL |
30441da177e4SLinus Torvalds 					   IEC958_AES0_NONAUDIO |
30451da177e4SLinus Torvalds 					   IEC958_AES0_CON_EMPHASIS_5015 |
30461da177e4SLinus Torvalds 					   IEC958_AES0_CON_NOT_COPYRIGHT;
30471da177e4SLinus Torvalds 	ucontrol->value.iec958.status[1] = IEC958_AES1_CON_CATEGORY |
30481da177e4SLinus Torvalds 					   IEC958_AES1_CON_ORIGINAL;
30491da177e4SLinus Torvalds 	return 0;
30501da177e4SLinus Torvalds }
30511da177e4SLinus Torvalds 
30520ba21762STakashi Iwai static int snd_hda_spdif_pmask_get(struct snd_kcontrol *kcontrol,
30530ba21762STakashi Iwai 				   struct snd_ctl_elem_value *ucontrol)
30541da177e4SLinus Torvalds {
30551da177e4SLinus Torvalds 	ucontrol->value.iec958.status[0] = IEC958_AES0_PROFESSIONAL |
30561da177e4SLinus Torvalds 					   IEC958_AES0_NONAUDIO |
30571da177e4SLinus Torvalds 					   IEC958_AES0_PRO_EMPHASIS_5015;
30581da177e4SLinus Torvalds 	return 0;
30591da177e4SLinus Torvalds }
30601da177e4SLinus Torvalds 
30610ba21762STakashi Iwai static int snd_hda_spdif_default_get(struct snd_kcontrol *kcontrol,
30620ba21762STakashi Iwai 				     struct snd_ctl_elem_value *ucontrol)
30631da177e4SLinus Torvalds {
30641da177e4SLinus Torvalds 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
30657c935976SStephen Warren 	int idx = kcontrol->private_value;
3066e3245cddSTakashi Iwai 	struct hda_spdif_out *spdif;
30671da177e4SLinus Torvalds 
3068e3245cddSTakashi Iwai 	mutex_lock(&codec->spdif_mutex);
3069e3245cddSTakashi Iwai 	spdif = snd_array_elem(&codec->spdif_out, idx);
30707c935976SStephen Warren 	ucontrol->value.iec958.status[0] = spdif->status & 0xff;
30717c935976SStephen Warren 	ucontrol->value.iec958.status[1] = (spdif->status >> 8) & 0xff;
30727c935976SStephen Warren 	ucontrol->value.iec958.status[2] = (spdif->status >> 16) & 0xff;
30737c935976SStephen Warren 	ucontrol->value.iec958.status[3] = (spdif->status >> 24) & 0xff;
3074e3245cddSTakashi Iwai 	mutex_unlock(&codec->spdif_mutex);
30751da177e4SLinus Torvalds 
30761da177e4SLinus Torvalds 	return 0;
30771da177e4SLinus Torvalds }
30781da177e4SLinus Torvalds 
30791da177e4SLinus Torvalds /* convert from SPDIF status bits to HDA SPDIF bits
30801da177e4SLinus Torvalds  * bit 0 (DigEn) is always set zero (to be filled later)
30811da177e4SLinus Torvalds  */
30821da177e4SLinus Torvalds static unsigned short convert_from_spdif_status(unsigned int sbits)
30831da177e4SLinus Torvalds {
30841da177e4SLinus Torvalds 	unsigned short val = 0;
30851da177e4SLinus Torvalds 
30861da177e4SLinus Torvalds 	if (sbits & IEC958_AES0_PROFESSIONAL)
30870ba21762STakashi Iwai 		val |= AC_DIG1_PROFESSIONAL;
30881da177e4SLinus Torvalds 	if (sbits & IEC958_AES0_NONAUDIO)
30890ba21762STakashi Iwai 		val |= AC_DIG1_NONAUDIO;
30901da177e4SLinus Torvalds 	if (sbits & IEC958_AES0_PROFESSIONAL) {
30910ba21762STakashi Iwai 		if ((sbits & IEC958_AES0_PRO_EMPHASIS) ==
30920ba21762STakashi Iwai 		    IEC958_AES0_PRO_EMPHASIS_5015)
30930ba21762STakashi Iwai 			val |= AC_DIG1_EMPHASIS;
30941da177e4SLinus Torvalds 	} else {
30950ba21762STakashi Iwai 		if ((sbits & IEC958_AES0_CON_EMPHASIS) ==
30960ba21762STakashi Iwai 		    IEC958_AES0_CON_EMPHASIS_5015)
30970ba21762STakashi Iwai 			val |= AC_DIG1_EMPHASIS;
30981da177e4SLinus Torvalds 		if (!(sbits & IEC958_AES0_CON_NOT_COPYRIGHT))
30990ba21762STakashi Iwai 			val |= AC_DIG1_COPYRIGHT;
31001da177e4SLinus Torvalds 		if (sbits & (IEC958_AES1_CON_ORIGINAL << 8))
31010ba21762STakashi Iwai 			val |= AC_DIG1_LEVEL;
31021da177e4SLinus Torvalds 		val |= sbits & (IEC958_AES1_CON_CATEGORY << 8);
31031da177e4SLinus Torvalds 	}
31041da177e4SLinus Torvalds 	return val;
31051da177e4SLinus Torvalds }
31061da177e4SLinus Torvalds 
31071da177e4SLinus Torvalds /* convert to SPDIF status bits from HDA SPDIF bits
31081da177e4SLinus Torvalds  */
31091da177e4SLinus Torvalds static unsigned int convert_to_spdif_status(unsigned short val)
31101da177e4SLinus Torvalds {
31111da177e4SLinus Torvalds 	unsigned int sbits = 0;
31121da177e4SLinus Torvalds 
31130ba21762STakashi Iwai 	if (val & AC_DIG1_NONAUDIO)
31141da177e4SLinus Torvalds 		sbits |= IEC958_AES0_NONAUDIO;
31150ba21762STakashi Iwai 	if (val & AC_DIG1_PROFESSIONAL)
31161da177e4SLinus Torvalds 		sbits |= IEC958_AES0_PROFESSIONAL;
31171da177e4SLinus Torvalds 	if (sbits & IEC958_AES0_PROFESSIONAL) {
31180ba21762STakashi Iwai 		if (sbits & AC_DIG1_EMPHASIS)
31191da177e4SLinus Torvalds 			sbits |= IEC958_AES0_PRO_EMPHASIS_5015;
31201da177e4SLinus Torvalds 	} else {
31210ba21762STakashi Iwai 		if (val & AC_DIG1_EMPHASIS)
31221da177e4SLinus Torvalds 			sbits |= IEC958_AES0_CON_EMPHASIS_5015;
31230ba21762STakashi Iwai 		if (!(val & AC_DIG1_COPYRIGHT))
31241da177e4SLinus Torvalds 			sbits |= IEC958_AES0_CON_NOT_COPYRIGHT;
31250ba21762STakashi Iwai 		if (val & AC_DIG1_LEVEL)
31261da177e4SLinus Torvalds 			sbits |= (IEC958_AES1_CON_ORIGINAL << 8);
31271da177e4SLinus Torvalds 		sbits |= val & (0x7f << 8);
31281da177e4SLinus Torvalds 	}
31291da177e4SLinus Torvalds 	return sbits;
31301da177e4SLinus Torvalds }
31311da177e4SLinus Torvalds 
31322f72853cSTakashi Iwai /* set digital convert verbs both for the given NID and its slaves */
31332f72853cSTakashi Iwai static void set_dig_out(struct hda_codec *codec, hda_nid_t nid,
31342f72853cSTakashi Iwai 			int verb, int val)
31352f72853cSTakashi Iwai {
3136dda14410STakashi Iwai 	const hda_nid_t *d;
31372f72853cSTakashi Iwai 
31389e976976STakashi Iwai 	snd_hda_codec_write_cache(codec, nid, 0, verb, val);
31392f72853cSTakashi Iwai 	d = codec->slave_dig_outs;
31402f72853cSTakashi Iwai 	if (!d)
31412f72853cSTakashi Iwai 		return;
31422f72853cSTakashi Iwai 	for (; *d; d++)
31439e976976STakashi Iwai 		snd_hda_codec_write_cache(codec, *d, 0, verb, val);
31442f72853cSTakashi Iwai }
31452f72853cSTakashi Iwai 
31462f72853cSTakashi Iwai static inline void set_dig_out_convert(struct hda_codec *codec, hda_nid_t nid,
31472f72853cSTakashi Iwai 				       int dig1, int dig2)
31482f72853cSTakashi Iwai {
31492f72853cSTakashi Iwai 	if (dig1 != -1)
31502f72853cSTakashi Iwai 		set_dig_out(codec, nid, AC_VERB_SET_DIGI_CONVERT_1, dig1);
31512f72853cSTakashi Iwai 	if (dig2 != -1)
31522f72853cSTakashi Iwai 		set_dig_out(codec, nid, AC_VERB_SET_DIGI_CONVERT_2, dig2);
31532f72853cSTakashi Iwai }
31542f72853cSTakashi Iwai 
31550ba21762STakashi Iwai static int snd_hda_spdif_default_put(struct snd_kcontrol *kcontrol,
31560ba21762STakashi Iwai 				     struct snd_ctl_elem_value *ucontrol)
31571da177e4SLinus Torvalds {
31581da177e4SLinus Torvalds 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
31597c935976SStephen Warren 	int idx = kcontrol->private_value;
3160e3245cddSTakashi Iwai 	struct hda_spdif_out *spdif;
3161e3245cddSTakashi Iwai 	hda_nid_t nid;
31621da177e4SLinus Torvalds 	unsigned short val;
31631da177e4SLinus Torvalds 	int change;
31641da177e4SLinus Torvalds 
316562932df8SIngo Molnar 	mutex_lock(&codec->spdif_mutex);
3166e3245cddSTakashi Iwai 	spdif = snd_array_elem(&codec->spdif_out, idx);
3167e3245cddSTakashi Iwai 	nid = spdif->nid;
31687c935976SStephen Warren 	spdif->status = ucontrol->value.iec958.status[0] |
31691da177e4SLinus Torvalds 		((unsigned int)ucontrol->value.iec958.status[1] << 8) |
31701da177e4SLinus Torvalds 		((unsigned int)ucontrol->value.iec958.status[2] << 16) |
31711da177e4SLinus Torvalds 		((unsigned int)ucontrol->value.iec958.status[3] << 24);
31727c935976SStephen Warren 	val = convert_from_spdif_status(spdif->status);
31737c935976SStephen Warren 	val |= spdif->ctls & 1;
31747c935976SStephen Warren 	change = spdif->ctls != val;
31757c935976SStephen Warren 	spdif->ctls = val;
317674b654c9SStephen Warren 	if (change && nid != (u16)-1)
31772f72853cSTakashi Iwai 		set_dig_out_convert(codec, nid, val & 0xff, (val >> 8) & 0xff);
317862932df8SIngo Molnar 	mutex_unlock(&codec->spdif_mutex);
31791da177e4SLinus Torvalds 	return change;
31801da177e4SLinus Torvalds }
31811da177e4SLinus Torvalds 
3182a5ce8890STakashi Iwai #define snd_hda_spdif_out_switch_info	snd_ctl_boolean_mono_info
31831da177e4SLinus Torvalds 
31840ba21762STakashi Iwai static int snd_hda_spdif_out_switch_get(struct snd_kcontrol *kcontrol,
31850ba21762STakashi Iwai 					struct snd_ctl_elem_value *ucontrol)
31861da177e4SLinus Torvalds {
31871da177e4SLinus Torvalds 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
31887c935976SStephen Warren 	int idx = kcontrol->private_value;
3189e3245cddSTakashi Iwai 	struct hda_spdif_out *spdif;
31901da177e4SLinus Torvalds 
3191e3245cddSTakashi Iwai 	mutex_lock(&codec->spdif_mutex);
3192e3245cddSTakashi Iwai 	spdif = snd_array_elem(&codec->spdif_out, idx);
31937c935976SStephen Warren 	ucontrol->value.integer.value[0] = spdif->ctls & AC_DIG1_ENABLE;
3194e3245cddSTakashi Iwai 	mutex_unlock(&codec->spdif_mutex);
31951da177e4SLinus Torvalds 	return 0;
31961da177e4SLinus Torvalds }
31971da177e4SLinus Torvalds 
319874b654c9SStephen Warren static inline void set_spdif_ctls(struct hda_codec *codec, hda_nid_t nid,
319974b654c9SStephen Warren 				  int dig1, int dig2)
320074b654c9SStephen Warren {
320174b654c9SStephen Warren 	set_dig_out_convert(codec, nid, dig1, dig2);
320274b654c9SStephen Warren 	/* unmute amp switch (if any) */
320374b654c9SStephen Warren 	if ((get_wcaps(codec, nid) & AC_WCAP_OUT_AMP) &&
320474b654c9SStephen Warren 	    (dig1 & AC_DIG1_ENABLE))
320574b654c9SStephen Warren 		snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0,
320674b654c9SStephen Warren 					    HDA_AMP_MUTE, 0);
320774b654c9SStephen Warren }
320874b654c9SStephen Warren 
32090ba21762STakashi Iwai static int snd_hda_spdif_out_switch_put(struct snd_kcontrol *kcontrol,
32100ba21762STakashi Iwai 					struct snd_ctl_elem_value *ucontrol)
32111da177e4SLinus Torvalds {
32121da177e4SLinus Torvalds 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
32137c935976SStephen Warren 	int idx = kcontrol->private_value;
3214e3245cddSTakashi Iwai 	struct hda_spdif_out *spdif;
3215e3245cddSTakashi Iwai 	hda_nid_t nid;
32161da177e4SLinus Torvalds 	unsigned short val;
32171da177e4SLinus Torvalds 	int change;
32181da177e4SLinus Torvalds 
321962932df8SIngo Molnar 	mutex_lock(&codec->spdif_mutex);
3220e3245cddSTakashi Iwai 	spdif = snd_array_elem(&codec->spdif_out, idx);
3221e3245cddSTakashi Iwai 	nid = spdif->nid;
32227c935976SStephen Warren 	val = spdif->ctls & ~AC_DIG1_ENABLE;
32231da177e4SLinus Torvalds 	if (ucontrol->value.integer.value[0])
32240ba21762STakashi Iwai 		val |= AC_DIG1_ENABLE;
32257c935976SStephen Warren 	change = spdif->ctls != val;
32267c935976SStephen Warren 	spdif->ctls = val;
322774b654c9SStephen Warren 	if (change && nid != (u16)-1)
322874b654c9SStephen Warren 		set_spdif_ctls(codec, nid, val & 0xff, -1);
322962932df8SIngo Molnar 	mutex_unlock(&codec->spdif_mutex);
32301da177e4SLinus Torvalds 	return change;
32311da177e4SLinus Torvalds }
32321da177e4SLinus Torvalds 
3233c8b6bf9bSTakashi Iwai static struct snd_kcontrol_new dig_mixes[] = {
32341da177e4SLinus Torvalds 	{
32351da177e4SLinus Torvalds 		.access = SNDRV_CTL_ELEM_ACCESS_READ,
32361da177e4SLinus Torvalds 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
32371da177e4SLinus Torvalds 		.name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, CON_MASK),
32381da177e4SLinus Torvalds 		.info = snd_hda_spdif_mask_info,
32391da177e4SLinus Torvalds 		.get = snd_hda_spdif_cmask_get,
32401da177e4SLinus Torvalds 	},
32411da177e4SLinus Torvalds 	{
32421da177e4SLinus Torvalds 		.access = SNDRV_CTL_ELEM_ACCESS_READ,
32431da177e4SLinus Torvalds 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
32441da177e4SLinus Torvalds 		.name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, PRO_MASK),
32451da177e4SLinus Torvalds 		.info = snd_hda_spdif_mask_info,
32461da177e4SLinus Torvalds 		.get = snd_hda_spdif_pmask_get,
32471da177e4SLinus Torvalds 	},
32481da177e4SLinus Torvalds 	{
32491da177e4SLinus Torvalds 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
32501da177e4SLinus Torvalds 		.name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, DEFAULT),
32511da177e4SLinus Torvalds 		.info = snd_hda_spdif_mask_info,
32521da177e4SLinus Torvalds 		.get = snd_hda_spdif_default_get,
32531da177e4SLinus Torvalds 		.put = snd_hda_spdif_default_put,
32541da177e4SLinus Torvalds 	},
32551da177e4SLinus Torvalds 	{
32561da177e4SLinus Torvalds 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
32571da177e4SLinus Torvalds 		.name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, SWITCH),
32581da177e4SLinus Torvalds 		.info = snd_hda_spdif_out_switch_info,
32591da177e4SLinus Torvalds 		.get = snd_hda_spdif_out_switch_get,
32601da177e4SLinus Torvalds 		.put = snd_hda_spdif_out_switch_put,
32611da177e4SLinus Torvalds 	},
32621da177e4SLinus Torvalds 	{ } /* end */
32631da177e4SLinus Torvalds };
32641da177e4SLinus Torvalds 
32651da177e4SLinus Torvalds /**
3266dcda5806STakashi Iwai  * snd_hda_create_dig_out_ctls - create Output SPDIF-related controls
32671da177e4SLinus Torvalds  * @codec: the HDA codec
3268dcda5806STakashi Iwai  * @associated_nid: NID that new ctls associated with
3269dcda5806STakashi Iwai  * @cvt_nid: converter NID
3270dcda5806STakashi Iwai  * @type: HDA_PCM_TYPE_*
3271dcda5806STakashi Iwai  * Creates controls related with the digital output.
3272dcda5806STakashi Iwai  * Called from each patch supporting the digital out.
32731da177e4SLinus Torvalds  *
32741da177e4SLinus Torvalds  * Returns 0 if successful, or a negative error code.
32751da177e4SLinus Torvalds  */
3276dcda5806STakashi Iwai int snd_hda_create_dig_out_ctls(struct hda_codec *codec,
327774b654c9SStephen Warren 				hda_nid_t associated_nid,
3278dcda5806STakashi Iwai 				hda_nid_t cvt_nid,
3279dcda5806STakashi Iwai 				int type)
32801da177e4SLinus Torvalds {
32811da177e4SLinus Torvalds 	int err;
3282c8b6bf9bSTakashi Iwai 	struct snd_kcontrol *kctl;
3283c8b6bf9bSTakashi Iwai 	struct snd_kcontrol_new *dig_mix;
3284dcda5806STakashi Iwai 	int idx, dev = 0;
3285dcda5806STakashi Iwai 	const int spdif_pcm_dev = 1;
32867c935976SStephen Warren 	struct hda_spdif_out *spdif;
32871da177e4SLinus Torvalds 
3288dcda5806STakashi Iwai 	if (codec->primary_dig_out_type == HDA_PCM_TYPE_HDMI &&
3289dcda5806STakashi Iwai 	    type == HDA_PCM_TYPE_SPDIF) {
3290dcda5806STakashi Iwai 		dev = spdif_pcm_dev;
3291dcda5806STakashi Iwai 	} else if (codec->primary_dig_out_type == HDA_PCM_TYPE_SPDIF &&
3292dcda5806STakashi Iwai 		   type == HDA_PCM_TYPE_HDMI) {
3293dcda5806STakashi Iwai 		for (idx = 0; idx < codec->spdif_out.used; idx++) {
3294dcda5806STakashi Iwai 			spdif = snd_array_elem(&codec->spdif_out, idx);
3295dcda5806STakashi Iwai 			for (dig_mix = dig_mixes; dig_mix->name; dig_mix++) {
3296dcda5806STakashi Iwai 				kctl = find_mixer_ctl(codec, dig_mix->name, 0, idx);
3297dcda5806STakashi Iwai 				if (!kctl)
3298dcda5806STakashi Iwai 					break;
3299dcda5806STakashi Iwai 				kctl->id.device = spdif_pcm_dev;
3300dcda5806STakashi Iwai 			}
3301dcda5806STakashi Iwai 		}
3302dcda5806STakashi Iwai 		codec->primary_dig_out_type = HDA_PCM_TYPE_HDMI;
3303dcda5806STakashi Iwai 	}
3304dcda5806STakashi Iwai 	if (!codec->primary_dig_out_type)
3305dcda5806STakashi Iwai 		codec->primary_dig_out_type = type;
3306dcda5806STakashi Iwai 
3307dcda5806STakashi Iwai 	idx = find_empty_mixer_ctl_idx(codec, "IEC958 Playback Switch", dev);
33081afe206aSTakashi Iwai 	if (idx < 0) {
330909f99701STakashi Iwai 		printk(KERN_ERR "hda_codec: too many IEC958 outputs\n");
331009f99701STakashi Iwai 		return -EBUSY;
331109f99701STakashi Iwai 	}
33127c935976SStephen Warren 	spdif = snd_array_new(&codec->spdif_out);
33131da177e4SLinus Torvalds 	for (dig_mix = dig_mixes; dig_mix->name; dig_mix++) {
33141da177e4SLinus Torvalds 		kctl = snd_ctl_new1(dig_mix, codec);
3315b91f080fSTakashi Iwai 		if (!kctl)
3316b91f080fSTakashi Iwai 			return -ENOMEM;
3317dcda5806STakashi Iwai 		kctl->id.device = dev;
331809f99701STakashi Iwai 		kctl->id.index = idx;
33197c935976SStephen Warren 		kctl->private_value = codec->spdif_out.used - 1;
332074b654c9SStephen Warren 		err = snd_hda_ctl_add(codec, associated_nid, kctl);
33210ba21762STakashi Iwai 		if (err < 0)
33221da177e4SLinus Torvalds 			return err;
33231da177e4SLinus Torvalds 	}
332474b654c9SStephen Warren 	spdif->nid = cvt_nid;
332574b654c9SStephen Warren 	spdif->ctls = snd_hda_codec_read(codec, cvt_nid, 0,
33263982d17eSAndrew Paprocki 					 AC_VERB_GET_DIGI_CONVERT_1, 0);
33277c935976SStephen Warren 	spdif->status = convert_to_spdif_status(spdif->ctls);
33281da177e4SLinus Torvalds 	return 0;
33291da177e4SLinus Torvalds }
3330dcda5806STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_create_dig_out_ctls);
33311da177e4SLinus Torvalds 
3332e3245cddSTakashi Iwai /* get the hda_spdif_out entry from the given NID
3333e3245cddSTakashi Iwai  * call within spdif_mutex lock
3334e3245cddSTakashi Iwai  */
33357c935976SStephen Warren struct hda_spdif_out *snd_hda_spdif_out_of_nid(struct hda_codec *codec,
33367c935976SStephen Warren 					       hda_nid_t nid)
33377c935976SStephen Warren {
33387c935976SStephen Warren 	int i;
33397c935976SStephen Warren 	for (i = 0; i < codec->spdif_out.used; i++) {
33407c935976SStephen Warren 		struct hda_spdif_out *spdif =
33417c935976SStephen Warren 				snd_array_elem(&codec->spdif_out, i);
33427c935976SStephen Warren 		if (spdif->nid == nid)
33437c935976SStephen Warren 			return spdif;
33447c935976SStephen Warren 	}
33457c935976SStephen Warren 	return NULL;
33467c935976SStephen Warren }
33477c935976SStephen Warren EXPORT_SYMBOL_HDA(snd_hda_spdif_out_of_nid);
33487c935976SStephen Warren 
334974b654c9SStephen Warren void snd_hda_spdif_ctls_unassign(struct hda_codec *codec, int idx)
335074b654c9SStephen Warren {
3351e3245cddSTakashi Iwai 	struct hda_spdif_out *spdif;
335274b654c9SStephen Warren 
335374b654c9SStephen Warren 	mutex_lock(&codec->spdif_mutex);
3354e3245cddSTakashi Iwai 	spdif = snd_array_elem(&codec->spdif_out, idx);
335574b654c9SStephen Warren 	spdif->nid = (u16)-1;
335674b654c9SStephen Warren 	mutex_unlock(&codec->spdif_mutex);
335774b654c9SStephen Warren }
335874b654c9SStephen Warren EXPORT_SYMBOL_HDA(snd_hda_spdif_ctls_unassign);
335974b654c9SStephen Warren 
336074b654c9SStephen Warren void snd_hda_spdif_ctls_assign(struct hda_codec *codec, int idx, hda_nid_t nid)
336174b654c9SStephen Warren {
3362e3245cddSTakashi Iwai 	struct hda_spdif_out *spdif;
336374b654c9SStephen Warren 	unsigned short val;
336474b654c9SStephen Warren 
336574b654c9SStephen Warren 	mutex_lock(&codec->spdif_mutex);
3366e3245cddSTakashi Iwai 	spdif = snd_array_elem(&codec->spdif_out, idx);
336774b654c9SStephen Warren 	if (spdif->nid != nid) {
336874b654c9SStephen Warren 		spdif->nid = nid;
336974b654c9SStephen Warren 		val = spdif->ctls;
337074b654c9SStephen Warren 		set_spdif_ctls(codec, nid, val & 0xff, (val >> 8) & 0xff);
337174b654c9SStephen Warren 	}
337274b654c9SStephen Warren 	mutex_unlock(&codec->spdif_mutex);
337374b654c9SStephen Warren }
337474b654c9SStephen Warren EXPORT_SYMBOL_HDA(snd_hda_spdif_ctls_assign);
337574b654c9SStephen Warren 
33761da177e4SLinus Torvalds /*
33779a08160bSTakashi Iwai  * SPDIF sharing with analog output
33789a08160bSTakashi Iwai  */
33799a08160bSTakashi Iwai static int spdif_share_sw_get(struct snd_kcontrol *kcontrol,
33809a08160bSTakashi Iwai 			      struct snd_ctl_elem_value *ucontrol)
33819a08160bSTakashi Iwai {
33829a08160bSTakashi Iwai 	struct hda_multi_out *mout = snd_kcontrol_chip(kcontrol);
33839a08160bSTakashi Iwai 	ucontrol->value.integer.value[0] = mout->share_spdif;
33849a08160bSTakashi Iwai 	return 0;
33859a08160bSTakashi Iwai }
33869a08160bSTakashi Iwai 
33879a08160bSTakashi Iwai static int spdif_share_sw_put(struct snd_kcontrol *kcontrol,
33889a08160bSTakashi Iwai 			      struct snd_ctl_elem_value *ucontrol)
33899a08160bSTakashi Iwai {
33909a08160bSTakashi Iwai 	struct hda_multi_out *mout = snd_kcontrol_chip(kcontrol);
33919a08160bSTakashi Iwai 	mout->share_spdif = !!ucontrol->value.integer.value[0];
33929a08160bSTakashi Iwai 	return 0;
33939a08160bSTakashi Iwai }
33949a08160bSTakashi Iwai 
33959a08160bSTakashi Iwai static struct snd_kcontrol_new spdif_share_sw = {
33969a08160bSTakashi Iwai 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
33979a08160bSTakashi Iwai 	.name = "IEC958 Default PCM Playback Switch",
33989a08160bSTakashi Iwai 	.info = snd_ctl_boolean_mono_info,
33999a08160bSTakashi Iwai 	.get = spdif_share_sw_get,
34009a08160bSTakashi Iwai 	.put = spdif_share_sw_put,
34019a08160bSTakashi Iwai };
34029a08160bSTakashi Iwai 
3403d5191e50STakashi Iwai /**
3404d5191e50STakashi Iwai  * snd_hda_create_spdif_share_sw - create Default PCM switch
3405d5191e50STakashi Iwai  * @codec: the HDA codec
3406d5191e50STakashi Iwai  * @mout: multi-out instance
3407d5191e50STakashi Iwai  */
34089a08160bSTakashi Iwai int snd_hda_create_spdif_share_sw(struct hda_codec *codec,
34099a08160bSTakashi Iwai 				  struct hda_multi_out *mout)
34109a08160bSTakashi Iwai {
34119a08160bSTakashi Iwai 	if (!mout->dig_out_nid)
34129a08160bSTakashi Iwai 		return 0;
34139a08160bSTakashi Iwai 	/* ATTENTION: here mout is passed as private_data, instead of codec */
34143911a4c1SJaroslav Kysela 	return snd_hda_ctl_add(codec, mout->dig_out_nid,
34159a08160bSTakashi Iwai 			      snd_ctl_new1(&spdif_share_sw, mout));
34169a08160bSTakashi Iwai }
3417ff7a3267STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_create_spdif_share_sw);
34189a08160bSTakashi Iwai 
34199a08160bSTakashi Iwai /*
34201da177e4SLinus Torvalds  * SPDIF input
34211da177e4SLinus Torvalds  */
34221da177e4SLinus Torvalds 
34231da177e4SLinus Torvalds #define snd_hda_spdif_in_switch_info	snd_hda_spdif_out_switch_info
34241da177e4SLinus Torvalds 
34250ba21762STakashi Iwai static int snd_hda_spdif_in_switch_get(struct snd_kcontrol *kcontrol,
34260ba21762STakashi Iwai 				       struct snd_ctl_elem_value *ucontrol)
34271da177e4SLinus Torvalds {
34281da177e4SLinus Torvalds 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
34291da177e4SLinus Torvalds 
34301da177e4SLinus Torvalds 	ucontrol->value.integer.value[0] = codec->spdif_in_enable;
34311da177e4SLinus Torvalds 	return 0;
34321da177e4SLinus Torvalds }
34331da177e4SLinus Torvalds 
34340ba21762STakashi Iwai static int snd_hda_spdif_in_switch_put(struct snd_kcontrol *kcontrol,
34350ba21762STakashi Iwai 				       struct snd_ctl_elem_value *ucontrol)
34361da177e4SLinus Torvalds {
34371da177e4SLinus Torvalds 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
34381da177e4SLinus Torvalds 	hda_nid_t nid = kcontrol->private_value;
34391da177e4SLinus Torvalds 	unsigned int val = !!ucontrol->value.integer.value[0];
34401da177e4SLinus Torvalds 	int change;
34411da177e4SLinus Torvalds 
344262932df8SIngo Molnar 	mutex_lock(&codec->spdif_mutex);
34431da177e4SLinus Torvalds 	change = codec->spdif_in_enable != val;
344482beb8fdSTakashi Iwai 	if (change) {
34451da177e4SLinus Torvalds 		codec->spdif_in_enable = val;
344682beb8fdSTakashi Iwai 		snd_hda_codec_write_cache(codec, nid, 0,
344782beb8fdSTakashi Iwai 					  AC_VERB_SET_DIGI_CONVERT_1, val);
34481da177e4SLinus Torvalds 	}
344962932df8SIngo Molnar 	mutex_unlock(&codec->spdif_mutex);
34501da177e4SLinus Torvalds 	return change;
34511da177e4SLinus Torvalds }
34521da177e4SLinus Torvalds 
34530ba21762STakashi Iwai static int snd_hda_spdif_in_status_get(struct snd_kcontrol *kcontrol,
34540ba21762STakashi Iwai 				       struct snd_ctl_elem_value *ucontrol)
34551da177e4SLinus Torvalds {
34561da177e4SLinus Torvalds 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
34571da177e4SLinus Torvalds 	hda_nid_t nid = kcontrol->private_value;
34581da177e4SLinus Torvalds 	unsigned short val;
34591da177e4SLinus Torvalds 	unsigned int sbits;
34601da177e4SLinus Torvalds 
34613982d17eSAndrew Paprocki 	val = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_DIGI_CONVERT_1, 0);
34621da177e4SLinus Torvalds 	sbits = convert_to_spdif_status(val);
34631da177e4SLinus Torvalds 	ucontrol->value.iec958.status[0] = sbits;
34641da177e4SLinus Torvalds 	ucontrol->value.iec958.status[1] = sbits >> 8;
34651da177e4SLinus Torvalds 	ucontrol->value.iec958.status[2] = sbits >> 16;
34661da177e4SLinus Torvalds 	ucontrol->value.iec958.status[3] = sbits >> 24;
34671da177e4SLinus Torvalds 	return 0;
34681da177e4SLinus Torvalds }
34691da177e4SLinus Torvalds 
3470c8b6bf9bSTakashi Iwai static struct snd_kcontrol_new dig_in_ctls[] = {
34711da177e4SLinus Torvalds 	{
34721da177e4SLinus Torvalds 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
34731da177e4SLinus Torvalds 		.name = SNDRV_CTL_NAME_IEC958("", CAPTURE, SWITCH),
34741da177e4SLinus Torvalds 		.info = snd_hda_spdif_in_switch_info,
34751da177e4SLinus Torvalds 		.get = snd_hda_spdif_in_switch_get,
34761da177e4SLinus Torvalds 		.put = snd_hda_spdif_in_switch_put,
34771da177e4SLinus Torvalds 	},
34781da177e4SLinus Torvalds 	{
34791da177e4SLinus Torvalds 		.access = SNDRV_CTL_ELEM_ACCESS_READ,
34801da177e4SLinus Torvalds 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
34811da177e4SLinus Torvalds 		.name = SNDRV_CTL_NAME_IEC958("", CAPTURE, DEFAULT),
34821da177e4SLinus Torvalds 		.info = snd_hda_spdif_mask_info,
34831da177e4SLinus Torvalds 		.get = snd_hda_spdif_in_status_get,
34841da177e4SLinus Torvalds 	},
34851da177e4SLinus Torvalds 	{ } /* end */
34861da177e4SLinus Torvalds };
34871da177e4SLinus Torvalds 
34881da177e4SLinus Torvalds /**
34891da177e4SLinus Torvalds  * snd_hda_create_spdif_in_ctls - create Input SPDIF-related controls
34901da177e4SLinus Torvalds  * @codec: the HDA codec
34911da177e4SLinus Torvalds  * @nid: audio in widget NID
34921da177e4SLinus Torvalds  *
34931da177e4SLinus Torvalds  * Creates controls related with the SPDIF input.
34941da177e4SLinus Torvalds  * Called from each patch supporting the SPDIF in.
34951da177e4SLinus Torvalds  *
34961da177e4SLinus Torvalds  * Returns 0 if successful, or a negative error code.
34971da177e4SLinus Torvalds  */
349812f288bfSTakashi Iwai int snd_hda_create_spdif_in_ctls(struct hda_codec *codec, hda_nid_t nid)
34991da177e4SLinus Torvalds {
35001da177e4SLinus Torvalds 	int err;
3501c8b6bf9bSTakashi Iwai 	struct snd_kcontrol *kctl;
3502c8b6bf9bSTakashi Iwai 	struct snd_kcontrol_new *dig_mix;
350309f99701STakashi Iwai 	int idx;
35041da177e4SLinus Torvalds 
3505dcda5806STakashi Iwai 	idx = find_empty_mixer_ctl_idx(codec, "IEC958 Capture Switch", 0);
35061afe206aSTakashi Iwai 	if (idx < 0) {
350709f99701STakashi Iwai 		printk(KERN_ERR "hda_codec: too many IEC958 inputs\n");
350809f99701STakashi Iwai 		return -EBUSY;
350909f99701STakashi Iwai 	}
35101da177e4SLinus Torvalds 	for (dig_mix = dig_in_ctls; dig_mix->name; dig_mix++) {
35111da177e4SLinus Torvalds 		kctl = snd_ctl_new1(dig_mix, codec);
3512c8dcdf82STakashi Iwai 		if (!kctl)
3513c8dcdf82STakashi Iwai 			return -ENOMEM;
35141da177e4SLinus Torvalds 		kctl->private_value = nid;
35153911a4c1SJaroslav Kysela 		err = snd_hda_ctl_add(codec, nid, kctl);
35160ba21762STakashi Iwai 		if (err < 0)
35171da177e4SLinus Torvalds 			return err;
35181da177e4SLinus Torvalds 	}
35190ba21762STakashi Iwai 	codec->spdif_in_enable =
35203982d17eSAndrew Paprocki 		snd_hda_codec_read(codec, nid, 0,
35213982d17eSAndrew Paprocki 				   AC_VERB_GET_DIGI_CONVERT_1, 0) &
35220ba21762STakashi Iwai 		AC_DIG1_ENABLE;
35231da177e4SLinus Torvalds 	return 0;
35241da177e4SLinus Torvalds }
3525ff7a3267STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_create_spdif_in_ctls);
35261da177e4SLinus Torvalds 
352782beb8fdSTakashi Iwai /*
352882beb8fdSTakashi Iwai  * command cache
352982beb8fdSTakashi Iwai  */
35301da177e4SLinus Torvalds 
3531c370dd6eSTakashi Iwai /* build a 31bit cache key with the widget id and the command parameter */
3532b3ac5636STakashi Iwai #define build_cmd_cache_key(nid, verb)	((verb << 8) | nid)
3533b3ac5636STakashi Iwai #define get_cmd_cache_nid(key)		((key) & 0xff)
3534b3ac5636STakashi Iwai #define get_cmd_cache_cmd(key)		(((key) >> 8) & 0xffff)
3535b3ac5636STakashi Iwai 
3536b3ac5636STakashi Iwai /**
3537b3ac5636STakashi Iwai  * snd_hda_codec_write_cache - send a single command with caching
3538b3ac5636STakashi Iwai  * @codec: the HDA codec
3539b3ac5636STakashi Iwai  * @nid: NID to send the command
3540b3ac5636STakashi Iwai  * @direct: direct flag
3541b3ac5636STakashi Iwai  * @verb: the verb to send
3542b3ac5636STakashi Iwai  * @parm: the parameter for the verb
3543b3ac5636STakashi Iwai  *
3544b3ac5636STakashi Iwai  * Send a single command without waiting for response.
3545b3ac5636STakashi Iwai  *
3546b3ac5636STakashi Iwai  * Returns 0 if successful, or a negative error code.
3547b3ac5636STakashi Iwai  */
3548b3ac5636STakashi Iwai int snd_hda_codec_write_cache(struct hda_codec *codec, hda_nid_t nid,
3549b3ac5636STakashi Iwai 			      int direct, unsigned int verb, unsigned int parm)
3550b3ac5636STakashi Iwai {
3551c370dd6eSTakashi Iwai 	int err;
3552b3ac5636STakashi Iwai 	struct hda_cache_head *c;
3553fcad94a4STakashi Iwai 	u32 key;
3554de1e37b7STakashi Iwai 	unsigned int cache_only;
3555aa2936f5STakashi Iwai 
3556de1e37b7STakashi Iwai 	cache_only = codec->cached_write;
3557de1e37b7STakashi Iwai 	if (!cache_only) {
3558c370dd6eSTakashi Iwai 		err = snd_hda_codec_write(codec, nid, direct, verb, parm);
3559aa2936f5STakashi Iwai 		if (err < 0)
3560aa2936f5STakashi Iwai 			return err;
3561c370dd6eSTakashi Iwai 	}
3562c370dd6eSTakashi Iwai 
3563fcad94a4STakashi Iwai 	/* parm may contain the verb stuff for get/set amp */
3564fcad94a4STakashi Iwai 	verb = verb | (parm >> 8);
3565fcad94a4STakashi Iwai 	parm &= 0xff;
3566fcad94a4STakashi Iwai 	key = build_cmd_cache_key(nid, verb);
3567aa2936f5STakashi Iwai 	mutex_lock(&codec->bus->cmd_mutex);
3568b3ac5636STakashi Iwai 	c = get_alloc_hash(&codec->cmd_cache, key);
3569c370dd6eSTakashi Iwai 	if (c) {
3570b3ac5636STakashi Iwai 		c->val = parm;
3571de1e37b7STakashi Iwai 		c->dirty = cache_only;
3572c370dd6eSTakashi Iwai 	}
3573aa2936f5STakashi Iwai 	mutex_unlock(&codec->bus->cmd_mutex);
3574aa2936f5STakashi Iwai 	return 0;
3575b3ac5636STakashi Iwai }
3576ff7a3267STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_codec_write_cache);
3577b3ac5636STakashi Iwai 
3578d5191e50STakashi Iwai /**
3579a68d5a54STakashi Iwai  * snd_hda_codec_update_cache - check cache and write the cmd only when needed
3580a68d5a54STakashi Iwai  * @codec: the HDA codec
3581a68d5a54STakashi Iwai  * @nid: NID to send the command
3582a68d5a54STakashi Iwai  * @direct: direct flag
3583a68d5a54STakashi Iwai  * @verb: the verb to send
3584a68d5a54STakashi Iwai  * @parm: the parameter for the verb
3585a68d5a54STakashi Iwai  *
3586a68d5a54STakashi Iwai  * This function works like snd_hda_codec_write_cache(), but it doesn't send
3587a68d5a54STakashi Iwai  * command if the parameter is already identical with the cached value.
3588a68d5a54STakashi Iwai  * If not, it sends the command and refreshes the cache.
3589a68d5a54STakashi Iwai  *
3590a68d5a54STakashi Iwai  * Returns 0 if successful, or a negative error code.
3591a68d5a54STakashi Iwai  */
3592a68d5a54STakashi Iwai int snd_hda_codec_update_cache(struct hda_codec *codec, hda_nid_t nid,
3593a68d5a54STakashi Iwai 			       int direct, unsigned int verb, unsigned int parm)
3594a68d5a54STakashi Iwai {
3595a68d5a54STakashi Iwai 	struct hda_cache_head *c;
3596a68d5a54STakashi Iwai 	u32 key;
3597a68d5a54STakashi Iwai 
3598a68d5a54STakashi Iwai 	/* parm may contain the verb stuff for get/set amp */
3599a68d5a54STakashi Iwai 	verb = verb | (parm >> 8);
3600a68d5a54STakashi Iwai 	parm &= 0xff;
3601a68d5a54STakashi Iwai 	key = build_cmd_cache_key(nid, verb);
3602a68d5a54STakashi Iwai 	mutex_lock(&codec->bus->cmd_mutex);
3603a68d5a54STakashi Iwai 	c = get_hash(&codec->cmd_cache, key);
3604a68d5a54STakashi Iwai 	if (c && c->val == parm) {
3605a68d5a54STakashi Iwai 		mutex_unlock(&codec->bus->cmd_mutex);
3606a68d5a54STakashi Iwai 		return 0;
3607a68d5a54STakashi Iwai 	}
3608a68d5a54STakashi Iwai 	mutex_unlock(&codec->bus->cmd_mutex);
3609a68d5a54STakashi Iwai 	return snd_hda_codec_write_cache(codec, nid, direct, verb, parm);
3610a68d5a54STakashi Iwai }
3611a68d5a54STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_codec_update_cache);
3612a68d5a54STakashi Iwai 
3613a68d5a54STakashi Iwai /**
3614d5191e50STakashi Iwai  * snd_hda_codec_resume_cache - Resume the all commands from the cache
3615d5191e50STakashi Iwai  * @codec: HD-audio codec
3616d5191e50STakashi Iwai  *
3617d5191e50STakashi Iwai  * Execute all verbs recorded in the command caches to resume.
3618d5191e50STakashi Iwai  */
3619b3ac5636STakashi Iwai void snd_hda_codec_resume_cache(struct hda_codec *codec)
3620b3ac5636STakashi Iwai {
3621b3ac5636STakashi Iwai 	int i;
3622b3ac5636STakashi Iwai 
3623c370dd6eSTakashi Iwai 	mutex_lock(&codec->hash_mutex);
3624aa88a355STakashi Iwai 	codec->cached_write = 0;
3625c370dd6eSTakashi Iwai 	for (i = 0; i < codec->cmd_cache.buf.used; i++) {
3626c370dd6eSTakashi Iwai 		struct hda_cache_head *buffer;
3627c370dd6eSTakashi Iwai 		u32 key;
3628c370dd6eSTakashi Iwai 
3629c370dd6eSTakashi Iwai 		buffer = snd_array_elem(&codec->cmd_cache.buf, i);
3630c370dd6eSTakashi Iwai 		key = buffer->key;
3631b3ac5636STakashi Iwai 		if (!key)
3632b3ac5636STakashi Iwai 			continue;
3633c370dd6eSTakashi Iwai 		if (!buffer->dirty)
3634c370dd6eSTakashi Iwai 			continue;
3635c370dd6eSTakashi Iwai 		buffer->dirty = 0;
3636c370dd6eSTakashi Iwai 		mutex_unlock(&codec->hash_mutex);
3637b3ac5636STakashi Iwai 		snd_hda_codec_write(codec, get_cmd_cache_nid(key), 0,
3638b3ac5636STakashi Iwai 				    get_cmd_cache_cmd(key), buffer->val);
3639c370dd6eSTakashi Iwai 		mutex_lock(&codec->hash_mutex);
3640b3ac5636STakashi Iwai 	}
3641c370dd6eSTakashi Iwai 	mutex_unlock(&codec->hash_mutex);
3642b3ac5636STakashi Iwai }
3643ff7a3267STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_codec_resume_cache);
3644b3ac5636STakashi Iwai 
3645b3ac5636STakashi Iwai /**
3646b3ac5636STakashi Iwai  * snd_hda_sequence_write_cache - sequence writes with caching
3647b3ac5636STakashi Iwai  * @codec: the HDA codec
3648b3ac5636STakashi Iwai  * @seq: VERB array to send
3649b3ac5636STakashi Iwai  *
3650b3ac5636STakashi Iwai  * Send the commands sequentially from the given array.
3651b3ac5636STakashi Iwai  * Thte commands are recorded on cache for power-save and resume.
3652b3ac5636STakashi Iwai  * The array must be terminated with NID=0.
3653b3ac5636STakashi Iwai  */
3654b3ac5636STakashi Iwai void snd_hda_sequence_write_cache(struct hda_codec *codec,
3655b3ac5636STakashi Iwai 				  const struct hda_verb *seq)
3656b3ac5636STakashi Iwai {
3657b3ac5636STakashi Iwai 	for (; seq->nid; seq++)
3658b3ac5636STakashi Iwai 		snd_hda_codec_write_cache(codec, seq->nid, 0, seq->verb,
3659b3ac5636STakashi Iwai 					  seq->param);
3660b3ac5636STakashi Iwai }
3661ff7a3267STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_sequence_write_cache);
3662b3ac5636STakashi Iwai 
3663dc870f38STakashi Iwai /**
3664dc870f38STakashi Iwai  * snd_hda_codec_flush_cache - Execute all pending (cached) amps / verbs
3665dc870f38STakashi Iwai  * @codec: HD-audio codec
3666dc870f38STakashi Iwai  */
3667dc870f38STakashi Iwai void snd_hda_codec_flush_cache(struct hda_codec *codec)
3668dc870f38STakashi Iwai {
3669dc870f38STakashi Iwai 	snd_hda_codec_resume_amp(codec);
3670dc870f38STakashi Iwai 	snd_hda_codec_resume_cache(codec);
3671dc870f38STakashi Iwai }
3672dc870f38STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_codec_flush_cache);
3673dc870f38STakashi Iwai 
36744d7fbdbcSTakashi Iwai void snd_hda_codec_set_power_to_all(struct hda_codec *codec, hda_nid_t fg,
36759419ab6bSTakashi Iwai 				    unsigned int power_state)
367654d17403STakashi Iwai {
36774d7fbdbcSTakashi Iwai 	hda_nid_t nid = codec->start_nid;
3678cb53c626STakashi Iwai 	int i;
367954d17403STakashi Iwai 
3680cb53c626STakashi Iwai 	for (i = 0; i < codec->num_nodes; i++, nid++) {
36817eba5c9dSTakashi Iwai 		unsigned int wcaps = get_wcaps(codec, nid);
36829419ab6bSTakashi Iwai 		unsigned int state = power_state;
36834d7fbdbcSTakashi Iwai 		if (!(wcaps & AC_WCAP_POWER))
36844d7fbdbcSTakashi Iwai 			continue;
36859419ab6bSTakashi Iwai 		if (codec->power_filter) {
36869419ab6bSTakashi Iwai 			state = codec->power_filter(codec, nid, power_state);
36879419ab6bSTakashi Iwai 			if (state != power_state && power_state == AC_PWRST_D3)
36881194b5b7STakashi Iwai 				continue;
36891194b5b7STakashi Iwai 		}
36904d7fbdbcSTakashi Iwai 		snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_POWER_STATE,
36919419ab6bSTakashi Iwai 				    state);
369254d17403STakashi Iwai 	}
3693cb53c626STakashi Iwai }
36944d7fbdbcSTakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_codec_set_power_to_all);
36954d7fbdbcSTakashi Iwai 
36964d7fbdbcSTakashi Iwai /*
36970c7f46adSWang Xingchao  *  supported power states check
36980c7f46adSWang Xingchao  */
36990c7f46adSWang Xingchao static bool snd_hda_codec_get_supported_ps(struct hda_codec *codec, hda_nid_t fg,
37000c7f46adSWang Xingchao 				unsigned int power_state)
37010c7f46adSWang Xingchao {
37020c7f46adSWang Xingchao 	int sup = snd_hda_param_read(codec, fg, AC_PAR_POWER_STATE);
37030c7f46adSWang Xingchao 
3704e037cb4aSMengdong Lin 	if (sup == -1)
37050c7f46adSWang Xingchao 		return false;
37060c7f46adSWang Xingchao 	if (sup & power_state)
37070c7f46adSWang Xingchao 		return true;
37080c7f46adSWang Xingchao 	else
37090c7f46adSWang Xingchao 		return false;
37100c7f46adSWang Xingchao }
37110c7f46adSWang Xingchao 
37120c7f46adSWang Xingchao /*
3713432c641eSTakashi Iwai  * wait until the state is reached, returns the current state
3714432c641eSTakashi Iwai  */
3715432c641eSTakashi Iwai static unsigned int hda_sync_power_state(struct hda_codec *codec,
3716432c641eSTakashi Iwai 					 hda_nid_t fg,
3717432c641eSTakashi Iwai 					 unsigned int power_state)
3718432c641eSTakashi Iwai {
3719432c641eSTakashi Iwai 	unsigned long end_time = jiffies + msecs_to_jiffies(500);
3720432c641eSTakashi Iwai 	unsigned int state, actual_state;
3721432c641eSTakashi Iwai 
3722432c641eSTakashi Iwai 	for (;;) {
3723432c641eSTakashi Iwai 		state = snd_hda_codec_read(codec, fg, 0,
3724432c641eSTakashi Iwai 					   AC_VERB_GET_POWER_STATE, 0);
3725432c641eSTakashi Iwai 		if (state & AC_PWRST_ERROR)
3726432c641eSTakashi Iwai 			break;
3727432c641eSTakashi Iwai 		actual_state = (state >> 4) & 0x0f;
3728432c641eSTakashi Iwai 		if (actual_state == power_state)
3729432c641eSTakashi Iwai 			break;
3730432c641eSTakashi Iwai 		if (time_after_eq(jiffies, end_time))
3731432c641eSTakashi Iwai 			break;
3732432c641eSTakashi Iwai 		/* wait until the codec reachs to the target state */
3733432c641eSTakashi Iwai 		msleep(1);
3734432c641eSTakashi Iwai 	}
3735432c641eSTakashi Iwai 	return state;
3736432c641eSTakashi Iwai }
3737432c641eSTakashi Iwai 
37389419ab6bSTakashi Iwai /* don't power down the widget if it controls eapd and EAPD_BTLENABLE is set */
37399419ab6bSTakashi Iwai static unsigned int default_power_filter(struct hda_codec *codec, hda_nid_t nid,
37409419ab6bSTakashi Iwai 					 unsigned int power_state)
37419419ab6bSTakashi Iwai {
37429419ab6bSTakashi Iwai 	if (power_state == AC_PWRST_D3 &&
37439419ab6bSTakashi Iwai 	    get_wcaps_type(get_wcaps(codec, nid)) == AC_WID_PIN &&
37449419ab6bSTakashi Iwai 	    (snd_hda_query_pin_caps(codec, nid) & AC_PINCAP_EAPD)) {
37459419ab6bSTakashi Iwai 		int eapd = snd_hda_codec_read(codec, nid, 0,
37469419ab6bSTakashi Iwai 					      AC_VERB_GET_EAPD_BTLENABLE, 0);
37479419ab6bSTakashi Iwai 		if (eapd & 0x02)
37489419ab6bSTakashi Iwai 			return AC_PWRST_D0;
37499419ab6bSTakashi Iwai 	}
37509419ab6bSTakashi Iwai 	return power_state;
37519419ab6bSTakashi Iwai }
37529419ab6bSTakashi Iwai 
3753432c641eSTakashi Iwai /*
375408fa20aeSTakashi Iwai  * set power state of the codec, and return the power state
37554d7fbdbcSTakashi Iwai  */
3756d819387eSTakashi Iwai static unsigned int hda_set_power_state(struct hda_codec *codec,
37574d7fbdbcSTakashi Iwai 					unsigned int power_state)
37584d7fbdbcSTakashi Iwai {
3759d819387eSTakashi Iwai 	hda_nid_t fg = codec->afg ? codec->afg : codec->mfg;
376009617ce4SWang Xingchao 	int count;
376109617ce4SWang Xingchao 	unsigned int state;
376209617ce4SWang Xingchao 
37634d7fbdbcSTakashi Iwai 	/* this delay seems necessary to avoid click noise at power-down */
37640f4ccbb0SWang Xingchao 	if (power_state == AC_PWRST_D3) {
37650f4ccbb0SWang Xingchao 		/* transition time less than 10ms for power down */
3766983f6b93STakashi Iwai 		msleep(codec->epss ? 10 : 100);
37670f4ccbb0SWang Xingchao 	}
376809617ce4SWang Xingchao 
376909617ce4SWang Xingchao 	/* repeat power states setting at most 10 times*/
377009617ce4SWang Xingchao 	for (count = 0; count < 10; count++) {
3771432c641eSTakashi Iwai 		if (codec->patch_ops.set_power_state)
3772432c641eSTakashi Iwai 			codec->patch_ops.set_power_state(codec, fg,
37734d7fbdbcSTakashi Iwai 							 power_state);
3774432c641eSTakashi Iwai 		else {
3775432c641eSTakashi Iwai 			snd_hda_codec_read(codec, fg, 0,
3776432c641eSTakashi Iwai 					   AC_VERB_SET_POWER_STATE,
3777432c641eSTakashi Iwai 					   power_state);
37789419ab6bSTakashi Iwai 			snd_hda_codec_set_power_to_all(codec, fg, power_state);
3779432c641eSTakashi Iwai 		}
3780432c641eSTakashi Iwai 		state = hda_sync_power_state(codec, fg, power_state);
378109617ce4SWang Xingchao 		if (!(state & AC_PWRST_ERROR))
378209617ce4SWang Xingchao 			break;
378309617ce4SWang Xingchao 	}
3784b8dfc462SMengdong Lin 
378508fa20aeSTakashi Iwai 	return state;
37864d7fbdbcSTakashi Iwai }
3787cb53c626STakashi Iwai 
3788b9c590bbSTakashi Iwai /* sync power states of all widgets;
3789b9c590bbSTakashi Iwai  * this is called at the end of codec parsing
3790b9c590bbSTakashi Iwai  */
3791b9c590bbSTakashi Iwai static void sync_power_up_states(struct hda_codec *codec)
3792b9c590bbSTakashi Iwai {
3793b9c590bbSTakashi Iwai 	hda_nid_t nid = codec->start_nid;
3794b9c590bbSTakashi Iwai 	int i;
3795b9c590bbSTakashi Iwai 
3796b9c590bbSTakashi Iwai 	/* don't care if no or standard filter is used */
3797b9c590bbSTakashi Iwai 	if (!codec->power_filter || codec->power_filter == default_power_filter)
3798b9c590bbSTakashi Iwai 		return;
3799b9c590bbSTakashi Iwai 
3800b9c590bbSTakashi Iwai 	for (i = 0; i < codec->num_nodes; i++, nid++) {
3801b9c590bbSTakashi Iwai 		unsigned int wcaps = get_wcaps(codec, nid);
38029040d102STakashi Iwai 		unsigned int target;
3803b9c590bbSTakashi Iwai 		if (!(wcaps & AC_WCAP_POWER))
3804b9c590bbSTakashi Iwai 			continue;
3805b9c590bbSTakashi Iwai 		target = codec->power_filter(codec, nid, AC_PWRST_D0);
3806b9c590bbSTakashi Iwai 		if (target == AC_PWRST_D0)
3807b9c590bbSTakashi Iwai 			continue;
38089040d102STakashi Iwai 		if (!snd_hda_check_power_state(codec, nid, target))
3809b9c590bbSTakashi Iwai 			snd_hda_codec_write(codec, nid, 0,
3810b9c590bbSTakashi Iwai 					    AC_VERB_SET_POWER_STATE, target);
3811b9c590bbSTakashi Iwai 	}
3812b9c590bbSTakashi Iwai }
3813b9c590bbSTakashi Iwai 
381411aeff08STakashi Iwai #ifdef CONFIG_SND_HDA_HWDEP
381511aeff08STakashi Iwai /* execute additional init verbs */
381611aeff08STakashi Iwai static void hda_exec_init_verbs(struct hda_codec *codec)
381711aeff08STakashi Iwai {
381811aeff08STakashi Iwai 	if (codec->init_verbs.list)
381911aeff08STakashi Iwai 		snd_hda_sequence_write(codec, codec->init_verbs.list);
382011aeff08STakashi Iwai }
382111aeff08STakashi Iwai #else
382211aeff08STakashi Iwai static inline void hda_exec_init_verbs(struct hda_codec *codec) {}
382311aeff08STakashi Iwai #endif
382411aeff08STakashi Iwai 
38252a43952aSTakashi Iwai #ifdef CONFIG_PM
3826cb53c626STakashi Iwai /*
3827cb53c626STakashi Iwai  * call suspend and power-down; used both from PM and power-save
382808fa20aeSTakashi Iwai  * this function returns the power state in the end
3829cb53c626STakashi Iwai  */
3830d17344b3SDylan Reid static unsigned int hda_call_codec_suspend(struct hda_codec *codec, bool in_wq)
3831cb53c626STakashi Iwai {
383208fa20aeSTakashi Iwai 	unsigned int state;
383308fa20aeSTakashi Iwai 
3834989c3187STakashi Iwai 	codec->in_pm = 1;
3835989c3187STakashi Iwai 
3836cb53c626STakashi Iwai 	if (codec->patch_ops.suspend)
383768cb2b55STakashi Iwai 		codec->patch_ops.suspend(codec);
3838eb541337STakashi Iwai 	hda_cleanup_all_streams(codec);
3839d819387eSTakashi Iwai 	state = hda_set_power_state(codec, AC_PWRST_D3);
3840d17344b3SDylan Reid 	/* Cancel delayed work if we aren't currently running from it. */
3841d17344b3SDylan Reid 	if (!in_wq)
3842d17344b3SDylan Reid 		cancel_delayed_work_sync(&codec->power_work);
3843a2d96e77STakashi Iwai 	spin_lock(&codec->power_lock);
3844a2d96e77STakashi Iwai 	snd_hda_update_power_acct(codec);
3845a2d96e77STakashi Iwai 	trace_hda_power_down(codec);
384695e99fdaSTakashi Iwai 	codec->power_on = 0;
3847a221e287STakashi Iwai 	codec->power_transition = 0;
3848a2f6309eSTakashi Iwai 	codec->power_jiffies = jiffies;
3849a2d96e77STakashi Iwai 	spin_unlock(&codec->power_lock);
3850989c3187STakashi Iwai 	codec->in_pm = 0;
385108fa20aeSTakashi Iwai 	return state;
3852cb53c626STakashi Iwai }
3853cb53c626STakashi Iwai 
3854c370dd6eSTakashi Iwai /* mark all entries of cmd and amp caches dirty */
3855c370dd6eSTakashi Iwai static void hda_mark_cmd_cache_dirty(struct hda_codec *codec)
3856c370dd6eSTakashi Iwai {
3857c370dd6eSTakashi Iwai 	int i;
3858c370dd6eSTakashi Iwai 	for (i = 0; i < codec->cmd_cache.buf.used; i++) {
3859c370dd6eSTakashi Iwai 		struct hda_cache_head *cmd;
3860c370dd6eSTakashi Iwai 		cmd = snd_array_elem(&codec->cmd_cache.buf, i);
3861c370dd6eSTakashi Iwai 		cmd->dirty = 1;
3862c370dd6eSTakashi Iwai 	}
3863c370dd6eSTakashi Iwai 	for (i = 0; i < codec->amp_cache.buf.used; i++) {
3864c370dd6eSTakashi Iwai 		struct hda_amp_info *amp;
3865f038fcacSDavid Henningsson 		amp = snd_array_elem(&codec->amp_cache.buf, i);
3866c370dd6eSTakashi Iwai 		amp->head.dirty = 1;
3867c370dd6eSTakashi Iwai 	}
3868c370dd6eSTakashi Iwai }
3869c370dd6eSTakashi Iwai 
3870cb53c626STakashi Iwai /*
3871cb53c626STakashi Iwai  * kick up codec; used both from PM and power-save
3872cb53c626STakashi Iwai  */
3873cb53c626STakashi Iwai static void hda_call_codec_resume(struct hda_codec *codec)
3874cb53c626STakashi Iwai {
3875989c3187STakashi Iwai 	codec->in_pm = 1;
3876989c3187STakashi Iwai 
3877c370dd6eSTakashi Iwai 	hda_mark_cmd_cache_dirty(codec);
3878c370dd6eSTakashi Iwai 
38797f30830bSTakashi Iwai 	/* set as if powered on for avoiding re-entering the resume
38807f30830bSTakashi Iwai 	 * in the resume / power-save sequence
38817f30830bSTakashi Iwai 	 */
38827f30830bSTakashi Iwai 	hda_keep_power_on(codec);
3883d819387eSTakashi Iwai 	hda_set_power_state(codec, AC_PWRST_D0);
3884ac0547dcSTakashi Iwai 	restore_shutup_pins(codec);
388511aeff08STakashi Iwai 	hda_exec_init_verbs(codec);
388631614bb8STakashi Iwai 	snd_hda_jack_set_dirty_all(codec);
3887cb53c626STakashi Iwai 	if (codec->patch_ops.resume)
3888cb53c626STakashi Iwai 		codec->patch_ops.resume(codec);
3889cb53c626STakashi Iwai 	else {
38909d99f312STakashi Iwai 		if (codec->patch_ops.init)
3891cb53c626STakashi Iwai 			codec->patch_ops.init(codec);
3892cb53c626STakashi Iwai 		snd_hda_codec_resume_amp(codec);
3893cb53c626STakashi Iwai 		snd_hda_codec_resume_cache(codec);
3894cb53c626STakashi Iwai 	}
389526a6cb6cSDavid Henningsson 
389626a6cb6cSDavid Henningsson 	if (codec->jackpoll_interval)
389726a6cb6cSDavid Henningsson 		hda_jackpoll_work(&codec->jackpoll_work.work);
389831614bb8STakashi Iwai 	else
38998a535414STakashi Iwai 		snd_hda_jack_report_sync(codec);
3900989c3187STakashi Iwai 
3901989c3187STakashi Iwai 	codec->in_pm = 0;
39027f30830bSTakashi Iwai 	snd_hda_power_down(codec); /* flag down before returning */
3903cb53c626STakashi Iwai }
39042a43952aSTakashi Iwai #endif /* CONFIG_PM */
390554d17403STakashi Iwai 
390654d17403STakashi Iwai 
39071da177e4SLinus Torvalds /**
39081da177e4SLinus Torvalds  * snd_hda_build_controls - build mixer controls
39091da177e4SLinus Torvalds  * @bus: the BUS
39101da177e4SLinus Torvalds  *
39111da177e4SLinus Torvalds  * Creates mixer controls for each codec included in the bus.
39121da177e4SLinus Torvalds  *
39131da177e4SLinus Torvalds  * Returns 0 if successful, otherwise a negative error code.
39141da177e4SLinus Torvalds  */
39156a0f56a7STakashi Iwai int snd_hda_build_controls(struct hda_bus *bus)
39161da177e4SLinus Torvalds {
39170ba21762STakashi Iwai 	struct hda_codec *codec;
39181da177e4SLinus Torvalds 
39190ba21762STakashi Iwai 	list_for_each_entry(codec, &bus->codec_list, list) {
39206c1f45eaSTakashi Iwai 		int err = snd_hda_codec_build_controls(codec);
3921f93d461bSTakashi Iwai 		if (err < 0) {
3922f93d461bSTakashi Iwai 			printk(KERN_ERR "hda_codec: cannot build controls "
3923f93d461bSTakashi Iwai 			       "for #%d (error %d)\n", codec->addr, err);
3924f93d461bSTakashi Iwai 			err = snd_hda_codec_reset(codec);
3925f93d461bSTakashi Iwai 			if (err < 0) {
3926f93d461bSTakashi Iwai 				printk(KERN_ERR
3927f93d461bSTakashi Iwai 				       "hda_codec: cannot revert codec\n");
39286c1f45eaSTakashi Iwai 				return err;
39296c1f45eaSTakashi Iwai 			}
3930f93d461bSTakashi Iwai 		}
3931f93d461bSTakashi Iwai 	}
39326c1f45eaSTakashi Iwai 	return 0;
39336c1f45eaSTakashi Iwai }
3934ff7a3267STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_build_controls);
39356c1f45eaSTakashi Iwai 
39369c9a5175STakashi Iwai /*
39379c9a5175STakashi Iwai  * add standard channel maps if not specified
39389c9a5175STakashi Iwai  */
39399c9a5175STakashi Iwai static int add_std_chmaps(struct hda_codec *codec)
39409c9a5175STakashi Iwai {
39419c9a5175STakashi Iwai 	int i, str, err;
39429c9a5175STakashi Iwai 
39439c9a5175STakashi Iwai 	for (i = 0; i < codec->num_pcms; i++) {
39449c9a5175STakashi Iwai 		for (str = 0; str < 2; str++) {
39459c9a5175STakashi Iwai 			struct snd_pcm *pcm = codec->pcm_info[i].pcm;
39469c9a5175STakashi Iwai 			struct hda_pcm_stream *hinfo =
39479c9a5175STakashi Iwai 				&codec->pcm_info[i].stream[str];
39489c9a5175STakashi Iwai 			struct snd_pcm_chmap *chmap;
3949ee81abb6STakashi Iwai 			const struct snd_pcm_chmap_elem *elem;
39509c9a5175STakashi Iwai 
39519c9a5175STakashi Iwai 			if (codec->pcm_info[i].own_chmap)
39529c9a5175STakashi Iwai 				continue;
39539c9a5175STakashi Iwai 			if (!pcm || !hinfo->substreams)
39549c9a5175STakashi Iwai 				continue;
3955ee81abb6STakashi Iwai 			elem = hinfo->chmap ? hinfo->chmap : snd_pcm_std_chmaps;
3956ee81abb6STakashi Iwai 			err = snd_pcm_add_chmap_ctls(pcm, str, elem,
39579c9a5175STakashi Iwai 						     hinfo->channels_max,
39589c9a5175STakashi Iwai 						     0, &chmap);
39599c9a5175STakashi Iwai 			if (err < 0)
39609c9a5175STakashi Iwai 				return err;
39619c9a5175STakashi Iwai 			chmap->channel_mask = SND_PCM_CHMAP_MASK_2468;
39629c9a5175STakashi Iwai 		}
39639c9a5175STakashi Iwai 	}
39649c9a5175STakashi Iwai 	return 0;
39659c9a5175STakashi Iwai }
39669c9a5175STakashi Iwai 
3967ee81abb6STakashi Iwai /* default channel maps for 2.1 speakers;
3968ee81abb6STakashi Iwai  * since HD-audio supports only stereo, odd number channels are omitted
3969ee81abb6STakashi Iwai  */
3970ee81abb6STakashi Iwai const struct snd_pcm_chmap_elem snd_pcm_2_1_chmaps[] = {
3971ee81abb6STakashi Iwai 	{ .channels = 2,
3972ee81abb6STakashi Iwai 	  .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR } },
3973ee81abb6STakashi Iwai 	{ .channels = 4,
3974ee81abb6STakashi Iwai 	  .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR,
3975ee81abb6STakashi Iwai 		   SNDRV_CHMAP_LFE, SNDRV_CHMAP_LFE } },
3976ee81abb6STakashi Iwai 	{ }
3977ee81abb6STakashi Iwai };
3978ee81abb6STakashi Iwai EXPORT_SYMBOL_GPL(snd_pcm_2_1_chmaps);
3979ee81abb6STakashi Iwai 
39806c1f45eaSTakashi Iwai int snd_hda_codec_build_controls(struct hda_codec *codec)
39816c1f45eaSTakashi Iwai {
3982cb53c626STakashi Iwai 	int err = 0;
398311aeff08STakashi Iwai 	hda_exec_init_verbs(codec);
3984cb53c626STakashi Iwai 	/* continue to initialize... */
3985cb53c626STakashi Iwai 	if (codec->patch_ops.init)
3986cb53c626STakashi Iwai 		err = codec->patch_ops.init(codec);
3987cb53c626STakashi Iwai 	if (!err && codec->patch_ops.build_controls)
39881da177e4SLinus Torvalds 		err = codec->patch_ops.build_controls(codec);
39891da177e4SLinus Torvalds 	if (err < 0)
39901da177e4SLinus Torvalds 		return err;
39919c9a5175STakashi Iwai 
39929c9a5175STakashi Iwai 	/* we create chmaps here instead of build_pcms */
39939c9a5175STakashi Iwai 	err = add_std_chmaps(codec);
39949c9a5175STakashi Iwai 	if (err < 0)
39959c9a5175STakashi Iwai 		return err;
39969c9a5175STakashi Iwai 
399726a6cb6cSDavid Henningsson 	if (codec->jackpoll_interval)
399826a6cb6cSDavid Henningsson 		hda_jackpoll_work(&codec->jackpoll_work.work);
399926a6cb6cSDavid Henningsson 	else
40008a535414STakashi Iwai 		snd_hda_jack_report_sync(codec); /* call at the last init point */
4001b9c590bbSTakashi Iwai 	sync_power_up_states(codec);
40021da177e4SLinus Torvalds 	return 0;
40031da177e4SLinus Torvalds }
40041da177e4SLinus Torvalds 
40051da177e4SLinus Torvalds /*
40061da177e4SLinus Torvalds  * stream formats
40071da177e4SLinus Torvalds  */
4008befdf316STakashi Iwai struct hda_rate_tbl {
4009befdf316STakashi Iwai 	unsigned int hz;
4010befdf316STakashi Iwai 	unsigned int alsa_bits;
4011befdf316STakashi Iwai 	unsigned int hda_fmt;
4012befdf316STakashi Iwai };
4013befdf316STakashi Iwai 
401492f10b3fSTakashi Iwai /* rate = base * mult / div */
401592f10b3fSTakashi Iwai #define HDA_RATE(base, mult, div) \
401692f10b3fSTakashi Iwai 	(AC_FMT_BASE_##base##K | (((mult) - 1) << AC_FMT_MULT_SHIFT) | \
401792f10b3fSTakashi Iwai 	 (((div) - 1) << AC_FMT_DIV_SHIFT))
401892f10b3fSTakashi Iwai 
4019befdf316STakashi Iwai static struct hda_rate_tbl rate_bits[] = {
40201da177e4SLinus Torvalds 	/* rate in Hz, ALSA rate bitmask, HDA format value */
40219d8f53f2SNicolas Graziano 
40229d8f53f2SNicolas Graziano 	/* autodetected value used in snd_hda_query_supported_pcm */
402392f10b3fSTakashi Iwai 	{ 8000, SNDRV_PCM_RATE_8000, HDA_RATE(48, 1, 6) },
402492f10b3fSTakashi Iwai 	{ 11025, SNDRV_PCM_RATE_11025, HDA_RATE(44, 1, 4) },
402592f10b3fSTakashi Iwai 	{ 16000, SNDRV_PCM_RATE_16000, HDA_RATE(48, 1, 3) },
402692f10b3fSTakashi Iwai 	{ 22050, SNDRV_PCM_RATE_22050, HDA_RATE(44, 1, 2) },
402792f10b3fSTakashi Iwai 	{ 32000, SNDRV_PCM_RATE_32000, HDA_RATE(48, 2, 3) },
402892f10b3fSTakashi Iwai 	{ 44100, SNDRV_PCM_RATE_44100, HDA_RATE(44, 1, 1) },
402992f10b3fSTakashi Iwai 	{ 48000, SNDRV_PCM_RATE_48000, HDA_RATE(48, 1, 1) },
403092f10b3fSTakashi Iwai 	{ 88200, SNDRV_PCM_RATE_88200, HDA_RATE(44, 2, 1) },
403192f10b3fSTakashi Iwai 	{ 96000, SNDRV_PCM_RATE_96000, HDA_RATE(48, 2, 1) },
403292f10b3fSTakashi Iwai 	{ 176400, SNDRV_PCM_RATE_176400, HDA_RATE(44, 4, 1) },
403392f10b3fSTakashi Iwai 	{ 192000, SNDRV_PCM_RATE_192000, HDA_RATE(48, 4, 1) },
4034a961f9feSTakashi Iwai #define AC_PAR_PCM_RATE_BITS	11
4035a961f9feSTakashi Iwai 	/* up to bits 10, 384kHZ isn't supported properly */
4036a961f9feSTakashi Iwai 
4037a961f9feSTakashi Iwai 	/* not autodetected value */
403892f10b3fSTakashi Iwai 	{ 9600, SNDRV_PCM_RATE_KNOT, HDA_RATE(48, 1, 5) },
40399d8f53f2SNicolas Graziano 
4040befdf316STakashi Iwai 	{ 0 } /* terminator */
40411da177e4SLinus Torvalds };
40421da177e4SLinus Torvalds 
40431da177e4SLinus Torvalds /**
40441da177e4SLinus Torvalds  * snd_hda_calc_stream_format - calculate format bitset
40451da177e4SLinus Torvalds  * @rate: the sample rate
40461da177e4SLinus Torvalds  * @channels: the number of channels
40471da177e4SLinus Torvalds  * @format: the PCM format (SNDRV_PCM_FORMAT_XXX)
40481da177e4SLinus Torvalds  * @maxbps: the max. bps
40491da177e4SLinus Torvalds  *
40501da177e4SLinus Torvalds  * Calculate the format bitset from the given rate, channels and th PCM format.
40511da177e4SLinus Torvalds  *
40521da177e4SLinus Torvalds  * Return zero if invalid.
40531da177e4SLinus Torvalds  */
40541da177e4SLinus Torvalds unsigned int snd_hda_calc_stream_format(unsigned int rate,
40551da177e4SLinus Torvalds 					unsigned int channels,
40561da177e4SLinus Torvalds 					unsigned int format,
405732c168c8SAnssi Hannula 					unsigned int maxbps,
405832c168c8SAnssi Hannula 					unsigned short spdif_ctls)
40591da177e4SLinus Torvalds {
40601da177e4SLinus Torvalds 	int i;
40611da177e4SLinus Torvalds 	unsigned int val = 0;
40621da177e4SLinus Torvalds 
4063befdf316STakashi Iwai 	for (i = 0; rate_bits[i].hz; i++)
4064befdf316STakashi Iwai 		if (rate_bits[i].hz == rate) {
4065befdf316STakashi Iwai 			val = rate_bits[i].hda_fmt;
40661da177e4SLinus Torvalds 			break;
40671da177e4SLinus Torvalds 		}
4068befdf316STakashi Iwai 	if (!rate_bits[i].hz) {
40691da177e4SLinus Torvalds 		snd_printdd("invalid rate %d\n", rate);
40701da177e4SLinus Torvalds 		return 0;
40711da177e4SLinus Torvalds 	}
40721da177e4SLinus Torvalds 
40731da177e4SLinus Torvalds 	if (channels == 0 || channels > 8) {
40741da177e4SLinus Torvalds 		snd_printdd("invalid channels %d\n", channels);
40751da177e4SLinus Torvalds 		return 0;
40761da177e4SLinus Torvalds 	}
40771da177e4SLinus Torvalds 	val |= channels - 1;
40781da177e4SLinus Torvalds 
40791da177e4SLinus Torvalds 	switch (snd_pcm_format_width(format)) {
408028aedaf7SNorberto Lopes 	case 8:
408192f10b3fSTakashi Iwai 		val |= AC_FMT_BITS_8;
408228aedaf7SNorberto Lopes 		break;
408328aedaf7SNorberto Lopes 	case 16:
408492f10b3fSTakashi Iwai 		val |= AC_FMT_BITS_16;
408528aedaf7SNorberto Lopes 		break;
40861da177e4SLinus Torvalds 	case 20:
40871da177e4SLinus Torvalds 	case 24:
40881da177e4SLinus Torvalds 	case 32:
4089b0bb3aa6STakashi Iwai 		if (maxbps >= 32 || format == SNDRV_PCM_FORMAT_FLOAT_LE)
409092f10b3fSTakashi Iwai 			val |= AC_FMT_BITS_32;
40911da177e4SLinus Torvalds 		else if (maxbps >= 24)
409292f10b3fSTakashi Iwai 			val |= AC_FMT_BITS_24;
40931da177e4SLinus Torvalds 		else
409492f10b3fSTakashi Iwai 			val |= AC_FMT_BITS_20;
40951da177e4SLinus Torvalds 		break;
40961da177e4SLinus Torvalds 	default:
40970ba21762STakashi Iwai 		snd_printdd("invalid format width %d\n",
40980ba21762STakashi Iwai 			    snd_pcm_format_width(format));
40991da177e4SLinus Torvalds 		return 0;
41001da177e4SLinus Torvalds 	}
41011da177e4SLinus Torvalds 
410232c168c8SAnssi Hannula 	if (spdif_ctls & AC_DIG1_NONAUDIO)
410392f10b3fSTakashi Iwai 		val |= AC_FMT_TYPE_NON_PCM;
410432c168c8SAnssi Hannula 
41051da177e4SLinus Torvalds 	return val;
41061da177e4SLinus Torvalds }
4107ff7a3267STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_calc_stream_format);
41081da177e4SLinus Torvalds 
4109c3b6bcc2STakashi Iwai static unsigned int get_pcm_param(struct hda_codec *codec, hda_nid_t nid,
4110c3b6bcc2STakashi Iwai 				  int dir)
411192c7c8a7STakashi Iwai {
411292c7c8a7STakashi Iwai 	unsigned int val = 0;
411392c7c8a7STakashi Iwai 	if (nid != codec->afg &&
411492c7c8a7STakashi Iwai 	    (get_wcaps(codec, nid) & AC_WCAP_FORMAT_OVRD))
411592c7c8a7STakashi Iwai 		val = snd_hda_param_read(codec, nid, AC_PAR_PCM);
411692c7c8a7STakashi Iwai 	if (!val || val == -1)
411792c7c8a7STakashi Iwai 		val = snd_hda_param_read(codec, codec->afg, AC_PAR_PCM);
411892c7c8a7STakashi Iwai 	if (!val || val == -1)
411992c7c8a7STakashi Iwai 		return 0;
412092c7c8a7STakashi Iwai 	return val;
412192c7c8a7STakashi Iwai }
412292c7c8a7STakashi Iwai 
412392c7c8a7STakashi Iwai static unsigned int query_pcm_param(struct hda_codec *codec, hda_nid_t nid)
412492c7c8a7STakashi Iwai {
4125c3b6bcc2STakashi Iwai 	return query_caps_hash(codec, nid, 0, HDA_HASH_PARPCM_KEY(nid),
412692c7c8a7STakashi Iwai 			       get_pcm_param);
412792c7c8a7STakashi Iwai }
412892c7c8a7STakashi Iwai 
4129c3b6bcc2STakashi Iwai static unsigned int get_stream_param(struct hda_codec *codec, hda_nid_t nid,
4130c3b6bcc2STakashi Iwai 				     int dir)
413192c7c8a7STakashi Iwai {
413292c7c8a7STakashi Iwai 	unsigned int streams = snd_hda_param_read(codec, nid, AC_PAR_STREAM);
413392c7c8a7STakashi Iwai 	if (!streams || streams == -1)
413492c7c8a7STakashi Iwai 		streams = snd_hda_param_read(codec, codec->afg, AC_PAR_STREAM);
413592c7c8a7STakashi Iwai 	if (!streams || streams == -1)
413692c7c8a7STakashi Iwai 		return 0;
413792c7c8a7STakashi Iwai 	return streams;
413892c7c8a7STakashi Iwai }
413992c7c8a7STakashi Iwai 
414092c7c8a7STakashi Iwai static unsigned int query_stream_param(struct hda_codec *codec, hda_nid_t nid)
414192c7c8a7STakashi Iwai {
4142c3b6bcc2STakashi Iwai 	return query_caps_hash(codec, nid, 0, HDA_HASH_PARSTR_KEY(nid),
414392c7c8a7STakashi Iwai 			       get_stream_param);
414492c7c8a7STakashi Iwai }
414592c7c8a7STakashi Iwai 
41461da177e4SLinus Torvalds /**
41471da177e4SLinus Torvalds  * snd_hda_query_supported_pcm - query the supported PCM rates and formats
41481da177e4SLinus Torvalds  * @codec: the HDA codec
41491da177e4SLinus Torvalds  * @nid: NID to query
41501da177e4SLinus Torvalds  * @ratesp: the pointer to store the detected rate bitflags
41511da177e4SLinus Torvalds  * @formatsp: the pointer to store the detected formats
41521da177e4SLinus Torvalds  * @bpsp: the pointer to store the detected format widths
41531da177e4SLinus Torvalds  *
41541da177e4SLinus Torvalds  * Queries the supported PCM rates and formats.  The NULL @ratesp, @formatsp
41551da177e4SLinus Torvalds  * or @bsps argument is ignored.
41561da177e4SLinus Torvalds  *
41571da177e4SLinus Torvalds  * Returns 0 if successful, otherwise a negative error code.
41581da177e4SLinus Torvalds  */
4159384a48d7SStephen Warren int snd_hda_query_supported_pcm(struct hda_codec *codec, hda_nid_t nid,
41601da177e4SLinus Torvalds 				u32 *ratesp, u64 *formatsp, unsigned int *bpsp)
41611da177e4SLinus Torvalds {
4162ee504710SJaroslav Kysela 	unsigned int i, val, wcaps;
41631da177e4SLinus Torvalds 
4164ee504710SJaroslav Kysela 	wcaps = get_wcaps(codec, nid);
416592c7c8a7STakashi Iwai 	val = query_pcm_param(codec, nid);
41661da177e4SLinus Torvalds 
41671da177e4SLinus Torvalds 	if (ratesp) {
41681da177e4SLinus Torvalds 		u32 rates = 0;
4169a961f9feSTakashi Iwai 		for (i = 0; i < AC_PAR_PCM_RATE_BITS; i++) {
41701da177e4SLinus Torvalds 			if (val & (1 << i))
4171befdf316STakashi Iwai 				rates |= rate_bits[i].alsa_bits;
41721da177e4SLinus Torvalds 		}
4173ee504710SJaroslav Kysela 		if (rates == 0) {
4174ee504710SJaroslav Kysela 			snd_printk(KERN_ERR "hda_codec: rates == 0 "
4175ee504710SJaroslav Kysela 				   "(nid=0x%x, val=0x%x, ovrd=%i)\n",
4176ee504710SJaroslav Kysela 					nid, val,
4177ee504710SJaroslav Kysela 					(wcaps & AC_WCAP_FORMAT_OVRD) ? 1 : 0);
4178ee504710SJaroslav Kysela 			return -EIO;
4179ee504710SJaroslav Kysela 		}
41801da177e4SLinus Torvalds 		*ratesp = rates;
41811da177e4SLinus Torvalds 	}
41821da177e4SLinus Torvalds 
41831da177e4SLinus Torvalds 	if (formatsp || bpsp) {
41841da177e4SLinus Torvalds 		u64 formats = 0;
4185ee504710SJaroslav Kysela 		unsigned int streams, bps;
41861da177e4SLinus Torvalds 
418792c7c8a7STakashi Iwai 		streams = query_stream_param(codec, nid);
418892c7c8a7STakashi Iwai 		if (!streams)
41891da177e4SLinus Torvalds 			return -EIO;
41901da177e4SLinus Torvalds 
41911da177e4SLinus Torvalds 		bps = 0;
41921da177e4SLinus Torvalds 		if (streams & AC_SUPFMT_PCM) {
41931da177e4SLinus Torvalds 			if (val & AC_SUPPCM_BITS_8) {
41941da177e4SLinus Torvalds 				formats |= SNDRV_PCM_FMTBIT_U8;
41951da177e4SLinus Torvalds 				bps = 8;
41961da177e4SLinus Torvalds 			}
41971da177e4SLinus Torvalds 			if (val & AC_SUPPCM_BITS_16) {
41981da177e4SLinus Torvalds 				formats |= SNDRV_PCM_FMTBIT_S16_LE;
41991da177e4SLinus Torvalds 				bps = 16;
42001da177e4SLinus Torvalds 			}
42011da177e4SLinus Torvalds 			if (wcaps & AC_WCAP_DIGITAL) {
42021da177e4SLinus Torvalds 				if (val & AC_SUPPCM_BITS_32)
42031da177e4SLinus Torvalds 					formats |= SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_LE;
42041da177e4SLinus Torvalds 				if (val & (AC_SUPPCM_BITS_20|AC_SUPPCM_BITS_24))
42051da177e4SLinus Torvalds 					formats |= SNDRV_PCM_FMTBIT_S32_LE;
42061da177e4SLinus Torvalds 				if (val & AC_SUPPCM_BITS_24)
42071da177e4SLinus Torvalds 					bps = 24;
42081da177e4SLinus Torvalds 				else if (val & AC_SUPPCM_BITS_20)
42091da177e4SLinus Torvalds 					bps = 20;
42100ba21762STakashi Iwai 			} else if (val & (AC_SUPPCM_BITS_20|AC_SUPPCM_BITS_24|
42110ba21762STakashi Iwai 					  AC_SUPPCM_BITS_32)) {
42121da177e4SLinus Torvalds 				formats |= SNDRV_PCM_FMTBIT_S32_LE;
42131da177e4SLinus Torvalds 				if (val & AC_SUPPCM_BITS_32)
42141da177e4SLinus Torvalds 					bps = 32;
42151da177e4SLinus Torvalds 				else if (val & AC_SUPPCM_BITS_24)
42161da177e4SLinus Torvalds 					bps = 24;
421733ef7651SNicolas Graziano 				else if (val & AC_SUPPCM_BITS_20)
421833ef7651SNicolas Graziano 					bps = 20;
42191da177e4SLinus Torvalds 			}
42201da177e4SLinus Torvalds 		}
42218c7dd890STakashi Iwai #if 0 /* FIXME: CS4206 doesn't work, which is the only codec supporting float */
4222b5025c50STakashi Iwai 		if (streams & AC_SUPFMT_FLOAT32) {
42231da177e4SLinus Torvalds 			formats |= SNDRV_PCM_FMTBIT_FLOAT_LE;
4224b0bb3aa6STakashi Iwai 			if (!bps)
42251da177e4SLinus Torvalds 				bps = 32;
4226b5025c50STakashi Iwai 		}
42278c7dd890STakashi Iwai #endif
4228b5025c50STakashi Iwai 		if (streams == AC_SUPFMT_AC3) {
42290ba21762STakashi Iwai 			/* should be exclusive */
42301da177e4SLinus Torvalds 			/* temporary hack: we have still no proper support
42311da177e4SLinus Torvalds 			 * for the direct AC3 stream...
42321da177e4SLinus Torvalds 			 */
42331da177e4SLinus Torvalds 			formats |= SNDRV_PCM_FMTBIT_U8;
42341da177e4SLinus Torvalds 			bps = 8;
42351da177e4SLinus Torvalds 		}
4236ee504710SJaroslav Kysela 		if (formats == 0) {
4237ee504710SJaroslav Kysela 			snd_printk(KERN_ERR "hda_codec: formats == 0 "
4238ee504710SJaroslav Kysela 				   "(nid=0x%x, val=0x%x, ovrd=%i, "
4239ee504710SJaroslav Kysela 				   "streams=0x%x)\n",
4240ee504710SJaroslav Kysela 					nid, val,
4241ee504710SJaroslav Kysela 					(wcaps & AC_WCAP_FORMAT_OVRD) ? 1 : 0,
4242ee504710SJaroslav Kysela 					streams);
4243ee504710SJaroslav Kysela 			return -EIO;
4244ee504710SJaroslav Kysela 		}
42451da177e4SLinus Torvalds 		if (formatsp)
42461da177e4SLinus Torvalds 			*formatsp = formats;
42471da177e4SLinus Torvalds 		if (bpsp)
42481da177e4SLinus Torvalds 			*bpsp = bps;
42491da177e4SLinus Torvalds 	}
42501da177e4SLinus Torvalds 
42511da177e4SLinus Torvalds 	return 0;
42521da177e4SLinus Torvalds }
4253384a48d7SStephen Warren EXPORT_SYMBOL_HDA(snd_hda_query_supported_pcm);
42541da177e4SLinus Torvalds 
42551da177e4SLinus Torvalds /**
4256d5191e50STakashi Iwai  * snd_hda_is_supported_format - Check the validity of the format
4257d5191e50STakashi Iwai  * @codec: HD-audio codec
4258d5191e50STakashi Iwai  * @nid: NID to check
4259d5191e50STakashi Iwai  * @format: the HD-audio format value to check
4260d5191e50STakashi Iwai  *
4261d5191e50STakashi Iwai  * Check whether the given node supports the format value.
42621da177e4SLinus Torvalds  *
42631da177e4SLinus Torvalds  * Returns 1 if supported, 0 if not.
42641da177e4SLinus Torvalds  */
42651da177e4SLinus Torvalds int snd_hda_is_supported_format(struct hda_codec *codec, hda_nid_t nid,
42661da177e4SLinus Torvalds 				unsigned int format)
42671da177e4SLinus Torvalds {
42681da177e4SLinus Torvalds 	int i;
42691da177e4SLinus Torvalds 	unsigned int val = 0, rate, stream;
42701da177e4SLinus Torvalds 
427192c7c8a7STakashi Iwai 	val = query_pcm_param(codec, nid);
427292c7c8a7STakashi Iwai 	if (!val)
42731da177e4SLinus Torvalds 		return 0;
42741da177e4SLinus Torvalds 
42751da177e4SLinus Torvalds 	rate = format & 0xff00;
4276a961f9feSTakashi Iwai 	for (i = 0; i < AC_PAR_PCM_RATE_BITS; i++)
4277befdf316STakashi Iwai 		if (rate_bits[i].hda_fmt == rate) {
42781da177e4SLinus Torvalds 			if (val & (1 << i))
42791da177e4SLinus Torvalds 				break;
42801da177e4SLinus Torvalds 			return 0;
42811da177e4SLinus Torvalds 		}
4282a961f9feSTakashi Iwai 	if (i >= AC_PAR_PCM_RATE_BITS)
42831da177e4SLinus Torvalds 		return 0;
42841da177e4SLinus Torvalds 
428592c7c8a7STakashi Iwai 	stream = query_stream_param(codec, nid);
428692c7c8a7STakashi Iwai 	if (!stream)
42871da177e4SLinus Torvalds 		return 0;
42881da177e4SLinus Torvalds 
42891da177e4SLinus Torvalds 	if (stream & AC_SUPFMT_PCM) {
42901da177e4SLinus Torvalds 		switch (format & 0xf0) {
42911da177e4SLinus Torvalds 		case 0x00:
42921da177e4SLinus Torvalds 			if (!(val & AC_SUPPCM_BITS_8))
42931da177e4SLinus Torvalds 				return 0;
42941da177e4SLinus Torvalds 			break;
42951da177e4SLinus Torvalds 		case 0x10:
42961da177e4SLinus Torvalds 			if (!(val & AC_SUPPCM_BITS_16))
42971da177e4SLinus Torvalds 				return 0;
42981da177e4SLinus Torvalds 			break;
42991da177e4SLinus Torvalds 		case 0x20:
43001da177e4SLinus Torvalds 			if (!(val & AC_SUPPCM_BITS_20))
43011da177e4SLinus Torvalds 				return 0;
43021da177e4SLinus Torvalds 			break;
43031da177e4SLinus Torvalds 		case 0x30:
43041da177e4SLinus Torvalds 			if (!(val & AC_SUPPCM_BITS_24))
43051da177e4SLinus Torvalds 				return 0;
43061da177e4SLinus Torvalds 			break;
43071da177e4SLinus Torvalds 		case 0x40:
43081da177e4SLinus Torvalds 			if (!(val & AC_SUPPCM_BITS_32))
43091da177e4SLinus Torvalds 				return 0;
43101da177e4SLinus Torvalds 			break;
43111da177e4SLinus Torvalds 		default:
43121da177e4SLinus Torvalds 			return 0;
43131da177e4SLinus Torvalds 		}
43141da177e4SLinus Torvalds 	} else {
43151da177e4SLinus Torvalds 		/* FIXME: check for float32 and AC3? */
43161da177e4SLinus Torvalds 	}
43171da177e4SLinus Torvalds 
43181da177e4SLinus Torvalds 	return 1;
43191da177e4SLinus Torvalds }
4320ff7a3267STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_is_supported_format);
43211da177e4SLinus Torvalds 
43221da177e4SLinus Torvalds /*
43231da177e4SLinus Torvalds  * PCM stuff
43241da177e4SLinus Torvalds  */
43251da177e4SLinus Torvalds static int hda_pcm_default_open_close(struct hda_pcm_stream *hinfo,
43261da177e4SLinus Torvalds 				      struct hda_codec *codec,
4327c8b6bf9bSTakashi Iwai 				      struct snd_pcm_substream *substream)
43281da177e4SLinus Torvalds {
43291da177e4SLinus Torvalds 	return 0;
43301da177e4SLinus Torvalds }
43311da177e4SLinus Torvalds 
43321da177e4SLinus Torvalds static int hda_pcm_default_prepare(struct hda_pcm_stream *hinfo,
43331da177e4SLinus Torvalds 				   struct hda_codec *codec,
43341da177e4SLinus Torvalds 				   unsigned int stream_tag,
43351da177e4SLinus Torvalds 				   unsigned int format,
4336c8b6bf9bSTakashi Iwai 				   struct snd_pcm_substream *substream)
43371da177e4SLinus Torvalds {
43381da177e4SLinus Torvalds 	snd_hda_codec_setup_stream(codec, hinfo->nid, stream_tag, 0, format);
43391da177e4SLinus Torvalds 	return 0;
43401da177e4SLinus Torvalds }
43411da177e4SLinus Torvalds 
43421da177e4SLinus Torvalds static int hda_pcm_default_cleanup(struct hda_pcm_stream *hinfo,
43431da177e4SLinus Torvalds 				   struct hda_codec *codec,
4344c8b6bf9bSTakashi Iwai 				   struct snd_pcm_substream *substream)
43451da177e4SLinus Torvalds {
4346888afa15STakashi Iwai 	snd_hda_codec_cleanup_stream(codec, hinfo->nid);
43471da177e4SLinus Torvalds 	return 0;
43481da177e4SLinus Torvalds }
43491da177e4SLinus Torvalds 
43506c1f45eaSTakashi Iwai static int set_pcm_default_values(struct hda_codec *codec,
43510ba21762STakashi Iwai 				  struct hda_pcm_stream *info)
43521da177e4SLinus Torvalds {
4353ee504710SJaroslav Kysela 	int err;
4354ee504710SJaroslav Kysela 
43551da177e4SLinus Torvalds 	/* query support PCM information from the given NID */
43560ba21762STakashi Iwai 	if (info->nid && (!info->rates || !info->formats)) {
4357ee504710SJaroslav Kysela 		err = snd_hda_query_supported_pcm(codec, info->nid,
43581da177e4SLinus Torvalds 				info->rates ? NULL : &info->rates,
43591da177e4SLinus Torvalds 				info->formats ? NULL : &info->formats,
43601da177e4SLinus Torvalds 				info->maxbps ? NULL : &info->maxbps);
4361ee504710SJaroslav Kysela 		if (err < 0)
4362ee504710SJaroslav Kysela 			return err;
43631da177e4SLinus Torvalds 	}
43641da177e4SLinus Torvalds 	if (info->ops.open == NULL)
43651da177e4SLinus Torvalds 		info->ops.open = hda_pcm_default_open_close;
43661da177e4SLinus Torvalds 	if (info->ops.close == NULL)
43671da177e4SLinus Torvalds 		info->ops.close = hda_pcm_default_open_close;
43681da177e4SLinus Torvalds 	if (info->ops.prepare == NULL) {
4369da3cec35STakashi Iwai 		if (snd_BUG_ON(!info->nid))
4370da3cec35STakashi Iwai 			return -EINVAL;
43711da177e4SLinus Torvalds 		info->ops.prepare = hda_pcm_default_prepare;
43721da177e4SLinus Torvalds 	}
43731da177e4SLinus Torvalds 	if (info->ops.cleanup == NULL) {
4374da3cec35STakashi Iwai 		if (snd_BUG_ON(!info->nid))
4375da3cec35STakashi Iwai 			return -EINVAL;
43761da177e4SLinus Torvalds 		info->ops.cleanup = hda_pcm_default_cleanup;
43771da177e4SLinus Torvalds 	}
43781da177e4SLinus Torvalds 	return 0;
43791da177e4SLinus Torvalds }
43801da177e4SLinus Torvalds 
4381eb541337STakashi Iwai /*
4382eb541337STakashi Iwai  * codec prepare/cleanup entries
4383eb541337STakashi Iwai  */
4384eb541337STakashi Iwai int snd_hda_codec_prepare(struct hda_codec *codec,
4385eb541337STakashi Iwai 			  struct hda_pcm_stream *hinfo,
4386eb541337STakashi Iwai 			  unsigned int stream,
4387eb541337STakashi Iwai 			  unsigned int format,
4388eb541337STakashi Iwai 			  struct snd_pcm_substream *substream)
4389eb541337STakashi Iwai {
4390eb541337STakashi Iwai 	int ret;
43913f50ac6aSTakashi Iwai 	mutex_lock(&codec->bus->prepare_mutex);
4392eb541337STakashi Iwai 	ret = hinfo->ops.prepare(hinfo, codec, stream, format, substream);
4393eb541337STakashi Iwai 	if (ret >= 0)
4394eb541337STakashi Iwai 		purify_inactive_streams(codec);
43953f50ac6aSTakashi Iwai 	mutex_unlock(&codec->bus->prepare_mutex);
4396eb541337STakashi Iwai 	return ret;
4397eb541337STakashi Iwai }
4398eb541337STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_codec_prepare);
4399eb541337STakashi Iwai 
4400eb541337STakashi Iwai void snd_hda_codec_cleanup(struct hda_codec *codec,
4401eb541337STakashi Iwai 			   struct hda_pcm_stream *hinfo,
4402eb541337STakashi Iwai 			   struct snd_pcm_substream *substream)
4403eb541337STakashi Iwai {
44043f50ac6aSTakashi Iwai 	mutex_lock(&codec->bus->prepare_mutex);
4405eb541337STakashi Iwai 	hinfo->ops.cleanup(hinfo, codec, substream);
44063f50ac6aSTakashi Iwai 	mutex_unlock(&codec->bus->prepare_mutex);
4407eb541337STakashi Iwai }
4408eb541337STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_codec_cleanup);
4409eb541337STakashi Iwai 
4410d5191e50STakashi Iwai /* global */
4411e3303235SJaroslav Kysela const char *snd_hda_pcm_type_name[HDA_PCM_NTYPES] = {
4412e3303235SJaroslav Kysela 	"Audio", "SPDIF", "HDMI", "Modem"
4413e3303235SJaroslav Kysela };
4414e3303235SJaroslav Kysela 
4415176d5335STakashi Iwai /*
4416529bd6c4STakashi Iwai  * get the empty PCM device number to assign
4417c8936222STakashi Iwai  *
4418c8936222STakashi Iwai  * note the max device number is limited by HDA_MAX_PCMS, currently 10
4419529bd6c4STakashi Iwai  */
4420529bd6c4STakashi Iwai static int get_empty_pcm_device(struct hda_bus *bus, int type)
4421529bd6c4STakashi Iwai {
4422f5d6def5SWu Fengguang 	/* audio device indices; not linear to keep compatibility */
4423f5d6def5SWu Fengguang 	static int audio_idx[HDA_PCM_NTYPES][5] = {
4424f5d6def5SWu Fengguang 		[HDA_PCM_TYPE_AUDIO] = { 0, 2, 4, 5, -1 },
4425f5d6def5SWu Fengguang 		[HDA_PCM_TYPE_SPDIF] = { 1, -1 },
442692608badSWu Fengguang 		[HDA_PCM_TYPE_HDMI]  = { 3, 7, 8, 9, -1 },
4427f5d6def5SWu Fengguang 		[HDA_PCM_TYPE_MODEM] = { 6, -1 },
4428529bd6c4STakashi Iwai 	};
4429f5d6def5SWu Fengguang 	int i;
4430529bd6c4STakashi Iwai 
4431f5d6def5SWu Fengguang 	if (type >= HDA_PCM_NTYPES) {
4432529bd6c4STakashi Iwai 		snd_printk(KERN_WARNING "Invalid PCM type %d\n", type);
4433529bd6c4STakashi Iwai 		return -EINVAL;
4434529bd6c4STakashi Iwai 	}
4435f5d6def5SWu Fengguang 
4436f5d6def5SWu Fengguang 	for (i = 0; audio_idx[type][i] >= 0 ; i++)
4437f5d6def5SWu Fengguang 		if (!test_and_set_bit(audio_idx[type][i], bus->pcm_dev_bits))
4438f5d6def5SWu Fengguang 			return audio_idx[type][i];
4439f5d6def5SWu Fengguang 
444001b65bfbSTakashi Iwai 	/* non-fixed slots starting from 10 */
444101b65bfbSTakashi Iwai 	for (i = 10; i < 32; i++) {
444201b65bfbSTakashi Iwai 		if (!test_and_set_bit(i, bus->pcm_dev_bits))
444301b65bfbSTakashi Iwai 			return i;
444401b65bfbSTakashi Iwai 	}
444501b65bfbSTakashi Iwai 
444628aedaf7SNorberto Lopes 	snd_printk(KERN_WARNING "Too many %s devices\n",
444728aedaf7SNorberto Lopes 		snd_hda_pcm_type_name[type]);
4448f5d6def5SWu Fengguang 	return -EAGAIN;
4449529bd6c4STakashi Iwai }
4450529bd6c4STakashi Iwai 
4451529bd6c4STakashi Iwai /*
4452176d5335STakashi Iwai  * attach a new PCM stream
4453176d5335STakashi Iwai  */
4454529bd6c4STakashi Iwai static int snd_hda_attach_pcm(struct hda_codec *codec, struct hda_pcm *pcm)
4455176d5335STakashi Iwai {
445633fa35edSTakashi Iwai 	struct hda_bus *bus = codec->bus;
4457176d5335STakashi Iwai 	struct hda_pcm_stream *info;
4458176d5335STakashi Iwai 	int stream, err;
4459176d5335STakashi Iwai 
4460b91f080fSTakashi Iwai 	if (snd_BUG_ON(!pcm->name))
4461176d5335STakashi Iwai 		return -EINVAL;
4462176d5335STakashi Iwai 	for (stream = 0; stream < 2; stream++) {
4463176d5335STakashi Iwai 		info = &pcm->stream[stream];
4464176d5335STakashi Iwai 		if (info->substreams) {
4465176d5335STakashi Iwai 			err = set_pcm_default_values(codec, info);
4466176d5335STakashi Iwai 			if (err < 0)
4467176d5335STakashi Iwai 				return err;
4468176d5335STakashi Iwai 		}
4469176d5335STakashi Iwai 	}
447033fa35edSTakashi Iwai 	return bus->ops.attach_pcm(bus, codec, pcm);
4471176d5335STakashi Iwai }
4472176d5335STakashi Iwai 
4473529bd6c4STakashi Iwai /* assign all PCMs of the given codec */
4474529bd6c4STakashi Iwai int snd_hda_codec_build_pcms(struct hda_codec *codec)
4475529bd6c4STakashi Iwai {
4476529bd6c4STakashi Iwai 	unsigned int pcm;
4477529bd6c4STakashi Iwai 	int err;
4478529bd6c4STakashi Iwai 
4479529bd6c4STakashi Iwai 	if (!codec->num_pcms) {
4480529bd6c4STakashi Iwai 		if (!codec->patch_ops.build_pcms)
4481529bd6c4STakashi Iwai 			return 0;
4482529bd6c4STakashi Iwai 		err = codec->patch_ops.build_pcms(codec);
44836e655bf2STakashi Iwai 		if (err < 0) {
44846e655bf2STakashi Iwai 			printk(KERN_ERR "hda_codec: cannot build PCMs"
44856e655bf2STakashi Iwai 			       "for #%d (error %d)\n", codec->addr, err);
44866e655bf2STakashi Iwai 			err = snd_hda_codec_reset(codec);
44876e655bf2STakashi Iwai 			if (err < 0) {
44886e655bf2STakashi Iwai 				printk(KERN_ERR
44896e655bf2STakashi Iwai 				       "hda_codec: cannot revert codec\n");
4490529bd6c4STakashi Iwai 				return err;
4491529bd6c4STakashi Iwai 			}
44926e655bf2STakashi Iwai 		}
44936e655bf2STakashi Iwai 	}
4494529bd6c4STakashi Iwai 	for (pcm = 0; pcm < codec->num_pcms; pcm++) {
4495529bd6c4STakashi Iwai 		struct hda_pcm *cpcm = &codec->pcm_info[pcm];
4496529bd6c4STakashi Iwai 		int dev;
4497529bd6c4STakashi Iwai 
4498529bd6c4STakashi Iwai 		if (!cpcm->stream[0].substreams && !cpcm->stream[1].substreams)
449941b5b01aSTakashi Iwai 			continue; /* no substreams assigned */
4500529bd6c4STakashi Iwai 
4501529bd6c4STakashi Iwai 		if (!cpcm->pcm) {
4502529bd6c4STakashi Iwai 			dev = get_empty_pcm_device(codec->bus, cpcm->pcm_type);
4503529bd6c4STakashi Iwai 			if (dev < 0)
45046e655bf2STakashi Iwai 				continue; /* no fatal error */
4505529bd6c4STakashi Iwai 			cpcm->device = dev;
4506529bd6c4STakashi Iwai 			err = snd_hda_attach_pcm(codec, cpcm);
45076e655bf2STakashi Iwai 			if (err < 0) {
45086e655bf2STakashi Iwai 				printk(KERN_ERR "hda_codec: cannot attach "
45096e655bf2STakashi Iwai 				       "PCM stream %d for codec #%d\n",
45106e655bf2STakashi Iwai 				       dev, codec->addr);
45116e655bf2STakashi Iwai 				continue; /* no fatal error */
45126e655bf2STakashi Iwai 			}
4513529bd6c4STakashi Iwai 		}
4514529bd6c4STakashi Iwai 	}
4515529bd6c4STakashi Iwai 	return 0;
4516529bd6c4STakashi Iwai }
4517529bd6c4STakashi Iwai 
45181da177e4SLinus Torvalds /**
45191da177e4SLinus Torvalds  * snd_hda_build_pcms - build PCM information
45201da177e4SLinus Torvalds  * @bus: the BUS
45211da177e4SLinus Torvalds  *
45221da177e4SLinus Torvalds  * Create PCM information for each codec included in the bus.
45231da177e4SLinus Torvalds  *
45241da177e4SLinus Torvalds  * The build_pcms codec patch is requested to set up codec->num_pcms and
45251da177e4SLinus Torvalds  * codec->pcm_info properly.  The array is referred by the top-level driver
45261da177e4SLinus Torvalds  * to create its PCM instances.
45271da177e4SLinus Torvalds  * The allocated codec->pcm_info should be released in codec->patch_ops.free
45281da177e4SLinus Torvalds  * callback.
45291da177e4SLinus Torvalds  *
45301da177e4SLinus Torvalds  * At least, substreams, channels_min and channels_max must be filled for
45311da177e4SLinus Torvalds  * each stream.  substreams = 0 indicates that the stream doesn't exist.
45321da177e4SLinus Torvalds  * When rates and/or formats are zero, the supported values are queried
45331da177e4SLinus Torvalds  * from the given nid.  The nid is used also by the default ops.prepare
45341da177e4SLinus Torvalds  * and ops.cleanup callbacks.
45351da177e4SLinus Torvalds  *
45361da177e4SLinus Torvalds  * The driver needs to call ops.open in its open callback.  Similarly,
45371da177e4SLinus Torvalds  * ops.close is supposed to be called in the close callback.
45381da177e4SLinus Torvalds  * ops.prepare should be called in the prepare or hw_params callback
45391da177e4SLinus Torvalds  * with the proper parameters for set up.
45401da177e4SLinus Torvalds  * ops.cleanup should be called in hw_free for clean up of streams.
45411da177e4SLinus Torvalds  *
454225985edcSLucas De Marchi  * This function returns 0 if successful, or a negative error code.
45431da177e4SLinus Torvalds  */
45445cb543dbSTakashi Iwai int snd_hda_build_pcms(struct hda_bus *bus)
45451da177e4SLinus Torvalds {
45460ba21762STakashi Iwai 	struct hda_codec *codec;
45471da177e4SLinus Torvalds 
45480ba21762STakashi Iwai 	list_for_each_entry(codec, &bus->codec_list, list) {
4549529bd6c4STakashi Iwai 		int err = snd_hda_codec_build_pcms(codec);
45501da177e4SLinus Torvalds 		if (err < 0)
45511da177e4SLinus Torvalds 			return err;
45526c1f45eaSTakashi Iwai 	}
45531da177e4SLinus Torvalds 	return 0;
45541da177e4SLinus Torvalds }
4555ff7a3267STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_build_pcms);
45561da177e4SLinus Torvalds 
45571da177e4SLinus Torvalds /**
45581da177e4SLinus Torvalds  * snd_hda_check_board_config - compare the current codec with the config table
45591da177e4SLinus Torvalds  * @codec: the HDA codec
4560f5fcc13cSTakashi Iwai  * @num_configs: number of config enums
4561f5fcc13cSTakashi Iwai  * @models: array of model name strings
45621da177e4SLinus Torvalds  * @tbl: configuration table, terminated by null entries
45631da177e4SLinus Torvalds  *
45641da177e4SLinus Torvalds  * Compares the modelname or PCI subsystem id of the current codec with the
45651da177e4SLinus Torvalds  * given configuration table.  If a matching entry is found, returns its
45661da177e4SLinus Torvalds  * config value (supposed to be 0 or positive).
45671da177e4SLinus Torvalds  *
45681da177e4SLinus Torvalds  * If no entries are matching, the function returns a negative value.
45691da177e4SLinus Torvalds  */
457012f288bfSTakashi Iwai int snd_hda_check_board_config(struct hda_codec *codec,
4571ea734963STakashi Iwai 			       int num_configs, const char * const *models,
4572f5fcc13cSTakashi Iwai 			       const struct snd_pci_quirk *tbl)
45731da177e4SLinus Torvalds {
4574f44ac837STakashi Iwai 	if (codec->modelname && models) {
4575f5fcc13cSTakashi Iwai 		int i;
4576f5fcc13cSTakashi Iwai 		for (i = 0; i < num_configs; i++) {
4577f5fcc13cSTakashi Iwai 			if (models[i] &&
4578f44ac837STakashi Iwai 			    !strcmp(codec->modelname, models[i])) {
4579f5fcc13cSTakashi Iwai 				snd_printd(KERN_INFO "hda_codec: model '%s' is "
4580f5fcc13cSTakashi Iwai 					   "selected\n", models[i]);
4581f5fcc13cSTakashi Iwai 				return i;
45821da177e4SLinus Torvalds 			}
45831da177e4SLinus Torvalds 		}
45841da177e4SLinus Torvalds 	}
45851da177e4SLinus Torvalds 
4586f5fcc13cSTakashi Iwai 	if (!codec->bus->pci || !tbl)
4587f5fcc13cSTakashi Iwai 		return -1;
4588f5fcc13cSTakashi Iwai 
4589f5fcc13cSTakashi Iwai 	tbl = snd_pci_quirk_lookup(codec->bus->pci, tbl);
4590f5fcc13cSTakashi Iwai 	if (!tbl)
4591f5fcc13cSTakashi Iwai 		return -1;
4592f5fcc13cSTakashi Iwai 	if (tbl->value >= 0 && tbl->value < num_configs) {
459362cf872aSTakashi Iwai #ifdef CONFIG_SND_DEBUG_VERBOSE
4594f5fcc13cSTakashi Iwai 		char tmp[10];
4595f5fcc13cSTakashi Iwai 		const char *model = NULL;
4596f5fcc13cSTakashi Iwai 		if (models)
4597f5fcc13cSTakashi Iwai 			model = models[tbl->value];
4598f5fcc13cSTakashi Iwai 		if (!model) {
4599f5fcc13cSTakashi Iwai 			sprintf(tmp, "#%d", tbl->value);
4600f5fcc13cSTakashi Iwai 			model = tmp;
46011da177e4SLinus Torvalds 		}
4602f5fcc13cSTakashi Iwai 		snd_printdd(KERN_INFO "hda_codec: model '%s' is selected "
4603f5fcc13cSTakashi Iwai 			    "for config %x:%x (%s)\n",
4604f5fcc13cSTakashi Iwai 			    model, tbl->subvendor, tbl->subdevice,
4605f5fcc13cSTakashi Iwai 			    (tbl->name ? tbl->name : "Unknown device"));
4606f5fcc13cSTakashi Iwai #endif
4607f5fcc13cSTakashi Iwai 		return tbl->value;
4608cb8e2f83STakashi Iwai 	}
46091da177e4SLinus Torvalds 	return -1;
46101da177e4SLinus Torvalds }
4611ff7a3267STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_check_board_config);
46121da177e4SLinus Torvalds 
46131da177e4SLinus Torvalds /**
46142eda3445SMauro Carvalho Chehab  * snd_hda_check_board_codec_sid_config - compare the current codec
46152eda3445SMauro Carvalho Chehab 					subsystem ID with the
46162eda3445SMauro Carvalho Chehab 					config table
46172eda3445SMauro Carvalho Chehab 
46182eda3445SMauro Carvalho Chehab 	   This is important for Gateway notebooks with SB450 HDA Audio
46192eda3445SMauro Carvalho Chehab 	   where the vendor ID of the PCI device is:
46202eda3445SMauro Carvalho Chehab 		ATI Technologies Inc SB450 HDA Audio [1002:437b]
46212eda3445SMauro Carvalho Chehab 	   and the vendor/subvendor are found only at the codec.
46222eda3445SMauro Carvalho Chehab 
46232eda3445SMauro Carvalho Chehab  * @codec: the HDA codec
46242eda3445SMauro Carvalho Chehab  * @num_configs: number of config enums
46252eda3445SMauro Carvalho Chehab  * @models: array of model name strings
46262eda3445SMauro Carvalho Chehab  * @tbl: configuration table, terminated by null entries
46272eda3445SMauro Carvalho Chehab  *
46282eda3445SMauro Carvalho Chehab  * Compares the modelname or PCI subsystem id of the current codec with the
46292eda3445SMauro Carvalho Chehab  * given configuration table.  If a matching entry is found, returns its
46302eda3445SMauro Carvalho Chehab  * config value (supposed to be 0 or positive).
46312eda3445SMauro Carvalho Chehab  *
46322eda3445SMauro Carvalho Chehab  * If no entries are matching, the function returns a negative value.
46332eda3445SMauro Carvalho Chehab  */
46342eda3445SMauro Carvalho Chehab int snd_hda_check_board_codec_sid_config(struct hda_codec *codec,
4635ea734963STakashi Iwai 			       int num_configs, const char * const *models,
46362eda3445SMauro Carvalho Chehab 			       const struct snd_pci_quirk *tbl)
46372eda3445SMauro Carvalho Chehab {
46382eda3445SMauro Carvalho Chehab 	const struct snd_pci_quirk *q;
46392eda3445SMauro Carvalho Chehab 
46402eda3445SMauro Carvalho Chehab 	/* Search for codec ID */
46412eda3445SMauro Carvalho Chehab 	for (q = tbl; q->subvendor; q++) {
4642e2301a4dSTakashi Iwai 		unsigned int mask = 0xffff0000 | q->subdevice_mask;
4643e2301a4dSTakashi Iwai 		unsigned int id = (q->subdevice | (q->subvendor << 16)) & mask;
4644e2301a4dSTakashi Iwai 		if ((codec->subsystem_id & mask) == id)
46452eda3445SMauro Carvalho Chehab 			break;
46462eda3445SMauro Carvalho Chehab 	}
46472eda3445SMauro Carvalho Chehab 
46482eda3445SMauro Carvalho Chehab 	if (!q->subvendor)
46492eda3445SMauro Carvalho Chehab 		return -1;
46502eda3445SMauro Carvalho Chehab 
46512eda3445SMauro Carvalho Chehab 	tbl = q;
46522eda3445SMauro Carvalho Chehab 
46532eda3445SMauro Carvalho Chehab 	if (tbl->value >= 0 && tbl->value < num_configs) {
4654d94ff6b7STakashi Iwai #ifdef CONFIG_SND_DEBUG_VERBOSE
46552eda3445SMauro Carvalho Chehab 		char tmp[10];
46562eda3445SMauro Carvalho Chehab 		const char *model = NULL;
46572eda3445SMauro Carvalho Chehab 		if (models)
46582eda3445SMauro Carvalho Chehab 			model = models[tbl->value];
46592eda3445SMauro Carvalho Chehab 		if (!model) {
46602eda3445SMauro Carvalho Chehab 			sprintf(tmp, "#%d", tbl->value);
46612eda3445SMauro Carvalho Chehab 			model = tmp;
46622eda3445SMauro Carvalho Chehab 		}
46632eda3445SMauro Carvalho Chehab 		snd_printdd(KERN_INFO "hda_codec: model '%s' is selected "
46642eda3445SMauro Carvalho Chehab 			    "for config %x:%x (%s)\n",
46652eda3445SMauro Carvalho Chehab 			    model, tbl->subvendor, tbl->subdevice,
46662eda3445SMauro Carvalho Chehab 			    (tbl->name ? tbl->name : "Unknown device"));
46672eda3445SMauro Carvalho Chehab #endif
46682eda3445SMauro Carvalho Chehab 		return tbl->value;
46692eda3445SMauro Carvalho Chehab 	}
46702eda3445SMauro Carvalho Chehab 	return -1;
46712eda3445SMauro Carvalho Chehab }
46722eda3445SMauro Carvalho Chehab EXPORT_SYMBOL_HDA(snd_hda_check_board_codec_sid_config);
46732eda3445SMauro Carvalho Chehab 
46742eda3445SMauro Carvalho Chehab /**
46751da177e4SLinus Torvalds  * snd_hda_add_new_ctls - create controls from the array
46761da177e4SLinus Torvalds  * @codec: the HDA codec
4677c8b6bf9bSTakashi Iwai  * @knew: the array of struct snd_kcontrol_new
46781da177e4SLinus Torvalds  *
46791da177e4SLinus Torvalds  * This helper function creates and add new controls in the given array.
46801da177e4SLinus Torvalds  * The array must be terminated with an empty entry as terminator.
46811da177e4SLinus Torvalds  *
46821da177e4SLinus Torvalds  * Returns 0 if successful, or a negative error code.
46831da177e4SLinus Torvalds  */
4684031024eeSTakashi Iwai int snd_hda_add_new_ctls(struct hda_codec *codec,
4685031024eeSTakashi Iwai 			 const struct snd_kcontrol_new *knew)
46861da177e4SLinus Torvalds {
46871da177e4SLinus Torvalds 	int err;
46881da177e4SLinus Torvalds 
46891da177e4SLinus Torvalds 	for (; knew->name; knew++) {
469054d17403STakashi Iwai 		struct snd_kcontrol *kctl;
46911afe206aSTakashi Iwai 		int addr = 0, idx = 0;
46925b0cb1d8SJaroslav Kysela 		if (knew->iface == -1)	/* skip this codec private value */
46935b0cb1d8SJaroslav Kysela 			continue;
46941afe206aSTakashi Iwai 		for (;;) {
469554d17403STakashi Iwai 			kctl = snd_ctl_new1(knew, codec);
469654d17403STakashi Iwai 			if (!kctl)
469754d17403STakashi Iwai 				return -ENOMEM;
46981afe206aSTakashi Iwai 			if (addr > 0)
46991afe206aSTakashi Iwai 				kctl->id.device = addr;
47001afe206aSTakashi Iwai 			if (idx > 0)
47011afe206aSTakashi Iwai 				kctl->id.index = idx;
47023911a4c1SJaroslav Kysela 			err = snd_hda_ctl_add(codec, 0, kctl);
47031afe206aSTakashi Iwai 			if (!err)
47041afe206aSTakashi Iwai 				break;
47051afe206aSTakashi Iwai 			/* try first with another device index corresponding to
47061afe206aSTakashi Iwai 			 * the codec addr; if it still fails (or it's the
47071afe206aSTakashi Iwai 			 * primary codec), then try another control index
47081afe206aSTakashi Iwai 			 */
47091afe206aSTakashi Iwai 			if (!addr && codec->addr)
47101afe206aSTakashi Iwai 				addr = codec->addr;
47111afe206aSTakashi Iwai 			else if (!idx && !knew->index) {
47121afe206aSTakashi Iwai 				idx = find_empty_mixer_ctl_idx(codec,
4713dcda5806STakashi Iwai 							       knew->name, 0);
47141afe206aSTakashi Iwai 				if (idx <= 0)
47151da177e4SLinus Torvalds 					return err;
47161afe206aSTakashi Iwai 			} else
471754d17403STakashi Iwai 				return err;
471854d17403STakashi Iwai 		}
47191da177e4SLinus Torvalds 	}
47201da177e4SLinus Torvalds 	return 0;
47211da177e4SLinus Torvalds }
4722ff7a3267STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_add_new_ctls);
47231da177e4SLinus Torvalds 
472483012a7cSTakashi Iwai #ifdef CONFIG_PM
4725cb53c626STakashi Iwai static void hda_power_work(struct work_struct *work)
4726cb53c626STakashi Iwai {
4727cb53c626STakashi Iwai 	struct hda_codec *codec =
4728cb53c626STakashi Iwai 		container_of(work, struct hda_codec, power_work.work);
472933fa35edSTakashi Iwai 	struct hda_bus *bus = codec->bus;
473008fa20aeSTakashi Iwai 	unsigned int state;
4731cb53c626STakashi Iwai 
47325536c6d6STakashi Iwai 	spin_lock(&codec->power_lock);
4733a2d96e77STakashi Iwai 	if (codec->power_transition > 0) { /* during power-up sequence? */
4734a2d96e77STakashi Iwai 		spin_unlock(&codec->power_lock);
4735a2d96e77STakashi Iwai 		return;
4736a2d96e77STakashi Iwai 	}
47372e492462SMaxim Levitsky 	if (!codec->power_on || codec->power_count) {
47382e492462SMaxim Levitsky 		codec->power_transition = 0;
47395536c6d6STakashi Iwai 		spin_unlock(&codec->power_lock);
4740cb53c626STakashi Iwai 		return;
47412e492462SMaxim Levitsky 	}
47425536c6d6STakashi Iwai 	spin_unlock(&codec->power_lock);
47435536c6d6STakashi Iwai 
4744d17344b3SDylan Reid 	state = hda_call_codec_suspend(codec, true);
474508fa20aeSTakashi Iwai 	codec->pm_down_notified = 0;
474608fa20aeSTakashi Iwai 	if (!bus->power_keep_link_on && (state & AC_PWRST_CLK_STOP_OK)) {
474708fa20aeSTakashi Iwai 		codec->pm_down_notified = 1;
474868467f51STakashi Iwai 		hda_call_pm_notify(bus, false);
4749cb53c626STakashi Iwai 	}
475008fa20aeSTakashi Iwai }
4751cb53c626STakashi Iwai 
4752cb53c626STakashi Iwai static void hda_keep_power_on(struct hda_codec *codec)
4753cb53c626STakashi Iwai {
47545536c6d6STakashi Iwai 	spin_lock(&codec->power_lock);
4755cb53c626STakashi Iwai 	codec->power_count++;
4756cb53c626STakashi Iwai 	codec->power_on = 1;
4757a2f6309eSTakashi Iwai 	codec->power_jiffies = jiffies;
47585536c6d6STakashi Iwai 	spin_unlock(&codec->power_lock);
4759a2f6309eSTakashi Iwai }
4760a2f6309eSTakashi Iwai 
4761d5191e50STakashi Iwai /* update the power on/off account with the current jiffies */
4762a2f6309eSTakashi Iwai void snd_hda_update_power_acct(struct hda_codec *codec)
4763a2f6309eSTakashi Iwai {
4764a2f6309eSTakashi Iwai 	unsigned long delta = jiffies - codec->power_jiffies;
4765a2f6309eSTakashi Iwai 	if (codec->power_on)
4766a2f6309eSTakashi Iwai 		codec->power_on_acct += delta;
4767a2f6309eSTakashi Iwai 	else
4768a2f6309eSTakashi Iwai 		codec->power_off_acct += delta;
4769a2f6309eSTakashi Iwai 	codec->power_jiffies += delta;
4770cb53c626STakashi Iwai }
4771cb53c626STakashi Iwai 
4772b4a91cf0SDylan Reid /* Transition to powered up, if wait_power_down then wait for a pending
4773b4a91cf0SDylan Reid  * transition to D3 to complete. A pending D3 transition is indicated
4774b4a91cf0SDylan Reid  * with power_transition == -1. */
4775c376e2c7STakashi Iwai /* call this with codec->power_lock held! */
4776b4a91cf0SDylan Reid static void __snd_hda_power_up(struct hda_codec *codec, bool wait_power_down)
4777cb53c626STakashi Iwai {
477833fa35edSTakashi Iwai 	struct hda_bus *bus = codec->bus;
477933fa35edSTakashi Iwai 
4780b4a91cf0SDylan Reid 	/* Return if power_on or transitioning to power_on, unless currently
4781b4a91cf0SDylan Reid 	 * powering down. */
4782b4a91cf0SDylan Reid 	if ((codec->power_on || codec->power_transition > 0) &&
4783c376e2c7STakashi Iwai 	    !(wait_power_down && codec->power_transition < 0))
4784cb53c626STakashi Iwai 		return;
4785a2d96e77STakashi Iwai 	spin_unlock(&codec->power_lock);
4786cb53c626STakashi Iwai 
4787a2d96e77STakashi Iwai 	cancel_delayed_work_sync(&codec->power_work);
4788a2d96e77STakashi Iwai 
4789a2d96e77STakashi Iwai 	spin_lock(&codec->power_lock);
4790b43d2247SDylan Reid 	/* If the power down delayed work was cancelled above before starting,
4791b43d2247SDylan Reid 	 * then there is no need to go through power up here.
4792b43d2247SDylan Reid 	 */
4793b43d2247SDylan Reid 	if (codec->power_on) {
4794535b6c51STakashi Iwai 		if (codec->power_transition < 0)
4795535b6c51STakashi Iwai 			codec->power_transition = 0;
4796b43d2247SDylan Reid 		return;
4797b43d2247SDylan Reid 	}
4798c376e2c7STakashi Iwai 
4799d66fee5dSTakashi Iwai 	trace_hda_power_up(codec);
4800a2f6309eSTakashi Iwai 	snd_hda_update_power_acct(codec);
4801cb53c626STakashi Iwai 	codec->power_on = 1;
4802a2f6309eSTakashi Iwai 	codec->power_jiffies = jiffies;
48037f30830bSTakashi Iwai 	codec->power_transition = 1; /* avoid reentrance */
48045536c6d6STakashi Iwai 	spin_unlock(&codec->power_lock);
48055536c6d6STakashi Iwai 
480608fa20aeSTakashi Iwai 	if (codec->pm_down_notified) {
480708fa20aeSTakashi Iwai 		codec->pm_down_notified = 0;
480868467f51STakashi Iwai 		hda_call_pm_notify(bus, true);
480908fa20aeSTakashi Iwai 	}
481008fa20aeSTakashi Iwai 
4811cb53c626STakashi Iwai 	hda_call_codec_resume(codec);
48125536c6d6STakashi Iwai 
48135536c6d6STakashi Iwai 	spin_lock(&codec->power_lock);
4814a221e287STakashi Iwai 	codec->power_transition = 0;
4815cb53c626STakashi Iwai }
4816b4a91cf0SDylan Reid 
48171289e9e8STakashi Iwai #define power_save(codec)	\
48181289e9e8STakashi Iwai 	((codec)->bus->power_save ? *(codec)->bus->power_save : 0)
4819cb53c626STakashi Iwai 
4820c376e2c7STakashi Iwai /* Transition to powered down */
4821c376e2c7STakashi Iwai static void __snd_hda_power_down(struct hda_codec *codec)
4822cb53c626STakashi Iwai {
4823c376e2c7STakashi Iwai 	if (!codec->power_on || codec->power_count || codec->power_transition)
4824cb53c626STakashi Iwai 		return;
4825c376e2c7STakashi Iwai 
4826fee2fba3STakashi Iwai 	if (power_save(codec)) {
4827a2d96e77STakashi Iwai 		codec->power_transition = -1; /* avoid reentrance */
4828c107b41cSTakashi Iwai 		queue_delayed_work(codec->bus->workq, &codec->power_work,
4829fee2fba3STakashi Iwai 				msecs_to_jiffies(power_save(codec) * 1000));
4830cb53c626STakashi Iwai 	}
4831c376e2c7STakashi Iwai }
4832c376e2c7STakashi Iwai 
4833c376e2c7STakashi Iwai /**
4834c376e2c7STakashi Iwai  * snd_hda_power_save - Power-up/down/sync the codec
4835c376e2c7STakashi Iwai  * @codec: HD-audio codec
4836c376e2c7STakashi Iwai  * @delta: the counter delta to change
4837c376e2c7STakashi Iwai  *
4838c376e2c7STakashi Iwai  * Change the power-up counter via @delta, and power up or down the hardware
4839c376e2c7STakashi Iwai  * appropriately.  For the power-down, queue to the delayed action.
4840c376e2c7STakashi Iwai  * Passing zero to @delta means to synchronize the power state.
4841c376e2c7STakashi Iwai  */
4842c376e2c7STakashi Iwai void snd_hda_power_save(struct hda_codec *codec, int delta, bool d3wait)
4843c376e2c7STakashi Iwai {
4844c376e2c7STakashi Iwai 	spin_lock(&codec->power_lock);
4845c376e2c7STakashi Iwai 	codec->power_count += delta;
4846c376e2c7STakashi Iwai 	trace_hda_power_count(codec);
4847c376e2c7STakashi Iwai 	if (delta > 0)
4848c376e2c7STakashi Iwai 		__snd_hda_power_up(codec, d3wait);
4849c376e2c7STakashi Iwai 	else
4850c376e2c7STakashi Iwai 		__snd_hda_power_down(codec);
48515536c6d6STakashi Iwai 	spin_unlock(&codec->power_lock);
4852a221e287STakashi Iwai }
4853c376e2c7STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_power_save);
4854cb53c626STakashi Iwai 
4855d5191e50STakashi Iwai /**
4856d5191e50STakashi Iwai  * snd_hda_check_amp_list_power - Check the amp list and update the power
4857d5191e50STakashi Iwai  * @codec: HD-audio codec
4858d5191e50STakashi Iwai  * @check: the object containing an AMP list and the status
4859d5191e50STakashi Iwai  * @nid: NID to check / update
4860d5191e50STakashi Iwai  *
4861d5191e50STakashi Iwai  * Check whether the given NID is in the amp list.  If it's in the list,
4862d5191e50STakashi Iwai  * check the current AMP status, and update the the power-status according
4863d5191e50STakashi Iwai  * to the mute status.
4864d5191e50STakashi Iwai  *
4865d5191e50STakashi Iwai  * This function is supposed to be set or called from the check_power_status
4866d5191e50STakashi Iwai  * patch ops.
4867d5191e50STakashi Iwai  */
4868cb53c626STakashi Iwai int snd_hda_check_amp_list_power(struct hda_codec *codec,
4869cb53c626STakashi Iwai 				 struct hda_loopback_check *check,
4870cb53c626STakashi Iwai 				 hda_nid_t nid)
4871cb53c626STakashi Iwai {
4872031024eeSTakashi Iwai 	const struct hda_amp_list *p;
4873cb53c626STakashi Iwai 	int ch, v;
4874cb53c626STakashi Iwai 
4875cb53c626STakashi Iwai 	if (!check->amplist)
4876cb53c626STakashi Iwai 		return 0;
4877cb53c626STakashi Iwai 	for (p = check->amplist; p->nid; p++) {
4878cb53c626STakashi Iwai 		if (p->nid == nid)
4879cb53c626STakashi Iwai 			break;
4880cb53c626STakashi Iwai 	}
4881cb53c626STakashi Iwai 	if (!p->nid)
4882cb53c626STakashi Iwai 		return 0; /* nothing changed */
4883cb53c626STakashi Iwai 
4884cb53c626STakashi Iwai 	for (p = check->amplist; p->nid; p++) {
4885cb53c626STakashi Iwai 		for (ch = 0; ch < 2; ch++) {
4886cb53c626STakashi Iwai 			v = snd_hda_codec_amp_read(codec, p->nid, ch, p->dir,
4887cb53c626STakashi Iwai 						   p->idx);
4888cb53c626STakashi Iwai 			if (!(v & HDA_AMP_MUTE) && v > 0) {
4889cb53c626STakashi Iwai 				if (!check->power_on) {
4890cb53c626STakashi Iwai 					check->power_on = 1;
4891cb53c626STakashi Iwai 					snd_hda_power_up(codec);
4892cb53c626STakashi Iwai 				}
4893cb53c626STakashi Iwai 				return 1;
4894cb53c626STakashi Iwai 			}
4895cb53c626STakashi Iwai 		}
4896cb53c626STakashi Iwai 	}
4897cb53c626STakashi Iwai 	if (check->power_on) {
4898cb53c626STakashi Iwai 		check->power_on = 0;
4899cb53c626STakashi Iwai 		snd_hda_power_down(codec);
4900cb53c626STakashi Iwai 	}
4901cb53c626STakashi Iwai 	return 0;
4902cb53c626STakashi Iwai }
4903ff7a3267STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_check_amp_list_power);
4904cb53c626STakashi Iwai #endif
49051da177e4SLinus Torvalds 
4906d2a6d7dcSTakashi Iwai /*
4907d2a6d7dcSTakashi Iwai  * Channel mode helper
4908d2a6d7dcSTakashi Iwai  */
4909d5191e50STakashi Iwai 
4910d5191e50STakashi Iwai /**
4911d5191e50STakashi Iwai  * snd_hda_ch_mode_info - Info callback helper for the channel mode enum
4912d5191e50STakashi Iwai  */
49130ba21762STakashi Iwai int snd_hda_ch_mode_info(struct hda_codec *codec,
49140ba21762STakashi Iwai 			 struct snd_ctl_elem_info *uinfo,
49150ba21762STakashi Iwai 			 const struct hda_channel_mode *chmode,
49160ba21762STakashi Iwai 			 int num_chmodes)
4917d2a6d7dcSTakashi Iwai {
4918d2a6d7dcSTakashi Iwai 	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
4919d2a6d7dcSTakashi Iwai 	uinfo->count = 1;
4920d2a6d7dcSTakashi Iwai 	uinfo->value.enumerated.items = num_chmodes;
4921d2a6d7dcSTakashi Iwai 	if (uinfo->value.enumerated.item >= num_chmodes)
4922d2a6d7dcSTakashi Iwai 		uinfo->value.enumerated.item = num_chmodes - 1;
4923d2a6d7dcSTakashi Iwai 	sprintf(uinfo->value.enumerated.name, "%dch",
4924d2a6d7dcSTakashi Iwai 		chmode[uinfo->value.enumerated.item].channels);
4925d2a6d7dcSTakashi Iwai 	return 0;
4926d2a6d7dcSTakashi Iwai }
4927ff7a3267STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_ch_mode_info);
4928d2a6d7dcSTakashi Iwai 
4929d5191e50STakashi Iwai /**
4930d5191e50STakashi Iwai  * snd_hda_ch_mode_get - Get callback helper for the channel mode enum
4931d5191e50STakashi Iwai  */
49320ba21762STakashi Iwai int snd_hda_ch_mode_get(struct hda_codec *codec,
49330ba21762STakashi Iwai 			struct snd_ctl_elem_value *ucontrol,
49340ba21762STakashi Iwai 			const struct hda_channel_mode *chmode,
49350ba21762STakashi Iwai 			int num_chmodes,
4936d2a6d7dcSTakashi Iwai 			int max_channels)
4937d2a6d7dcSTakashi Iwai {
4938d2a6d7dcSTakashi Iwai 	int i;
4939d2a6d7dcSTakashi Iwai 
4940d2a6d7dcSTakashi Iwai 	for (i = 0; i < num_chmodes; i++) {
4941d2a6d7dcSTakashi Iwai 		if (max_channels == chmode[i].channels) {
4942d2a6d7dcSTakashi Iwai 			ucontrol->value.enumerated.item[0] = i;
4943d2a6d7dcSTakashi Iwai 			break;
4944d2a6d7dcSTakashi Iwai 		}
4945d2a6d7dcSTakashi Iwai 	}
4946d2a6d7dcSTakashi Iwai 	return 0;
4947d2a6d7dcSTakashi Iwai }
4948ff7a3267STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_ch_mode_get);
4949d2a6d7dcSTakashi Iwai 
4950d5191e50STakashi Iwai /**
4951d5191e50STakashi Iwai  * snd_hda_ch_mode_put - Put callback helper for the channel mode enum
4952d5191e50STakashi Iwai  */
49530ba21762STakashi Iwai int snd_hda_ch_mode_put(struct hda_codec *codec,
49540ba21762STakashi Iwai 			struct snd_ctl_elem_value *ucontrol,
49550ba21762STakashi Iwai 			const struct hda_channel_mode *chmode,
49560ba21762STakashi Iwai 			int num_chmodes,
4957d2a6d7dcSTakashi Iwai 			int *max_channelsp)
4958d2a6d7dcSTakashi Iwai {
4959d2a6d7dcSTakashi Iwai 	unsigned int mode;
4960d2a6d7dcSTakashi Iwai 
4961d2a6d7dcSTakashi Iwai 	mode = ucontrol->value.enumerated.item[0];
496268ea7b2fSTakashi Iwai 	if (mode >= num_chmodes)
496368ea7b2fSTakashi Iwai 		return -EINVAL;
496482beb8fdSTakashi Iwai 	if (*max_channelsp == chmode[mode].channels)
4965d2a6d7dcSTakashi Iwai 		return 0;
4966d2a6d7dcSTakashi Iwai 	/* change the current channel setting */
4967d2a6d7dcSTakashi Iwai 	*max_channelsp = chmode[mode].channels;
4968d2a6d7dcSTakashi Iwai 	if (chmode[mode].sequence)
496982beb8fdSTakashi Iwai 		snd_hda_sequence_write_cache(codec, chmode[mode].sequence);
4970d2a6d7dcSTakashi Iwai 	return 1;
4971d2a6d7dcSTakashi Iwai }
4972ff7a3267STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_ch_mode_put);
4973d2a6d7dcSTakashi Iwai 
49741da177e4SLinus Torvalds /*
49751da177e4SLinus Torvalds  * input MUX helper
49761da177e4SLinus Torvalds  */
4977d5191e50STakashi Iwai 
4978d5191e50STakashi Iwai /**
4979d5191e50STakashi Iwai  * snd_hda_input_mux_info_info - Info callback helper for the input-mux enum
4980d5191e50STakashi Iwai  */
49810ba21762STakashi Iwai int snd_hda_input_mux_info(const struct hda_input_mux *imux,
49820ba21762STakashi Iwai 			   struct snd_ctl_elem_info *uinfo)
49831da177e4SLinus Torvalds {
49841da177e4SLinus Torvalds 	unsigned int index;
49851da177e4SLinus Torvalds 
49861da177e4SLinus Torvalds 	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
49871da177e4SLinus Torvalds 	uinfo->count = 1;
49881da177e4SLinus Torvalds 	uinfo->value.enumerated.items = imux->num_items;
49895513b0c5STakashi Iwai 	if (!imux->num_items)
49905513b0c5STakashi Iwai 		return 0;
49911da177e4SLinus Torvalds 	index = uinfo->value.enumerated.item;
49921da177e4SLinus Torvalds 	if (index >= imux->num_items)
49931da177e4SLinus Torvalds 		index = imux->num_items - 1;
49941da177e4SLinus Torvalds 	strcpy(uinfo->value.enumerated.name, imux->items[index].label);
49951da177e4SLinus Torvalds 	return 0;
49961da177e4SLinus Torvalds }
4997ff7a3267STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_input_mux_info);
49981da177e4SLinus Torvalds 
4999d5191e50STakashi Iwai /**
5000d5191e50STakashi Iwai  * snd_hda_input_mux_info_put - Put callback helper for the input-mux enum
5001d5191e50STakashi Iwai  */
50020ba21762STakashi Iwai int snd_hda_input_mux_put(struct hda_codec *codec,
50030ba21762STakashi Iwai 			  const struct hda_input_mux *imux,
50040ba21762STakashi Iwai 			  struct snd_ctl_elem_value *ucontrol,
50050ba21762STakashi Iwai 			  hda_nid_t nid,
50061da177e4SLinus Torvalds 			  unsigned int *cur_val)
50071da177e4SLinus Torvalds {
50081da177e4SLinus Torvalds 	unsigned int idx;
50091da177e4SLinus Torvalds 
50105513b0c5STakashi Iwai 	if (!imux->num_items)
50115513b0c5STakashi Iwai 		return 0;
50121da177e4SLinus Torvalds 	idx = ucontrol->value.enumerated.item[0];
50131da177e4SLinus Torvalds 	if (idx >= imux->num_items)
50141da177e4SLinus Torvalds 		idx = imux->num_items - 1;
501582beb8fdSTakashi Iwai 	if (*cur_val == idx)
50161da177e4SLinus Torvalds 		return 0;
501782beb8fdSTakashi Iwai 	snd_hda_codec_write_cache(codec, nid, 0, AC_VERB_SET_CONNECT_SEL,
50181da177e4SLinus Torvalds 				  imux->items[idx].index);
50191da177e4SLinus Torvalds 	*cur_val = idx;
50201da177e4SLinus Torvalds 	return 1;
50211da177e4SLinus Torvalds }
5022ff7a3267STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_input_mux_put);
50231da177e4SLinus Torvalds 
50241da177e4SLinus Torvalds 
50251da177e4SLinus Torvalds /*
5026dda415d4STakashi Iwai  * process kcontrol info callback of a simple string enum array
5027dda415d4STakashi Iwai  * when @num_items is 0 or @texts is NULL, assume a boolean enum array
5028dda415d4STakashi Iwai  */
5029dda415d4STakashi Iwai int snd_hda_enum_helper_info(struct snd_kcontrol *kcontrol,
5030dda415d4STakashi Iwai 			     struct snd_ctl_elem_info *uinfo,
5031dda415d4STakashi Iwai 			     int num_items, const char * const *texts)
5032dda415d4STakashi Iwai {
5033dda415d4STakashi Iwai 	static const char * const texts_default[] = {
5034dda415d4STakashi Iwai 		"Disabled", "Enabled"
5035dda415d4STakashi Iwai 	};
5036dda415d4STakashi Iwai 
5037dda415d4STakashi Iwai 	if (!texts || !num_items) {
5038dda415d4STakashi Iwai 		num_items = 2;
5039dda415d4STakashi Iwai 		texts = texts_default;
5040dda415d4STakashi Iwai 	}
5041dda415d4STakashi Iwai 
5042dda415d4STakashi Iwai 	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
5043dda415d4STakashi Iwai 	uinfo->count = 1;
5044dda415d4STakashi Iwai 	uinfo->value.enumerated.items = num_items;
5045dda415d4STakashi Iwai 	if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
5046dda415d4STakashi Iwai 		uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
5047dda415d4STakashi Iwai 	strcpy(uinfo->value.enumerated.name,
5048dda415d4STakashi Iwai 	       texts[uinfo->value.enumerated.item]);
5049dda415d4STakashi Iwai 	return 0;
5050dda415d4STakashi Iwai }
5051dda415d4STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_enum_helper_info);
5052dda415d4STakashi Iwai 
5053dda415d4STakashi Iwai /*
50541da177e4SLinus Torvalds  * Multi-channel / digital-out PCM helper functions
50551da177e4SLinus Torvalds  */
50561da177e4SLinus Torvalds 
50576b97eb45STakashi Iwai /* setup SPDIF output stream */
50586b97eb45STakashi Iwai static void setup_dig_out_stream(struct hda_codec *codec, hda_nid_t nid,
50596b97eb45STakashi Iwai 				 unsigned int stream_tag, unsigned int format)
50606b97eb45STakashi Iwai {
50613bef1c37SLaurence Darby 	struct hda_spdif_out *spdif;
50623bef1c37SLaurence Darby 	unsigned int curr_fmt;
50633bef1c37SLaurence Darby 	bool reset;
50647c935976SStephen Warren 
50653bef1c37SLaurence Darby 	spdif = snd_hda_spdif_out_of_nid(codec, nid);
50663bef1c37SLaurence Darby 	curr_fmt = snd_hda_codec_read(codec, nid, 0,
50673bef1c37SLaurence Darby 				      AC_VERB_GET_STREAM_FORMAT, 0);
50683bef1c37SLaurence Darby 	reset = codec->spdif_status_reset &&
50693bef1c37SLaurence Darby 		(spdif->ctls & AC_DIG1_ENABLE) &&
50703bef1c37SLaurence Darby 		curr_fmt != format;
50713bef1c37SLaurence Darby 
50723bef1c37SLaurence Darby 	/* turn off SPDIF if needed; otherwise the IEC958 bits won't be
50733bef1c37SLaurence Darby 	   updated */
50743bef1c37SLaurence Darby 	if (reset)
50752f72853cSTakashi Iwai 		set_dig_out_convert(codec, nid,
50767c935976SStephen Warren 				    spdif->ctls & ~AC_DIG1_ENABLE & 0xff,
50772f72853cSTakashi Iwai 				    -1);
50786b97eb45STakashi Iwai 	snd_hda_codec_setup_stream(codec, nid, stream_tag, 0, format);
50792f72853cSTakashi Iwai 	if (codec->slave_dig_outs) {
5080dda14410STakashi Iwai 		const hda_nid_t *d;
5081de51ca12SMatthew Ranostay 		for (d = codec->slave_dig_outs; *d; d++)
50822f72853cSTakashi Iwai 			snd_hda_codec_setup_stream(codec, *d, stream_tag, 0,
50832f72853cSTakashi Iwai 						   format);
50842f72853cSTakashi Iwai 	}
50852f72853cSTakashi Iwai 	/* turn on again (if needed) */
50863bef1c37SLaurence Darby 	if (reset)
50872f72853cSTakashi Iwai 		set_dig_out_convert(codec, nid,
50887c935976SStephen Warren 				    spdif->ctls & 0xff, -1);
5089de51ca12SMatthew Ranostay }
5090de51ca12SMatthew Ranostay 
50912f72853cSTakashi Iwai static void cleanup_dig_out_stream(struct hda_codec *codec, hda_nid_t nid)
50922f72853cSTakashi Iwai {
50932f72853cSTakashi Iwai 	snd_hda_codec_cleanup_stream(codec, nid);
50942f72853cSTakashi Iwai 	if (codec->slave_dig_outs) {
5095dda14410STakashi Iwai 		const hda_nid_t *d;
50962f72853cSTakashi Iwai 		for (d = codec->slave_dig_outs; *d; d++)
50972f72853cSTakashi Iwai 			snd_hda_codec_cleanup_stream(codec, *d);
50982f72853cSTakashi Iwai 	}
50996b97eb45STakashi Iwai }
51006b97eb45STakashi Iwai 
5101d5191e50STakashi Iwai /**
5102d5191e50STakashi Iwai  * snd_hda_bus_reboot_notify - call the reboot notifier of each codec
5103d5191e50STakashi Iwai  * @bus: HD-audio bus
5104d5191e50STakashi Iwai  */
5105fb8d1a34STakashi Iwai void snd_hda_bus_reboot_notify(struct hda_bus *bus)
5106fb8d1a34STakashi Iwai {
5107fb8d1a34STakashi Iwai 	struct hda_codec *codec;
5108fb8d1a34STakashi Iwai 
5109fb8d1a34STakashi Iwai 	if (!bus)
5110fb8d1a34STakashi Iwai 		return;
5111fb8d1a34STakashi Iwai 	list_for_each_entry(codec, &bus->codec_list, list) {
5112e581f3dbSTakashi Iwai 		if (hda_codec_is_power_on(codec) &&
5113e581f3dbSTakashi Iwai 		    codec->patch_ops.reboot_notify)
5114fb8d1a34STakashi Iwai 			codec->patch_ops.reboot_notify(codec);
5115fb8d1a34STakashi Iwai 	}
5116fb8d1a34STakashi Iwai }
51178f217a22STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_bus_reboot_notify);
5118fb8d1a34STakashi Iwai 
5119d5191e50STakashi Iwai /**
5120d5191e50STakashi Iwai  * snd_hda_multi_out_dig_open - open the digital out in the exclusive mode
51211da177e4SLinus Torvalds  */
51220ba21762STakashi Iwai int snd_hda_multi_out_dig_open(struct hda_codec *codec,
51230ba21762STakashi Iwai 			       struct hda_multi_out *mout)
51241da177e4SLinus Torvalds {
512562932df8SIngo Molnar 	mutex_lock(&codec->spdif_mutex);
51265930ca41STakashi Iwai 	if (mout->dig_out_used == HDA_DIG_ANALOG_DUP)
51275930ca41STakashi Iwai 		/* already opened as analog dup; reset it once */
51282f72853cSTakashi Iwai 		cleanup_dig_out_stream(codec, mout->dig_out_nid);
51291da177e4SLinus Torvalds 	mout->dig_out_used = HDA_DIG_EXCLUSIVE;
513062932df8SIngo Molnar 	mutex_unlock(&codec->spdif_mutex);
51311da177e4SLinus Torvalds 	return 0;
51321da177e4SLinus Torvalds }
5133ff7a3267STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_multi_out_dig_open);
51341da177e4SLinus Torvalds 
5135d5191e50STakashi Iwai /**
5136d5191e50STakashi Iwai  * snd_hda_multi_out_dig_prepare - prepare the digital out stream
5137d5191e50STakashi Iwai  */
51386b97eb45STakashi Iwai int snd_hda_multi_out_dig_prepare(struct hda_codec *codec,
51396b97eb45STakashi Iwai 				  struct hda_multi_out *mout,
51406b97eb45STakashi Iwai 				  unsigned int stream_tag,
51416b97eb45STakashi Iwai 				  unsigned int format,
51426b97eb45STakashi Iwai 				  struct snd_pcm_substream *substream)
51436b97eb45STakashi Iwai {
51446b97eb45STakashi Iwai 	mutex_lock(&codec->spdif_mutex);
51456b97eb45STakashi Iwai 	setup_dig_out_stream(codec, mout->dig_out_nid, stream_tag, format);
51466b97eb45STakashi Iwai 	mutex_unlock(&codec->spdif_mutex);
51476b97eb45STakashi Iwai 	return 0;
51486b97eb45STakashi Iwai }
5149ff7a3267STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_multi_out_dig_prepare);
51506b97eb45STakashi Iwai 
5151d5191e50STakashi Iwai /**
5152d5191e50STakashi Iwai  * snd_hda_multi_out_dig_cleanup - clean-up the digital out stream
5153d5191e50STakashi Iwai  */
51549411e21cSTakashi Iwai int snd_hda_multi_out_dig_cleanup(struct hda_codec *codec,
51559411e21cSTakashi Iwai 				  struct hda_multi_out *mout)
51569411e21cSTakashi Iwai {
51579411e21cSTakashi Iwai 	mutex_lock(&codec->spdif_mutex);
51589411e21cSTakashi Iwai 	cleanup_dig_out_stream(codec, mout->dig_out_nid);
51599411e21cSTakashi Iwai 	mutex_unlock(&codec->spdif_mutex);
51609411e21cSTakashi Iwai 	return 0;
51619411e21cSTakashi Iwai }
51629411e21cSTakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_multi_out_dig_cleanup);
51639411e21cSTakashi Iwai 
5164d5191e50STakashi Iwai /**
5165d5191e50STakashi Iwai  * snd_hda_multi_out_dig_close - release the digital out stream
51661da177e4SLinus Torvalds  */
51670ba21762STakashi Iwai int snd_hda_multi_out_dig_close(struct hda_codec *codec,
51680ba21762STakashi Iwai 				struct hda_multi_out *mout)
51691da177e4SLinus Torvalds {
517062932df8SIngo Molnar 	mutex_lock(&codec->spdif_mutex);
51711da177e4SLinus Torvalds 	mout->dig_out_used = 0;
517262932df8SIngo Molnar 	mutex_unlock(&codec->spdif_mutex);
51731da177e4SLinus Torvalds 	return 0;
51741da177e4SLinus Torvalds }
5175ff7a3267STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_multi_out_dig_close);
51761da177e4SLinus Torvalds 
5177d5191e50STakashi Iwai /**
5178d5191e50STakashi Iwai  * snd_hda_multi_out_analog_open - open analog outputs
5179d5191e50STakashi Iwai  *
5180d5191e50STakashi Iwai  * Open analog outputs and set up the hw-constraints.
5181d5191e50STakashi Iwai  * If the digital outputs can be opened as slave, open the digital
5182d5191e50STakashi Iwai  * outputs, too.
51831da177e4SLinus Torvalds  */
51840ba21762STakashi Iwai int snd_hda_multi_out_analog_open(struct hda_codec *codec,
51850ba21762STakashi Iwai 				  struct hda_multi_out *mout,
51869a08160bSTakashi Iwai 				  struct snd_pcm_substream *substream,
51879a08160bSTakashi Iwai 				  struct hda_pcm_stream *hinfo)
51881da177e4SLinus Torvalds {
51899a08160bSTakashi Iwai 	struct snd_pcm_runtime *runtime = substream->runtime;
51909a08160bSTakashi Iwai 	runtime->hw.channels_max = mout->max_channels;
51919a08160bSTakashi Iwai 	if (mout->dig_out_nid) {
51929a08160bSTakashi Iwai 		if (!mout->analog_rates) {
51939a08160bSTakashi Iwai 			mout->analog_rates = hinfo->rates;
51949a08160bSTakashi Iwai 			mout->analog_formats = hinfo->formats;
51959a08160bSTakashi Iwai 			mout->analog_maxbps = hinfo->maxbps;
51969a08160bSTakashi Iwai 		} else {
51979a08160bSTakashi Iwai 			runtime->hw.rates = mout->analog_rates;
51989a08160bSTakashi Iwai 			runtime->hw.formats = mout->analog_formats;
51999a08160bSTakashi Iwai 			hinfo->maxbps = mout->analog_maxbps;
52009a08160bSTakashi Iwai 		}
52019a08160bSTakashi Iwai 		if (!mout->spdif_rates) {
52029a08160bSTakashi Iwai 			snd_hda_query_supported_pcm(codec, mout->dig_out_nid,
52039a08160bSTakashi Iwai 						    &mout->spdif_rates,
52049a08160bSTakashi Iwai 						    &mout->spdif_formats,
52059a08160bSTakashi Iwai 						    &mout->spdif_maxbps);
52069a08160bSTakashi Iwai 		}
52079a08160bSTakashi Iwai 		mutex_lock(&codec->spdif_mutex);
52089a08160bSTakashi Iwai 		if (mout->share_spdif) {
5209022b466fSTakashi Iwai 			if ((runtime->hw.rates & mout->spdif_rates) &&
5210022b466fSTakashi Iwai 			    (runtime->hw.formats & mout->spdif_formats)) {
52119a08160bSTakashi Iwai 				runtime->hw.rates &= mout->spdif_rates;
52129a08160bSTakashi Iwai 				runtime->hw.formats &= mout->spdif_formats;
52139a08160bSTakashi Iwai 				if (mout->spdif_maxbps < hinfo->maxbps)
52149a08160bSTakashi Iwai 					hinfo->maxbps = mout->spdif_maxbps;
5215022b466fSTakashi Iwai 			} else {
5216022b466fSTakashi Iwai 				mout->share_spdif = 0;
5217022b466fSTakashi Iwai 				/* FIXME: need notify? */
5218022b466fSTakashi Iwai 			}
52199a08160bSTakashi Iwai 		}
52209a08160bSTakashi Iwai 		mutex_unlock(&codec->spdif_mutex);
5221eaa9985bSFrederik Deweerdt 	}
52221da177e4SLinus Torvalds 	return snd_pcm_hw_constraint_step(substream->runtime, 0,
52231da177e4SLinus Torvalds 					  SNDRV_PCM_HW_PARAM_CHANNELS, 2);
52241da177e4SLinus Torvalds }
5225ff7a3267STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_multi_out_analog_open);
52261da177e4SLinus Torvalds 
5227d5191e50STakashi Iwai /**
5228d5191e50STakashi Iwai  * snd_hda_multi_out_analog_prepare - Preapre the analog outputs.
5229d5191e50STakashi Iwai  *
5230d5191e50STakashi Iwai  * Set up the i/o for analog out.
5231d5191e50STakashi Iwai  * When the digital out is available, copy the front out to digital out, too.
52321da177e4SLinus Torvalds  */
52330ba21762STakashi Iwai int snd_hda_multi_out_analog_prepare(struct hda_codec *codec,
52340ba21762STakashi Iwai 				     struct hda_multi_out *mout,
52351da177e4SLinus Torvalds 				     unsigned int stream_tag,
52361da177e4SLinus Torvalds 				     unsigned int format,
5237c8b6bf9bSTakashi Iwai 				     struct snd_pcm_substream *substream)
52381da177e4SLinus Torvalds {
5239dda14410STakashi Iwai 	const hda_nid_t *nids = mout->dac_nids;
52401da177e4SLinus Torvalds 	int chs = substream->runtime->channels;
5241e3245cddSTakashi Iwai 	struct hda_spdif_out *spdif;
52421da177e4SLinus Torvalds 	int i;
52431da177e4SLinus Torvalds 
524462932df8SIngo Molnar 	mutex_lock(&codec->spdif_mutex);
5245e3245cddSTakashi Iwai 	spdif = snd_hda_spdif_out_of_nid(codec, mout->dig_out_nid);
52469a08160bSTakashi Iwai 	if (mout->dig_out_nid && mout->share_spdif &&
52479a08160bSTakashi Iwai 	    mout->dig_out_used != HDA_DIG_EXCLUSIVE) {
52481da177e4SLinus Torvalds 		if (chs == 2 &&
52490ba21762STakashi Iwai 		    snd_hda_is_supported_format(codec, mout->dig_out_nid,
52500ba21762STakashi Iwai 						format) &&
52517c935976SStephen Warren 		    !(spdif->status & IEC958_AES0_NONAUDIO)) {
52521da177e4SLinus Torvalds 			mout->dig_out_used = HDA_DIG_ANALOG_DUP;
52536b97eb45STakashi Iwai 			setup_dig_out_stream(codec, mout->dig_out_nid,
52546b97eb45STakashi Iwai 					     stream_tag, format);
52551da177e4SLinus Torvalds 		} else {
52561da177e4SLinus Torvalds 			mout->dig_out_used = 0;
52572f72853cSTakashi Iwai 			cleanup_dig_out_stream(codec, mout->dig_out_nid);
52581da177e4SLinus Torvalds 		}
52591da177e4SLinus Torvalds 	}
526062932df8SIngo Molnar 	mutex_unlock(&codec->spdif_mutex);
52611da177e4SLinus Torvalds 
52621da177e4SLinus Torvalds 	/* front */
52630ba21762STakashi Iwai 	snd_hda_codec_setup_stream(codec, nids[HDA_FRONT], stream_tag,
52640ba21762STakashi Iwai 				   0, format);
5265d29240ceSTakashi Iwai 	if (!mout->no_share_stream &&
5266d29240ceSTakashi Iwai 	    mout->hp_nid && mout->hp_nid != nids[HDA_FRONT])
52671da177e4SLinus Torvalds 		/* headphone out will just decode front left/right (stereo) */
52680ba21762STakashi Iwai 		snd_hda_codec_setup_stream(codec, mout->hp_nid, stream_tag,
52690ba21762STakashi Iwai 					   0, format);
527082bc955fSTakashi Iwai 	/* extra outputs copied from front */
5271a06dbfc2STakashi Iwai 	for (i = 0; i < ARRAY_SIZE(mout->hp_out_nid); i++)
5272a06dbfc2STakashi Iwai 		if (!mout->no_share_stream && mout->hp_out_nid[i])
5273a06dbfc2STakashi Iwai 			snd_hda_codec_setup_stream(codec,
5274a06dbfc2STakashi Iwai 						   mout->hp_out_nid[i],
5275a06dbfc2STakashi Iwai 						   stream_tag, 0, format);
527682bc955fSTakashi Iwai 	for (i = 0; i < ARRAY_SIZE(mout->extra_out_nid); i++)
5277d29240ceSTakashi Iwai 		if (!mout->no_share_stream && mout->extra_out_nid[i])
527882bc955fSTakashi Iwai 			snd_hda_codec_setup_stream(codec,
527982bc955fSTakashi Iwai 						   mout->extra_out_nid[i],
528082bc955fSTakashi Iwai 						   stream_tag, 0, format);
528182bc955fSTakashi Iwai 
52821da177e4SLinus Torvalds 	/* surrounds */
52831da177e4SLinus Torvalds 	for (i = 1; i < mout->num_dacs; i++) {
52844b3acaf5STakashi Iwai 		if (chs >= (i + 1) * 2) /* independent out */
52850ba21762STakashi Iwai 			snd_hda_codec_setup_stream(codec, nids[i], stream_tag,
52860ba21762STakashi Iwai 						   i * 2, format);
5287d29240ceSTakashi Iwai 		else if (!mout->no_share_stream) /* copy front */
52880ba21762STakashi Iwai 			snd_hda_codec_setup_stream(codec, nids[i], stream_tag,
52890ba21762STakashi Iwai 						   0, format);
52901da177e4SLinus Torvalds 	}
52911da177e4SLinus Torvalds 	return 0;
52921da177e4SLinus Torvalds }
5293ff7a3267STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_multi_out_analog_prepare);
52941da177e4SLinus Torvalds 
5295d5191e50STakashi Iwai /**
5296d5191e50STakashi Iwai  * snd_hda_multi_out_analog_cleanup - clean up the setting for analog out
52971da177e4SLinus Torvalds  */
52980ba21762STakashi Iwai int snd_hda_multi_out_analog_cleanup(struct hda_codec *codec,
52990ba21762STakashi Iwai 				     struct hda_multi_out *mout)
53001da177e4SLinus Torvalds {
5301dda14410STakashi Iwai 	const hda_nid_t *nids = mout->dac_nids;
53021da177e4SLinus Torvalds 	int i;
53031da177e4SLinus Torvalds 
53041da177e4SLinus Torvalds 	for (i = 0; i < mout->num_dacs; i++)
5305888afa15STakashi Iwai 		snd_hda_codec_cleanup_stream(codec, nids[i]);
53061da177e4SLinus Torvalds 	if (mout->hp_nid)
5307888afa15STakashi Iwai 		snd_hda_codec_cleanup_stream(codec, mout->hp_nid);
5308a06dbfc2STakashi Iwai 	for (i = 0; i < ARRAY_SIZE(mout->hp_out_nid); i++)
5309a06dbfc2STakashi Iwai 		if (mout->hp_out_nid[i])
5310a06dbfc2STakashi Iwai 			snd_hda_codec_cleanup_stream(codec,
5311a06dbfc2STakashi Iwai 						     mout->hp_out_nid[i]);
531282bc955fSTakashi Iwai 	for (i = 0; i < ARRAY_SIZE(mout->extra_out_nid); i++)
531382bc955fSTakashi Iwai 		if (mout->extra_out_nid[i])
5314888afa15STakashi Iwai 			snd_hda_codec_cleanup_stream(codec,
5315888afa15STakashi Iwai 						     mout->extra_out_nid[i]);
531662932df8SIngo Molnar 	mutex_lock(&codec->spdif_mutex);
53171da177e4SLinus Torvalds 	if (mout->dig_out_nid && mout->dig_out_used == HDA_DIG_ANALOG_DUP) {
53182f72853cSTakashi Iwai 		cleanup_dig_out_stream(codec, mout->dig_out_nid);
53191da177e4SLinus Torvalds 		mout->dig_out_used = 0;
53201da177e4SLinus Torvalds 	}
532162932df8SIngo Molnar 	mutex_unlock(&codec->spdif_mutex);
53221da177e4SLinus Torvalds 	return 0;
53231da177e4SLinus Torvalds }
5324ff7a3267STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_multi_out_analog_cleanup);
53251da177e4SLinus Torvalds 
53264740860bSTakashi Iwai /**
53274740860bSTakashi Iwai  * snd_hda_get_default_vref - Get the default (mic) VREF pin bits
53284740860bSTakashi Iwai  *
53294740860bSTakashi Iwai  * Guess the suitable VREF pin bits to be set as the pin-control value.
53304740860bSTakashi Iwai  * Note: the function doesn't set the AC_PINCTL_IN_EN bit.
53314740860bSTakashi Iwai  */
53324740860bSTakashi Iwai unsigned int snd_hda_get_default_vref(struct hda_codec *codec, hda_nid_t pin)
53334740860bSTakashi Iwai {
53344740860bSTakashi Iwai 	unsigned int pincap;
53354740860bSTakashi Iwai 	unsigned int oldval;
53364740860bSTakashi Iwai 	oldval = snd_hda_codec_read(codec, pin, 0,
53374740860bSTakashi Iwai 				    AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
53384740860bSTakashi Iwai 	pincap = snd_hda_query_pin_caps(codec, pin);
53394740860bSTakashi Iwai 	pincap = (pincap & AC_PINCAP_VREF) >> AC_PINCAP_VREF_SHIFT;
53404740860bSTakashi Iwai 	/* Exception: if the default pin setup is vref50, we give it priority */
53414740860bSTakashi Iwai 	if ((pincap & AC_PINCAP_VREF_80) && oldval != PIN_VREF50)
53424740860bSTakashi Iwai 		return AC_PINCTL_VREF_80;
53434740860bSTakashi Iwai 	else if (pincap & AC_PINCAP_VREF_50)
53444740860bSTakashi Iwai 		return AC_PINCTL_VREF_50;
53454740860bSTakashi Iwai 	else if (pincap & AC_PINCAP_VREF_100)
53464740860bSTakashi Iwai 		return AC_PINCTL_VREF_100;
53474740860bSTakashi Iwai 	else if (pincap & AC_PINCAP_VREF_GRD)
53484740860bSTakashi Iwai 		return AC_PINCTL_VREF_GRD;
53494740860bSTakashi Iwai 	return AC_PINCTL_VREF_HIZ;
53504740860bSTakashi Iwai }
53514740860bSTakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_get_default_vref);
53524740860bSTakashi Iwai 
535362f3a2f7STakashi Iwai /* correct the pin ctl value for matching with the pin cap */
535462f3a2f7STakashi Iwai unsigned int snd_hda_correct_pin_ctl(struct hda_codec *codec,
535562f3a2f7STakashi Iwai 				     hda_nid_t pin, unsigned int val)
535662f3a2f7STakashi Iwai {
535762f3a2f7STakashi Iwai 	static unsigned int cap_lists[][2] = {
535862f3a2f7STakashi Iwai 		{ AC_PINCTL_VREF_100, AC_PINCAP_VREF_100 },
535962f3a2f7STakashi Iwai 		{ AC_PINCTL_VREF_80, AC_PINCAP_VREF_80 },
536062f3a2f7STakashi Iwai 		{ AC_PINCTL_VREF_50, AC_PINCAP_VREF_50 },
536162f3a2f7STakashi Iwai 		{ AC_PINCTL_VREF_GRD, AC_PINCAP_VREF_GRD },
536262f3a2f7STakashi Iwai 	};
536362f3a2f7STakashi Iwai 	unsigned int cap;
536462f3a2f7STakashi Iwai 
536562f3a2f7STakashi Iwai 	if (!val)
536662f3a2f7STakashi Iwai 		return 0;
536762f3a2f7STakashi Iwai 	cap = snd_hda_query_pin_caps(codec, pin);
536862f3a2f7STakashi Iwai 	if (!cap)
536962f3a2f7STakashi Iwai 		return val; /* don't know what to do... */
537062f3a2f7STakashi Iwai 
537162f3a2f7STakashi Iwai 	if (val & AC_PINCTL_OUT_EN) {
537262f3a2f7STakashi Iwai 		if (!(cap & AC_PINCAP_OUT))
537362f3a2f7STakashi Iwai 			val &= ~(AC_PINCTL_OUT_EN | AC_PINCTL_HP_EN);
537462f3a2f7STakashi Iwai 		else if ((val & AC_PINCTL_HP_EN) && !(cap & AC_PINCAP_HP_DRV))
537562f3a2f7STakashi Iwai 			val &= ~AC_PINCTL_HP_EN;
537662f3a2f7STakashi Iwai 	}
537762f3a2f7STakashi Iwai 
537862f3a2f7STakashi Iwai 	if (val & AC_PINCTL_IN_EN) {
537962f3a2f7STakashi Iwai 		if (!(cap & AC_PINCAP_IN))
538062f3a2f7STakashi Iwai 			val &= ~(AC_PINCTL_IN_EN | AC_PINCTL_VREFEN);
538162f3a2f7STakashi Iwai 		else {
538262f3a2f7STakashi Iwai 			unsigned int vcap, vref;
538362f3a2f7STakashi Iwai 			int i;
538462f3a2f7STakashi Iwai 			vcap = (cap & AC_PINCAP_VREF) >> AC_PINCAP_VREF_SHIFT;
538562f3a2f7STakashi Iwai 			vref = val & AC_PINCTL_VREFEN;
538662f3a2f7STakashi Iwai 			for (i = 0; i < ARRAY_SIZE(cap_lists); i++) {
538762f3a2f7STakashi Iwai 				if (vref == cap_lists[i][0] &&
538862f3a2f7STakashi Iwai 				    !(vcap & cap_lists[i][1])) {
538962f3a2f7STakashi Iwai 					if (i == ARRAY_SIZE(cap_lists) - 1)
539062f3a2f7STakashi Iwai 						vref = AC_PINCTL_VREF_HIZ;
539162f3a2f7STakashi Iwai 					else
539262f3a2f7STakashi Iwai 						vref = cap_lists[i + 1][0];
539362f3a2f7STakashi Iwai 				}
539462f3a2f7STakashi Iwai 			}
539562f3a2f7STakashi Iwai 			val &= ~AC_PINCTL_VREFEN;
539662f3a2f7STakashi Iwai 			val |= vref;
539762f3a2f7STakashi Iwai 		}
539862f3a2f7STakashi Iwai 	}
539962f3a2f7STakashi Iwai 
540062f3a2f7STakashi Iwai 	return val;
540162f3a2f7STakashi Iwai }
540262f3a2f7STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_correct_pin_ctl);
540362f3a2f7STakashi Iwai 
5404cdd03cedSTakashi Iwai int _snd_hda_set_pin_ctl(struct hda_codec *codec, hda_nid_t pin,
5405cdd03cedSTakashi Iwai 			 unsigned int val, bool cached)
5406cdd03cedSTakashi Iwai {
540762f3a2f7STakashi Iwai 	val = snd_hda_correct_pin_ctl(codec, pin, val);
5408d7fdc00aSTakashi Iwai 	snd_hda_codec_set_pin_target(codec, pin, val);
5409cdd03cedSTakashi Iwai 	if (cached)
5410cdd03cedSTakashi Iwai 		return snd_hda_codec_update_cache(codec, pin, 0,
5411cdd03cedSTakashi Iwai 				AC_VERB_SET_PIN_WIDGET_CONTROL, val);
5412cdd03cedSTakashi Iwai 	else
5413cdd03cedSTakashi Iwai 		return snd_hda_codec_write(codec, pin, 0,
5414cdd03cedSTakashi Iwai 					   AC_VERB_SET_PIN_WIDGET_CONTROL, val);
5415cdd03cedSTakashi Iwai }
5416cdd03cedSTakashi Iwai EXPORT_SYMBOL_HDA(_snd_hda_set_pin_ctl);
5417cdd03cedSTakashi Iwai 
5418990061c2STakashi Iwai /**
5419990061c2STakashi Iwai  * snd_hda_add_imux_item - Add an item to input_mux
5420990061c2STakashi Iwai  *
5421990061c2STakashi Iwai  * When the same label is used already in the existing items, the number
5422990061c2STakashi Iwai  * suffix is appended to the label.  This label index number is stored
5423990061c2STakashi Iwai  * to type_idx when non-NULL pointer is given.
5424990061c2STakashi Iwai  */
542510a20af7STakashi Iwai int snd_hda_add_imux_item(struct hda_input_mux *imux, const char *label,
542610a20af7STakashi Iwai 			  int index, int *type_idx)
542710a20af7STakashi Iwai {
542810a20af7STakashi Iwai 	int i, label_idx = 0;
542910a20af7STakashi Iwai 	if (imux->num_items >= HDA_MAX_NUM_INPUTS) {
543010a20af7STakashi Iwai 		snd_printd(KERN_ERR "hda_codec: Too many imux items!\n");
543110a20af7STakashi Iwai 		return -EINVAL;
543210a20af7STakashi Iwai 	}
543310a20af7STakashi Iwai 	for (i = 0; i < imux->num_items; i++) {
543410a20af7STakashi Iwai 		if (!strncmp(label, imux->items[i].label, strlen(label)))
543510a20af7STakashi Iwai 			label_idx++;
543610a20af7STakashi Iwai 	}
543710a20af7STakashi Iwai 	if (type_idx)
543810a20af7STakashi Iwai 		*type_idx = label_idx;
543910a20af7STakashi Iwai 	if (label_idx > 0)
544010a20af7STakashi Iwai 		snprintf(imux->items[imux->num_items].label,
544110a20af7STakashi Iwai 			 sizeof(imux->items[imux->num_items].label),
544210a20af7STakashi Iwai 			 "%s %d", label, label_idx);
5443b5786e85STakashi Iwai 	else
544410a20af7STakashi Iwai 		strlcpy(imux->items[imux->num_items].label, label,
544510a20af7STakashi Iwai 			sizeof(imux->items[imux->num_items].label));
544610a20af7STakashi Iwai 	imux->items[imux->num_items].index = index;
544710a20af7STakashi Iwai 	imux->num_items++;
544810a20af7STakashi Iwai 	return 0;
5449d7b1ae9dSTakashi Iwai }
545010a20af7STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_add_imux_item);
5451d7b1ae9dSTakashi Iwai 
54524a471b7dSTakashi Iwai 
54531da177e4SLinus Torvalds #ifdef CONFIG_PM
54541da177e4SLinus Torvalds /*
54551da177e4SLinus Torvalds  * power management
54561da177e4SLinus Torvalds  */
54571da177e4SLinus Torvalds 
54581da177e4SLinus Torvalds /**
54591da177e4SLinus Torvalds  * snd_hda_suspend - suspend the codecs
54601da177e4SLinus Torvalds  * @bus: the HDA bus
54611da177e4SLinus Torvalds  *
54621da177e4SLinus Torvalds  * Returns 0 if successful.
54631da177e4SLinus Torvalds  */
54648dd78330STakashi Iwai int snd_hda_suspend(struct hda_bus *bus)
54651da177e4SLinus Torvalds {
54660ba21762STakashi Iwai 	struct hda_codec *codec;
54671da177e4SLinus Torvalds 
54680ba21762STakashi Iwai 	list_for_each_entry(codec, &bus->codec_list, list) {
546926a6cb6cSDavid Henningsson 		cancel_delayed_work_sync(&codec->jackpoll_work);
5470e581f3dbSTakashi Iwai 		if (hda_codec_is_power_on(codec))
5471d17344b3SDylan Reid 			hda_call_codec_suspend(codec, false);
54721da177e4SLinus Torvalds 	}
54731da177e4SLinus Torvalds 	return 0;
54741da177e4SLinus Torvalds }
5475ff7a3267STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_suspend);
54761da177e4SLinus Torvalds 
54771da177e4SLinus Torvalds /**
54781da177e4SLinus Torvalds  * snd_hda_resume - resume the codecs
54791da177e4SLinus Torvalds  * @bus: the HDA bus
54801da177e4SLinus Torvalds  *
54811da177e4SLinus Torvalds  * Returns 0 if successful.
54821da177e4SLinus Torvalds  */
54831da177e4SLinus Torvalds int snd_hda_resume(struct hda_bus *bus)
54841da177e4SLinus Torvalds {
54850ba21762STakashi Iwai 	struct hda_codec *codec;
54861da177e4SLinus Torvalds 
54870ba21762STakashi Iwai 	list_for_each_entry(codec, &bus->codec_list, list) {
5488cb53c626STakashi Iwai 		hda_call_codec_resume(codec);
54891da177e4SLinus Torvalds 	}
54901da177e4SLinus Torvalds 	return 0;
54911da177e4SLinus Torvalds }
5492ff7a3267STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_resume);
54931289e9e8STakashi Iwai #endif /* CONFIG_PM */
5494b2e18597STakashi Iwai 
5495b2e18597STakashi Iwai /*
5496b2e18597STakashi Iwai  * generic arrays
5497b2e18597STakashi Iwai  */
5498b2e18597STakashi Iwai 
5499d5191e50STakashi Iwai /**
5500d5191e50STakashi Iwai  * snd_array_new - get a new element from the given array
5501d5191e50STakashi Iwai  * @array: the array object
5502d5191e50STakashi Iwai  *
5503d5191e50STakashi Iwai  * Get a new element from the given array.  If it exceeds the
5504d5191e50STakashi Iwai  * pre-allocated array size, re-allocate the array.
5505d5191e50STakashi Iwai  *
5506d5191e50STakashi Iwai  * Returns NULL if allocation failed.
5507b2e18597STakashi Iwai  */
5508b2e18597STakashi Iwai void *snd_array_new(struct snd_array *array)
5509b2e18597STakashi Iwai {
551012f17717STakashi Iwai 	if (snd_BUG_ON(!array->elem_size))
551112f17717STakashi Iwai 		return NULL;
5512b2e18597STakashi Iwai 	if (array->used >= array->alloced) {
5513b2e18597STakashi Iwai 		int num = array->alloced + array->alloc_align;
55143101ba03STakashi Iwai 		int size = (num + 1) * array->elem_size;
551500ef9610STakashi Iwai 		int oldsize = array->alloced * array->elem_size;
5516b910d9aeSTakashi Iwai 		void *nlist;
5517b910d9aeSTakashi Iwai 		if (snd_BUG_ON(num >= 4096))
5518b910d9aeSTakashi Iwai 			return NULL;
55193101ba03STakashi Iwai 		nlist = krealloc(array->list, size, GFP_KERNEL);
5520b2e18597STakashi Iwai 		if (!nlist)
5521b2e18597STakashi Iwai 			return NULL;
552200ef9610STakashi Iwai 		memset(nlist + oldsize, 0, size - oldsize);
5523b2e18597STakashi Iwai 		array->list = nlist;
5524b2e18597STakashi Iwai 		array->alloced = num;
5525b2e18597STakashi Iwai 	}
5526f43aa025STakashi Iwai 	return snd_array_elem(array, array->used++);
5527b2e18597STakashi Iwai }
5528ff7a3267STakashi Iwai EXPORT_SYMBOL_HDA(snd_array_new);
5529b2e18597STakashi Iwai 
5530d5191e50STakashi Iwai /**
5531d5191e50STakashi Iwai  * snd_array_free - free the given array elements
5532d5191e50STakashi Iwai  * @array: the array object
5533d5191e50STakashi Iwai  */
5534b2e18597STakashi Iwai void snd_array_free(struct snd_array *array)
5535b2e18597STakashi Iwai {
5536b2e18597STakashi Iwai 	kfree(array->list);
5537b2e18597STakashi Iwai 	array->used = 0;
5538b2e18597STakashi Iwai 	array->alloced = 0;
5539b2e18597STakashi Iwai 	array->list = NULL;
5540b2e18597STakashi Iwai }
5541ff7a3267STakashi Iwai EXPORT_SYMBOL_HDA(snd_array_free);
5542b2022266STakashi Iwai 
5543d5191e50STakashi Iwai /**
5544d5191e50STakashi Iwai  * snd_print_pcm_bits - Print the supported PCM fmt bits to the string buffer
5545d5191e50STakashi Iwai  * @pcm: PCM caps bits
5546d5191e50STakashi Iwai  * @buf: the string buffer to write
5547d5191e50STakashi Iwai  * @buflen: the max buffer length
5548d5191e50STakashi Iwai  *
5549d5191e50STakashi Iwai  * used by hda_proc.c and hda_eld.c
5550d5191e50STakashi Iwai  */
5551b2022266STakashi Iwai void snd_print_pcm_bits(int pcm, char *buf, int buflen)
5552b2022266STakashi Iwai {
5553b2022266STakashi Iwai 	static unsigned int bits[] = { 8, 16, 20, 24, 32 };
5554b2022266STakashi Iwai 	int i, j;
5555b2022266STakashi Iwai 
5556b2022266STakashi Iwai 	for (i = 0, j = 0; i < ARRAY_SIZE(bits); i++)
5557b2022266STakashi Iwai 		if (pcm & (AC_SUPPCM_BITS_8 << i))
5558b2022266STakashi Iwai 			j += snprintf(buf + j, buflen - j,  " %d", bits[i]);
5559b2022266STakashi Iwai 
5560b2022266STakashi Iwai 	buf[j] = '\0'; /* necessary when j == 0 */
5561b2022266STakashi Iwai }
5562ff7a3267STakashi Iwai EXPORT_SYMBOL_HDA(snd_print_pcm_bits);
55631289e9e8STakashi Iwai 
55641289e9e8STakashi Iwai MODULE_DESCRIPTION("HDA codec core");
55651289e9e8STakashi Iwai MODULE_LICENSE("GPL");
5566