xref: /openbmc/linux/sound/pci/hda/hda_codec.c (revision d37cf9b63113f13d742713881ce691fc615d8b3b)
1d0fa1179SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
21da177e4SLinus Torvalds /*
31da177e4SLinus Torvalds  * Universal Interface for Intel High Definition Audio Codec
41da177e4SLinus Torvalds  *
51da177e4SLinus Torvalds  * Copyright (c) 2004 Takashi Iwai <tiwai@suse.de>
61da177e4SLinus Torvalds  */
71da177e4SLinus Torvalds 
81da177e4SLinus Torvalds #include <linux/init.h>
91da177e4SLinus Torvalds #include <linux/delay.h>
101da177e4SLinus Torvalds #include <linux/slab.h>
1162932df8SIngo Molnar #include <linux/mutex.h>
12da155d5bSPaul Gortmaker #include <linux/module.h>
13cc72da7dSTakashi Iwai #include <linux/pm.h>
14cc72da7dSTakashi Iwai #include <linux/pm_runtime.h>
151da177e4SLinus Torvalds #include <sound/core.h>
16be57bfffSPierre-Louis Bossart #include <sound/hda_codec.h>
171da177e4SLinus Torvalds #include <sound/asoundef.h>
18302e9c5aSJaroslav Kysela #include <sound/tlv.h>
191da177e4SLinus Torvalds #include <sound/initval.h>
20cd372fb3STakashi Iwai #include <sound/jack.h>
211da177e4SLinus Torvalds #include "hda_local.h"
22123c07aeSJaroslav Kysela #include "hda_beep.h"
231835a0f9STakashi Iwai #include "hda_jack.h"
242807314dSTakashi Iwai #include <sound/hda_hwdep.h>
25029d92c2STakashi Iwai #include <sound/hda_component.h>
261da177e4SLinus Torvalds 
27feb20faeSTakashi Iwai #define codec_in_pm(codec)		snd_hdac_is_in_pm(&codec->core)
28feb20faeSTakashi Iwai #define hda_codec_is_power_on(codec)	snd_hdac_is_power_on(&codec->core)
297639a06cSTakashi Iwai #define codec_has_epss(codec) \
307639a06cSTakashi Iwai 	((codec)->core.power_caps & AC_PWRST_EPSS)
317639a06cSTakashi Iwai #define codec_has_clkstop(codec) \
327639a06cSTakashi Iwai 	((codec)->core.power_caps & AC_PWRST_CLKSTOP)
337639a06cSTakashi Iwai 
3433fa35edSTakashi Iwai /*
3505852448STakashi Iwai  * Send and receive a verb - passed to exec_verb override for hdac_device
36aa2936f5STakashi Iwai  */
codec_exec_verb(struct hdac_device * dev,unsigned int cmd,unsigned int flags,unsigned int * res)3705852448STakashi Iwai static int codec_exec_verb(struct hdac_device *dev, unsigned int cmd,
3805852448STakashi Iwai 			   unsigned int flags, unsigned int *res)
39aa2936f5STakashi Iwai {
4005852448STakashi Iwai 	struct hda_codec *codec = container_of(dev, struct hda_codec, core);
41aa2936f5STakashi Iwai 	struct hda_bus *bus = codec->bus;
428dd78330STakashi Iwai 	int err;
43aa2936f5STakashi Iwai 
446430aeebSWu Fengguang 	if (cmd == ~0)
456430aeebSWu Fengguang 		return -1;
466430aeebSWu Fengguang 
478dd78330STakashi Iwai  again:
48664c7155STakashi Iwai 	snd_hda_power_up_pm(codec);
49d068ebc2STakashi Iwai 	mutex_lock(&bus->core.cmd_mutex);
5063e51fd7STakashi Iwai 	if (flags & HDA_RW_NO_RESPONSE_FALLBACK)
5163e51fd7STakashi Iwai 		bus->no_response_fallback = 1;
52d068ebc2STakashi Iwai 	err = snd_hdac_bus_exec_verb_unlocked(&bus->core, codec->core.addr,
53d068ebc2STakashi Iwai 					      cmd, res);
5463e51fd7STakashi Iwai 	bus->no_response_fallback = 0;
55d068ebc2STakashi Iwai 	mutex_unlock(&bus->core.cmd_mutex);
56664c7155STakashi Iwai 	snd_hda_power_down_pm(codec);
57cad372f1STakashi Iwai 	if (!codec_in_pm(codec) && res && err == -EAGAIN) {
588dd78330STakashi Iwai 		if (bus->response_reset) {
594e76a883STakashi Iwai 			codec_dbg(codec,
604e76a883STakashi Iwai 				  "resetting BUS due to fatal communication error\n");
610a50575bSTakashi Iwai 			snd_hda_bus_reset(bus);
628dd78330STakashi Iwai 		}
638dd78330STakashi Iwai 		goto again;
648dd78330STakashi Iwai 	}
658dd78330STakashi Iwai 	/* clear reset-flag when the communication gets recovered */
66d846b174STakashi Iwai 	if (!err || codec_in_pm(codec))
678dd78330STakashi Iwai 		bus->response_reset = 0;
68aa2936f5STakashi Iwai 	return err;
69aa2936f5STakashi Iwai }
70aa2936f5STakashi Iwai 
711da177e4SLinus Torvalds /**
721da177e4SLinus Torvalds  * snd_hda_sequence_write - sequence writes
731da177e4SLinus Torvalds  * @codec: the HDA codec
741da177e4SLinus Torvalds  * @seq: VERB array to send
751da177e4SLinus Torvalds  *
761da177e4SLinus Torvalds  * Send the commands sequentially from the given array.
771da177e4SLinus Torvalds  * The array must be terminated with NID=0.
781da177e4SLinus Torvalds  */
snd_hda_sequence_write(struct hda_codec * codec,const struct hda_verb * seq)791da177e4SLinus Torvalds void snd_hda_sequence_write(struct hda_codec *codec, const struct hda_verb *seq)
801da177e4SLinus Torvalds {
811da177e4SLinus Torvalds 	for (; seq->nid; seq++)
821da177e4SLinus Torvalds 		snd_hda_codec_write(codec, seq->nid, 0, seq->verb, seq->param);
831da177e4SLinus Torvalds }
842698ea98STakashi Iwai EXPORT_SYMBOL_GPL(snd_hda_sequence_write);
851da177e4SLinus Torvalds 
86ee8e765bSTakashi Iwai /* connection list element */
87ee8e765bSTakashi Iwai struct hda_conn_list {
88ee8e765bSTakashi Iwai 	struct list_head list;
89ee8e765bSTakashi Iwai 	int len;
90ee8e765bSTakashi Iwai 	hda_nid_t nid;
91bb80b964SGustavo A. R. Silva 	hda_nid_t conns[];
92ee8e765bSTakashi Iwai };
93ee8e765bSTakashi Iwai 
94b2f934a0STakashi Iwai /* look up the cached results */
95ee8e765bSTakashi Iwai static struct hda_conn_list *
lookup_conn_list(struct hda_codec * codec,hda_nid_t nid)96ee8e765bSTakashi Iwai lookup_conn_list(struct hda_codec *codec, hda_nid_t nid)
97b2f934a0STakashi Iwai {
98ee8e765bSTakashi Iwai 	struct hda_conn_list *p;
99ee8e765bSTakashi Iwai 	list_for_each_entry(p, &codec->conn_list, list) {
100ee8e765bSTakashi Iwai 		if (p->nid == nid)
101b2f934a0STakashi Iwai 			return p;
102b2f934a0STakashi Iwai 	}
103b2f934a0STakashi Iwai 	return NULL;
104b2f934a0STakashi Iwai }
105a12d3e1eSTakashi Iwai 
add_conn_list(struct hda_codec * codec,hda_nid_t nid,int len,const hda_nid_t * list)106ee8e765bSTakashi Iwai static int add_conn_list(struct hda_codec *codec, hda_nid_t nid, int len,
107ee8e765bSTakashi Iwai 			 const hda_nid_t *list)
108ee8e765bSTakashi Iwai {
109ee8e765bSTakashi Iwai 	struct hda_conn_list *p;
110ee8e765bSTakashi Iwai 
111a2d4560fSTakashi Iwai 	p = kmalloc(struct_size(p, conns, len), GFP_KERNEL);
112ee8e765bSTakashi Iwai 	if (!p)
113ee8e765bSTakashi Iwai 		return -ENOMEM;
114ee8e765bSTakashi Iwai 	p->len = len;
115ee8e765bSTakashi Iwai 	p->nid = nid;
116ee8e765bSTakashi Iwai 	memcpy(p->conns, list, len * sizeof(hda_nid_t));
117ee8e765bSTakashi Iwai 	list_add(&p->list, &codec->conn_list);
118ee8e765bSTakashi Iwai 	return 0;
119ee8e765bSTakashi Iwai }
120ee8e765bSTakashi Iwai 
remove_conn_list(struct hda_codec * codec)121ee8e765bSTakashi Iwai static void remove_conn_list(struct hda_codec *codec)
122ee8e765bSTakashi Iwai {
123ee8e765bSTakashi Iwai 	while (!list_empty(&codec->conn_list)) {
124ee8e765bSTakashi Iwai 		struct hda_conn_list *p;
125ee8e765bSTakashi Iwai 		p = list_first_entry(&codec->conn_list, typeof(*p), list);
126ee8e765bSTakashi Iwai 		list_del(&p->list);
127ee8e765bSTakashi Iwai 		kfree(p);
128ee8e765bSTakashi Iwai 	}
129ee8e765bSTakashi Iwai }
130ee8e765bSTakashi Iwai 
131b2f934a0STakashi Iwai /* read the connection and add to the cache */
read_and_add_raw_conns(struct hda_codec * codec,hda_nid_t nid)13209cf03b8STakashi Iwai static int read_and_add_raw_conns(struct hda_codec *codec, hda_nid_t nid)
13309cf03b8STakashi Iwai {
1344eea3091STakashi Iwai 	hda_nid_t list[32];
1354eea3091STakashi Iwai 	hda_nid_t *result = list;
13609cf03b8STakashi Iwai 	int len;
13709cf03b8STakashi Iwai 
13809cf03b8STakashi Iwai 	len = snd_hda_get_raw_connections(codec, nid, list, ARRAY_SIZE(list));
1394eea3091STakashi Iwai 	if (len == -ENOSPC) {
1404eea3091STakashi Iwai 		len = snd_hda_get_num_raw_conns(codec, nid);
1416da2ec56SKees Cook 		result = kmalloc_array(len, sizeof(hda_nid_t), GFP_KERNEL);
1424eea3091STakashi Iwai 		if (!result)
1434eea3091STakashi Iwai 			return -ENOMEM;
1444eea3091STakashi Iwai 		len = snd_hda_get_raw_connections(codec, nid, result, len);
1454eea3091STakashi Iwai 	}
1464eea3091STakashi Iwai 	if (len >= 0)
1474eea3091STakashi Iwai 		len = snd_hda_override_conn_list(codec, nid, len, result);
1484eea3091STakashi Iwai 	if (result != list)
1494eea3091STakashi Iwai 		kfree(result);
150a12d3e1eSTakashi Iwai 	return len;
151a12d3e1eSTakashi Iwai }
152dce2079bSTakashi Iwai 
153dce2079bSTakashi Iwai /**
154ee8e765bSTakashi Iwai  * snd_hda_get_conn_list - get connection list
155ee8e765bSTakashi Iwai  * @codec: the HDA codec
156ee8e765bSTakashi Iwai  * @nid: NID to parse
157ee8e765bSTakashi Iwai  * @listp: the pointer to store NID list
158ee8e765bSTakashi Iwai  *
159ee8e765bSTakashi Iwai  * Parses the connection list of the given widget and stores the pointer
160ee8e765bSTakashi Iwai  * to the list of NIDs.
161ee8e765bSTakashi Iwai  *
162ee8e765bSTakashi Iwai  * Returns the number of connections, or a negative error code.
163ee8e765bSTakashi Iwai  *
164ee8e765bSTakashi Iwai  * Note that the returned pointer isn't protected against the list
165ee8e765bSTakashi Iwai  * modification.  If snd_hda_override_conn_list() might be called
166ee8e765bSTakashi Iwai  * concurrently, protect with a mutex appropriately.
167ee8e765bSTakashi Iwai  */
snd_hda_get_conn_list(struct hda_codec * codec,hda_nid_t nid,const hda_nid_t ** listp)168ee8e765bSTakashi Iwai int snd_hda_get_conn_list(struct hda_codec *codec, hda_nid_t nid,
169ee8e765bSTakashi Iwai 			  const hda_nid_t **listp)
170ee8e765bSTakashi Iwai {
171ee8e765bSTakashi Iwai 	bool added = false;
172ee8e765bSTakashi Iwai 
173ee8e765bSTakashi Iwai 	for (;;) {
174ee8e765bSTakashi Iwai 		int err;
175ee8e765bSTakashi Iwai 		const struct hda_conn_list *p;
176ee8e765bSTakashi Iwai 
177ee8e765bSTakashi Iwai 		/* if the connection-list is already cached, read it */
178ee8e765bSTakashi Iwai 		p = lookup_conn_list(codec, nid);
179ee8e765bSTakashi Iwai 		if (p) {
180ee8e765bSTakashi Iwai 			if (listp)
181ee8e765bSTakashi Iwai 				*listp = p->conns;
182ee8e765bSTakashi Iwai 			return p->len;
183ee8e765bSTakashi Iwai 		}
184ee8e765bSTakashi Iwai 		if (snd_BUG_ON(added))
185ee8e765bSTakashi Iwai 			return -EINVAL;
186ee8e765bSTakashi Iwai 
187ee8e765bSTakashi Iwai 		err = read_and_add_raw_conns(codec, nid);
188ee8e765bSTakashi Iwai 		if (err < 0)
189ee8e765bSTakashi Iwai 			return err;
190ee8e765bSTakashi Iwai 		added = true;
191ee8e765bSTakashi Iwai 	}
192ee8e765bSTakashi Iwai }
1932698ea98STakashi Iwai EXPORT_SYMBOL_GPL(snd_hda_get_conn_list);
194ee8e765bSTakashi Iwai 
195ee8e765bSTakashi Iwai /**
196dce2079bSTakashi Iwai  * snd_hda_get_connections - copy connection list
1971da177e4SLinus Torvalds  * @codec: the HDA codec
1981da177e4SLinus Torvalds  * @nid: NID to parse
19909cf03b8STakashi Iwai  * @conn_list: connection list array; when NULL, checks only the size
2001da177e4SLinus Torvalds  * @max_conns: max. number of connections to store
2011da177e4SLinus Torvalds  *
2021da177e4SLinus Torvalds  * Parses the connection list of the given widget and stores the list
2031da177e4SLinus Torvalds  * of NIDs.
2041da177e4SLinus Torvalds  *
2051da177e4SLinus Torvalds  * Returns the number of connections, or a negative error code.
2061da177e4SLinus Torvalds  */
snd_hda_get_connections(struct hda_codec * codec,hda_nid_t nid,hda_nid_t * conn_list,int max_conns)2071da177e4SLinus Torvalds int snd_hda_get_connections(struct hda_codec *codec, hda_nid_t nid,
2081da177e4SLinus Torvalds 			    hda_nid_t *conn_list, int max_conns)
2091da177e4SLinus Torvalds {
210ee8e765bSTakashi Iwai 	const hda_nid_t *list;
211ee8e765bSTakashi Iwai 	int len = snd_hda_get_conn_list(codec, nid, &list);
212a12d3e1eSTakashi Iwai 
213ee8e765bSTakashi Iwai 	if (len > 0 && conn_list) {
214ee8e765bSTakashi Iwai 		if (len > max_conns) {
2154e76a883STakashi Iwai 			codec_err(codec, "Too many connections %d for NID 0x%x\n",
216dce2079bSTakashi Iwai 				   len, nid);
217dce2079bSTakashi Iwai 			return -EINVAL;
218dce2079bSTakashi Iwai 		}
219ee8e765bSTakashi Iwai 		memcpy(conn_list, list, len * sizeof(hda_nid_t));
22009cf03b8STakashi Iwai 	}
22109cf03b8STakashi Iwai 
22209cf03b8STakashi Iwai 	return len;
223a12d3e1eSTakashi Iwai }
2242698ea98STakashi Iwai EXPORT_SYMBOL_GPL(snd_hda_get_connections);
225a12d3e1eSTakashi Iwai 
2261da177e4SLinus Torvalds /**
227b2f934a0STakashi Iwai  * snd_hda_override_conn_list - add/modify the connection-list to cache
228b2f934a0STakashi Iwai  * @codec: the HDA codec
229b2f934a0STakashi Iwai  * @nid: NID to parse
230b2f934a0STakashi Iwai  * @len: number of connection list entries
231b2f934a0STakashi Iwai  * @list: the list of connection entries
232b2f934a0STakashi Iwai  *
233b2f934a0STakashi Iwai  * Add or modify the given connection-list to the cache.  If the corresponding
234b2f934a0STakashi Iwai  * cache already exists, invalidate it and append a new one.
235b2f934a0STakashi Iwai  *
236b2f934a0STakashi Iwai  * Returns zero or a negative error code.
237b2f934a0STakashi Iwai  */
snd_hda_override_conn_list(struct hda_codec * codec,hda_nid_t nid,int len,const hda_nid_t * list)238b2f934a0STakashi Iwai int snd_hda_override_conn_list(struct hda_codec *codec, hda_nid_t nid, int len,
239b2f934a0STakashi Iwai 			       const hda_nid_t *list)
2401da177e4SLinus Torvalds {
241ee8e765bSTakashi Iwai 	struct hda_conn_list *p;
242b2f934a0STakashi Iwai 
243ee8e765bSTakashi Iwai 	p = lookup_conn_list(codec, nid);
244ee8e765bSTakashi Iwai 	if (p) {
245ee8e765bSTakashi Iwai 		list_del(&p->list);
246ee8e765bSTakashi Iwai 		kfree(p);
247ee8e765bSTakashi Iwai 	}
248b2f934a0STakashi Iwai 
249ee8e765bSTakashi Iwai 	return add_conn_list(codec, nid, len, list);
2501da177e4SLinus Torvalds }
2512698ea98STakashi Iwai EXPORT_SYMBOL_GPL(snd_hda_override_conn_list);
252b2f934a0STakashi Iwai 
253b2f934a0STakashi Iwai /**
2548d087c76STakashi Iwai  * snd_hda_get_conn_index - get the connection index of the given NID
2558d087c76STakashi Iwai  * @codec: the HDA codec
2568d087c76STakashi Iwai  * @mux: NID containing the list
2578d087c76STakashi Iwai  * @nid: NID to select
2588d087c76STakashi Iwai  * @recursive: 1 when searching NID recursively, otherwise 0
2598d087c76STakashi Iwai  *
2608d087c76STakashi Iwai  * Parses the connection list of the widget @mux and checks whether the
2618d087c76STakashi Iwai  * widget @nid is present.  If it is, return the connection index.
2628d087c76STakashi Iwai  * Otherwise it returns -1.
2638d087c76STakashi Iwai  */
snd_hda_get_conn_index(struct hda_codec * codec,hda_nid_t mux,hda_nid_t nid,int recursive)2648d087c76STakashi Iwai int snd_hda_get_conn_index(struct hda_codec *codec, hda_nid_t mux,
2658d087c76STakashi Iwai 			   hda_nid_t nid, int recursive)
2668d087c76STakashi Iwai {
267ee8e765bSTakashi Iwai 	const hda_nid_t *conn;
2688d087c76STakashi Iwai 	int i, nums;
2698d087c76STakashi Iwai 
270ee8e765bSTakashi Iwai 	nums = snd_hda_get_conn_list(codec, mux, &conn);
2718d087c76STakashi Iwai 	for (i = 0; i < nums; i++)
2728d087c76STakashi Iwai 		if (conn[i] == nid)
2738d087c76STakashi Iwai 			return i;
2748d087c76STakashi Iwai 	if (!recursive)
2758d087c76STakashi Iwai 		return -1;
276d94ddd85STakashi Iwai 	if (recursive > 10) {
2774e76a883STakashi Iwai 		codec_dbg(codec, "too deep connection for 0x%x\n", nid);
2788d087c76STakashi Iwai 		return -1;
2791da177e4SLinus Torvalds 	}
2808d087c76STakashi Iwai 	recursive++;
28199e14c9dSTakashi Iwai 	for (i = 0; i < nums; i++) {
28299e14c9dSTakashi Iwai 		unsigned int type = get_wcaps_type(get_wcaps(codec, conn[i]));
28399e14c9dSTakashi Iwai 		if (type == AC_WID_PIN || type == AC_WID_AUD_OUT)
28499e14c9dSTakashi Iwai 			continue;
2858d087c76STakashi Iwai 		if (snd_hda_get_conn_index(codec, conn[i], nid, recursive) >= 0)
2868d087c76STakashi Iwai 			return i;
28799e14c9dSTakashi Iwai 	}
2888d087c76STakashi Iwai 	return -1;
2898d087c76STakashi Iwai }
2902698ea98STakashi Iwai EXPORT_SYMBOL_GPL(snd_hda_get_conn_index);
2911da177e4SLinus Torvalds 
29213800f39SLibin Yang /**
29313800f39SLibin Yang  * snd_hda_get_num_devices - get DEVLIST_LEN parameter of the given widget
29413800f39SLibin Yang  *  @codec: the HDA codec
29513800f39SLibin Yang  *  @nid: NID of the pin to parse
29613800f39SLibin Yang  *
29713800f39SLibin Yang  * Get the device entry number on the given widget. This is a feature of
29813800f39SLibin Yang  * DP MST audio. Each pin can have several device entries in it.
29913800f39SLibin Yang  */
snd_hda_get_num_devices(struct hda_codec * codec,hda_nid_t nid)30013800f39SLibin Yang unsigned int snd_hda_get_num_devices(struct hda_codec *codec, hda_nid_t nid)
301f1aa0684SMengdong Lin {
302f1aa0684SMengdong Lin 	unsigned int wcaps = get_wcaps(codec, nid);
303f1aa0684SMengdong Lin 	unsigned int parm;
304f1aa0684SMengdong Lin 
305f1aa0684SMengdong Lin 	if (!codec->dp_mst || !(wcaps & AC_WCAP_DIGITAL) ||
306f1aa0684SMengdong Lin 	    get_wcaps_type(wcaps) != AC_WID_PIN)
307f1aa0684SMengdong Lin 		return 0;
308f1aa0684SMengdong Lin 
309132bd96bSDave Airlie 	parm = snd_hdac_read_parm_uncached(&codec->core, nid, AC_PAR_DEVLIST_LEN);
3108654844cSTakashi Iwai 	if (parm == -1)
311f1aa0684SMengdong Lin 		parm = 0;
312f1aa0684SMengdong Lin 	return parm & AC_DEV_LIST_LEN_MASK;
313f1aa0684SMengdong Lin }
31413800f39SLibin Yang EXPORT_SYMBOL_GPL(snd_hda_get_num_devices);
315f1aa0684SMengdong Lin 
316f1aa0684SMengdong Lin /**
317f1aa0684SMengdong Lin  * snd_hda_get_devices - copy device list without cache
318f1aa0684SMengdong Lin  * @codec: the HDA codec
319f1aa0684SMengdong Lin  * @nid: NID of the pin to parse
320f1aa0684SMengdong Lin  * @dev_list: device list array
321f1aa0684SMengdong Lin  * @max_devices: max. number of devices to store
322f1aa0684SMengdong Lin  *
323f1aa0684SMengdong Lin  * Copy the device list. This info is dynamic and so not cached.
324f1aa0684SMengdong Lin  * Currently called only from hda_proc.c, so not exported.
325f1aa0684SMengdong Lin  */
snd_hda_get_devices(struct hda_codec * codec,hda_nid_t nid,u8 * dev_list,int max_devices)326f1aa0684SMengdong Lin int snd_hda_get_devices(struct hda_codec *codec, hda_nid_t nid,
327f1aa0684SMengdong Lin 			u8 *dev_list, int max_devices)
328f1aa0684SMengdong Lin {
329f1aa0684SMengdong Lin 	unsigned int parm;
330f1aa0684SMengdong Lin 	int i, dev_len, devices;
331f1aa0684SMengdong Lin 
33213800f39SLibin Yang 	parm = snd_hda_get_num_devices(codec, nid);
333f1aa0684SMengdong Lin 	if (!parm)	/* not multi-stream capable */
334f1aa0684SMengdong Lin 		return 0;
335f1aa0684SMengdong Lin 
336f1aa0684SMengdong Lin 	dev_len = parm + 1;
337f1aa0684SMengdong Lin 	dev_len = dev_len < max_devices ? dev_len : max_devices;
338f1aa0684SMengdong Lin 
339f1aa0684SMengdong Lin 	devices = 0;
340f1aa0684SMengdong Lin 	while (devices < dev_len) {
341cad372f1STakashi Iwai 		if (snd_hdac_read(&codec->core, nid,
342cad372f1STakashi Iwai 				  AC_VERB_GET_DEVICE_LIST, devices, &parm))
343cad372f1STakashi Iwai 			break; /* error */
344f1aa0684SMengdong Lin 
345f1aa0684SMengdong Lin 		for (i = 0; i < 8; i++) {
346f1aa0684SMengdong Lin 			dev_list[devices] = (u8)parm;
347f1aa0684SMengdong Lin 			parm >>= 4;
348f1aa0684SMengdong Lin 			devices++;
349f1aa0684SMengdong Lin 			if (devices >= dev_len)
350f1aa0684SMengdong Lin 				break;
351f1aa0684SMengdong Lin 		}
352f1aa0684SMengdong Lin 	}
353f1aa0684SMengdong Lin 	return devices;
354f1aa0684SMengdong Lin }
355f1aa0684SMengdong Lin 
35613800f39SLibin Yang /**
35713800f39SLibin Yang  * snd_hda_get_dev_select - get device entry select on the pin
35813800f39SLibin Yang  * @codec: the HDA codec
35913800f39SLibin Yang  * @nid: NID of the pin to get device entry select
36013800f39SLibin Yang  *
36113800f39SLibin Yang  * Get the devcie entry select on the pin. Return the device entry
36213800f39SLibin Yang  * id selected on the pin. Return 0 means the first device entry
36313800f39SLibin Yang  * is selected or MST is not supported.
36413800f39SLibin Yang  */
snd_hda_get_dev_select(struct hda_codec * codec,hda_nid_t nid)36513800f39SLibin Yang int snd_hda_get_dev_select(struct hda_codec *codec, hda_nid_t nid)
36613800f39SLibin Yang {
36713800f39SLibin Yang 	/* not support dp_mst will always return 0, using first dev_entry */
36813800f39SLibin Yang 	if (!codec->dp_mst)
36913800f39SLibin Yang 		return 0;
37013800f39SLibin Yang 
37113800f39SLibin Yang 	return snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_DEVICE_SEL, 0);
37213800f39SLibin Yang }
37313800f39SLibin Yang EXPORT_SYMBOL_GPL(snd_hda_get_dev_select);
37413800f39SLibin Yang 
37513800f39SLibin Yang /**
37613800f39SLibin Yang  * snd_hda_set_dev_select - set device entry select on the pin
37713800f39SLibin Yang  * @codec: the HDA codec
37813800f39SLibin Yang  * @nid: NID of the pin to set device entry select
37913800f39SLibin Yang  * @dev_id: device entry id to be set
38013800f39SLibin Yang  *
38113800f39SLibin Yang  * Set the device entry select on the pin nid.
38213800f39SLibin Yang  */
snd_hda_set_dev_select(struct hda_codec * codec,hda_nid_t nid,int dev_id)38313800f39SLibin Yang int snd_hda_set_dev_select(struct hda_codec *codec, hda_nid_t nid, int dev_id)
38413800f39SLibin Yang {
38513800f39SLibin Yang 	int ret, num_devices;
38613800f39SLibin Yang 
38713800f39SLibin Yang 	/* not support dp_mst will always return 0, using first dev_entry */
38813800f39SLibin Yang 	if (!codec->dp_mst)
38913800f39SLibin Yang 		return 0;
39013800f39SLibin Yang 
39113800f39SLibin Yang 	/* AC_PAR_DEVLIST_LEN is 0 based. */
39213800f39SLibin Yang 	num_devices = snd_hda_get_num_devices(codec, nid) + 1;
39313800f39SLibin Yang 	/* If Device List Length is 0 (num_device = 1),
39413800f39SLibin Yang 	 * the pin is not multi stream capable.
39513800f39SLibin Yang 	 * Do nothing in this case.
39613800f39SLibin Yang 	 */
39713800f39SLibin Yang 	if (num_devices == 1)
39813800f39SLibin Yang 		return 0;
39913800f39SLibin Yang 
40013800f39SLibin Yang 	/* Behavior of setting index being equal to or greater than
40113800f39SLibin Yang 	 * Device List Length is not predictable
40213800f39SLibin Yang 	 */
40313800f39SLibin Yang 	if (num_devices <= dev_id)
40413800f39SLibin Yang 		return -EINVAL;
40513800f39SLibin Yang 
40613800f39SLibin Yang 	ret = snd_hda_codec_write(codec, nid, 0,
40713800f39SLibin Yang 			AC_VERB_SET_DEVICE_SEL, dev_id);
40813800f39SLibin Yang 
40913800f39SLibin Yang 	return ret;
41013800f39SLibin Yang }
41113800f39SLibin Yang EXPORT_SYMBOL_GPL(snd_hda_set_dev_select);
41213800f39SLibin Yang 
4131da177e4SLinus Torvalds /*
41454d17403STakashi Iwai  * read widget caps for each widget and store in cache
41554d17403STakashi Iwai  */
read_widget_caps(struct hda_codec * codec,hda_nid_t fg_node)41654d17403STakashi Iwai static int read_widget_caps(struct hda_codec *codec, hda_nid_t fg_node)
41754d17403STakashi Iwai {
41854d17403STakashi Iwai 	int i;
41954d17403STakashi Iwai 	hda_nid_t nid;
42054d17403STakashi Iwai 
4216da2ec56SKees Cook 	codec->wcaps = kmalloc_array(codec->core.num_nodes, 4, GFP_KERNEL);
42254d17403STakashi Iwai 	if (!codec->wcaps)
42354d17403STakashi Iwai 		return -ENOMEM;
4247639a06cSTakashi Iwai 	nid = codec->core.start_nid;
4257639a06cSTakashi Iwai 	for (i = 0; i < codec->core.num_nodes; i++, nid++)
4269ba17b4dSTakashi Iwai 		codec->wcaps[i] = snd_hdac_read_parm_uncached(&codec->core,
4279ba17b4dSTakashi Iwai 					nid, AC_PAR_AUDIO_WIDGET_CAP);
42854d17403STakashi Iwai 	return 0;
42954d17403STakashi Iwai }
43054d17403STakashi Iwai 
4313be14149STakashi Iwai /* read all pin default configurations and save codec->init_pins */
read_pin_defaults(struct hda_codec * codec)4323be14149STakashi Iwai static int read_pin_defaults(struct hda_codec *codec)
4333be14149STakashi Iwai {
4347639a06cSTakashi Iwai 	hda_nid_t nid;
4353be14149STakashi Iwai 
4367639a06cSTakashi Iwai 	for_each_hda_codec_node(nid, codec) {
4373be14149STakashi Iwai 		struct hda_pincfg *pin;
4383be14149STakashi Iwai 		unsigned int wcaps = get_wcaps(codec, nid);
439a22d543aSTakashi Iwai 		unsigned int wid_type = get_wcaps_type(wcaps);
4403be14149STakashi Iwai 		if (wid_type != AC_WID_PIN)
4413be14149STakashi Iwai 			continue;
4423be14149STakashi Iwai 		pin = snd_array_new(&codec->init_pins);
4433be14149STakashi Iwai 		if (!pin)
4443be14149STakashi Iwai 			return -ENOMEM;
4453be14149STakashi Iwai 		pin->nid = nid;
4463be14149STakashi Iwai 		pin->cfg = snd_hda_codec_read(codec, nid, 0,
4473be14149STakashi Iwai 					      AC_VERB_GET_CONFIG_DEFAULT, 0);
4489152085dSLibin Yang 		/*
4499152085dSLibin Yang 		 * all device entries are the same widget control so far
4509152085dSLibin Yang 		 * fixme: if any codec is different, need fix here
4519152085dSLibin Yang 		 */
452ac0547dcSTakashi Iwai 		pin->ctrl = snd_hda_codec_read(codec, nid, 0,
453ac0547dcSTakashi Iwai 					       AC_VERB_GET_PIN_WIDGET_CONTROL,
454ac0547dcSTakashi Iwai 					       0);
4553be14149STakashi Iwai 	}
4563be14149STakashi Iwai 	return 0;
4573be14149STakashi Iwai }
4583be14149STakashi Iwai 
4593be14149STakashi Iwai /* look up the given pin config list and return the item matching with NID */
look_up_pincfg(struct hda_codec * codec,struct snd_array * array,hda_nid_t nid)4603be14149STakashi Iwai static struct hda_pincfg *look_up_pincfg(struct hda_codec *codec,
4613be14149STakashi Iwai 					 struct snd_array *array,
4623be14149STakashi Iwai 					 hda_nid_t nid)
4633be14149STakashi Iwai {
464a9c2dfc8STakashi Iwai 	struct hda_pincfg *pin;
4653be14149STakashi Iwai 	int i;
466a9c2dfc8STakashi Iwai 
467a9c2dfc8STakashi Iwai 	snd_array_for_each(array, i, pin) {
4683be14149STakashi Iwai 		if (pin->nid == nid)
4693be14149STakashi Iwai 			return pin;
4703be14149STakashi Iwai 	}
4713be14149STakashi Iwai 	return NULL;
4723be14149STakashi Iwai }
4733be14149STakashi Iwai 
4743be14149STakashi Iwai /* set the current pin config value for the given NID.
4753be14149STakashi Iwai  * the value is cached, and read via snd_hda_codec_get_pincfg()
4763be14149STakashi Iwai  */
snd_hda_add_pincfg(struct hda_codec * codec,struct snd_array * list,hda_nid_t nid,unsigned int cfg)4773be14149STakashi Iwai int snd_hda_add_pincfg(struct hda_codec *codec, struct snd_array *list,
4783be14149STakashi Iwai 		       hda_nid_t nid, unsigned int cfg)
4793be14149STakashi Iwai {
4803be14149STakashi Iwai 	struct hda_pincfg *pin;
4813be14149STakashi Iwai 
482d5657ec9STakashi Iwai 	/* the check below may be invalid when pins are added by a fixup
483d5657ec9STakashi Iwai 	 * dynamically (e.g. via snd_hda_codec_update_widgets()), so disabled
484d5657ec9STakashi Iwai 	 * for now
485d5657ec9STakashi Iwai 	 */
486d5657ec9STakashi Iwai 	/*
487b82855a0STakashi Iwai 	if (get_wcaps_type(get_wcaps(codec, nid)) != AC_WID_PIN)
488b82855a0STakashi Iwai 		return -EINVAL;
489d5657ec9STakashi Iwai 	*/
490b82855a0STakashi Iwai 
4913be14149STakashi Iwai 	pin = look_up_pincfg(codec, list, nid);
4923be14149STakashi Iwai 	if (!pin) {
4933be14149STakashi Iwai 		pin = snd_array_new(list);
4943be14149STakashi Iwai 		if (!pin)
4953be14149STakashi Iwai 			return -ENOMEM;
4963be14149STakashi Iwai 		pin->nid = nid;
4973be14149STakashi Iwai 	}
4983be14149STakashi Iwai 	pin->cfg = cfg;
4993be14149STakashi Iwai 	return 0;
5003be14149STakashi Iwai }
5013be14149STakashi Iwai 
502d5191e50STakashi Iwai /**
503d5191e50STakashi Iwai  * snd_hda_codec_set_pincfg - Override a pin default configuration
504d5191e50STakashi Iwai  * @codec: the HDA codec
505d5191e50STakashi Iwai  * @nid: NID to set the pin config
506d5191e50STakashi Iwai  * @cfg: the pin default config value
507d5191e50STakashi Iwai  *
508d5191e50STakashi Iwai  * Override a pin default configuration value in the cache.
509d5191e50STakashi Iwai  * This value can be read by snd_hda_codec_get_pincfg() in a higher
510d5191e50STakashi Iwai  * priority than the real hardware value.
511d5191e50STakashi Iwai  */
snd_hda_codec_set_pincfg(struct hda_codec * codec,hda_nid_t nid,unsigned int cfg)5123be14149STakashi Iwai int snd_hda_codec_set_pincfg(struct hda_codec *codec,
5133be14149STakashi Iwai 			     hda_nid_t nid, unsigned int cfg)
5143be14149STakashi Iwai {
515346ff70fSTakashi Iwai 	return snd_hda_add_pincfg(codec, &codec->driver_pins, nid, cfg);
5163be14149STakashi Iwai }
5172698ea98STakashi Iwai EXPORT_SYMBOL_GPL(snd_hda_codec_set_pincfg);
5183be14149STakashi Iwai 
519d5191e50STakashi Iwai /**
520d5191e50STakashi Iwai  * snd_hda_codec_get_pincfg - Obtain a pin-default configuration
521d5191e50STakashi Iwai  * @codec: the HDA codec
522d5191e50STakashi Iwai  * @nid: NID to get the pin config
523d5191e50STakashi Iwai  *
524d5191e50STakashi Iwai  * Get the current pin config value of the given pin NID.
525d5191e50STakashi Iwai  * If the pincfg value is cached or overridden via sysfs or driver,
526d5191e50STakashi Iwai  * returns the cached value.
527d5191e50STakashi Iwai  */
snd_hda_codec_get_pincfg(struct hda_codec * codec,hda_nid_t nid)5283be14149STakashi Iwai unsigned int snd_hda_codec_get_pincfg(struct hda_codec *codec, hda_nid_t nid)
5293be14149STakashi Iwai {
5303be14149STakashi Iwai 	struct hda_pincfg *pin;
5313be14149STakashi Iwai 
532648a8d27STakashi Iwai #ifdef CONFIG_SND_HDA_RECONFIG
53309b70e85STakashi Iwai 	{
53409b70e85STakashi Iwai 		unsigned int cfg = 0;
53509b70e85STakashi Iwai 		mutex_lock(&codec->user_mutex);
536346ff70fSTakashi Iwai 		pin = look_up_pincfg(codec, &codec->user_pins, nid);
5373be14149STakashi Iwai 		if (pin)
53809b70e85STakashi Iwai 			cfg = pin->cfg;
53909b70e85STakashi Iwai 		mutex_unlock(&codec->user_mutex);
54009b70e85STakashi Iwai 		if (cfg)
54109b70e85STakashi Iwai 			return cfg;
54209b70e85STakashi Iwai 	}
5433be14149STakashi Iwai #endif
5445e7b8e0dSTakashi Iwai 	pin = look_up_pincfg(codec, &codec->driver_pins, nid);
5455e7b8e0dSTakashi Iwai 	if (pin)
5465e7b8e0dSTakashi Iwai 		return pin->cfg;
5473be14149STakashi Iwai 	pin = look_up_pincfg(codec, &codec->init_pins, nid);
5483be14149STakashi Iwai 	if (pin)
5493be14149STakashi Iwai 		return pin->cfg;
5503be14149STakashi Iwai 	return 0;
5513be14149STakashi Iwai }
5522698ea98STakashi Iwai EXPORT_SYMBOL_GPL(snd_hda_codec_get_pincfg);
5533be14149STakashi Iwai 
55495a962c3STakashi Iwai /**
55595a962c3STakashi Iwai  * snd_hda_codec_set_pin_target - remember the current pinctl target value
55695a962c3STakashi Iwai  * @codec: the HDA codec
55795a962c3STakashi Iwai  * @nid: pin NID
55895a962c3STakashi Iwai  * @val: assigned pinctl value
55995a962c3STakashi Iwai  *
56095a962c3STakashi Iwai  * This function stores the given value to a pinctl target value in the
56195a962c3STakashi Iwai  * pincfg table.  This isn't always as same as the actually written value
56295a962c3STakashi Iwai  * but can be referred at any time via snd_hda_codec_get_pin_target().
56395a962c3STakashi Iwai  */
snd_hda_codec_set_pin_target(struct hda_codec * codec,hda_nid_t nid,unsigned int val)564d7fdc00aSTakashi Iwai int snd_hda_codec_set_pin_target(struct hda_codec *codec, hda_nid_t nid,
565d7fdc00aSTakashi Iwai 				 unsigned int val)
566d7fdc00aSTakashi Iwai {
567d7fdc00aSTakashi Iwai 	struct hda_pincfg *pin;
568d7fdc00aSTakashi Iwai 
569d7fdc00aSTakashi Iwai 	pin = look_up_pincfg(codec, &codec->init_pins, nid);
570d7fdc00aSTakashi Iwai 	if (!pin)
571d7fdc00aSTakashi Iwai 		return -EINVAL;
572d7fdc00aSTakashi Iwai 	pin->target = val;
573d7fdc00aSTakashi Iwai 	return 0;
574d7fdc00aSTakashi Iwai }
5752698ea98STakashi Iwai EXPORT_SYMBOL_GPL(snd_hda_codec_set_pin_target);
576d7fdc00aSTakashi Iwai 
57795a962c3STakashi Iwai /**
57895a962c3STakashi Iwai  * snd_hda_codec_get_pin_target - return the current pinctl target value
57995a962c3STakashi Iwai  * @codec: the HDA codec
58095a962c3STakashi Iwai  * @nid: pin NID
58195a962c3STakashi Iwai  */
snd_hda_codec_get_pin_target(struct hda_codec * codec,hda_nid_t nid)582d7fdc00aSTakashi Iwai int snd_hda_codec_get_pin_target(struct hda_codec *codec, hda_nid_t nid)
583d7fdc00aSTakashi Iwai {
584d7fdc00aSTakashi Iwai 	struct hda_pincfg *pin;
585d7fdc00aSTakashi Iwai 
586d7fdc00aSTakashi Iwai 	pin = look_up_pincfg(codec, &codec->init_pins, nid);
587d7fdc00aSTakashi Iwai 	if (!pin)
588d7fdc00aSTakashi Iwai 		return 0;
589d7fdc00aSTakashi Iwai 	return pin->target;
590d7fdc00aSTakashi Iwai }
5912698ea98STakashi Iwai EXPORT_SYMBOL_GPL(snd_hda_codec_get_pin_target);
592d7fdc00aSTakashi Iwai 
59392ee6162STakashi Iwai /**
59492ee6162STakashi Iwai  * snd_hda_shutup_pins - Shut up all pins
59592ee6162STakashi Iwai  * @codec: the HDA codec
59692ee6162STakashi Iwai  *
59792ee6162STakashi Iwai  * Clear all pin controls to shup up before suspend for avoiding click noise.
59892ee6162STakashi Iwai  * The controls aren't cached so that they can be resumed properly.
59992ee6162STakashi Iwai  */
snd_hda_shutup_pins(struct hda_codec * codec)60092ee6162STakashi Iwai void snd_hda_shutup_pins(struct hda_codec *codec)
60192ee6162STakashi Iwai {
602a9c2dfc8STakashi Iwai 	const struct hda_pincfg *pin;
60392ee6162STakashi Iwai 	int i;
604a9c2dfc8STakashi Iwai 
605ac0547dcSTakashi Iwai 	/* don't shut up pins when unloading the driver; otherwise it breaks
606ac0547dcSTakashi Iwai 	 * the default pin setup at the next load of the driver
607ac0547dcSTakashi Iwai 	 */
608ac0547dcSTakashi Iwai 	if (codec->bus->shutdown)
609ac0547dcSTakashi Iwai 		return;
610a9c2dfc8STakashi Iwai 	snd_array_for_each(&codec->init_pins, i, pin) {
61192ee6162STakashi Iwai 		/* use read here for syncing after issuing each verb */
61292ee6162STakashi Iwai 		snd_hda_codec_read(codec, pin->nid, 0,
61392ee6162STakashi Iwai 				   AC_VERB_SET_PIN_WIDGET_CONTROL, 0);
61492ee6162STakashi Iwai 	}
615ac0547dcSTakashi Iwai 	codec->pins_shutup = 1;
61692ee6162STakashi Iwai }
6172698ea98STakashi Iwai EXPORT_SYMBOL_GPL(snd_hda_shutup_pins);
61892ee6162STakashi Iwai 
6192a43952aSTakashi Iwai #ifdef CONFIG_PM
620ac0547dcSTakashi Iwai /* Restore the pin controls cleared previously via snd_hda_shutup_pins() */
restore_shutup_pins(struct hda_codec * codec)621ac0547dcSTakashi Iwai static void restore_shutup_pins(struct hda_codec *codec)
622ac0547dcSTakashi Iwai {
623a9c2dfc8STakashi Iwai 	const struct hda_pincfg *pin;
624ac0547dcSTakashi Iwai 	int i;
625a9c2dfc8STakashi Iwai 
626ac0547dcSTakashi Iwai 	if (!codec->pins_shutup)
627ac0547dcSTakashi Iwai 		return;
628ac0547dcSTakashi Iwai 	if (codec->bus->shutdown)
629ac0547dcSTakashi Iwai 		return;
630a9c2dfc8STakashi Iwai 	snd_array_for_each(&codec->init_pins, i, pin) {
631ac0547dcSTakashi Iwai 		snd_hda_codec_write(codec, pin->nid, 0,
632ac0547dcSTakashi Iwai 				    AC_VERB_SET_PIN_WIDGET_CONTROL,
633ac0547dcSTakashi Iwai 				    pin->ctrl);
634ac0547dcSTakashi Iwai 	}
635ac0547dcSTakashi Iwai 	codec->pins_shutup = 0;
636ac0547dcSTakashi Iwai }
6371c7276cfSMike Waychison #endif
638ac0547dcSTakashi Iwai 
hda_jackpoll_work(struct work_struct * work)63926a6cb6cSDavid Henningsson static void hda_jackpoll_work(struct work_struct *work)
64026a6cb6cSDavid Henningsson {
64126a6cb6cSDavid Henningsson 	struct hda_codec *codec =
64226a6cb6cSDavid Henningsson 		container_of(work, struct hda_codec, jackpoll_work.work);
64326a6cb6cSDavid Henningsson 
6448d6762afSTakashi Iwai 	/* for non-polling trigger: we need nothing if already powered on */
6458d6762afSTakashi Iwai 	if (!codec->jackpoll_interval && snd_hdac_is_power_on(&codec->core))
6468d6762afSTakashi Iwai 		return;
6478d6762afSTakashi Iwai 
6488d6762afSTakashi Iwai 	/* the power-up/down sequence triggers the runtime resume */
6498d6762afSTakashi Iwai 	snd_hda_power_up_pm(codec);
6508d6762afSTakashi Iwai 	/* update jacks manually if polling is required, too */
6518d6762afSTakashi Iwai 	if (codec->jackpoll_interval) {
65226a6cb6cSDavid Henningsson 		snd_hda_jack_set_dirty_all(codec);
65326a6cb6cSDavid Henningsson 		snd_hda_jack_poll_all(codec);
6548d6762afSTakashi Iwai 	}
6558d6762afSTakashi Iwai 	snd_hda_power_down_pm(codec);
65618e60627SWang Xingchao 
65718e60627SWang Xingchao 	if (!codec->jackpoll_interval)
65818e60627SWang Xingchao 		return;
65918e60627SWang Xingchao 
6602f35c630STakashi Iwai 	schedule_delayed_work(&codec->jackpoll_work,
66126a6cb6cSDavid Henningsson 			      codec->jackpoll_interval);
66226a6cb6cSDavid Henningsson }
66326a6cb6cSDavid Henningsson 
6643fdf1469STakashi Iwai /* release all pincfg lists */
free_init_pincfgs(struct hda_codec * codec)6653fdf1469STakashi Iwai static void free_init_pincfgs(struct hda_codec *codec)
6663be14149STakashi Iwai {
667346ff70fSTakashi Iwai 	snd_array_free(&codec->driver_pins);
668648a8d27STakashi Iwai #ifdef CONFIG_SND_HDA_RECONFIG
669346ff70fSTakashi Iwai 	snd_array_free(&codec->user_pins);
6703be14149STakashi Iwai #endif
6713be14149STakashi Iwai 	snd_array_free(&codec->init_pins);
6723be14149STakashi Iwai }
6733be14149STakashi Iwai 
67454d17403STakashi Iwai /*
675eb541337STakashi Iwai  * audio-converter setup caches
676eb541337STakashi Iwai  */
677eb541337STakashi Iwai struct hda_cvt_setup {
678eb541337STakashi Iwai 	hda_nid_t nid;
679eb541337STakashi Iwai 	u8 stream_tag;
680eb541337STakashi Iwai 	u8 channel_id;
681eb541337STakashi Iwai 	u16 format_id;
682eb541337STakashi Iwai 	unsigned char active;	/* cvt is currently used */
683eb541337STakashi Iwai 	unsigned char dirty;	/* setups should be cleared */
684eb541337STakashi Iwai };
685eb541337STakashi Iwai 
686eb541337STakashi Iwai /* get or create a cache entry for the given audio converter NID */
687eb541337STakashi Iwai static struct hda_cvt_setup *
get_hda_cvt_setup(struct hda_codec * codec,hda_nid_t nid)688eb541337STakashi Iwai get_hda_cvt_setup(struct hda_codec *codec, hda_nid_t nid)
689eb541337STakashi Iwai {
690eb541337STakashi Iwai 	struct hda_cvt_setup *p;
691eb541337STakashi Iwai 	int i;
692eb541337STakashi Iwai 
693a9c2dfc8STakashi Iwai 	snd_array_for_each(&codec->cvt_setups, i, p) {
694eb541337STakashi Iwai 		if (p->nid == nid)
695eb541337STakashi Iwai 			return p;
696eb541337STakashi Iwai 	}
697eb541337STakashi Iwai 	p = snd_array_new(&codec->cvt_setups);
698eb541337STakashi Iwai 	if (p)
699eb541337STakashi Iwai 		p->nid = nid;
700eb541337STakashi Iwai 	return p;
701eb541337STakashi Iwai }
702eb541337STakashi Iwai 
703eb541337STakashi Iwai /*
704bbbc7e85STakashi Iwai  * PCM device
705bbbc7e85STakashi Iwai  */
snd_hda_codec_pcm_put(struct hda_pcm * pcm)706bbbc7e85STakashi Iwai void snd_hda_codec_pcm_put(struct hda_pcm *pcm)
707bbbc7e85STakashi Iwai {
7087206998fSTakashi Iwai 	if (refcount_dec_and_test(&pcm->codec->pcm_ref))
7097206998fSTakashi Iwai 		wake_up(&pcm->codec->remove_sleep);
710bbbc7e85STakashi Iwai }
711bbbc7e85STakashi Iwai EXPORT_SYMBOL_GPL(snd_hda_codec_pcm_put);
712bbbc7e85STakashi Iwai 
snd_hda_codec_pcm_new(struct hda_codec * codec,const char * fmt,...)713bbbc7e85STakashi Iwai struct hda_pcm *snd_hda_codec_pcm_new(struct hda_codec *codec,
714bbbc7e85STakashi Iwai 				      const char *fmt, ...)
715bbbc7e85STakashi Iwai {
716bbbc7e85STakashi Iwai 	struct hda_pcm *pcm;
717bbbc7e85STakashi Iwai 	va_list args;
718bbbc7e85STakashi Iwai 
719bbbc7e85STakashi Iwai 	pcm = kzalloc(sizeof(*pcm), GFP_KERNEL);
720bbbc7e85STakashi Iwai 	if (!pcm)
721bbbc7e85STakashi Iwai 		return NULL;
722bbbc7e85STakashi Iwai 
723bbbc7e85STakashi Iwai 	pcm->codec = codec;
72430e5f003STakashi Iwai 	va_start(args, fmt);
725bbbc7e85STakashi Iwai 	pcm->name = kvasprintf(GFP_KERNEL, fmt, args);
72630e5f003STakashi Iwai 	va_end(args);
727bbbc7e85STakashi Iwai 	if (!pcm->name) {
728bbbc7e85STakashi Iwai 		kfree(pcm);
729bbbc7e85STakashi Iwai 		return NULL;
730bbbc7e85STakashi Iwai 	}
731bbbc7e85STakashi Iwai 
732bbbc7e85STakashi Iwai 	list_add_tail(&pcm->list, &codec->pcm_list_head);
7337206998fSTakashi Iwai 	refcount_inc(&codec->pcm_ref);
734bbbc7e85STakashi Iwai 	return pcm;
735bbbc7e85STakashi Iwai }
736bbbc7e85STakashi Iwai EXPORT_SYMBOL_GPL(snd_hda_codec_pcm_new);
737bbbc7e85STakashi Iwai 
7389a6246ffSTakashi Iwai /*
7399a6246ffSTakashi Iwai  * codec destructor
7409a6246ffSTakashi Iwai  */
snd_hda_codec_disconnect_pcms(struct hda_codec * codec)7417206998fSTakashi Iwai void snd_hda_codec_disconnect_pcms(struct hda_codec *codec)
7427206998fSTakashi Iwai {
7437206998fSTakashi Iwai 	struct hda_pcm *pcm;
7447206998fSTakashi Iwai 
7457206998fSTakashi Iwai 	list_for_each_entry(pcm, &codec->pcm_list_head, list) {
7467206998fSTakashi Iwai 		if (pcm->disconnected)
7477206998fSTakashi Iwai 			continue;
7487206998fSTakashi Iwai 		if (pcm->pcm)
7497206998fSTakashi Iwai 			snd_device_disconnect(codec->card, pcm->pcm);
7507206998fSTakashi Iwai 		snd_hda_codec_pcm_put(pcm);
7517206998fSTakashi Iwai 		pcm->disconnected = 1;
7527206998fSTakashi Iwai 	}
7537206998fSTakashi Iwai }
7547206998fSTakashi Iwai 
codec_release_pcms(struct hda_codec * codec)755bbbc7e85STakashi Iwai static void codec_release_pcms(struct hda_codec *codec)
756bbbc7e85STakashi Iwai {
757bbbc7e85STakashi Iwai 	struct hda_pcm *pcm, *n;
758bbbc7e85STakashi Iwai 
759bbbc7e85STakashi Iwai 	list_for_each_entry_safe(pcm, n, &codec->pcm_list_head, list) {
7607206998fSTakashi Iwai 		list_del(&pcm->list);
7619a6246ffSTakashi Iwai 		if (pcm->pcm)
7627206998fSTakashi Iwai 			snd_device_free(pcm->codec->card, pcm->pcm);
7637206998fSTakashi Iwai 		clear_bit(pcm->device, pcm->codec->bus->pcm_dev_bits);
7647206998fSTakashi Iwai 		kfree(pcm->name);
7657206998fSTakashi Iwai 		kfree(pcm);
766bbbc7e85STakashi Iwai 	}
767bbbc7e85STakashi Iwai }
768bbbc7e85STakashi Iwai 
769bb682f7aSCezary Rojewski /**
770bb682f7aSCezary Rojewski  * snd_hda_codec_cleanup_for_unbind - Prepare codec for removal
771bb682f7aSCezary Rojewski  * @codec: codec device to cleanup
772bb682f7aSCezary Rojewski  */
snd_hda_codec_cleanup_for_unbind(struct hda_codec * codec)7739a6246ffSTakashi Iwai void snd_hda_codec_cleanup_for_unbind(struct hda_codec *codec)
7749a6246ffSTakashi Iwai {
775e7255c00SCezary Rojewski 	if (codec->core.registered) {
776c4c2533fSTakashi Iwai 		/* pm_runtime_put() is called in snd_hdac_device_exit() */
777c4c2533fSTakashi Iwai 		pm_runtime_get_noresume(hda_codec_dev(codec));
778c4c2533fSTakashi Iwai 		pm_runtime_disable(hda_codec_dev(codec));
779e7255c00SCezary Rojewski 		codec->core.registered = 0;
780c4c2533fSTakashi Iwai 	}
781c4c2533fSTakashi Iwai 
7827206998fSTakashi Iwai 	snd_hda_codec_disconnect_pcms(codec);
7839a6246ffSTakashi Iwai 	cancel_delayed_work_sync(&codec->jackpoll_work);
7849a6246ffSTakashi Iwai 	if (!codec->in_freeing)
7859a6246ffSTakashi Iwai 		snd_hda_ctls_clear(codec);
7869a6246ffSTakashi Iwai 	codec_release_pcms(codec);
7879a6246ffSTakashi Iwai 	snd_hda_detach_beep_device(codec);
7889a6246ffSTakashi Iwai 	memset(&codec->patch_ops, 0, sizeof(codec->patch_ops));
7899a6246ffSTakashi Iwai 	snd_hda_jack_tbl_clear(codec);
7909a6246ffSTakashi Iwai 	codec->proc_widget_hook = NULL;
7919a6246ffSTakashi Iwai 	codec->spec = NULL;
7929a6246ffSTakashi Iwai 
7939a6246ffSTakashi Iwai 	/* free only driver_pins so that init_pins + user_pins are restored */
7949a6246ffSTakashi Iwai 	snd_array_free(&codec->driver_pins);
7959a6246ffSTakashi Iwai 	snd_array_free(&codec->cvt_setups);
7969a6246ffSTakashi Iwai 	snd_array_free(&codec->spdif_out);
7979a6246ffSTakashi Iwai 	snd_array_free(&codec->verbs);
7989ab0cb30STakashi Iwai 	codec->follower_dig_outs = NULL;
7999a6246ffSTakashi Iwai 	codec->spdif_status_reset = 0;
8009a6246ffSTakashi Iwai 	snd_array_free(&codec->mixers);
8019a6246ffSTakashi Iwai 	snd_array_free(&codec->nids);
8029a6246ffSTakashi Iwai 	remove_conn_list(codec);
8034d75faa0STakashi Iwai 	snd_hdac_regmap_exit(&codec->core);
804c0f1886dSTakashi Iwai 	codec->configured = 0;
8057206998fSTakashi Iwai 	refcount_set(&codec->pcm_ref, 1); /* reset refcount */
8069a6246ffSTakashi Iwai }
807cc1d0cd8SKai Vehmanen EXPORT_SYMBOL_GPL(snd_hda_codec_cleanup_for_unbind);
8089a6246ffSTakashi Iwai 
809d819387eSTakashi Iwai static unsigned int hda_set_power_state(struct hda_codec *codec,
810bb6ac72fSTakashi Iwai 				unsigned int power_state);
811bb6ac72fSTakashi Iwai 
812029d92c2STakashi Iwai /* enable/disable display power per codec */
snd_hda_codec_display_power(struct hda_codec * codec,bool enable)8133099406eSImre Deak void snd_hda_codec_display_power(struct hda_codec *codec, bool enable)
814029d92c2STakashi Iwai {
815029d92c2STakashi Iwai 	if (codec->display_power_control)
816029d92c2STakashi Iwai 		snd_hdac_display_power(&codec->bus->core, codec->addr, enable);
817029d92c2STakashi Iwai }
818029d92c2STakashi Iwai 
81917e0c4cbSCezary Rojewski /**
82017e0c4cbSCezary Rojewski  * snd_hda_codec_register - Finalize codec initialization
82117e0c4cbSCezary Rojewski  * @codec: codec device to register
82217e0c4cbSCezary Rojewski  *
82317e0c4cbSCezary Rojewski  * Also called from hda_bind.c
82417e0c4cbSCezary Rojewski  */
snd_hda_codec_register(struct hda_codec * codec)825c4c2533fSTakashi Iwai void snd_hda_codec_register(struct hda_codec *codec)
82613aeaf68STakashi Iwai {
827e7255c00SCezary Rojewski 	if (codec->core.registered)
828c4c2533fSTakashi Iwai 		return;
829c4c2533fSTakashi Iwai 	if (device_is_registered(hda_codec_dev(codec))) {
8303099406eSImre Deak 		snd_hda_codec_display_power(codec, true);
831cc72da7dSTakashi Iwai 		pm_runtime_enable(hda_codec_dev(codec));
832709949fbSTakashi Iwai 		/* it was powered up in snd_hda_codec_new(), now all done */
833709949fbSTakashi Iwai 		snd_hda_power_down(codec);
834e7255c00SCezary Rojewski 		codec->core.registered = 1;
835c4c2533fSTakashi Iwai 	}
836c4c2533fSTakashi Iwai }
83717e0c4cbSCezary Rojewski EXPORT_SYMBOL_GPL(snd_hda_codec_register);
838c4c2533fSTakashi Iwai 
snd_hda_codec_dev_register(struct snd_device * device)839c4c2533fSTakashi Iwai static int snd_hda_codec_dev_register(struct snd_device *device)
840c4c2533fSTakashi Iwai {
841c4c2533fSTakashi Iwai 	snd_hda_codec_register(device->device_data);
842d604b399STakashi Iwai 	return 0;
84313aeaf68STakashi Iwai }
84413aeaf68STakashi Iwai 
84517e0c4cbSCezary Rojewski /**
84617e0c4cbSCezary Rojewski  * snd_hda_codec_unregister - Unregister specified codec device
84717e0c4cbSCezary Rojewski  * @codec: codec device to unregister
84817e0c4cbSCezary Rojewski  */
snd_hda_codec_unregister(struct hda_codec * codec)84917e0c4cbSCezary Rojewski void snd_hda_codec_unregister(struct hda_codec *codec)
8502565c899STakashi Iwai {
851d56db741STakashi Iwai 	codec->in_freeing = 1;
8524d95c517SBard liao 	/*
8534d95c517SBard liao 	 * snd_hda_codec_device_new() is used by legacy HDA and ASoC driver.
8544d95c517SBard liao 	 * We can't unregister ASoC device since it will be unregistered in
8554d95c517SBard liao 	 * snd_hdac_ext_bus_device_remove().
8564d95c517SBard liao 	 */
8574d95c517SBard liao 	if (codec->core.type == HDA_DEV_LEGACY)
8583256be65STakashi Iwai 		snd_hdac_device_unregister(&codec->core);
8593099406eSImre Deak 	snd_hda_codec_display_power(codec, false);
860d6947bb2SRanjani Sridharan 
861d6947bb2SRanjani Sridharan 	/*
862d6947bb2SRanjani Sridharan 	 * In the case of ASoC HD-audio bus, the device refcount is released in
863d6947bb2SRanjani Sridharan 	 * snd_hdac_ext_bus_device_remove() explicitly.
864d6947bb2SRanjani Sridharan 	 */
865d6947bb2SRanjani Sridharan 	if (codec->core.type == HDA_DEV_LEGACY)
866d56db741STakashi Iwai 		put_device(hda_codec_dev(codec));
86717e0c4cbSCezary Rojewski }
86817e0c4cbSCezary Rojewski EXPORT_SYMBOL_GPL(snd_hda_codec_unregister);
869d6947bb2SRanjani Sridharan 
snd_hda_codec_dev_free(struct snd_device * device)87017e0c4cbSCezary Rojewski static int snd_hda_codec_dev_free(struct snd_device *device)
87117e0c4cbSCezary Rojewski {
87217e0c4cbSCezary Rojewski 	snd_hda_codec_unregister(device->device_data);
8732565c899STakashi Iwai 	return 0;
8742565c899STakashi Iwai }
8752565c899STakashi Iwai 
snd_hda_codec_dev_release(struct device * dev)87613aeaf68STakashi Iwai static void snd_hda_codec_dev_release(struct device *dev)
87713aeaf68STakashi Iwai {
878d56db741STakashi Iwai 	struct hda_codec *codec = dev_to_hda_codec(dev);
879d56db741STakashi Iwai 
880d56db741STakashi Iwai 	free_init_pincfgs(codec);
8817639a06cSTakashi Iwai 	snd_hdac_device_exit(&codec->core);
882d56db741STakashi Iwai 	snd_hda_sysfs_clear(codec);
883d56db741STakashi Iwai 	kfree(codec->modelname);
884d56db741STakashi Iwai 	kfree(codec->wcaps);
885d56db741STakashi Iwai 	kfree(codec);
88613aeaf68STakashi Iwai }
88713aeaf68STakashi Iwai 
88824494d3fSRakesh Ughreja #define DEV_NAME_LEN 31
88924494d3fSRakesh Ughreja 
890595511a3SCezary Rojewski /**
891595511a3SCezary Rojewski  * snd_hda_codec_device_init - allocate HDA codec device
892595511a3SCezary Rojewski  * @bus: codec's parent bus
893595511a3SCezary Rojewski  * @codec_addr: the codec address on the parent bus
894595511a3SCezary Rojewski  * @fmt: format string for the device's name
895595511a3SCezary Rojewski  *
896595511a3SCezary Rojewski  * Returns newly allocated codec device or ERR_PTR() on failure.
897595511a3SCezary Rojewski  */
898595511a3SCezary Rojewski struct hda_codec *
snd_hda_codec_device_init(struct hda_bus * bus,unsigned int codec_addr,const char * fmt,...)899595511a3SCezary Rojewski snd_hda_codec_device_init(struct hda_bus *bus, unsigned int codec_addr,
900595511a3SCezary Rojewski 			  const char *fmt, ...)
90124494d3fSRakesh Ughreja {
902595511a3SCezary Rojewski 	va_list vargs;
90324494d3fSRakesh Ughreja 	char name[DEV_NAME_LEN];
90424494d3fSRakesh Ughreja 	struct hda_codec *codec;
90524494d3fSRakesh Ughreja 	int err;
90624494d3fSRakesh Ughreja 
90724494d3fSRakesh Ughreja 	if (snd_BUG_ON(!bus))
908595511a3SCezary Rojewski 		return ERR_PTR(-EINVAL);
90924494d3fSRakesh Ughreja 	if (snd_BUG_ON(codec_addr > HDA_MAX_CODEC_ADDRESS))
910595511a3SCezary Rojewski 		return ERR_PTR(-EINVAL);
91124494d3fSRakesh Ughreja 
91224494d3fSRakesh Ughreja 	codec = kzalloc(sizeof(*codec), GFP_KERNEL);
91324494d3fSRakesh Ughreja 	if (!codec)
914595511a3SCezary Rojewski 		return ERR_PTR(-ENOMEM);
91524494d3fSRakesh Ughreja 
916595511a3SCezary Rojewski 	va_start(vargs, fmt);
917595511a3SCezary Rojewski 	vsprintf(name, fmt, vargs);
918595511a3SCezary Rojewski 	va_end(vargs);
919595511a3SCezary Rojewski 
92024494d3fSRakesh Ughreja 	err = snd_hdac_device_init(&codec->core, &bus->core, name, codec_addr);
92124494d3fSRakesh Ughreja 	if (err < 0) {
92224494d3fSRakesh Ughreja 		kfree(codec);
923595511a3SCezary Rojewski 		return ERR_PTR(err);
92424494d3fSRakesh Ughreja 	}
92524494d3fSRakesh Ughreja 
926595511a3SCezary Rojewski 	codec->bus = bus;
927f2bd1c5aSCezary Rojewski 	codec->depop_delay = -1;
928f2bd1c5aSCezary Rojewski 	codec->fixup_id = HDA_FIXUP_ID_NOT_SET;
929f2bd1c5aSCezary Rojewski 	codec->core.dev.release = snd_hda_codec_dev_release;
93024494d3fSRakesh Ughreja 	codec->core.type = HDA_DEV_LEGACY;
93124494d3fSRakesh Ughreja 
932f2bd1c5aSCezary Rojewski 	mutex_init(&codec->spdif_mutex);
933f2bd1c5aSCezary Rojewski 	mutex_init(&codec->control_mutex);
934f2bd1c5aSCezary Rojewski 	snd_array_init(&codec->mixers, sizeof(struct hda_nid_item), 32);
935f2bd1c5aSCezary Rojewski 	snd_array_init(&codec->nids, sizeof(struct hda_nid_item), 32);
936f2bd1c5aSCezary Rojewski 	snd_array_init(&codec->init_pins, sizeof(struct hda_pincfg), 16);
937f2bd1c5aSCezary Rojewski 	snd_array_init(&codec->driver_pins, sizeof(struct hda_pincfg), 16);
938f2bd1c5aSCezary Rojewski 	snd_array_init(&codec->cvt_setups, sizeof(struct hda_cvt_setup), 8);
939f2bd1c5aSCezary Rojewski 	snd_array_init(&codec->spdif_out, sizeof(struct hda_spdif_out), 16);
940f2bd1c5aSCezary Rojewski 	snd_array_init(&codec->jacktbl, sizeof(struct hda_jack_tbl), 16);
941f2bd1c5aSCezary Rojewski 	snd_array_init(&codec->verbs, sizeof(struct hda_verb *), 8);
942f2bd1c5aSCezary Rojewski 	INIT_LIST_HEAD(&codec->conn_list);
943f2bd1c5aSCezary Rojewski 	INIT_LIST_HEAD(&codec->pcm_list_head);
944f2bd1c5aSCezary Rojewski 	INIT_DELAYED_WORK(&codec->jackpoll_work, hda_jackpoll_work);
945f2bd1c5aSCezary Rojewski 	refcount_set(&codec->pcm_ref, 1);
946f2bd1c5aSCezary Rojewski 	init_waitqueue_head(&codec->remove_sleep);
947f2bd1c5aSCezary Rojewski 
948595511a3SCezary Rojewski 	return codec;
94924494d3fSRakesh Ughreja }
950595511a3SCezary Rojewski EXPORT_SYMBOL_GPL(snd_hda_codec_device_init);
95124494d3fSRakesh Ughreja 
9521da177e4SLinus Torvalds /**
9531da177e4SLinus Torvalds  * snd_hda_codec_new - create a HDA codec
9541da177e4SLinus Torvalds  * @bus: the bus to assign
9554f5c2653SPierre-Louis Bossart  * @card: card for this codec
9561da177e4SLinus Torvalds  * @codec_addr: the codec address
9571da177e4SLinus Torvalds  * @codecp: the pointer to store the generated codec
9581da177e4SLinus Torvalds  *
9591da177e4SLinus Torvalds  * Returns 0 if successful, or a negative error code.
9601da177e4SLinus Torvalds  */
snd_hda_codec_new(struct hda_bus * bus,struct snd_card * card,unsigned int codec_addr,struct hda_codec ** codecp)9616efdd851STakashi Iwai int snd_hda_codec_new(struct hda_bus *bus, struct snd_card *card,
9626efdd851STakashi Iwai 		      unsigned int codec_addr, struct hda_codec **codecp)
9631da177e4SLinus Torvalds {
964595511a3SCezary Rojewski 	struct hda_codec *codec;
965ebe043a3SCezary Rojewski 	int ret;
96624494d3fSRakesh Ughreja 
967595511a3SCezary Rojewski 	codec = snd_hda_codec_device_init(bus, codec_addr, "hdaudioC%dD%d",
968595511a3SCezary Rojewski 					  card->number, codec_addr);
969595511a3SCezary Rojewski 	if (IS_ERR(codec))
970595511a3SCezary Rojewski 		return PTR_ERR(codec);
971595511a3SCezary Rojewski 	*codecp = codec;
97224494d3fSRakesh Ughreja 
973ebe043a3SCezary Rojewski 	ret = snd_hda_codec_device_new(bus, card, codec_addr, *codecp, true);
974ebe043a3SCezary Rojewski 	if (ret)
975ebe043a3SCezary Rojewski 		put_device(hda_codec_dev(*codecp));
976ebe043a3SCezary Rojewski 
977ebe043a3SCezary Rojewski 	return ret;
97824494d3fSRakesh Ughreja }
97924494d3fSRakesh Ughreja EXPORT_SYMBOL_GPL(snd_hda_codec_new);
98024494d3fSRakesh Ughreja 
snd_hda_codec_device_new(struct hda_bus * bus,struct snd_card * card,unsigned int codec_addr,struct hda_codec * codec,bool snddev_managed)98124494d3fSRakesh Ughreja int snd_hda_codec_device_new(struct hda_bus *bus, struct snd_card *card,
98217e0c4cbSCezary Rojewski 			unsigned int codec_addr, struct hda_codec *codec,
98317e0c4cbSCezary Rojewski 			bool snddev_managed)
98424494d3fSRakesh Ughreja {
985ba443687SJaroslav Kysela 	char component[31];
986d819387eSTakashi Iwai 	hda_nid_t fg;
9871da177e4SLinus Torvalds 	int err;
98841f394a8STakashi Iwai 	static const struct snd_device_ops dev_ops = {
98913aeaf68STakashi Iwai 		.dev_register = snd_hda_codec_dev_register,
9902565c899STakashi Iwai 		.dev_free = snd_hda_codec_dev_free,
9912565c899STakashi Iwai 	};
9921da177e4SLinus Torvalds 
99324494d3fSRakesh Ughreja 	dev_dbg(card->dev, "%s: entry\n", __func__);
99424494d3fSRakesh Ughreja 
995da3cec35STakashi Iwai 	if (snd_BUG_ON(!bus))
996da3cec35STakashi Iwai 		return -EINVAL;
997da3cec35STakashi Iwai 	if (snd_BUG_ON(codec_addr > HDA_MAX_CODEC_ADDRESS))
998da3cec35STakashi Iwai 		return -EINVAL;
9991da177e4SLinus Torvalds 
10003af4a4f7SCezary Rojewski 	codec->core.exec_verb = codec_exec_verb;
10016efdd851STakashi Iwai 	codec->card = card;
10021da177e4SLinus Torvalds 	codec->addr = codec_addr;
10031da177e4SLinus Torvalds 
100483012a7cSTakashi Iwai #ifdef CONFIG_PM
1005cc72da7dSTakashi Iwai 	codec->power_jiffies = jiffies;
1006cb53c626STakashi Iwai #endif
1007cb53c626STakashi Iwai 
1008648a8d27STakashi Iwai 	snd_hda_sysfs_init(codec);
1009648a8d27STakashi Iwai 
1010c382a9f0STakashi Iwai 	if (codec->bus->modelname) {
1011c382a9f0STakashi Iwai 		codec->modelname = kstrdup(codec->bus->modelname, GFP_KERNEL);
1012ebe043a3SCezary Rojewski 		if (!codec->modelname)
1013ebe043a3SCezary Rojewski 			return -ENOMEM;
1014c382a9f0STakashi Iwai 	}
1015c382a9f0STakashi Iwai 
10167639a06cSTakashi Iwai 	fg = codec->core.afg ? codec->core.afg : codec->core.mfg;
1017d819387eSTakashi Iwai 	err = read_widget_caps(codec, fg);
1018f4de8fe6STakashi Iwai 	if (err < 0)
1019ebe043a3SCezary Rojewski 		return err;
10203be14149STakashi Iwai 	err = read_pin_defaults(codec);
10213be14149STakashi Iwai 	if (err < 0)
1022ebe043a3SCezary Rojewski 		return err;
102354d17403STakashi Iwai 
1024bb6ac72fSTakashi Iwai 	/* power-up all before initialization */
1025d819387eSTakashi Iwai 	hda_set_power_state(codec, AC_PWRST_D0);
1026183ab39eSTakashi Iwai 	codec->core.dev.power.power_state = PMSG_ON;
1027bb6ac72fSTakashi Iwai 
10286c1f45eaSTakashi Iwai 	snd_hda_codec_proc_new(codec);
10296c1f45eaSTakashi Iwai 
10306c1f45eaSTakashi Iwai 	snd_hda_create_hwdep(codec);
10316c1f45eaSTakashi Iwai 
10327639a06cSTakashi Iwai 	sprintf(component, "HDA:%08x,%08x,%08x", codec->core.vendor_id,
10337639a06cSTakashi Iwai 		codec->core.subsystem_id, codec->core.revision_id);
10346efdd851STakashi Iwai 	snd_component_add(card, component);
10356c1f45eaSTakashi Iwai 
103617e0c4cbSCezary Rojewski 	if (snddev_managed) {
103717e0c4cbSCezary Rojewski 		/* ASoC features component management instead */
10386efdd851STakashi Iwai 		err = snd_device_new(card, SNDRV_DEV_CODEC, codec, &dev_ops);
10392565c899STakashi Iwai 		if (err < 0)
1040ebe043a3SCezary Rojewski 			return err;
104117e0c4cbSCezary Rojewski 	}
10422565c899STakashi Iwai 
10439c76958bSCezary Rojewski #ifdef CONFIG_PM
1044a0645dafSHarsha Priya 	/* PM runtime needs to be enabled later after binding codec */
10459c76958bSCezary Rojewski 	if (codec->core.dev.power.runtime_auto)
1046a0645dafSHarsha Priya 		pm_runtime_forbid(&codec->core.dev);
10479c76958bSCezary Rojewski 	else
10489c76958bSCezary Rojewski 		/* Keep the usage_count consistent across subsequent probing */
10499c76958bSCezary Rojewski 		pm_runtime_get_noresume(&codec->core.dev);
10509c76958bSCezary Rojewski #endif
1051a0645dafSHarsha Priya 
10526c1f45eaSTakashi Iwai 	return 0;
10536c1f45eaSTakashi Iwai }
105424494d3fSRakesh Ughreja EXPORT_SYMBOL_GPL(snd_hda_codec_device_new);
10556c1f45eaSTakashi Iwai 
105695a962c3STakashi Iwai /**
105795a962c3STakashi Iwai  * snd_hda_codec_update_widgets - Refresh widget caps and pin defaults
105895a962c3STakashi Iwai  * @codec: the HDA codec
105995a962c3STakashi Iwai  *
106095a962c3STakashi Iwai  * Forcibly refresh the all widget caps and the init pin configurations of
106195a962c3STakashi Iwai  * the given codec.
106295a962c3STakashi Iwai  */
snd_hda_codec_update_widgets(struct hda_codec * codec)1063a15d05dbSMengdong Lin int snd_hda_codec_update_widgets(struct hda_codec *codec)
1064a15d05dbSMengdong Lin {
1065a15d05dbSMengdong Lin 	hda_nid_t fg;
1066a15d05dbSMengdong Lin 	int err;
1067a15d05dbSMengdong Lin 
1068774a075aSTakashi Iwai 	err = snd_hdac_refresh_widgets(&codec->core);
10697639a06cSTakashi Iwai 	if (err < 0)
10707639a06cSTakashi Iwai 		return err;
10717639a06cSTakashi Iwai 
1072a15d05dbSMengdong Lin 	/* Assume the function group node does not change,
1073a15d05dbSMengdong Lin 	 * only the widget nodes may change.
1074a15d05dbSMengdong Lin 	 */
1075a15d05dbSMengdong Lin 	kfree(codec->wcaps);
10767639a06cSTakashi Iwai 	fg = codec->core.afg ? codec->core.afg : codec->core.mfg;
1077a15d05dbSMengdong Lin 	err = read_widget_caps(codec, fg);
1078f4de8fe6STakashi Iwai 	if (err < 0)
1079a15d05dbSMengdong Lin 		return err;
1080a15d05dbSMengdong Lin 
1081a15d05dbSMengdong Lin 	snd_array_free(&codec->init_pins);
1082a15d05dbSMengdong Lin 	err = read_pin_defaults(codec);
1083a15d05dbSMengdong Lin 
1084a15d05dbSMengdong Lin 	return err;
1085a15d05dbSMengdong Lin }
10862698ea98STakashi Iwai EXPORT_SYMBOL_GPL(snd_hda_codec_update_widgets);
1087a15d05dbSMengdong Lin 
1088ed360813STakashi Iwai /* update the stream-id if changed */
update_pcm_stream_id(struct hda_codec * codec,struct hda_cvt_setup * p,hda_nid_t nid,u32 stream_tag,int channel_id)1089ed360813STakashi Iwai static void update_pcm_stream_id(struct hda_codec *codec,
1090ed360813STakashi Iwai 				 struct hda_cvt_setup *p, hda_nid_t nid,
1091ed360813STakashi Iwai 				 u32 stream_tag, int channel_id)
1092ed360813STakashi Iwai {
1093ed360813STakashi Iwai 	unsigned int oldval, newval;
1094ed360813STakashi Iwai 
1095ed360813STakashi Iwai 	if (p->stream_tag != stream_tag || p->channel_id != channel_id) {
1096ed360813STakashi Iwai 		oldval = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONV, 0);
1097ed360813STakashi Iwai 		newval = (stream_tag << 4) | channel_id;
1098ed360813STakashi Iwai 		if (oldval != newval)
1099ed360813STakashi Iwai 			snd_hda_codec_write(codec, nid, 0,
1100ed360813STakashi Iwai 					    AC_VERB_SET_CHANNEL_STREAMID,
1101ed360813STakashi Iwai 					    newval);
1102ed360813STakashi Iwai 		p->stream_tag = stream_tag;
1103ed360813STakashi Iwai 		p->channel_id = channel_id;
1104ed360813STakashi Iwai 	}
1105ed360813STakashi Iwai }
1106ed360813STakashi Iwai 
1107ed360813STakashi Iwai /* update the format-id if changed */
update_pcm_format(struct hda_codec * codec,struct hda_cvt_setup * p,hda_nid_t nid,int format)1108ed360813STakashi Iwai static void update_pcm_format(struct hda_codec *codec, struct hda_cvt_setup *p,
1109ed360813STakashi Iwai 			      hda_nid_t nid, int format)
1110ed360813STakashi Iwai {
1111ed360813STakashi Iwai 	unsigned int oldval;
1112ed360813STakashi Iwai 
1113ed360813STakashi Iwai 	if (p->format_id != format) {
1114ed360813STakashi Iwai 		oldval = snd_hda_codec_read(codec, nid, 0,
1115ed360813STakashi Iwai 					    AC_VERB_GET_STREAM_FORMAT, 0);
1116ed360813STakashi Iwai 		if (oldval != format) {
1117ed360813STakashi Iwai 			msleep(1);
1118ed360813STakashi Iwai 			snd_hda_codec_write(codec, nid, 0,
1119ed360813STakashi Iwai 					    AC_VERB_SET_STREAM_FORMAT,
1120ed360813STakashi Iwai 					    format);
1121ed360813STakashi Iwai 		}
1122ed360813STakashi Iwai 		p->format_id = format;
1123ed360813STakashi Iwai 	}
1124ed360813STakashi Iwai }
1125ed360813STakashi Iwai 
11261da177e4SLinus Torvalds /**
11271da177e4SLinus Torvalds  * snd_hda_codec_setup_stream - set up the codec for streaming
11281da177e4SLinus Torvalds  * @codec: the CODEC to set up
11291da177e4SLinus Torvalds  * @nid: the NID to set up
11301da177e4SLinus Torvalds  * @stream_tag: stream tag to pass, it's between 0x1 and 0xf.
11311da177e4SLinus Torvalds  * @channel_id: channel id to pass, zero based.
11321da177e4SLinus Torvalds  * @format: stream format.
11331da177e4SLinus Torvalds  */
snd_hda_codec_setup_stream(struct hda_codec * codec,hda_nid_t nid,u32 stream_tag,int channel_id,int format)11340ba21762STakashi Iwai void snd_hda_codec_setup_stream(struct hda_codec *codec, hda_nid_t nid,
11350ba21762STakashi Iwai 				u32 stream_tag,
11361da177e4SLinus Torvalds 				int channel_id, int format)
11371da177e4SLinus Torvalds {
11383f50ac6aSTakashi Iwai 	struct hda_codec *c;
1139eb541337STakashi Iwai 	struct hda_cvt_setup *p;
114062b7e5e0STakashi Iwai 	int type;
1141eb541337STakashi Iwai 	int i;
1142eb541337STakashi Iwai 
1143d21b37eaSTakashi Iwai 	if (!nid)
1144d21b37eaSTakashi Iwai 		return;
1145d21b37eaSTakashi Iwai 
11464e76a883STakashi Iwai 	codec_dbg(codec,
11474e76a883STakashi Iwai 		  "hda_codec_setup_stream: NID=0x%x, stream=0x%x, channel=%d, format=0x%x\n",
11481da177e4SLinus Torvalds 		  nid, stream_tag, channel_id, format);
1149eb541337STakashi Iwai 	p = get_hda_cvt_setup(codec, nid);
11506c35ae3cSTakashi Iwai 	if (!p)
1151eb541337STakashi Iwai 		return;
1152ed360813STakashi Iwai 
1153e6feb5d0STakashi Iwai 	if (codec->patch_ops.stream_pm)
1154e6feb5d0STakashi Iwai 		codec->patch_ops.stream_pm(codec, nid, true);
1155ed360813STakashi Iwai 	if (codec->pcm_format_first)
1156ed360813STakashi Iwai 		update_pcm_format(codec, p, nid, format);
1157ed360813STakashi Iwai 	update_pcm_stream_id(codec, p, nid, stream_tag, channel_id);
1158ed360813STakashi Iwai 	if (!codec->pcm_format_first)
1159ed360813STakashi Iwai 		update_pcm_format(codec, p, nid, format);
1160ed360813STakashi Iwai 
1161eb541337STakashi Iwai 	p->active = 1;
1162eb541337STakashi Iwai 	p->dirty = 0;
1163eb541337STakashi Iwai 
1164eb541337STakashi Iwai 	/* make other inactive cvts with the same stream-tag dirty */
116562b7e5e0STakashi Iwai 	type = get_wcaps_type(get_wcaps(codec, nid));
1166d068ebc2STakashi Iwai 	list_for_each_codec(c, codec->bus) {
1167a9c2dfc8STakashi Iwai 		snd_array_for_each(&c->cvt_setups, i, p) {
116862b7e5e0STakashi Iwai 			if (!p->active && p->stream_tag == stream_tag &&
116954c2a89fSDavid Henningsson 			    get_wcaps_type(get_wcaps(c, p->nid)) == type)
1170eb541337STakashi Iwai 				p->dirty = 1;
1171eb541337STakashi Iwai 		}
11721da177e4SLinus Torvalds 	}
11733f50ac6aSTakashi Iwai }
11742698ea98STakashi Iwai EXPORT_SYMBOL_GPL(snd_hda_codec_setup_stream);
11751da177e4SLinus Torvalds 
1176f0cea797STakashi Iwai static void really_cleanup_stream(struct hda_codec *codec,
1177f0cea797STakashi Iwai 				  struct hda_cvt_setup *q);
1178f0cea797STakashi Iwai 
1179d5191e50STakashi Iwai /**
1180f0cea797STakashi Iwai  * __snd_hda_codec_cleanup_stream - clean up the codec for closing
1181d5191e50STakashi Iwai  * @codec: the CODEC to clean up
1182d5191e50STakashi Iwai  * @nid: the NID to clean up
1183f0cea797STakashi Iwai  * @do_now: really clean up the stream instead of clearing the active flag
1184d5191e50STakashi Iwai  */
__snd_hda_codec_cleanup_stream(struct hda_codec * codec,hda_nid_t nid,int do_now)1185f0cea797STakashi Iwai void __snd_hda_codec_cleanup_stream(struct hda_codec *codec, hda_nid_t nid,
1186f0cea797STakashi Iwai 				    int do_now)
1187888afa15STakashi Iwai {
1188eb541337STakashi Iwai 	struct hda_cvt_setup *p;
1189eb541337STakashi Iwai 
1190888afa15STakashi Iwai 	if (!nid)
1191888afa15STakashi Iwai 		return;
1192888afa15STakashi Iwai 
11930e7adbe2STakashi Iwai 	if (codec->no_sticky_stream)
11940e7adbe2STakashi Iwai 		do_now = 1;
11950e7adbe2STakashi Iwai 
11964e76a883STakashi Iwai 	codec_dbg(codec, "hda_codec_cleanup_stream: NID=0x%x\n", nid);
1197eb541337STakashi Iwai 	p = get_hda_cvt_setup(codec, nid);
11986c35ae3cSTakashi Iwai 	if (p) {
1199f0cea797STakashi Iwai 		/* here we just clear the active flag when do_now isn't set;
1200f0cea797STakashi Iwai 		 * actual clean-ups will be done later in
1201f0cea797STakashi Iwai 		 * purify_inactive_streams() called from snd_hda_codec_prpapre()
1202f0cea797STakashi Iwai 		 */
1203f0cea797STakashi Iwai 		if (do_now)
1204f0cea797STakashi Iwai 			really_cleanup_stream(codec, p);
1205f0cea797STakashi Iwai 		else
1206eb541337STakashi Iwai 			p->active = 0;
1207888afa15STakashi Iwai 	}
1208f0cea797STakashi Iwai }
12092698ea98STakashi Iwai EXPORT_SYMBOL_GPL(__snd_hda_codec_cleanup_stream);
1210888afa15STakashi Iwai 
really_cleanup_stream(struct hda_codec * codec,struct hda_cvt_setup * q)1211eb541337STakashi Iwai static void really_cleanup_stream(struct hda_codec *codec,
1212eb541337STakashi Iwai 				  struct hda_cvt_setup *q)
1213eb541337STakashi Iwai {
1214eb541337STakashi Iwai 	hda_nid_t nid = q->nid;
1215218264aeSTakashi Iwai 	if (q->stream_tag || q->channel_id)
1216eb541337STakashi Iwai 		snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CHANNEL_STREAMID, 0);
1217218264aeSTakashi Iwai 	if (q->format_id)
1218218264aeSTakashi Iwai 		snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_STREAM_FORMAT, 0
1219218264aeSTakashi Iwai );
1220eb541337STakashi Iwai 	memset(q, 0, sizeof(*q));
1221eb541337STakashi Iwai 	q->nid = nid;
1222e6feb5d0STakashi Iwai 	if (codec->patch_ops.stream_pm)
1223e6feb5d0STakashi Iwai 		codec->patch_ops.stream_pm(codec, nid, false);
1224eb541337STakashi Iwai }
1225eb541337STakashi Iwai 
1226eb541337STakashi Iwai /* clean up the all conflicting obsolete streams */
purify_inactive_streams(struct hda_codec * codec)1227eb541337STakashi Iwai static void purify_inactive_streams(struct hda_codec *codec)
1228eb541337STakashi Iwai {
12293f50ac6aSTakashi Iwai 	struct hda_codec *c;
1230a9c2dfc8STakashi Iwai 	struct hda_cvt_setup *p;
1231eb541337STakashi Iwai 	int i;
1232eb541337STakashi Iwai 
1233d068ebc2STakashi Iwai 	list_for_each_codec(c, codec->bus) {
1234a9c2dfc8STakashi Iwai 		snd_array_for_each(&c->cvt_setups, i, p) {
1235eb541337STakashi Iwai 			if (p->dirty)
12363f50ac6aSTakashi Iwai 				really_cleanup_stream(c, p);
12373f50ac6aSTakashi Iwai 		}
1238eb541337STakashi Iwai 	}
1239eb541337STakashi Iwai }
1240eb541337STakashi Iwai 
12412a43952aSTakashi Iwai #ifdef CONFIG_PM
1242eb541337STakashi Iwai /* clean up all streams; called from suspend */
hda_cleanup_all_streams(struct hda_codec * codec)1243eb541337STakashi Iwai static void hda_cleanup_all_streams(struct hda_codec *codec)
1244eb541337STakashi Iwai {
1245a9c2dfc8STakashi Iwai 	struct hda_cvt_setup *p;
1246eb541337STakashi Iwai 	int i;
1247eb541337STakashi Iwai 
1248a9c2dfc8STakashi Iwai 	snd_array_for_each(&codec->cvt_setups, i, p) {
1249eb541337STakashi Iwai 		if (p->stream_tag)
1250eb541337STakashi Iwai 			really_cleanup_stream(codec, p);
1251eb541337STakashi Iwai 	}
1252eb541337STakashi Iwai }
12531c7276cfSMike Waychison #endif
1254eb541337STakashi Iwai 
12551da177e4SLinus Torvalds /*
12561da177e4SLinus Torvalds  * amp access functions
12571da177e4SLinus Torvalds  */
12581da177e4SLinus Torvalds 
1259d5191e50STakashi Iwai /**
1260d5191e50STakashi Iwai  * query_amp_caps - query AMP capabilities
1261d5191e50STakashi Iwai  * @codec: the HD-auio codec
1262d5191e50STakashi Iwai  * @nid: the NID to query
1263d5191e50STakashi Iwai  * @direction: either #HDA_INPUT or #HDA_OUTPUT
1264d5191e50STakashi Iwai  *
1265d5191e50STakashi Iwai  * Query AMP capabilities for the given widget and direction.
1266d5191e50STakashi Iwai  * Returns the obtained capability bits.
1267d5191e50STakashi Iwai  *
1268d5191e50STakashi Iwai  * When cap bits have been already read, this doesn't read again but
1269d5191e50STakashi Iwai  * returns the cached value.
12701da177e4SLinus Torvalds  */
query_amp_caps(struct hda_codec * codec,hda_nid_t nid,int direction)127109a99959SMatthew Ranostay u32 query_amp_caps(struct hda_codec *codec, hda_nid_t nid, int direction)
12721da177e4SLinus Torvalds {
1273faa75f8aSTakashi Iwai 	if (!(get_wcaps(codec, nid) & AC_WCAP_AMP_OVRD))
1274faa75f8aSTakashi Iwai 		nid = codec->core.afg;
1275faa75f8aSTakashi Iwai 	return snd_hda_param_read(codec, nid,
1276faa75f8aSTakashi Iwai 				  direction == HDA_OUTPUT ?
1277faa75f8aSTakashi Iwai 				  AC_PAR_AMP_OUT_CAP : AC_PAR_AMP_IN_CAP);
12781da177e4SLinus Torvalds }
12792698ea98STakashi Iwai EXPORT_SYMBOL_GPL(query_amp_caps);
12801da177e4SLinus Torvalds 
1281d5191e50STakashi Iwai /**
1282861a04edSDavid Henningsson  * snd_hda_check_amp_caps - query AMP capabilities
1283861a04edSDavid Henningsson  * @codec: the HD-audio codec
1284861a04edSDavid Henningsson  * @nid: the NID to query
1285861a04edSDavid Henningsson  * @dir: either #HDA_INPUT or #HDA_OUTPUT
1286a11e9b16STakashi Iwai  * @bits: bit mask to check the result
1287861a04edSDavid Henningsson  *
1288861a04edSDavid Henningsson  * Check whether the widget has the given amp capability for the direction.
1289861a04edSDavid Henningsson  */
snd_hda_check_amp_caps(struct hda_codec * codec,hda_nid_t nid,int dir,unsigned int bits)1290861a04edSDavid Henningsson bool snd_hda_check_amp_caps(struct hda_codec *codec, hda_nid_t nid,
1291861a04edSDavid Henningsson 			   int dir, unsigned int bits)
1292861a04edSDavid Henningsson {
1293861a04edSDavid Henningsson 	if (!nid)
1294861a04edSDavid Henningsson 		return false;
1295861a04edSDavid Henningsson 	if (get_wcaps(codec, nid) & (1 << (dir + 1)))
1296861a04edSDavid Henningsson 		if (query_amp_caps(codec, nid, dir) & bits)
1297861a04edSDavid Henningsson 			return true;
1298861a04edSDavid Henningsson 	return false;
1299861a04edSDavid Henningsson }
1300861a04edSDavid Henningsson EXPORT_SYMBOL_GPL(snd_hda_check_amp_caps);
1301861a04edSDavid Henningsson 
1302861a04edSDavid Henningsson /**
1303d5191e50STakashi Iwai  * snd_hda_override_amp_caps - Override the AMP capabilities
1304d5191e50STakashi Iwai  * @codec: the CODEC to clean up
1305d5191e50STakashi Iwai  * @nid: the NID to clean up
1306a11e9b16STakashi Iwai  * @dir: either #HDA_INPUT or #HDA_OUTPUT
1307d5191e50STakashi Iwai  * @caps: the capability bits to set
1308d5191e50STakashi Iwai  *
1309d5191e50STakashi Iwai  * Override the cached AMP caps bits value by the given one.
1310d5191e50STakashi Iwai  * This function is useful if the driver needs to adjust the AMP ranges,
1311d5191e50STakashi Iwai  * e.g. limit to 0dB, etc.
1312d5191e50STakashi Iwai  *
1313d5191e50STakashi Iwai  * Returns zero if successful or a negative error code.
1314d5191e50STakashi Iwai  */
snd_hda_override_amp_caps(struct hda_codec * codec,hda_nid_t nid,int dir,unsigned int caps)1315897cc188STakashi Iwai int snd_hda_override_amp_caps(struct hda_codec *codec, hda_nid_t nid, int dir,
1316897cc188STakashi Iwai 			      unsigned int caps)
1317897cc188STakashi Iwai {
1318faa75f8aSTakashi Iwai 	unsigned int parm;
1319faa75f8aSTakashi Iwai 
1320faa75f8aSTakashi Iwai 	snd_hda_override_wcaps(codec, nid,
1321faa75f8aSTakashi Iwai 			       get_wcaps(codec, nid) | AC_WCAP_AMP_OVRD);
1322faa75f8aSTakashi Iwai 	parm = dir == HDA_OUTPUT ? AC_PAR_AMP_OUT_CAP : AC_PAR_AMP_IN_CAP;
1323faa75f8aSTakashi Iwai 	return snd_hdac_override_parm(&codec->core, nid, parm, caps);
1324897cc188STakashi Iwai }
13252698ea98STakashi Iwai EXPORT_SYMBOL_GPL(snd_hda_override_amp_caps);
1326897cc188STakashi Iwai 
encode_amp(struct hda_codec * codec,hda_nid_t nid,int ch,int dir,int idx)13271a462be5STakashi Iwai static unsigned int encode_amp(struct hda_codec *codec, hda_nid_t nid,
13281a462be5STakashi Iwai 			       int ch, int dir, int idx)
13291a462be5STakashi Iwai {
13301a462be5STakashi Iwai 	unsigned int cmd = snd_hdac_regmap_encode_amp(nid, ch, dir, idx);
13311a462be5STakashi Iwai 
13321a462be5STakashi Iwai 	/* enable fake mute if no h/w mute but min=mute */
13331a462be5STakashi Iwai 	if ((query_amp_caps(codec, nid, dir) &
13341a462be5STakashi Iwai 	     (AC_AMPCAP_MUTE | AC_AMPCAP_MIN_MUTE)) == AC_AMPCAP_MIN_MUTE)
13351a462be5STakashi Iwai 		cmd |= AC_AMP_FAKE_MUTE;
13361a462be5STakashi Iwai 	return cmd;
13371a462be5STakashi Iwai }
13381a462be5STakashi Iwai 
1339d5191e50STakashi Iwai /**
1340a686ec4cSTakashi Iwai  * snd_hda_codec_amp_update - update the AMP mono value
1341a686ec4cSTakashi Iwai  * @codec: HD-audio codec
1342a686ec4cSTakashi Iwai  * @nid: NID to read the AMP value
1343a686ec4cSTakashi Iwai  * @ch: channel to update (0 or 1)
1344a686ec4cSTakashi Iwai  * @dir: #HDA_INPUT or #HDA_OUTPUT
1345a686ec4cSTakashi Iwai  * @idx: the index value (only for input direction)
1346a686ec4cSTakashi Iwai  * @mask: bit mask to set
1347a686ec4cSTakashi Iwai  * @val: the bits value to set
1348a686ec4cSTakashi Iwai  *
1349a686ec4cSTakashi Iwai  * Update the AMP values for the given channel, direction and index.
1350a686ec4cSTakashi Iwai  */
snd_hda_codec_amp_update(struct hda_codec * codec,hda_nid_t nid,int ch,int dir,int idx,int mask,int val)1351a686ec4cSTakashi Iwai int snd_hda_codec_amp_update(struct hda_codec *codec, hda_nid_t nid,
1352a686ec4cSTakashi Iwai 			     int ch, int dir, int idx, int mask, int val)
1353a686ec4cSTakashi Iwai {
13541a462be5STakashi Iwai 	unsigned int cmd = encode_amp(codec, nid, ch, dir, idx);
1355a686ec4cSTakashi Iwai 
1356a686ec4cSTakashi Iwai 	return snd_hdac_regmap_update_raw(&codec->core, cmd, mask, val);
1357a686ec4cSTakashi Iwai }
1358a686ec4cSTakashi Iwai EXPORT_SYMBOL_GPL(snd_hda_codec_amp_update);
1359a686ec4cSTakashi Iwai 
1360a686ec4cSTakashi Iwai /**
1361d5191e50STakashi Iwai  * snd_hda_codec_amp_stereo - update the AMP stereo values
1362d5191e50STakashi Iwai  * @codec: HD-audio codec
1363d5191e50STakashi Iwai  * @nid: NID to read the AMP value
1364d5191e50STakashi Iwai  * @direction: #HDA_INPUT or #HDA_OUTPUT
1365d5191e50STakashi Iwai  * @idx: the index value (only for input direction)
1366d5191e50STakashi Iwai  * @mask: bit mask to set
1367d5191e50STakashi Iwai  * @val: the bits value to set
1368d5191e50STakashi Iwai  *
1369d5191e50STakashi Iwai  * Update the AMP values like snd_hda_codec_amp_update(), but for a
1370d5191e50STakashi Iwai  * stereo widget with the same mask and value.
137147fd830aSTakashi Iwai  */
snd_hda_codec_amp_stereo(struct hda_codec * codec,hda_nid_t nid,int direction,int idx,int mask,int val)137247fd830aSTakashi Iwai int snd_hda_codec_amp_stereo(struct hda_codec *codec, hda_nid_t nid,
137347fd830aSTakashi Iwai 			     int direction, int idx, int mask, int val)
137447fd830aSTakashi Iwai {
137547fd830aSTakashi Iwai 	int ch, ret = 0;
137646712646STakashi Iwai 
137746712646STakashi Iwai 	if (snd_BUG_ON(mask & ~0xff))
137846712646STakashi Iwai 		mask &= 0xff;
137947fd830aSTakashi Iwai 	for (ch = 0; ch < 2; ch++)
138047fd830aSTakashi Iwai 		ret |= snd_hda_codec_amp_update(codec, nid, ch, direction,
138147fd830aSTakashi Iwai 						idx, mask, val);
138247fd830aSTakashi Iwai 	return ret;
138347fd830aSTakashi Iwai }
13842698ea98STakashi Iwai EXPORT_SYMBOL_GPL(snd_hda_codec_amp_stereo);
138547fd830aSTakashi Iwai 
138695a962c3STakashi Iwai /**
138795a962c3STakashi Iwai  * snd_hda_codec_amp_init - initialize the AMP value
138895a962c3STakashi Iwai  * @codec: the HDA codec
138995a962c3STakashi Iwai  * @nid: NID to read the AMP value
139095a962c3STakashi Iwai  * @ch: channel (left=0 or right=1)
139195a962c3STakashi Iwai  * @dir: #HDA_INPUT or #HDA_OUTPUT
139295a962c3STakashi Iwai  * @idx: the index value (only for input direction)
139395a962c3STakashi Iwai  * @mask: bit mask to set
139495a962c3STakashi Iwai  * @val: the bits value to set
139595a962c3STakashi Iwai  *
139695a962c3STakashi Iwai  * Works like snd_hda_codec_amp_update() but it writes the value only at
1397280e57d5STakashi Iwai  * the first access.  If the amp was already initialized / updated beforehand,
1398280e57d5STakashi Iwai  * this does nothing.
1399280e57d5STakashi Iwai  */
snd_hda_codec_amp_init(struct hda_codec * codec,hda_nid_t nid,int ch,int dir,int idx,int mask,int val)1400280e57d5STakashi Iwai int snd_hda_codec_amp_init(struct hda_codec *codec, hda_nid_t nid, int ch,
1401280e57d5STakashi Iwai 			   int dir, int idx, int mask, int val)
1402280e57d5STakashi Iwai {
14031a462be5STakashi Iwai 	unsigned int cmd = encode_amp(codec, nid, ch, dir, idx);
1404eeecd9d1STakashi Iwai 
1405eeecd9d1STakashi Iwai 	if (!codec->core.regmap)
1406eeecd9d1STakashi Iwai 		return -EINVAL;
14071a462be5STakashi Iwai 	return snd_hdac_regmap_update_raw_once(&codec->core, cmd, mask, val);
1408280e57d5STakashi Iwai }
14092698ea98STakashi Iwai EXPORT_SYMBOL_GPL(snd_hda_codec_amp_init);
1410280e57d5STakashi Iwai 
141195a962c3STakashi Iwai /**
141295a962c3STakashi Iwai  * snd_hda_codec_amp_init_stereo - initialize the stereo AMP value
141395a962c3STakashi Iwai  * @codec: the HDA codec
141495a962c3STakashi Iwai  * @nid: NID to read the AMP value
141595a962c3STakashi Iwai  * @dir: #HDA_INPUT or #HDA_OUTPUT
141695a962c3STakashi Iwai  * @idx: the index value (only for input direction)
141795a962c3STakashi Iwai  * @mask: bit mask to set
141895a962c3STakashi Iwai  * @val: the bits value to set
141995a962c3STakashi Iwai  *
142095a962c3STakashi Iwai  * Call snd_hda_codec_amp_init() for both stereo channels.
142195a962c3STakashi Iwai  */
snd_hda_codec_amp_init_stereo(struct hda_codec * codec,hda_nid_t nid,int dir,int idx,int mask,int val)1422280e57d5STakashi Iwai int snd_hda_codec_amp_init_stereo(struct hda_codec *codec, hda_nid_t nid,
1423280e57d5STakashi Iwai 				  int dir, int idx, int mask, int val)
1424280e57d5STakashi Iwai {
1425280e57d5STakashi Iwai 	int ch, ret = 0;
1426280e57d5STakashi Iwai 
1427280e57d5STakashi Iwai 	if (snd_BUG_ON(mask & ~0xff))
1428280e57d5STakashi Iwai 		mask &= 0xff;
1429280e57d5STakashi Iwai 	for (ch = 0; ch < 2; ch++)
1430280e57d5STakashi Iwai 		ret |= snd_hda_codec_amp_init(codec, nid, ch, dir,
1431280e57d5STakashi Iwai 					      idx, mask, val);
1432280e57d5STakashi Iwai 	return ret;
1433280e57d5STakashi Iwai }
14342698ea98STakashi Iwai EXPORT_SYMBOL_GPL(snd_hda_codec_amp_init_stereo);
1435280e57d5STakashi Iwai 
get_amp_max_value(struct hda_codec * codec,hda_nid_t nid,int dir,unsigned int ofs)1436afbd9b84STakashi Iwai static u32 get_amp_max_value(struct hda_codec *codec, hda_nid_t nid, int dir,
1437afbd9b84STakashi Iwai 			     unsigned int ofs)
1438afbd9b84STakashi Iwai {
1439afbd9b84STakashi Iwai 	u32 caps = query_amp_caps(codec, nid, dir);
1440afbd9b84STakashi Iwai 	/* get num steps */
1441afbd9b84STakashi Iwai 	caps = (caps & AC_AMPCAP_NUM_STEPS) >> AC_AMPCAP_NUM_STEPS_SHIFT;
1442afbd9b84STakashi Iwai 	if (ofs < caps)
1443afbd9b84STakashi Iwai 		caps -= ofs;
1444afbd9b84STakashi Iwai 	return caps;
1445afbd9b84STakashi Iwai }
1446afbd9b84STakashi Iwai 
1447d5191e50STakashi Iwai /**
1448d5191e50STakashi Iwai  * snd_hda_mixer_amp_volume_info - Info callback for a standard AMP mixer
1449a11e9b16STakashi Iwai  * @kcontrol: referred ctl element
1450a11e9b16STakashi Iwai  * @uinfo: pointer to get/store the data
1451d5191e50STakashi Iwai  *
1452d5191e50STakashi Iwai  * The control element is supposed to have the private_value field
1453d5191e50STakashi Iwai  * set up via HDA_COMPOSE_AMP_VAL*() or related macros.
1454d5191e50STakashi Iwai  */
snd_hda_mixer_amp_volume_info(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_info * uinfo)14550ba21762STakashi Iwai int snd_hda_mixer_amp_volume_info(struct snd_kcontrol *kcontrol,
14560ba21762STakashi Iwai 				  struct snd_ctl_elem_info *uinfo)
14571da177e4SLinus Torvalds {
14581da177e4SLinus Torvalds 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
14591da177e4SLinus Torvalds 	u16 nid = get_amp_nid(kcontrol);
14601da177e4SLinus Torvalds 	u8 chs = get_amp_channels(kcontrol);
14611da177e4SLinus Torvalds 	int dir = get_amp_direction(kcontrol);
146229fdbec2STakashi Iwai 	unsigned int ofs = get_amp_offset(kcontrol);
14631da177e4SLinus Torvalds 
1464afbd9b84STakashi Iwai 	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
1465afbd9b84STakashi Iwai 	uinfo->count = chs == 3 ? 2 : 1;
1466afbd9b84STakashi Iwai 	uinfo->value.integer.min = 0;
1467afbd9b84STakashi Iwai 	uinfo->value.integer.max = get_amp_max_value(codec, nid, dir, ofs);
1468afbd9b84STakashi Iwai 	if (!uinfo->value.integer.max) {
14694e76a883STakashi Iwai 		codec_warn(codec,
14704e76a883STakashi Iwai 			   "num_steps = 0 for NID=0x%x (ctl = %s)\n",
14714e76a883STakashi Iwai 			   nid, kcontrol->id.name);
14721da177e4SLinus Torvalds 		return -EINVAL;
14731da177e4SLinus Torvalds 	}
14741da177e4SLinus Torvalds 	return 0;
14751da177e4SLinus Torvalds }
14762698ea98STakashi Iwai EXPORT_SYMBOL_GPL(snd_hda_mixer_amp_volume_info);
14771da177e4SLinus Torvalds 
147829fdbec2STakashi Iwai 
147929fdbec2STakashi Iwai static inline unsigned int
read_amp_value(struct hda_codec * codec,hda_nid_t nid,int ch,int dir,int idx,unsigned int ofs)148029fdbec2STakashi Iwai read_amp_value(struct hda_codec *codec, hda_nid_t nid,
148129fdbec2STakashi Iwai 	       int ch, int dir, int idx, unsigned int ofs)
148229fdbec2STakashi Iwai {
148329fdbec2STakashi Iwai 	unsigned int val;
148429fdbec2STakashi Iwai 	val = snd_hda_codec_amp_read(codec, nid, ch, dir, idx);
148529fdbec2STakashi Iwai 	val &= HDA_AMP_VOLMASK;
148629fdbec2STakashi Iwai 	if (val >= ofs)
148729fdbec2STakashi Iwai 		val -= ofs;
148829fdbec2STakashi Iwai 	else
148929fdbec2STakashi Iwai 		val = 0;
149029fdbec2STakashi Iwai 	return val;
149129fdbec2STakashi Iwai }
149229fdbec2STakashi Iwai 
149329fdbec2STakashi Iwai static inline int
update_amp_value(struct hda_codec * codec,hda_nid_t nid,int ch,int dir,int idx,unsigned int ofs,unsigned int val)149429fdbec2STakashi Iwai update_amp_value(struct hda_codec *codec, hda_nid_t nid,
149529fdbec2STakashi Iwai 		 int ch, int dir, int idx, unsigned int ofs,
149629fdbec2STakashi Iwai 		 unsigned int val)
149729fdbec2STakashi Iwai {
1498afbd9b84STakashi Iwai 	unsigned int maxval;
1499afbd9b84STakashi Iwai 
150029fdbec2STakashi Iwai 	if (val > 0)
150129fdbec2STakashi Iwai 		val += ofs;
15027ccc3efaSTakashi Iwai 	/* ofs = 0: raw max value */
15037ccc3efaSTakashi Iwai 	maxval = get_amp_max_value(codec, nid, dir, 0);
1504afbd9b84STakashi Iwai 	if (val > maxval)
1505afbd9b84STakashi Iwai 		val = maxval;
1506eeecd9d1STakashi Iwai 	return snd_hda_codec_amp_update(codec, nid, ch, dir, idx,
1507eeecd9d1STakashi Iwai 					HDA_AMP_VOLMASK, val);
150829fdbec2STakashi Iwai }
150929fdbec2STakashi Iwai 
1510d5191e50STakashi Iwai /**
1511d5191e50STakashi Iwai  * snd_hda_mixer_amp_volume_get - Get callback for a standard AMP mixer volume
1512a11e9b16STakashi Iwai  * @kcontrol: ctl element
1513a11e9b16STakashi Iwai  * @ucontrol: pointer to get/store the data
1514d5191e50STakashi Iwai  *
1515d5191e50STakashi Iwai  * The control element is supposed to have the private_value field
1516d5191e50STakashi Iwai  * set up via HDA_COMPOSE_AMP_VAL*() or related macros.
1517d5191e50STakashi Iwai  */
snd_hda_mixer_amp_volume_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)15180ba21762STakashi Iwai int snd_hda_mixer_amp_volume_get(struct snd_kcontrol *kcontrol,
15190ba21762STakashi Iwai 				 struct snd_ctl_elem_value *ucontrol)
15201da177e4SLinus Torvalds {
15211da177e4SLinus Torvalds 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
15221da177e4SLinus Torvalds 	hda_nid_t nid = get_amp_nid(kcontrol);
15231da177e4SLinus Torvalds 	int chs = get_amp_channels(kcontrol);
15241da177e4SLinus Torvalds 	int dir = get_amp_direction(kcontrol);
15251da177e4SLinus Torvalds 	int idx = get_amp_index(kcontrol);
152629fdbec2STakashi Iwai 	unsigned int ofs = get_amp_offset(kcontrol);
15271da177e4SLinus Torvalds 	long *valp = ucontrol->value.integer.value;
15281da177e4SLinus Torvalds 
15291da177e4SLinus Torvalds 	if (chs & 1)
153029fdbec2STakashi Iwai 		*valp++ = read_amp_value(codec, nid, 0, dir, idx, ofs);
15311da177e4SLinus Torvalds 	if (chs & 2)
153229fdbec2STakashi Iwai 		*valp = read_amp_value(codec, nid, 1, dir, idx, ofs);
15331da177e4SLinus Torvalds 	return 0;
15341da177e4SLinus Torvalds }
15352698ea98STakashi Iwai EXPORT_SYMBOL_GPL(snd_hda_mixer_amp_volume_get);
15361da177e4SLinus Torvalds 
1537d5191e50STakashi Iwai /**
1538d5191e50STakashi Iwai  * snd_hda_mixer_amp_volume_put - Put callback for a standard AMP mixer volume
1539a11e9b16STakashi Iwai  * @kcontrol: ctl element
1540a11e9b16STakashi Iwai  * @ucontrol: pointer to get/store the data
1541d5191e50STakashi Iwai  *
1542d5191e50STakashi Iwai  * The control element is supposed to have the private_value field
1543d5191e50STakashi Iwai  * set up via HDA_COMPOSE_AMP_VAL*() or related macros.
1544d5191e50STakashi Iwai  */
snd_hda_mixer_amp_volume_put(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)15450ba21762STakashi Iwai int snd_hda_mixer_amp_volume_put(struct snd_kcontrol *kcontrol,
15460ba21762STakashi Iwai 				 struct snd_ctl_elem_value *ucontrol)
15471da177e4SLinus Torvalds {
15481da177e4SLinus Torvalds 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
15491da177e4SLinus Torvalds 	hda_nid_t nid = get_amp_nid(kcontrol);
15501da177e4SLinus Torvalds 	int chs = get_amp_channels(kcontrol);
15511da177e4SLinus Torvalds 	int dir = get_amp_direction(kcontrol);
15521da177e4SLinus Torvalds 	int idx = get_amp_index(kcontrol);
155329fdbec2STakashi Iwai 	unsigned int ofs = get_amp_offset(kcontrol);
15541da177e4SLinus Torvalds 	long *valp = ucontrol->value.integer.value;
15551da177e4SLinus Torvalds 	int change = 0;
15561da177e4SLinus Torvalds 
1557b9f5a89cSNicolas Graziano 	if (chs & 1) {
155829fdbec2STakashi Iwai 		change = update_amp_value(codec, nid, 0, dir, idx, ofs, *valp);
1559b9f5a89cSNicolas Graziano 		valp++;
1560b9f5a89cSNicolas Graziano 	}
15614a19faeeSTakashi Iwai 	if (chs & 2)
156229fdbec2STakashi Iwai 		change |= update_amp_value(codec, nid, 1, dir, idx, ofs, *valp);
15631da177e4SLinus Torvalds 	return change;
15641da177e4SLinus Torvalds }
15652698ea98STakashi Iwai EXPORT_SYMBOL_GPL(snd_hda_mixer_amp_volume_put);
15661da177e4SLinus Torvalds 
156799b5c5bbSTakashi Iwai /* inquiry the amp caps and convert to TLV */
get_ctl_amp_tlv(struct snd_kcontrol * kcontrol,unsigned int * tlv)156899b5c5bbSTakashi Iwai static void get_ctl_amp_tlv(struct snd_kcontrol *kcontrol, unsigned int *tlv)
156999b5c5bbSTakashi Iwai {
157099b5c5bbSTakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
157199b5c5bbSTakashi Iwai 	hda_nid_t nid = get_amp_nid(kcontrol);
157299b5c5bbSTakashi Iwai 	int dir = get_amp_direction(kcontrol);
157399b5c5bbSTakashi Iwai 	unsigned int ofs = get_amp_offset(kcontrol);
157499b5c5bbSTakashi Iwai 	bool min_mute = get_amp_min_mute(kcontrol);
157599b5c5bbSTakashi Iwai 	u32 caps, val1, val2;
157699b5c5bbSTakashi Iwai 
157799b5c5bbSTakashi Iwai 	caps = query_amp_caps(codec, nid, dir);
157899b5c5bbSTakashi Iwai 	val2 = (caps & AC_AMPCAP_STEP_SIZE) >> AC_AMPCAP_STEP_SIZE_SHIFT;
157999b5c5bbSTakashi Iwai 	val2 = (val2 + 1) * 25;
158099b5c5bbSTakashi Iwai 	val1 = -((caps & AC_AMPCAP_OFFSET) >> AC_AMPCAP_OFFSET_SHIFT);
158199b5c5bbSTakashi Iwai 	val1 += ofs;
158299b5c5bbSTakashi Iwai 	val1 = ((int)val1) * ((int)val2);
158399b5c5bbSTakashi Iwai 	if (min_mute || (caps & AC_AMPCAP_MIN_MUTE))
158499b5c5bbSTakashi Iwai 		val2 |= TLV_DB_SCALE_MUTE;
158551cdc8b6STakashi Sakamoto 	tlv[SNDRV_CTL_TLVO_TYPE] = SNDRV_CTL_TLVT_DB_SCALE;
158651cdc8b6STakashi Sakamoto 	tlv[SNDRV_CTL_TLVO_LEN] = 2 * sizeof(unsigned int);
158751cdc8b6STakashi Sakamoto 	tlv[SNDRV_CTL_TLVO_DB_SCALE_MIN] = val1;
158851cdc8b6STakashi Sakamoto 	tlv[SNDRV_CTL_TLVO_DB_SCALE_MUTE_AND_STEP] = val2;
158999b5c5bbSTakashi Iwai }
159099b5c5bbSTakashi Iwai 
1591d5191e50STakashi Iwai /**
1592f0049e16STakashi Iwai  * snd_hda_mixer_amp_tlv - TLV callback for a standard AMP mixer volume
1593a11e9b16STakashi Iwai  * @kcontrol: ctl element
1594a11e9b16STakashi Iwai  * @op_flag: operation flag
1595a11e9b16STakashi Iwai  * @size: byte size of input TLV
1596a11e9b16STakashi Iwai  * @_tlv: TLV data
1597d5191e50STakashi Iwai  *
1598d5191e50STakashi Iwai  * The control element is supposed to have the private_value field
1599d5191e50STakashi Iwai  * set up via HDA_COMPOSE_AMP_VAL*() or related macros.
1600d5191e50STakashi Iwai  */
snd_hda_mixer_amp_tlv(struct snd_kcontrol * kcontrol,int op_flag,unsigned int size,unsigned int __user * _tlv)1601302e9c5aSJaroslav Kysela int snd_hda_mixer_amp_tlv(struct snd_kcontrol *kcontrol, int op_flag,
1602302e9c5aSJaroslav Kysela 			  unsigned int size, unsigned int __user *_tlv)
1603302e9c5aSJaroslav Kysela {
160499b5c5bbSTakashi Iwai 	unsigned int tlv[4];
1605302e9c5aSJaroslav Kysela 
1606302e9c5aSJaroslav Kysela 	if (size < 4 * sizeof(unsigned int))
1607302e9c5aSJaroslav Kysela 		return -ENOMEM;
160899b5c5bbSTakashi Iwai 	get_ctl_amp_tlv(kcontrol, tlv);
160999b5c5bbSTakashi Iwai 	if (copy_to_user(_tlv, tlv, sizeof(tlv)))
1610302e9c5aSJaroslav Kysela 		return -EFAULT;
1611302e9c5aSJaroslav Kysela 	return 0;
1612302e9c5aSJaroslav Kysela }
16132698ea98STakashi Iwai EXPORT_SYMBOL_GPL(snd_hda_mixer_amp_tlv);
1614302e9c5aSJaroslav Kysela 
1615d5191e50STakashi Iwai /**
1616d5191e50STakashi Iwai  * snd_hda_set_vmaster_tlv - Set TLV for a virtual master control
1617d5191e50STakashi Iwai  * @codec: HD-audio codec
1618d5191e50STakashi Iwai  * @nid: NID of a reference widget
1619d5191e50STakashi Iwai  * @dir: #HDA_INPUT or #HDA_OUTPUT
1620d5191e50STakashi Iwai  * @tlv: TLV data to be stored, at least 4 elements
1621d5191e50STakashi Iwai  *
1622d5191e50STakashi Iwai  * Set (static) TLV data for a virtual master volume using the AMP caps
1623d5191e50STakashi Iwai  * obtained from the reference NID.
1624d5191e50STakashi Iwai  * The volume range is recalculated as if the max volume is 0dB.
16252134ea4fSTakashi Iwai  */
snd_hda_set_vmaster_tlv(struct hda_codec * codec,hda_nid_t nid,int dir,unsigned int * tlv)16262134ea4fSTakashi Iwai void snd_hda_set_vmaster_tlv(struct hda_codec *codec, hda_nid_t nid, int dir,
16272134ea4fSTakashi Iwai 			     unsigned int *tlv)
16282134ea4fSTakashi Iwai {
16292134ea4fSTakashi Iwai 	u32 caps;
16302134ea4fSTakashi Iwai 	int nums, step;
16312134ea4fSTakashi Iwai 
16322134ea4fSTakashi Iwai 	caps = query_amp_caps(codec, nid, dir);
16332134ea4fSTakashi Iwai 	nums = (caps & AC_AMPCAP_NUM_STEPS) >> AC_AMPCAP_NUM_STEPS_SHIFT;
16342134ea4fSTakashi Iwai 	step = (caps & AC_AMPCAP_STEP_SIZE) >> AC_AMPCAP_STEP_SIZE_SHIFT;
16352134ea4fSTakashi Iwai 	step = (step + 1) * 25;
163651cdc8b6STakashi Sakamoto 	tlv[SNDRV_CTL_TLVO_TYPE] = SNDRV_CTL_TLVT_DB_SCALE;
163751cdc8b6STakashi Sakamoto 	tlv[SNDRV_CTL_TLVO_LEN] = 2 * sizeof(unsigned int);
163851cdc8b6STakashi Sakamoto 	tlv[SNDRV_CTL_TLVO_DB_SCALE_MIN] = -nums * step;
163951cdc8b6STakashi Sakamoto 	tlv[SNDRV_CTL_TLVO_DB_SCALE_MUTE_AND_STEP] = step;
16402134ea4fSTakashi Iwai }
16412698ea98STakashi Iwai EXPORT_SYMBOL_GPL(snd_hda_set_vmaster_tlv);
16422134ea4fSTakashi Iwai 
16432134ea4fSTakashi Iwai /* find a mixer control element with the given name */
164409f99701STakashi Iwai static struct snd_kcontrol *
find_mixer_ctl(struct hda_codec * codec,const char * name,int dev,int idx)1645dcda5806STakashi Iwai find_mixer_ctl(struct hda_codec *codec, const char *name, int dev, int idx)
16462134ea4fSTakashi Iwai {
16472134ea4fSTakashi Iwai 	struct snd_ctl_elem_id id;
16482134ea4fSTakashi Iwai 	memset(&id, 0, sizeof(id));
16492134ea4fSTakashi Iwai 	id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
1650dcda5806STakashi Iwai 	id.device = dev;
165109f99701STakashi Iwai 	id.index = idx;
165218cb7109STakashi Iwai 	if (snd_BUG_ON(strlen(name) >= sizeof(id.name)))
165318cb7109STakashi Iwai 		return NULL;
16542134ea4fSTakashi Iwai 	strcpy(id.name, name);
16556efdd851STakashi Iwai 	return snd_ctl_find_id(codec->card, &id);
16562134ea4fSTakashi Iwai }
16572134ea4fSTakashi Iwai 
1658d5191e50STakashi Iwai /**
1659d5191e50STakashi Iwai  * snd_hda_find_mixer_ctl - Find a mixer control element with the given name
1660d5191e50STakashi Iwai  * @codec: HD-audio codec
1661d5191e50STakashi Iwai  * @name: ctl id name string
1662d5191e50STakashi Iwai  *
1663d5191e50STakashi Iwai  * Get the control element with the given id string and IFACE_MIXER.
1664d5191e50STakashi Iwai  */
snd_hda_find_mixer_ctl(struct hda_codec * codec,const char * name)166509f99701STakashi Iwai struct snd_kcontrol *snd_hda_find_mixer_ctl(struct hda_codec *codec,
166609f99701STakashi Iwai 					    const char *name)
166709f99701STakashi Iwai {
1668dcda5806STakashi Iwai 	return find_mixer_ctl(codec, name, 0, 0);
166909f99701STakashi Iwai }
16702698ea98STakashi Iwai EXPORT_SYMBOL_GPL(snd_hda_find_mixer_ctl);
167109f99701STakashi Iwai 
find_empty_mixer_ctl_idx(struct hda_codec * codec,const char * name,int start_idx)1672dcda5806STakashi Iwai static int find_empty_mixer_ctl_idx(struct hda_codec *codec, const char *name,
1673ea9b43adSTakashi Iwai 				    int start_idx)
16741afe206aSTakashi Iwai {
1675ea9b43adSTakashi Iwai 	int i, idx;
1676ea9b43adSTakashi Iwai 	/* 16 ctlrs should be large enough */
1677ea9b43adSTakashi Iwai 	for (i = 0, idx = start_idx; i < 16; i++, idx++) {
1678ea9b43adSTakashi Iwai 		if (!find_mixer_ctl(codec, name, 0, idx))
16791afe206aSTakashi Iwai 			return idx;
16801afe206aSTakashi Iwai 	}
16811afe206aSTakashi Iwai 	return -EBUSY;
16821afe206aSTakashi Iwai }
16831afe206aSTakashi Iwai 
1684d5191e50STakashi Iwai /**
16855b0cb1d8SJaroslav Kysela  * snd_hda_ctl_add - Add a control element and assign to the codec
1686d5191e50STakashi Iwai  * @codec: HD-audio codec
1687d5191e50STakashi Iwai  * @nid: corresponding NID (optional)
1688d5191e50STakashi Iwai  * @kctl: the control element to assign
1689d5191e50STakashi Iwai  *
1690d5191e50STakashi Iwai  * Add the given control element to an array inside the codec instance.
1691d5191e50STakashi Iwai  * All control elements belonging to a codec are supposed to be added
1692d5191e50STakashi Iwai  * by this function so that a proper clean-up works at the free or
1693d5191e50STakashi Iwai  * reconfiguration time.
1694d5191e50STakashi Iwai  *
1695d5191e50STakashi Iwai  * If non-zero @nid is passed, the NID is assigned to the control element.
1696d5191e50STakashi Iwai  * The assignment is shown in the codec proc file.
1697d5191e50STakashi Iwai  *
1698d5191e50STakashi Iwai  * snd_hda_ctl_add() checks the control subdev id field whether
1699d5191e50STakashi Iwai  * #HDA_SUBDEV_NID_FLAG bit is set.  If set (and @nid is zero), the lower
17009e3fd871SJaroslav Kysela  * bits value is taken as the NID to assign. The #HDA_NID_ITEM_AMP bit
17019e3fd871SJaroslav Kysela  * specifies if kctl->private_value is a HDA amplifier value.
1702d5191e50STakashi Iwai  */
snd_hda_ctl_add(struct hda_codec * codec,hda_nid_t nid,struct snd_kcontrol * kctl)17033911a4c1SJaroslav Kysela int snd_hda_ctl_add(struct hda_codec *codec, hda_nid_t nid,
17043911a4c1SJaroslav Kysela 		    struct snd_kcontrol *kctl)
1705d13bd412STakashi Iwai {
1706d13bd412STakashi Iwai 	int err;
17079e3fd871SJaroslav Kysela 	unsigned short flags = 0;
17083911a4c1SJaroslav Kysela 	struct hda_nid_item *item;
1709d13bd412STakashi Iwai 
17105e26dfd0SJaroslav Kysela 	if (kctl->id.subdevice & HDA_SUBDEV_AMP_FLAG) {
17119e3fd871SJaroslav Kysela 		flags |= HDA_NID_ITEM_AMP;
17125e26dfd0SJaroslav Kysela 		if (nid == 0)
17135e26dfd0SJaroslav Kysela 			nid = get_amp_nid_(kctl->private_value);
17145e26dfd0SJaroslav Kysela 	}
17159e3fd871SJaroslav Kysela 	if ((kctl->id.subdevice & HDA_SUBDEV_NID_FLAG) != 0 && nid == 0)
17164d02d1b6SJaroslav Kysela 		nid = kctl->id.subdevice & 0xffff;
17175e26dfd0SJaroslav Kysela 	if (kctl->id.subdevice & (HDA_SUBDEV_NID_FLAG|HDA_SUBDEV_AMP_FLAG))
17184d02d1b6SJaroslav Kysela 		kctl->id.subdevice = 0;
17196efdd851STakashi Iwai 	err = snd_ctl_add(codec->card, kctl);
1720d13bd412STakashi Iwai 	if (err < 0)
1721d13bd412STakashi Iwai 		return err;
17223911a4c1SJaroslav Kysela 	item = snd_array_new(&codec->mixers);
17233911a4c1SJaroslav Kysela 	if (!item)
1724d13bd412STakashi Iwai 		return -ENOMEM;
17253911a4c1SJaroslav Kysela 	item->kctl = kctl;
17263911a4c1SJaroslav Kysela 	item->nid = nid;
17279e3fd871SJaroslav Kysela 	item->flags = flags;
1728d13bd412STakashi Iwai 	return 0;
1729d13bd412STakashi Iwai }
17302698ea98STakashi Iwai EXPORT_SYMBOL_GPL(snd_hda_ctl_add);
1731d13bd412STakashi Iwai 
1732d5191e50STakashi Iwai /**
17335b0cb1d8SJaroslav Kysela  * snd_hda_add_nid - Assign a NID to a control element
17345b0cb1d8SJaroslav Kysela  * @codec: HD-audio codec
17355b0cb1d8SJaroslav Kysela  * @nid: corresponding NID (optional)
17365b0cb1d8SJaroslav Kysela  * @kctl: the control element to assign
17375b0cb1d8SJaroslav Kysela  * @index: index to kctl
17385b0cb1d8SJaroslav Kysela  *
17395b0cb1d8SJaroslav Kysela  * Add the given control element to an array inside the codec instance.
17405b0cb1d8SJaroslav Kysela  * This function is used when #snd_hda_ctl_add cannot be used for 1:1
17415b0cb1d8SJaroslav Kysela  * NID:KCTL mapping - for example "Capture Source" selector.
17425b0cb1d8SJaroslav Kysela  */
snd_hda_add_nid(struct hda_codec * codec,struct snd_kcontrol * kctl,unsigned int index,hda_nid_t nid)17435b0cb1d8SJaroslav Kysela int snd_hda_add_nid(struct hda_codec *codec, struct snd_kcontrol *kctl,
17445b0cb1d8SJaroslav Kysela 		    unsigned int index, hda_nid_t nid)
17455b0cb1d8SJaroslav Kysela {
17465b0cb1d8SJaroslav Kysela 	struct hda_nid_item *item;
17475b0cb1d8SJaroslav Kysela 
17485b0cb1d8SJaroslav Kysela 	if (nid > 0) {
17495b0cb1d8SJaroslav Kysela 		item = snd_array_new(&codec->nids);
17505b0cb1d8SJaroslav Kysela 		if (!item)
17515b0cb1d8SJaroslav Kysela 			return -ENOMEM;
17525b0cb1d8SJaroslav Kysela 		item->kctl = kctl;
17535b0cb1d8SJaroslav Kysela 		item->index = index;
17545b0cb1d8SJaroslav Kysela 		item->nid = nid;
17555b0cb1d8SJaroslav Kysela 		return 0;
17565b0cb1d8SJaroslav Kysela 	}
17574e76a883STakashi Iwai 	codec_err(codec, "no NID for mapping control %s:%d:%d\n",
175828d1a85eSTakashi Iwai 		  kctl->id.name, kctl->id.index, index);
17595b0cb1d8SJaroslav Kysela 	return -EINVAL;
17605b0cb1d8SJaroslav Kysela }
17612698ea98STakashi Iwai EXPORT_SYMBOL_GPL(snd_hda_add_nid);
17625b0cb1d8SJaroslav Kysela 
17635b0cb1d8SJaroslav Kysela /**
1764d5191e50STakashi Iwai  * snd_hda_ctls_clear - Clear all controls assigned to the given codec
1765d5191e50STakashi Iwai  * @codec: HD-audio codec
1766d5191e50STakashi Iwai  */
snd_hda_ctls_clear(struct hda_codec * codec)1767d13bd412STakashi Iwai void snd_hda_ctls_clear(struct hda_codec *codec)
1768d13bd412STakashi Iwai {
1769d13bd412STakashi Iwai 	int i;
17703911a4c1SJaroslav Kysela 	struct hda_nid_item *items = codec->mixers.list;
177180bd64afSTakashi Iwai 
1772d13bd412STakashi Iwai 	for (i = 0; i < codec->mixers.used; i++)
17736efdd851STakashi Iwai 		snd_ctl_remove(codec->card, items[i].kctl);
1774d13bd412STakashi Iwai 	snd_array_free(&codec->mixers);
17755b0cb1d8SJaroslav Kysela 	snd_array_free(&codec->nids);
1776d13bd412STakashi Iwai }
1777d13bd412STakashi Iwai 
177895a962c3STakashi Iwai /**
177995a962c3STakashi Iwai  * snd_hda_lock_devices - pseudo device locking
178095a962c3STakashi Iwai  * @bus: the BUS
178195a962c3STakashi Iwai  *
1782a65d629cSTakashi Iwai  * toggle card->shutdown to allow/disallow the device access (as a hack)
1783a65d629cSTakashi Iwai  */
snd_hda_lock_devices(struct hda_bus * bus)1784d3d020bdSTakashi Iwai int snd_hda_lock_devices(struct hda_bus *bus)
17856c1f45eaSTakashi Iwai {
1786d3d020bdSTakashi Iwai 	struct snd_card *card = bus->card;
1787d3d020bdSTakashi Iwai 	struct hda_codec *codec;
1788d3d020bdSTakashi Iwai 
1789a65d629cSTakashi Iwai 	spin_lock(&card->files_lock);
1790d3d020bdSTakashi Iwai 	if (card->shutdown)
1791d3d020bdSTakashi Iwai 		goto err_unlock;
1792d3d020bdSTakashi Iwai 	card->shutdown = 1;
1793d3d020bdSTakashi Iwai 	if (!list_empty(&card->ctl_files))
1794d3d020bdSTakashi Iwai 		goto err_clear;
1795d3d020bdSTakashi Iwai 
1796d068ebc2STakashi Iwai 	list_for_each_codec(codec, bus) {
1797bbbc7e85STakashi Iwai 		struct hda_pcm *cpcm;
1798bbbc7e85STakashi Iwai 		list_for_each_entry(cpcm, &codec->pcm_list_head, list) {
1799d3d020bdSTakashi Iwai 			if (!cpcm->pcm)
1800d3d020bdSTakashi Iwai 				continue;
1801d3d020bdSTakashi Iwai 			if (cpcm->pcm->streams[0].substream_opened ||
1802d3d020bdSTakashi Iwai 			    cpcm->pcm->streams[1].substream_opened)
1803d3d020bdSTakashi Iwai 				goto err_clear;
1804d3d020bdSTakashi Iwai 		}
1805d3d020bdSTakashi Iwai 	}
1806d3d020bdSTakashi Iwai 	spin_unlock(&card->files_lock);
1807d3d020bdSTakashi Iwai 	return 0;
1808d3d020bdSTakashi Iwai 
1809d3d020bdSTakashi Iwai  err_clear:
1810d3d020bdSTakashi Iwai 	card->shutdown = 0;
1811d3d020bdSTakashi Iwai  err_unlock:
1812a65d629cSTakashi Iwai 	spin_unlock(&card->files_lock);
1813a65d629cSTakashi Iwai 	return -EINVAL;
1814a65d629cSTakashi Iwai }
18152698ea98STakashi Iwai EXPORT_SYMBOL_GPL(snd_hda_lock_devices);
1816a65d629cSTakashi Iwai 
181795a962c3STakashi Iwai /**
181895a962c3STakashi Iwai  * snd_hda_unlock_devices - pseudo device unlocking
181995a962c3STakashi Iwai  * @bus: the BUS
182095a962c3STakashi Iwai  */
snd_hda_unlock_devices(struct hda_bus * bus)1821d3d020bdSTakashi Iwai void snd_hda_unlock_devices(struct hda_bus *bus)
1822a65d629cSTakashi Iwai {
1823d3d020bdSTakashi Iwai 	struct snd_card *card = bus->card;
1824d3d020bdSTakashi Iwai 
1825a65d629cSTakashi Iwai 	spin_lock(&card->files_lock);
1826a65d629cSTakashi Iwai 	card->shutdown = 0;
1827a65d629cSTakashi Iwai 	spin_unlock(&card->files_lock);
1828a65d629cSTakashi Iwai }
18292698ea98STakashi Iwai EXPORT_SYMBOL_GPL(snd_hda_unlock_devices);
1830a65d629cSTakashi Iwai 
1831d5191e50STakashi Iwai /**
1832d5191e50STakashi Iwai  * snd_hda_codec_reset - Clear all objects assigned to the codec
1833d5191e50STakashi Iwai  * @codec: HD-audio codec
1834d5191e50STakashi Iwai  *
1835d5191e50STakashi Iwai  * This frees the all PCM and control elements assigned to the codec, and
1836d5191e50STakashi Iwai  * clears the caches and restores the pin default configurations.
1837d5191e50STakashi Iwai  *
1838d5191e50STakashi Iwai  * When a device is being used, it returns -EBSY.  If successfully freed,
1839d5191e50STakashi Iwai  * returns zero.
1840d5191e50STakashi Iwai  */
snd_hda_codec_reset(struct hda_codec * codec)1841a65d629cSTakashi Iwai int snd_hda_codec_reset(struct hda_codec *codec)
1842a65d629cSTakashi Iwai {
1843d3d020bdSTakashi Iwai 	struct hda_bus *bus = codec->bus;
1844a65d629cSTakashi Iwai 
1845d3d020bdSTakashi Iwai 	if (snd_hda_lock_devices(bus) < 0)
1846a65d629cSTakashi Iwai 		return -EBUSY;
1847a65d629cSTakashi Iwai 
1848a65d629cSTakashi Iwai 	/* OK, let it free */
18492506318eSTakashi Iwai 	device_release_driver(hda_codec_dev(codec));
1850d8a766a1STakashi Iwai 
1851a65d629cSTakashi Iwai 	/* allow device access again */
1852d3d020bdSTakashi Iwai 	snd_hda_unlock_devices(bus);
1853a65d629cSTakashi Iwai 	return 0;
18546c1f45eaSTakashi Iwai }
18556c1f45eaSTakashi Iwai 
18569ab0cb30STakashi Iwai typedef int (*map_follower_func_t)(struct hda_codec *, void *, struct snd_kcontrol *);
1857aeb4b88eSTakashi Iwai 
18589ab0cb30STakashi Iwai /* apply the function to all matching follower ctls in the mixer list */
map_followers(struct hda_codec * codec,const char * const * followers,const char * suffix,map_follower_func_t func,void * data)18599ab0cb30STakashi Iwai static int map_followers(struct hda_codec *codec, const char * const *followers,
18609ab0cb30STakashi Iwai 			 const char *suffix, map_follower_func_t func, void *data)
1861aeb4b88eSTakashi Iwai {
1862aeb4b88eSTakashi Iwai 	struct hda_nid_item *items;
1863aeb4b88eSTakashi Iwai 	const char * const *s;
1864aeb4b88eSTakashi Iwai 	int i, err;
1865aeb4b88eSTakashi Iwai 
1866aeb4b88eSTakashi Iwai 	items = codec->mixers.list;
1867aeb4b88eSTakashi Iwai 	for (i = 0; i < codec->mixers.used; i++) {
1868aeb4b88eSTakashi Iwai 		struct snd_kcontrol *sctl = items[i].kctl;
1869ca16ec02STakashi Iwai 		if (!sctl || sctl->id.iface != SNDRV_CTL_ELEM_IFACE_MIXER)
1870aeb4b88eSTakashi Iwai 			continue;
18719ab0cb30STakashi Iwai 		for (s = followers; *s; s++) {
18729322ca54STakashi Iwai 			char tmpname[sizeof(sctl->id.name)];
18739322ca54STakashi Iwai 			const char *name = *s;
18749322ca54STakashi Iwai 			if (suffix) {
18759322ca54STakashi Iwai 				snprintf(tmpname, sizeof(tmpname), "%s %s",
18769322ca54STakashi Iwai 					 name, suffix);
18779322ca54STakashi Iwai 				name = tmpname;
18789322ca54STakashi Iwai 			}
18799322ca54STakashi Iwai 			if (!strcmp(sctl->id.name, name)) {
18806194b99dSTakashi Iwai 				err = func(codec, data, sctl);
1881aeb4b88eSTakashi Iwai 				if (err)
1882aeb4b88eSTakashi Iwai 					return err;
1883aeb4b88eSTakashi Iwai 				break;
1884aeb4b88eSTakashi Iwai 			}
1885aeb4b88eSTakashi Iwai 		}
1886aeb4b88eSTakashi Iwai 	}
1887aeb4b88eSTakashi Iwai 	return 0;
1888aeb4b88eSTakashi Iwai }
1889aeb4b88eSTakashi Iwai 
check_follower_present(struct hda_codec * codec,void * data,struct snd_kcontrol * sctl)18909ab0cb30STakashi Iwai static int check_follower_present(struct hda_codec *codec,
18916194b99dSTakashi Iwai 				  void *data, struct snd_kcontrol *sctl)
1892aeb4b88eSTakashi Iwai {
1893aeb4b88eSTakashi Iwai 	return 1;
1894aeb4b88eSTakashi Iwai }
1895aeb4b88eSTakashi Iwai 
189618478e8bSTakashi Iwai /* call kctl->put with the given value(s) */
put_kctl_with_value(struct snd_kcontrol * kctl,int val)189718478e8bSTakashi Iwai static int put_kctl_with_value(struct snd_kcontrol *kctl, int val)
189818478e8bSTakashi Iwai {
189918478e8bSTakashi Iwai 	struct snd_ctl_elem_value *ucontrol;
190018478e8bSTakashi Iwai 	ucontrol = kzalloc(sizeof(*ucontrol), GFP_KERNEL);
190118478e8bSTakashi Iwai 	if (!ucontrol)
190218478e8bSTakashi Iwai 		return -ENOMEM;
190318478e8bSTakashi Iwai 	ucontrol->value.integer.value[0] = val;
190418478e8bSTakashi Iwai 	ucontrol->value.integer.value[1] = val;
190518478e8bSTakashi Iwai 	kctl->put(kctl, ucontrol);
190618478e8bSTakashi Iwai 	kfree(ucontrol);
190718478e8bSTakashi Iwai 	return 0;
190818478e8bSTakashi Iwai }
190918478e8bSTakashi Iwai 
19109ab0cb30STakashi Iwai struct follower_init_arg {
1911a91d6612STakashi Iwai 	struct hda_codec *codec;
1912a91d6612STakashi Iwai 	int step;
1913a91d6612STakashi Iwai };
1914a91d6612STakashi Iwai 
19159ab0cb30STakashi Iwai /* initialize the follower volume with 0dB via snd_ctl_apply_vmaster_followers() */
init_follower_0dB(struct snd_kcontrol * follower,struct snd_kcontrol * kctl,void * _arg)19169ab0cb30STakashi Iwai static int init_follower_0dB(struct snd_kcontrol *follower,
1917d6c0615fSTakashi Iwai 			     struct snd_kcontrol *kctl,
1918d6c0615fSTakashi Iwai 			     void *_arg)
191918478e8bSTakashi Iwai {
19209ab0cb30STakashi Iwai 	struct follower_init_arg *arg = _arg;
1921a91d6612STakashi Iwai 	int _tlv[4];
1922a91d6612STakashi Iwai 	const int *tlv = NULL;
1923a91d6612STakashi Iwai 	int step;
1924a91d6612STakashi Iwai 	int val;
1925a91d6612STakashi Iwai 
1926a91d6612STakashi Iwai 	if (kctl->vd[0].access & SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK) {
1927a91d6612STakashi Iwai 		if (kctl->tlv.c != snd_hda_mixer_amp_tlv) {
1928a91d6612STakashi Iwai 			codec_err(arg->codec,
19299ab0cb30STakashi Iwai 				  "Unexpected TLV callback for follower %s:%d\n",
1930a91d6612STakashi Iwai 				  kctl->id.name, kctl->id.index);
1931a91d6612STakashi Iwai 			return 0; /* ignore */
1932a91d6612STakashi Iwai 		}
1933a91d6612STakashi Iwai 		get_ctl_amp_tlv(kctl, _tlv);
1934a91d6612STakashi Iwai 		tlv = _tlv;
1935a91d6612STakashi Iwai 	} else if (kctl->vd[0].access & SNDRV_CTL_ELEM_ACCESS_TLV_READ)
1936a91d6612STakashi Iwai 		tlv = kctl->tlv.p;
1937a91d6612STakashi Iwai 
193851cdc8b6STakashi Sakamoto 	if (!tlv || tlv[SNDRV_CTL_TLVO_TYPE] != SNDRV_CTL_TLVT_DB_SCALE)
1939a91d6612STakashi Iwai 		return 0;
1940a91d6612STakashi Iwai 
194151cdc8b6STakashi Sakamoto 	step = tlv[SNDRV_CTL_TLVO_DB_SCALE_MUTE_AND_STEP];
1942a91d6612STakashi Iwai 	step &= ~TLV_DB_SCALE_MUTE;
1943a91d6612STakashi Iwai 	if (!step)
1944a91d6612STakashi Iwai 		return 0;
1945a91d6612STakashi Iwai 	if (arg->step && arg->step != step) {
1946a91d6612STakashi Iwai 		codec_err(arg->codec,
19479ab0cb30STakashi Iwai 			  "Mismatching dB step for vmaster follower (%d!=%d)\n",
1948a91d6612STakashi Iwai 			  arg->step, step);
194918478e8bSTakashi Iwai 		return 0;
195018478e8bSTakashi Iwai 	}
195118478e8bSTakashi Iwai 
1952a91d6612STakashi Iwai 	arg->step = step;
195351cdc8b6STakashi Sakamoto 	val = -tlv[SNDRV_CTL_TLVO_DB_SCALE_MIN] / step;
1954a91d6612STakashi Iwai 	if (val > 0) {
19559ab0cb30STakashi Iwai 		put_kctl_with_value(follower, val);
1956a91d6612STakashi Iwai 		return val;
1957a91d6612STakashi Iwai 	}
1958a91d6612STakashi Iwai 
1959a91d6612STakashi Iwai 	return 0;
1960a91d6612STakashi Iwai }
1961a91d6612STakashi Iwai 
19629ab0cb30STakashi Iwai /* unmute the follower via snd_ctl_apply_vmaster_followers() */
init_follower_unmute(struct snd_kcontrol * follower,struct snd_kcontrol * kctl,void * _arg)19639ab0cb30STakashi Iwai static int init_follower_unmute(struct snd_kcontrol *follower,
1964d6c0615fSTakashi Iwai 				struct snd_kcontrol *kctl,
1965d6c0615fSTakashi Iwai 				void *_arg)
196618478e8bSTakashi Iwai {
19679ab0cb30STakashi Iwai 	return put_kctl_with_value(follower, 1);
196818478e8bSTakashi Iwai }
196918478e8bSTakashi Iwai 
add_follower(struct hda_codec * codec,void * data,struct snd_kcontrol * follower)19709ab0cb30STakashi Iwai static int add_follower(struct hda_codec *codec,
19719ab0cb30STakashi Iwai 			void *data, struct snd_kcontrol *follower)
1972e8750940STakashi Iwai {
19739ab0cb30STakashi Iwai 	return snd_ctl_add_follower(data, follower);
1974e8750940STakashi Iwai }
1975e8750940STakashi Iwai 
1976d5191e50STakashi Iwai /**
19779ab0cb30STakashi Iwai  * __snd_hda_add_vmaster - create a virtual master control and add followers
1978d5191e50STakashi Iwai  * @codec: HD-audio codec
1979d5191e50STakashi Iwai  * @name: vmaster control name
1980d5191e50STakashi Iwai  * @tlv: TLV data (optional)
19819ab0cb30STakashi Iwai  * @followers: follower control names (optional)
19829ab0cb30STakashi Iwai  * @suffix: suffix string to each follower name (optional)
19839ab0cb30STakashi Iwai  * @init_follower_vol: initialize followers to unmute/0dB
1984618fad3dSRanjani Sridharan  * @access: kcontrol access rights
198529e5853dSTakashi Iwai  * @ctl_ret: store the vmaster kcontrol in return
1986d5191e50STakashi Iwai  *
1987d5191e50STakashi Iwai  * Create a virtual master control with the given name.  The TLV data
1988d5191e50STakashi Iwai  * must be either NULL or a valid data.
1989d5191e50STakashi Iwai  *
19909ab0cb30STakashi Iwai  * @followers is a NULL-terminated array of strings, each of which is a
19919ab0cb30STakashi Iwai  * follower control name.  All controls with these names are assigned to
1992d5191e50STakashi Iwai  * the new virtual master control.
1993d5191e50STakashi Iwai  *
1994d5191e50STakashi Iwai  * This function returns zero if successful or a negative error code.
1995d5191e50STakashi Iwai  */
__snd_hda_add_vmaster(struct hda_codec * codec,char * name,unsigned int * tlv,const char * const * followers,const char * suffix,bool init_follower_vol,unsigned int access,struct snd_kcontrol ** ctl_ret)199618478e8bSTakashi Iwai int __snd_hda_add_vmaster(struct hda_codec *codec, char *name,
19979ab0cb30STakashi Iwai 			  unsigned int *tlv, const char * const *followers,
19989ab0cb30STakashi Iwai 			  const char *suffix, bool init_follower_vol,
1999e65bf997SJaroslav Kysela 			  unsigned int access, struct snd_kcontrol **ctl_ret)
20002134ea4fSTakashi Iwai {
20012134ea4fSTakashi Iwai 	struct snd_kcontrol *kctl;
20022134ea4fSTakashi Iwai 	int err;
20032134ea4fSTakashi Iwai 
200429e5853dSTakashi Iwai 	if (ctl_ret)
200529e5853dSTakashi Iwai 		*ctl_ret = NULL;
200629e5853dSTakashi Iwai 
20079ab0cb30STakashi Iwai 	err = map_followers(codec, followers, suffix, check_follower_present, NULL);
2008aeb4b88eSTakashi Iwai 	if (err != 1) {
20099ab0cb30STakashi Iwai 		codec_dbg(codec, "No follower found for %s\n", name);
20102f085549STakashi Iwai 		return 0;
20112f085549STakashi Iwai 	}
20122134ea4fSTakashi Iwai 	kctl = snd_ctl_make_virtual_master(name, tlv);
20132134ea4fSTakashi Iwai 	if (!kctl)
20142134ea4fSTakashi Iwai 		return -ENOMEM;
2015e65bf997SJaroslav Kysela 	kctl->vd[0].access |= access;
20163911a4c1SJaroslav Kysela 	err = snd_hda_ctl_add(codec, 0, kctl);
20172134ea4fSTakashi Iwai 	if (err < 0)
20182134ea4fSTakashi Iwai 		return err;
20192134ea4fSTakashi Iwai 
20209ab0cb30STakashi Iwai 	err = map_followers(codec, followers, suffix, add_follower, kctl);
20212134ea4fSTakashi Iwai 	if (err < 0)
20222134ea4fSTakashi Iwai 		return err;
202318478e8bSTakashi Iwai 
202418478e8bSTakashi Iwai 	/* init with master mute & zero volume */
202518478e8bSTakashi Iwai 	put_kctl_with_value(kctl, 0);
20269ab0cb30STakashi Iwai 	if (init_follower_vol) {
20279ab0cb30STakashi Iwai 		struct follower_init_arg arg = {
2028a91d6612STakashi Iwai 			.codec = codec,
2029a91d6612STakashi Iwai 			.step = 0,
2030a91d6612STakashi Iwai 		};
20319ab0cb30STakashi Iwai 		snd_ctl_apply_vmaster_followers(kctl,
20329ab0cb30STakashi Iwai 						tlv ? init_follower_0dB : init_follower_unmute,
2033a91d6612STakashi Iwai 						&arg);
2034485e3e0cSTakashi Iwai 	}
203518478e8bSTakashi Iwai 
203629e5853dSTakashi Iwai 	if (ctl_ret)
203729e5853dSTakashi Iwai 		*ctl_ret = kctl;
20382134ea4fSTakashi Iwai 	return 0;
20392134ea4fSTakashi Iwai }
20402698ea98STakashi Iwai EXPORT_SYMBOL_GPL(__snd_hda_add_vmaster);
20412134ea4fSTakashi Iwai 
2042ee52e56eSTakashi Iwai /* meta hook to call each driver's vmaster hook */
vmaster_hook(void * private_data,int enabled)2043ee52e56eSTakashi Iwai static void vmaster_hook(void *private_data, int enabled)
2044ee52e56eSTakashi Iwai {
2045ee52e56eSTakashi Iwai 	struct hda_vmaster_mute_hook *hook = private_data;
2046ee52e56eSTakashi Iwai 
2047ee52e56eSTakashi Iwai 	hook->hook(hook->codec, enabled);
2048ee52e56eSTakashi Iwai }
2049ee52e56eSTakashi Iwai 
205095a962c3STakashi Iwai /**
2051e65bf997SJaroslav Kysela  * snd_hda_add_vmaster_hook - Add a vmaster hw specific hook
205295a962c3STakashi Iwai  * @codec: the HDA codec
205395a962c3STakashi Iwai  * @hook: the vmaster hook object
205495a962c3STakashi Iwai  *
2055e65bf997SJaroslav Kysela  * Add a hw specific hook (like EAPD) with the given vmaster switch kctl.
2056d2f344b5STakashi Iwai  */
snd_hda_add_vmaster_hook(struct hda_codec * codec,struct hda_vmaster_mute_hook * hook)2057d2f344b5STakashi Iwai int snd_hda_add_vmaster_hook(struct hda_codec *codec,
2058e65bf997SJaroslav Kysela 			     struct hda_vmaster_mute_hook *hook)
2059d2f344b5STakashi Iwai {
2060d2f344b5STakashi Iwai 	if (!hook->hook || !hook->sw_kctl)
2061d2f344b5STakashi Iwai 		return 0;
2062d2f344b5STakashi Iwai 	hook->codec = codec;
2063ee52e56eSTakashi Iwai 	snd_ctl_add_vmaster_hook(hook->sw_kctl, vmaster_hook, hook);
2064f29735cbSTakashi Iwai 	return 0;
2065d2f344b5STakashi Iwai }
20662698ea98STakashi Iwai EXPORT_SYMBOL_GPL(snd_hda_add_vmaster_hook);
2067d2f344b5STakashi Iwai 
206895a962c3STakashi Iwai /**
206995a962c3STakashi Iwai  * snd_hda_sync_vmaster_hook - Sync vmaster hook
207095a962c3STakashi Iwai  * @hook: the vmaster hook
207195a962c3STakashi Iwai  *
207295a962c3STakashi Iwai  * Call the hook with the current value for synchronization.
207395a962c3STakashi Iwai  * Should be called in init callback.
2074d2f344b5STakashi Iwai  */
snd_hda_sync_vmaster_hook(struct hda_vmaster_mute_hook * hook)2075d2f344b5STakashi Iwai void snd_hda_sync_vmaster_hook(struct hda_vmaster_mute_hook *hook)
2076d2f344b5STakashi Iwai {
2077d2f344b5STakashi Iwai 	if (!hook->hook || !hook->codec)
2078d2f344b5STakashi Iwai 		return;
2079594813ffSTakashi Iwai 	/* don't call vmaster hook in the destructor since it might have
2080594813ffSTakashi Iwai 	 * been already destroyed
2081594813ffSTakashi Iwai 	 */
2082594813ffSTakashi Iwai 	if (hook->codec->bus->shutdown)
2083594813ffSTakashi Iwai 		return;
2084d2f344b5STakashi Iwai 	snd_ctl_sync_vmaster_hook(hook->sw_kctl);
2085d2f344b5STakashi Iwai }
20862698ea98STakashi Iwai EXPORT_SYMBOL_GPL(snd_hda_sync_vmaster_hook);
2087d2f344b5STakashi Iwai 
2088d2f344b5STakashi Iwai 
2089d5191e50STakashi Iwai /**
2090d5191e50STakashi Iwai  * snd_hda_mixer_amp_switch_info - Info callback for a standard AMP mixer switch
2091a11e9b16STakashi Iwai  * @kcontrol: referred ctl element
2092a11e9b16STakashi Iwai  * @uinfo: pointer to get/store the data
2093d5191e50STakashi Iwai  *
2094d5191e50STakashi Iwai  * The control element is supposed to have the private_value field
2095d5191e50STakashi Iwai  * set up via HDA_COMPOSE_AMP_VAL*() or related macros.
2096d5191e50STakashi Iwai  */
snd_hda_mixer_amp_switch_info(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_info * uinfo)20970ba21762STakashi Iwai int snd_hda_mixer_amp_switch_info(struct snd_kcontrol *kcontrol,
20980ba21762STakashi Iwai 				  struct snd_ctl_elem_info *uinfo)
20991da177e4SLinus Torvalds {
21001da177e4SLinus Torvalds 	int chs = get_amp_channels(kcontrol);
21011da177e4SLinus Torvalds 
21021da177e4SLinus Torvalds 	uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
21031da177e4SLinus Torvalds 	uinfo->count = chs == 3 ? 2 : 1;
21041da177e4SLinus Torvalds 	uinfo->value.integer.min = 0;
21051da177e4SLinus Torvalds 	uinfo->value.integer.max = 1;
21061da177e4SLinus Torvalds 	return 0;
21071da177e4SLinus Torvalds }
21082698ea98STakashi Iwai EXPORT_SYMBOL_GPL(snd_hda_mixer_amp_switch_info);
21091da177e4SLinus Torvalds 
2110d5191e50STakashi Iwai /**
2111d5191e50STakashi Iwai  * snd_hda_mixer_amp_switch_get - Get callback for a standard AMP mixer switch
2112a11e9b16STakashi Iwai  * @kcontrol: ctl element
2113a11e9b16STakashi Iwai  * @ucontrol: pointer to get/store the data
2114d5191e50STakashi Iwai  *
2115d5191e50STakashi Iwai  * The control element is supposed to have the private_value field
2116d5191e50STakashi Iwai  * set up via HDA_COMPOSE_AMP_VAL*() or related macros.
2117d5191e50STakashi Iwai  */
snd_hda_mixer_amp_switch_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)21180ba21762STakashi Iwai int snd_hda_mixer_amp_switch_get(struct snd_kcontrol *kcontrol,
21190ba21762STakashi Iwai 				 struct snd_ctl_elem_value *ucontrol)
21201da177e4SLinus Torvalds {
21211da177e4SLinus Torvalds 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
21221da177e4SLinus Torvalds 	hda_nid_t nid = get_amp_nid(kcontrol);
21231da177e4SLinus Torvalds 	int chs = get_amp_channels(kcontrol);
21241da177e4SLinus Torvalds 	int dir = get_amp_direction(kcontrol);
21251da177e4SLinus Torvalds 	int idx = get_amp_index(kcontrol);
21261da177e4SLinus Torvalds 	long *valp = ucontrol->value.integer.value;
21271da177e4SLinus Torvalds 
21281da177e4SLinus Torvalds 	if (chs & 1)
21290ba21762STakashi Iwai 		*valp++ = (snd_hda_codec_amp_read(codec, nid, 0, dir, idx) &
213047fd830aSTakashi Iwai 			   HDA_AMP_MUTE) ? 0 : 1;
21311da177e4SLinus Torvalds 	if (chs & 2)
21320ba21762STakashi Iwai 		*valp = (snd_hda_codec_amp_read(codec, nid, 1, dir, idx) &
213347fd830aSTakashi Iwai 			 HDA_AMP_MUTE) ? 0 : 1;
21341da177e4SLinus Torvalds 	return 0;
21351da177e4SLinus Torvalds }
21362698ea98STakashi Iwai EXPORT_SYMBOL_GPL(snd_hda_mixer_amp_switch_get);
21371da177e4SLinus Torvalds 
2138d5191e50STakashi Iwai /**
2139d5191e50STakashi Iwai  * snd_hda_mixer_amp_switch_put - Put callback for a standard AMP mixer switch
2140a11e9b16STakashi Iwai  * @kcontrol: ctl element
2141a11e9b16STakashi Iwai  * @ucontrol: pointer to get/store the data
2142d5191e50STakashi Iwai  *
2143d5191e50STakashi Iwai  * The control element is supposed to have the private_value field
2144d5191e50STakashi Iwai  * set up via HDA_COMPOSE_AMP_VAL*() or related macros.
2145d5191e50STakashi Iwai  */
snd_hda_mixer_amp_switch_put(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)21460ba21762STakashi Iwai int snd_hda_mixer_amp_switch_put(struct snd_kcontrol *kcontrol,
21470ba21762STakashi Iwai 				 struct snd_ctl_elem_value *ucontrol)
21481da177e4SLinus Torvalds {
21491da177e4SLinus Torvalds 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
21501da177e4SLinus Torvalds 	hda_nid_t nid = get_amp_nid(kcontrol);
21511da177e4SLinus Torvalds 	int chs = get_amp_channels(kcontrol);
21521da177e4SLinus Torvalds 	int dir = get_amp_direction(kcontrol);
21531da177e4SLinus Torvalds 	int idx = get_amp_index(kcontrol);
21541da177e4SLinus Torvalds 	long *valp = ucontrol->value.integer.value;
21551da177e4SLinus Torvalds 	int change = 0;
21561da177e4SLinus Torvalds 
2157b9f5a89cSNicolas Graziano 	if (chs & 1) {
2158eeecd9d1STakashi Iwai 		change = snd_hda_codec_amp_update(codec, nid, 0, dir, idx,
215947fd830aSTakashi Iwai 						  HDA_AMP_MUTE,
2160eeecd9d1STakashi Iwai 						  *valp ? 0 : HDA_AMP_MUTE);
2161b9f5a89cSNicolas Graziano 		valp++;
2162b9f5a89cSNicolas Graziano 	}
21634a19faeeSTakashi Iwai 	if (chs & 2)
2164eeecd9d1STakashi Iwai 		change |= snd_hda_codec_amp_update(codec, nid, 1, dir, idx,
216547fd830aSTakashi Iwai 						   HDA_AMP_MUTE,
2166eeecd9d1STakashi Iwai 						   *valp ? 0 : HDA_AMP_MUTE);
21679e5341b9STakashi Iwai 	hda_call_check_power_status(codec, nid);
21681da177e4SLinus Torvalds 	return change;
21691da177e4SLinus Torvalds }
21702698ea98STakashi Iwai EXPORT_SYMBOL_GPL(snd_hda_mixer_amp_switch_put);
21711da177e4SLinus Torvalds 
2172532d5381STakashi Iwai /*
21731da177e4SLinus Torvalds  * SPDIF out controls
21741da177e4SLinus Torvalds  */
21751da177e4SLinus Torvalds 
snd_hda_spdif_mask_info(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_info * uinfo)21760ba21762STakashi Iwai static int snd_hda_spdif_mask_info(struct snd_kcontrol *kcontrol,
21770ba21762STakashi Iwai 				   struct snd_ctl_elem_info *uinfo)
21781da177e4SLinus Torvalds {
21791da177e4SLinus Torvalds 	uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
21801da177e4SLinus Torvalds 	uinfo->count = 1;
21811da177e4SLinus Torvalds 	return 0;
21821da177e4SLinus Torvalds }
21831da177e4SLinus Torvalds 
snd_hda_spdif_cmask_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)21840ba21762STakashi Iwai static int snd_hda_spdif_cmask_get(struct snd_kcontrol *kcontrol,
21850ba21762STakashi Iwai 				   struct snd_ctl_elem_value *ucontrol)
21861da177e4SLinus Torvalds {
21871da177e4SLinus Torvalds 	ucontrol->value.iec958.status[0] = IEC958_AES0_PROFESSIONAL |
21881da177e4SLinus Torvalds 					   IEC958_AES0_NONAUDIO |
21891da177e4SLinus Torvalds 					   IEC958_AES0_CON_EMPHASIS_5015 |
21901da177e4SLinus Torvalds 					   IEC958_AES0_CON_NOT_COPYRIGHT;
21911da177e4SLinus Torvalds 	ucontrol->value.iec958.status[1] = IEC958_AES1_CON_CATEGORY |
21921da177e4SLinus Torvalds 					   IEC958_AES1_CON_ORIGINAL;
21931da177e4SLinus Torvalds 	return 0;
21941da177e4SLinus Torvalds }
21951da177e4SLinus Torvalds 
snd_hda_spdif_pmask_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)21960ba21762STakashi Iwai static int snd_hda_spdif_pmask_get(struct snd_kcontrol *kcontrol,
21970ba21762STakashi Iwai 				   struct snd_ctl_elem_value *ucontrol)
21981da177e4SLinus Torvalds {
21991da177e4SLinus Torvalds 	ucontrol->value.iec958.status[0] = IEC958_AES0_PROFESSIONAL |
22001da177e4SLinus Torvalds 					   IEC958_AES0_NONAUDIO |
22011da177e4SLinus Torvalds 					   IEC958_AES0_PRO_EMPHASIS_5015;
22021da177e4SLinus Torvalds 	return 0;
22031da177e4SLinus Torvalds }
22041da177e4SLinus Torvalds 
snd_hda_spdif_default_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)22050ba21762STakashi Iwai static int snd_hda_spdif_default_get(struct snd_kcontrol *kcontrol,
22060ba21762STakashi Iwai 				     struct snd_ctl_elem_value *ucontrol)
22071da177e4SLinus Torvalds {
22081da177e4SLinus Torvalds 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
22097c935976SStephen Warren 	int idx = kcontrol->private_value;
2210e3245cddSTakashi Iwai 	struct hda_spdif_out *spdif;
22111da177e4SLinus Torvalds 
221208605068STakashi Iwai 	if (WARN_ON(codec->spdif_out.used <= idx))
221308605068STakashi Iwai 		return -EINVAL;
2214e3245cddSTakashi Iwai 	mutex_lock(&codec->spdif_mutex);
2215e3245cddSTakashi Iwai 	spdif = snd_array_elem(&codec->spdif_out, idx);
22167c935976SStephen Warren 	ucontrol->value.iec958.status[0] = spdif->status & 0xff;
22177c935976SStephen Warren 	ucontrol->value.iec958.status[1] = (spdif->status >> 8) & 0xff;
22187c935976SStephen Warren 	ucontrol->value.iec958.status[2] = (spdif->status >> 16) & 0xff;
22197c935976SStephen Warren 	ucontrol->value.iec958.status[3] = (spdif->status >> 24) & 0xff;
2220e3245cddSTakashi Iwai 	mutex_unlock(&codec->spdif_mutex);
22211da177e4SLinus Torvalds 
22221da177e4SLinus Torvalds 	return 0;
22231da177e4SLinus Torvalds }
22241da177e4SLinus Torvalds 
22251da177e4SLinus Torvalds /* convert from SPDIF status bits to HDA SPDIF bits
22261da177e4SLinus Torvalds  * bit 0 (DigEn) is always set zero (to be filled later)
22271da177e4SLinus Torvalds  */
convert_from_spdif_status(unsigned int sbits)22281da177e4SLinus Torvalds static unsigned short convert_from_spdif_status(unsigned int sbits)
22291da177e4SLinus Torvalds {
22301da177e4SLinus Torvalds 	unsigned short val = 0;
22311da177e4SLinus Torvalds 
22321da177e4SLinus Torvalds 	if (sbits & IEC958_AES0_PROFESSIONAL)
22330ba21762STakashi Iwai 		val |= AC_DIG1_PROFESSIONAL;
22341da177e4SLinus Torvalds 	if (sbits & IEC958_AES0_NONAUDIO)
22350ba21762STakashi Iwai 		val |= AC_DIG1_NONAUDIO;
22361da177e4SLinus Torvalds 	if (sbits & IEC958_AES0_PROFESSIONAL) {
22370ba21762STakashi Iwai 		if ((sbits & IEC958_AES0_PRO_EMPHASIS) ==
22380ba21762STakashi Iwai 		    IEC958_AES0_PRO_EMPHASIS_5015)
22390ba21762STakashi Iwai 			val |= AC_DIG1_EMPHASIS;
22401da177e4SLinus Torvalds 	} else {
22410ba21762STakashi Iwai 		if ((sbits & IEC958_AES0_CON_EMPHASIS) ==
22420ba21762STakashi Iwai 		    IEC958_AES0_CON_EMPHASIS_5015)
22430ba21762STakashi Iwai 			val |= AC_DIG1_EMPHASIS;
22441da177e4SLinus Torvalds 		if (!(sbits & IEC958_AES0_CON_NOT_COPYRIGHT))
22450ba21762STakashi Iwai 			val |= AC_DIG1_COPYRIGHT;
22461da177e4SLinus Torvalds 		if (sbits & (IEC958_AES1_CON_ORIGINAL << 8))
22470ba21762STakashi Iwai 			val |= AC_DIG1_LEVEL;
22481da177e4SLinus Torvalds 		val |= sbits & (IEC958_AES1_CON_CATEGORY << 8);
22491da177e4SLinus Torvalds 	}
22501da177e4SLinus Torvalds 	return val;
22511da177e4SLinus Torvalds }
22521da177e4SLinus Torvalds 
22531da177e4SLinus Torvalds /* convert to SPDIF status bits from HDA SPDIF bits
22541da177e4SLinus Torvalds  */
convert_to_spdif_status(unsigned short val)22551da177e4SLinus Torvalds static unsigned int convert_to_spdif_status(unsigned short val)
22561da177e4SLinus Torvalds {
22571da177e4SLinus Torvalds 	unsigned int sbits = 0;
22581da177e4SLinus Torvalds 
22590ba21762STakashi Iwai 	if (val & AC_DIG1_NONAUDIO)
22601da177e4SLinus Torvalds 		sbits |= IEC958_AES0_NONAUDIO;
22610ba21762STakashi Iwai 	if (val & AC_DIG1_PROFESSIONAL)
22621da177e4SLinus Torvalds 		sbits |= IEC958_AES0_PROFESSIONAL;
22631da177e4SLinus Torvalds 	if (sbits & IEC958_AES0_PROFESSIONAL) {
2264a686fd14STakashi Iwai 		if (val & AC_DIG1_EMPHASIS)
22651da177e4SLinus Torvalds 			sbits |= IEC958_AES0_PRO_EMPHASIS_5015;
22661da177e4SLinus Torvalds 	} else {
22670ba21762STakashi Iwai 		if (val & AC_DIG1_EMPHASIS)
22681da177e4SLinus Torvalds 			sbits |= IEC958_AES0_CON_EMPHASIS_5015;
22690ba21762STakashi Iwai 		if (!(val & AC_DIG1_COPYRIGHT))
22701da177e4SLinus Torvalds 			sbits |= IEC958_AES0_CON_NOT_COPYRIGHT;
22710ba21762STakashi Iwai 		if (val & AC_DIG1_LEVEL)
22721da177e4SLinus Torvalds 			sbits |= (IEC958_AES1_CON_ORIGINAL << 8);
22731da177e4SLinus Torvalds 		sbits |= val & (0x7f << 8);
22741da177e4SLinus Torvalds 	}
22751da177e4SLinus Torvalds 	return sbits;
22761da177e4SLinus Torvalds }
22771da177e4SLinus Torvalds 
22789ab0cb30STakashi Iwai /* set digital convert verbs both for the given NID and its followers */
set_dig_out(struct hda_codec * codec,hda_nid_t nid,int mask,int val)22792f72853cSTakashi Iwai static void set_dig_out(struct hda_codec *codec, hda_nid_t nid,
2280a551d914STakashi Iwai 			int mask, int val)
22812f72853cSTakashi Iwai {
2282dda14410STakashi Iwai 	const hda_nid_t *d;
22832f72853cSTakashi Iwai 
2284a551d914STakashi Iwai 	snd_hdac_regmap_update(&codec->core, nid, AC_VERB_SET_DIGI_CONVERT_1,
2285a551d914STakashi Iwai 			       mask, val);
22869ab0cb30STakashi Iwai 	d = codec->follower_dig_outs;
22872f72853cSTakashi Iwai 	if (!d)
22882f72853cSTakashi Iwai 		return;
22892f72853cSTakashi Iwai 	for (; *d; d++)
22907d4b5e97STakashi Iwai 		snd_hdac_regmap_update(&codec->core, *d,
2291a551d914STakashi Iwai 				       AC_VERB_SET_DIGI_CONVERT_1, mask, val);
22922f72853cSTakashi Iwai }
22932f72853cSTakashi Iwai 
set_dig_out_convert(struct hda_codec * codec,hda_nid_t nid,int dig1,int dig2)22942f72853cSTakashi Iwai static inline void set_dig_out_convert(struct hda_codec *codec, hda_nid_t nid,
22952f72853cSTakashi Iwai 				       int dig1, int dig2)
22962f72853cSTakashi Iwai {
2297a551d914STakashi Iwai 	unsigned int mask = 0;
2298a551d914STakashi Iwai 	unsigned int val = 0;
2299a551d914STakashi Iwai 
2300a551d914STakashi Iwai 	if (dig1 != -1) {
2301a551d914STakashi Iwai 		mask |= 0xff;
2302a551d914STakashi Iwai 		val = dig1;
2303a551d914STakashi Iwai 	}
2304a551d914STakashi Iwai 	if (dig2 != -1) {
2305a551d914STakashi Iwai 		mask |= 0xff00;
2306a551d914STakashi Iwai 		val |= dig2 << 8;
2307a551d914STakashi Iwai 	}
2308a551d914STakashi Iwai 	set_dig_out(codec, nid, mask, val);
23092f72853cSTakashi Iwai }
23102f72853cSTakashi Iwai 
snd_hda_spdif_default_put(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)23110ba21762STakashi Iwai static int snd_hda_spdif_default_put(struct snd_kcontrol *kcontrol,
23120ba21762STakashi Iwai 				     struct snd_ctl_elem_value *ucontrol)
23131da177e4SLinus Torvalds {
23141da177e4SLinus Torvalds 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
23157c935976SStephen Warren 	int idx = kcontrol->private_value;
2316e3245cddSTakashi Iwai 	struct hda_spdif_out *spdif;
2317e3245cddSTakashi Iwai 	hda_nid_t nid;
23181da177e4SLinus Torvalds 	unsigned short val;
23191da177e4SLinus Torvalds 	int change;
23201da177e4SLinus Torvalds 
232108605068STakashi Iwai 	if (WARN_ON(codec->spdif_out.used <= idx))
232208605068STakashi Iwai 		return -EINVAL;
232362932df8SIngo Molnar 	mutex_lock(&codec->spdif_mutex);
2324e3245cddSTakashi Iwai 	spdif = snd_array_elem(&codec->spdif_out, idx);
2325e3245cddSTakashi Iwai 	nid = spdif->nid;
23267c935976SStephen Warren 	spdif->status = ucontrol->value.iec958.status[0] |
23271da177e4SLinus Torvalds 		((unsigned int)ucontrol->value.iec958.status[1] << 8) |
23281da177e4SLinus Torvalds 		((unsigned int)ucontrol->value.iec958.status[2] << 16) |
23291da177e4SLinus Torvalds 		((unsigned int)ucontrol->value.iec958.status[3] << 24);
23307c935976SStephen Warren 	val = convert_from_spdif_status(spdif->status);
23317c935976SStephen Warren 	val |= spdif->ctls & 1;
23327c935976SStephen Warren 	change = spdif->ctls != val;
23337c935976SStephen Warren 	spdif->ctls = val;
233474b654c9SStephen Warren 	if (change && nid != (u16)-1)
23352f72853cSTakashi Iwai 		set_dig_out_convert(codec, nid, val & 0xff, (val >> 8) & 0xff);
233662932df8SIngo Molnar 	mutex_unlock(&codec->spdif_mutex);
23371da177e4SLinus Torvalds 	return change;
23381da177e4SLinus Torvalds }
23391da177e4SLinus Torvalds 
2340a5ce8890STakashi Iwai #define snd_hda_spdif_out_switch_info	snd_ctl_boolean_mono_info
23411da177e4SLinus Torvalds 
snd_hda_spdif_out_switch_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)23420ba21762STakashi Iwai static int snd_hda_spdif_out_switch_get(struct snd_kcontrol *kcontrol,
23430ba21762STakashi Iwai 					struct snd_ctl_elem_value *ucontrol)
23441da177e4SLinus Torvalds {
23451da177e4SLinus Torvalds 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
23467c935976SStephen Warren 	int idx = kcontrol->private_value;
2347e3245cddSTakashi Iwai 	struct hda_spdif_out *spdif;
23481da177e4SLinus Torvalds 
234908605068STakashi Iwai 	if (WARN_ON(codec->spdif_out.used <= idx))
235008605068STakashi Iwai 		return -EINVAL;
2351e3245cddSTakashi Iwai 	mutex_lock(&codec->spdif_mutex);
2352e3245cddSTakashi Iwai 	spdif = snd_array_elem(&codec->spdif_out, idx);
23537c935976SStephen Warren 	ucontrol->value.integer.value[0] = spdif->ctls & AC_DIG1_ENABLE;
2354e3245cddSTakashi Iwai 	mutex_unlock(&codec->spdif_mutex);
23551da177e4SLinus Torvalds 	return 0;
23561da177e4SLinus Torvalds }
23571da177e4SLinus Torvalds 
set_spdif_ctls(struct hda_codec * codec,hda_nid_t nid,int dig1,int dig2)235874b654c9SStephen Warren static inline void set_spdif_ctls(struct hda_codec *codec, hda_nid_t nid,
235974b654c9SStephen Warren 				  int dig1, int dig2)
236074b654c9SStephen Warren {
236174b654c9SStephen Warren 	set_dig_out_convert(codec, nid, dig1, dig2);
236274b654c9SStephen Warren 	/* unmute amp switch (if any) */
236374b654c9SStephen Warren 	if ((get_wcaps(codec, nid) & AC_WCAP_OUT_AMP) &&
236474b654c9SStephen Warren 	    (dig1 & AC_DIG1_ENABLE))
236574b654c9SStephen Warren 		snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0,
236674b654c9SStephen Warren 					    HDA_AMP_MUTE, 0);
236774b654c9SStephen Warren }
236874b654c9SStephen Warren 
snd_hda_spdif_out_switch_put(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)23690ba21762STakashi Iwai static int snd_hda_spdif_out_switch_put(struct snd_kcontrol *kcontrol,
23700ba21762STakashi Iwai 					struct snd_ctl_elem_value *ucontrol)
23711da177e4SLinus Torvalds {
23721da177e4SLinus Torvalds 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
23737c935976SStephen Warren 	int idx = kcontrol->private_value;
2374e3245cddSTakashi Iwai 	struct hda_spdif_out *spdif;
2375e3245cddSTakashi Iwai 	hda_nid_t nid;
23761da177e4SLinus Torvalds 	unsigned short val;
23771da177e4SLinus Torvalds 	int change;
23781da177e4SLinus Torvalds 
237908605068STakashi Iwai 	if (WARN_ON(codec->spdif_out.used <= idx))
238008605068STakashi Iwai 		return -EINVAL;
238162932df8SIngo Molnar 	mutex_lock(&codec->spdif_mutex);
2382e3245cddSTakashi Iwai 	spdif = snd_array_elem(&codec->spdif_out, idx);
2383e3245cddSTakashi Iwai 	nid = spdif->nid;
23847c935976SStephen Warren 	val = spdif->ctls & ~AC_DIG1_ENABLE;
23851da177e4SLinus Torvalds 	if (ucontrol->value.integer.value[0])
23860ba21762STakashi Iwai 		val |= AC_DIG1_ENABLE;
23877c935976SStephen Warren 	change = spdif->ctls != val;
23887c935976SStephen Warren 	spdif->ctls = val;
238974b654c9SStephen Warren 	if (change && nid != (u16)-1)
239074b654c9SStephen Warren 		set_spdif_ctls(codec, nid, val & 0xff, -1);
239162932df8SIngo Molnar 	mutex_unlock(&codec->spdif_mutex);
23921da177e4SLinus Torvalds 	return change;
23931da177e4SLinus Torvalds }
23941da177e4SLinus Torvalds 
239535ace5e8STakashi Iwai static const struct snd_kcontrol_new dig_mixes[] = {
23961da177e4SLinus Torvalds 	{
23971da177e4SLinus Torvalds 		.access = SNDRV_CTL_ELEM_ACCESS_READ,
23981da177e4SLinus Torvalds 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
23991da177e4SLinus Torvalds 		.name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, CON_MASK),
24001da177e4SLinus Torvalds 		.info = snd_hda_spdif_mask_info,
24011da177e4SLinus Torvalds 		.get = snd_hda_spdif_cmask_get,
24021da177e4SLinus Torvalds 	},
24031da177e4SLinus Torvalds 	{
24041da177e4SLinus Torvalds 		.access = SNDRV_CTL_ELEM_ACCESS_READ,
24051da177e4SLinus Torvalds 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
24061da177e4SLinus Torvalds 		.name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, PRO_MASK),
24071da177e4SLinus Torvalds 		.info = snd_hda_spdif_mask_info,
24081da177e4SLinus Torvalds 		.get = snd_hda_spdif_pmask_get,
24091da177e4SLinus Torvalds 	},
24101da177e4SLinus Torvalds 	{
24111da177e4SLinus Torvalds 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
24121da177e4SLinus Torvalds 		.name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, DEFAULT),
24131da177e4SLinus Torvalds 		.info = snd_hda_spdif_mask_info,
24141da177e4SLinus Torvalds 		.get = snd_hda_spdif_default_get,
24151da177e4SLinus Torvalds 		.put = snd_hda_spdif_default_put,
24161da177e4SLinus Torvalds 	},
24171da177e4SLinus Torvalds 	{
24181da177e4SLinus Torvalds 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
24191da177e4SLinus Torvalds 		.name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, SWITCH),
24201da177e4SLinus Torvalds 		.info = snd_hda_spdif_out_switch_info,
24211da177e4SLinus Torvalds 		.get = snd_hda_spdif_out_switch_get,
24221da177e4SLinus Torvalds 		.put = snd_hda_spdif_out_switch_put,
24231da177e4SLinus Torvalds 	},
24241da177e4SLinus Torvalds 	{ } /* end */
24251da177e4SLinus Torvalds };
24261da177e4SLinus Torvalds 
24271da177e4SLinus Torvalds /**
2428dcda5806STakashi Iwai  * snd_hda_create_dig_out_ctls - create Output SPDIF-related controls
24291da177e4SLinus Torvalds  * @codec: the HDA codec
2430dcda5806STakashi Iwai  * @associated_nid: NID that new ctls associated with
2431dcda5806STakashi Iwai  * @cvt_nid: converter NID
2432dcda5806STakashi Iwai  * @type: HDA_PCM_TYPE_*
2433dcda5806STakashi Iwai  * Creates controls related with the digital output.
2434dcda5806STakashi Iwai  * Called from each patch supporting the digital out.
24351da177e4SLinus Torvalds  *
24361da177e4SLinus Torvalds  * Returns 0 if successful, or a negative error code.
24371da177e4SLinus Torvalds  */
snd_hda_create_dig_out_ctls(struct hda_codec * codec,hda_nid_t associated_nid,hda_nid_t cvt_nid,int type)2438dcda5806STakashi Iwai int snd_hda_create_dig_out_ctls(struct hda_codec *codec,
243974b654c9SStephen Warren 				hda_nid_t associated_nid,
2440dcda5806STakashi Iwai 				hda_nid_t cvt_nid,
2441dcda5806STakashi Iwai 				int type)
24421da177e4SLinus Torvalds {
24431da177e4SLinus Torvalds 	int err;
2444c8b6bf9bSTakashi Iwai 	struct snd_kcontrol *kctl;
244535ace5e8STakashi Iwai 	const struct snd_kcontrol_new *dig_mix;
2446ea9b43adSTakashi Iwai 	int idx = 0;
2447a551d914STakashi Iwai 	int val = 0;
2448ea9b43adSTakashi Iwai 	const int spdif_index = 16;
24497c935976SStephen Warren 	struct hda_spdif_out *spdif;
2450ea9b43adSTakashi Iwai 	struct hda_bus *bus = codec->bus;
24511da177e4SLinus Torvalds 
2452ea9b43adSTakashi Iwai 	if (bus->primary_dig_out_type == HDA_PCM_TYPE_HDMI &&
2453dcda5806STakashi Iwai 	    type == HDA_PCM_TYPE_SPDIF) {
2454ea9b43adSTakashi Iwai 		idx = spdif_index;
2455ea9b43adSTakashi Iwai 	} else if (bus->primary_dig_out_type == HDA_PCM_TYPE_SPDIF &&
2456dcda5806STakashi Iwai 		   type == HDA_PCM_TYPE_HDMI) {
2457ea9b43adSTakashi Iwai 		/* suppose a single SPDIF device */
2458dcda5806STakashi Iwai 		for (dig_mix = dig_mixes; dig_mix->name; dig_mix++) {
24595c219a34STakashi Iwai 			struct snd_ctl_elem_id id;
24605c219a34STakashi Iwai 
2461ea9b43adSTakashi Iwai 			kctl = find_mixer_ctl(codec, dig_mix->name, 0, 0);
2462dcda5806STakashi Iwai 			if (!kctl)
2463dcda5806STakashi Iwai 				break;
24645c219a34STakashi Iwai 			id = kctl->id;
24655c219a34STakashi Iwai 			id.index = spdif_index;
2466*edcb866aSWentao Liang 			err = snd_ctl_rename_id(codec->card, &kctl->id, &id);
2467*edcb866aSWentao Liang 			if (err < 0)
2468*edcb866aSWentao Liang 				return err;
2469dcda5806STakashi Iwai 		}
2470ea9b43adSTakashi Iwai 		bus->primary_dig_out_type = HDA_PCM_TYPE_HDMI;
2471dcda5806STakashi Iwai 	}
2472ea9b43adSTakashi Iwai 	if (!bus->primary_dig_out_type)
2473ea9b43adSTakashi Iwai 		bus->primary_dig_out_type = type;
2474dcda5806STakashi Iwai 
2475ea9b43adSTakashi Iwai 	idx = find_empty_mixer_ctl_idx(codec, "IEC958 Playback Switch", idx);
24761afe206aSTakashi Iwai 	if (idx < 0) {
24774e76a883STakashi Iwai 		codec_err(codec, "too many IEC958 outputs\n");
247809f99701STakashi Iwai 		return -EBUSY;
247909f99701STakashi Iwai 	}
24807c935976SStephen Warren 	spdif = snd_array_new(&codec->spdif_out);
248125336e8aSMengdong Lin 	if (!spdif)
248225336e8aSMengdong Lin 		return -ENOMEM;
24831da177e4SLinus Torvalds 	for (dig_mix = dig_mixes; dig_mix->name; dig_mix++) {
24841da177e4SLinus Torvalds 		kctl = snd_ctl_new1(dig_mix, codec);
2485b91f080fSTakashi Iwai 		if (!kctl)
2486b91f080fSTakashi Iwai 			return -ENOMEM;
248709f99701STakashi Iwai 		kctl->id.index = idx;
24887c935976SStephen Warren 		kctl->private_value = codec->spdif_out.used - 1;
248974b654c9SStephen Warren 		err = snd_hda_ctl_add(codec, associated_nid, kctl);
24900ba21762STakashi Iwai 		if (err < 0)
24911da177e4SLinus Torvalds 			return err;
24921da177e4SLinus Torvalds 	}
249374b654c9SStephen Warren 	spdif->nid = cvt_nid;
2494a551d914STakashi Iwai 	snd_hdac_regmap_read(&codec->core, cvt_nid,
2495a551d914STakashi Iwai 			     AC_VERB_GET_DIGI_CONVERT_1, &val);
2496a551d914STakashi Iwai 	spdif->ctls = val;
24977c935976SStephen Warren 	spdif->status = convert_to_spdif_status(spdif->ctls);
24981da177e4SLinus Torvalds 	return 0;
24991da177e4SLinus Torvalds }
25002698ea98STakashi Iwai EXPORT_SYMBOL_GPL(snd_hda_create_dig_out_ctls);
25011da177e4SLinus Torvalds 
250295a962c3STakashi Iwai /**
250395a962c3STakashi Iwai  * snd_hda_spdif_out_of_nid - get the hda_spdif_out entry from the given NID
250495a962c3STakashi Iwai  * @codec: the HDA codec
250595a962c3STakashi Iwai  * @nid: widget NID
250695a962c3STakashi Iwai  *
2507e3245cddSTakashi Iwai  * call within spdif_mutex lock
2508e3245cddSTakashi Iwai  */
snd_hda_spdif_out_of_nid(struct hda_codec * codec,hda_nid_t nid)25097c935976SStephen Warren struct hda_spdif_out *snd_hda_spdif_out_of_nid(struct hda_codec *codec,
25107c935976SStephen Warren 					       hda_nid_t nid)
25117c935976SStephen Warren {
2512a9c2dfc8STakashi Iwai 	struct hda_spdif_out *spdif;
25137c935976SStephen Warren 	int i;
2514a9c2dfc8STakashi Iwai 
2515a9c2dfc8STakashi Iwai 	snd_array_for_each(&codec->spdif_out, i, spdif) {
25167c935976SStephen Warren 		if (spdif->nid == nid)
25177c935976SStephen Warren 			return spdif;
25187c935976SStephen Warren 	}
25197c935976SStephen Warren 	return NULL;
25207c935976SStephen Warren }
25212698ea98STakashi Iwai EXPORT_SYMBOL_GPL(snd_hda_spdif_out_of_nid);
25227c935976SStephen Warren 
252395a962c3STakashi Iwai /**
252495a962c3STakashi Iwai  * snd_hda_spdif_ctls_unassign - Unassign the given SPDIF ctl
252595a962c3STakashi Iwai  * @codec: the HDA codec
252695a962c3STakashi Iwai  * @idx: the SPDIF ctl index
252795a962c3STakashi Iwai  *
252895a962c3STakashi Iwai  * Unassign the widget from the given SPDIF control.
252995a962c3STakashi Iwai  */
snd_hda_spdif_ctls_unassign(struct hda_codec * codec,int idx)253074b654c9SStephen Warren void snd_hda_spdif_ctls_unassign(struct hda_codec *codec, int idx)
253174b654c9SStephen Warren {
2532e3245cddSTakashi Iwai 	struct hda_spdif_out *spdif;
253374b654c9SStephen Warren 
253408605068STakashi Iwai 	if (WARN_ON(codec->spdif_out.used <= idx))
253508605068STakashi Iwai 		return;
253674b654c9SStephen Warren 	mutex_lock(&codec->spdif_mutex);
2537e3245cddSTakashi Iwai 	spdif = snd_array_elem(&codec->spdif_out, idx);
253874b654c9SStephen Warren 	spdif->nid = (u16)-1;
253974b654c9SStephen Warren 	mutex_unlock(&codec->spdif_mutex);
254074b654c9SStephen Warren }
25412698ea98STakashi Iwai EXPORT_SYMBOL_GPL(snd_hda_spdif_ctls_unassign);
254274b654c9SStephen Warren 
254395a962c3STakashi Iwai /**
254495a962c3STakashi Iwai  * snd_hda_spdif_ctls_assign - Assign the SPDIF controls to the given NID
254595a962c3STakashi Iwai  * @codec: the HDA codec
254695a962c3STakashi Iwai  * @idx: the SPDIF ctl idx
254795a962c3STakashi Iwai  * @nid: widget NID
254895a962c3STakashi Iwai  *
254995a962c3STakashi Iwai  * Assign the widget to the SPDIF control with the given index.
255095a962c3STakashi Iwai  */
snd_hda_spdif_ctls_assign(struct hda_codec * codec,int idx,hda_nid_t nid)255174b654c9SStephen Warren void snd_hda_spdif_ctls_assign(struct hda_codec *codec, int idx, hda_nid_t nid)
255274b654c9SStephen Warren {
2553e3245cddSTakashi Iwai 	struct hda_spdif_out *spdif;
255474b654c9SStephen Warren 	unsigned short val;
255574b654c9SStephen Warren 
255608605068STakashi Iwai 	if (WARN_ON(codec->spdif_out.used <= idx))
255708605068STakashi Iwai 		return;
255874b654c9SStephen Warren 	mutex_lock(&codec->spdif_mutex);
2559e3245cddSTakashi Iwai 	spdif = snd_array_elem(&codec->spdif_out, idx);
256074b654c9SStephen Warren 	if (spdif->nid != nid) {
256174b654c9SStephen Warren 		spdif->nid = nid;
256274b654c9SStephen Warren 		val = spdif->ctls;
256374b654c9SStephen Warren 		set_spdif_ctls(codec, nid, val & 0xff, (val >> 8) & 0xff);
256474b654c9SStephen Warren 	}
256574b654c9SStephen Warren 	mutex_unlock(&codec->spdif_mutex);
256674b654c9SStephen Warren }
25672698ea98STakashi Iwai EXPORT_SYMBOL_GPL(snd_hda_spdif_ctls_assign);
256874b654c9SStephen Warren 
25691da177e4SLinus Torvalds /*
25709a08160bSTakashi Iwai  * SPDIF sharing with analog output
25719a08160bSTakashi Iwai  */
spdif_share_sw_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)25729a08160bSTakashi Iwai static int spdif_share_sw_get(struct snd_kcontrol *kcontrol,
25739a08160bSTakashi Iwai 			      struct snd_ctl_elem_value *ucontrol)
25749a08160bSTakashi Iwai {
25759a08160bSTakashi Iwai 	struct hda_multi_out *mout = snd_kcontrol_chip(kcontrol);
25769a08160bSTakashi Iwai 	ucontrol->value.integer.value[0] = mout->share_spdif;
25779a08160bSTakashi Iwai 	return 0;
25789a08160bSTakashi Iwai }
25799a08160bSTakashi Iwai 
spdif_share_sw_put(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)25809a08160bSTakashi Iwai static int spdif_share_sw_put(struct snd_kcontrol *kcontrol,
25819a08160bSTakashi Iwai 			      struct snd_ctl_elem_value *ucontrol)
25829a08160bSTakashi Iwai {
25839a08160bSTakashi Iwai 	struct hda_multi_out *mout = snd_kcontrol_chip(kcontrol);
25849a08160bSTakashi Iwai 	mout->share_spdif = !!ucontrol->value.integer.value[0];
25859a08160bSTakashi Iwai 	return 0;
25869a08160bSTakashi Iwai }
25879a08160bSTakashi Iwai 
2588f3b827e0SBhumika Goyal static const struct snd_kcontrol_new spdif_share_sw = {
25899a08160bSTakashi Iwai 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
25909a08160bSTakashi Iwai 	.name = "IEC958 Default PCM Playback Switch",
25919a08160bSTakashi Iwai 	.info = snd_ctl_boolean_mono_info,
25929a08160bSTakashi Iwai 	.get = spdif_share_sw_get,
25939a08160bSTakashi Iwai 	.put = spdif_share_sw_put,
25949a08160bSTakashi Iwai };
25959a08160bSTakashi Iwai 
2596d5191e50STakashi Iwai /**
2597d5191e50STakashi Iwai  * snd_hda_create_spdif_share_sw - create Default PCM switch
2598d5191e50STakashi Iwai  * @codec: the HDA codec
2599d5191e50STakashi Iwai  * @mout: multi-out instance
2600d5191e50STakashi Iwai  */
snd_hda_create_spdif_share_sw(struct hda_codec * codec,struct hda_multi_out * mout)26019a08160bSTakashi Iwai int snd_hda_create_spdif_share_sw(struct hda_codec *codec,
26029a08160bSTakashi Iwai 				  struct hda_multi_out *mout)
26039a08160bSTakashi Iwai {
26044c7a548aSMengdong Lin 	struct snd_kcontrol *kctl;
26054c7a548aSMengdong Lin 
26069a08160bSTakashi Iwai 	if (!mout->dig_out_nid)
26079a08160bSTakashi Iwai 		return 0;
26084c7a548aSMengdong Lin 
26094c7a548aSMengdong Lin 	kctl = snd_ctl_new1(&spdif_share_sw, mout);
26104c7a548aSMengdong Lin 	if (!kctl)
26114c7a548aSMengdong Lin 		return -ENOMEM;
26129a08160bSTakashi Iwai 	/* ATTENTION: here mout is passed as private_data, instead of codec */
26134c7a548aSMengdong Lin 	return snd_hda_ctl_add(codec, mout->dig_out_nid, kctl);
26149a08160bSTakashi Iwai }
26152698ea98STakashi Iwai EXPORT_SYMBOL_GPL(snd_hda_create_spdif_share_sw);
26169a08160bSTakashi Iwai 
26179a08160bSTakashi Iwai /*
26181da177e4SLinus Torvalds  * SPDIF input
26191da177e4SLinus Torvalds  */
26201da177e4SLinus Torvalds 
26211da177e4SLinus Torvalds #define snd_hda_spdif_in_switch_info	snd_hda_spdif_out_switch_info
26221da177e4SLinus Torvalds 
snd_hda_spdif_in_switch_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)26230ba21762STakashi Iwai static int snd_hda_spdif_in_switch_get(struct snd_kcontrol *kcontrol,
26240ba21762STakashi Iwai 				       struct snd_ctl_elem_value *ucontrol)
26251da177e4SLinus Torvalds {
26261da177e4SLinus Torvalds 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
26271da177e4SLinus Torvalds 
26281da177e4SLinus Torvalds 	ucontrol->value.integer.value[0] = codec->spdif_in_enable;
26291da177e4SLinus Torvalds 	return 0;
26301da177e4SLinus Torvalds }
26311da177e4SLinus Torvalds 
snd_hda_spdif_in_switch_put(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)26320ba21762STakashi Iwai static int snd_hda_spdif_in_switch_put(struct snd_kcontrol *kcontrol,
26330ba21762STakashi Iwai 				       struct snd_ctl_elem_value *ucontrol)
26341da177e4SLinus Torvalds {
26351da177e4SLinus Torvalds 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
26361da177e4SLinus Torvalds 	hda_nid_t nid = kcontrol->private_value;
26371da177e4SLinus Torvalds 	unsigned int val = !!ucontrol->value.integer.value[0];
26381da177e4SLinus Torvalds 	int change;
26391da177e4SLinus Torvalds 
264062932df8SIngo Molnar 	mutex_lock(&codec->spdif_mutex);
26411da177e4SLinus Torvalds 	change = codec->spdif_in_enable != val;
264282beb8fdSTakashi Iwai 	if (change) {
26431da177e4SLinus Torvalds 		codec->spdif_in_enable = val;
2644a551d914STakashi Iwai 		snd_hdac_regmap_write(&codec->core, nid,
264582beb8fdSTakashi Iwai 				      AC_VERB_SET_DIGI_CONVERT_1, val);
26461da177e4SLinus Torvalds 	}
264762932df8SIngo Molnar 	mutex_unlock(&codec->spdif_mutex);
26481da177e4SLinus Torvalds 	return change;
26491da177e4SLinus Torvalds }
26501da177e4SLinus Torvalds 
snd_hda_spdif_in_status_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)26510ba21762STakashi Iwai static int snd_hda_spdif_in_status_get(struct snd_kcontrol *kcontrol,
26520ba21762STakashi Iwai 				       struct snd_ctl_elem_value *ucontrol)
26531da177e4SLinus Torvalds {
26541da177e4SLinus Torvalds 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
26551da177e4SLinus Torvalds 	hda_nid_t nid = kcontrol->private_value;
2656a551d914STakashi Iwai 	unsigned int val;
26571da177e4SLinus Torvalds 	unsigned int sbits;
26581da177e4SLinus Torvalds 
2659a551d914STakashi Iwai 	snd_hdac_regmap_read(&codec->core, nid,
2660a551d914STakashi Iwai 			     AC_VERB_GET_DIGI_CONVERT_1, &val);
26611da177e4SLinus Torvalds 	sbits = convert_to_spdif_status(val);
26621da177e4SLinus Torvalds 	ucontrol->value.iec958.status[0] = sbits;
26631da177e4SLinus Torvalds 	ucontrol->value.iec958.status[1] = sbits >> 8;
26641da177e4SLinus Torvalds 	ucontrol->value.iec958.status[2] = sbits >> 16;
26651da177e4SLinus Torvalds 	ucontrol->value.iec958.status[3] = sbits >> 24;
26661da177e4SLinus Torvalds 	return 0;
26671da177e4SLinus Torvalds }
26681da177e4SLinus Torvalds 
266935ace5e8STakashi Iwai static const struct snd_kcontrol_new dig_in_ctls[] = {
26701da177e4SLinus Torvalds 	{
26711da177e4SLinus Torvalds 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
26721da177e4SLinus Torvalds 		.name = SNDRV_CTL_NAME_IEC958("", CAPTURE, SWITCH),
26731da177e4SLinus Torvalds 		.info = snd_hda_spdif_in_switch_info,
26741da177e4SLinus Torvalds 		.get = snd_hda_spdif_in_switch_get,
26751da177e4SLinus Torvalds 		.put = snd_hda_spdif_in_switch_put,
26761da177e4SLinus Torvalds 	},
26771da177e4SLinus Torvalds 	{
26781da177e4SLinus Torvalds 		.access = SNDRV_CTL_ELEM_ACCESS_READ,
26791da177e4SLinus Torvalds 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
26801da177e4SLinus Torvalds 		.name = SNDRV_CTL_NAME_IEC958("", CAPTURE, DEFAULT),
26811da177e4SLinus Torvalds 		.info = snd_hda_spdif_mask_info,
26821da177e4SLinus Torvalds 		.get = snd_hda_spdif_in_status_get,
26831da177e4SLinus Torvalds 	},
26841da177e4SLinus Torvalds 	{ } /* end */
26851da177e4SLinus Torvalds };
26861da177e4SLinus Torvalds 
26871da177e4SLinus Torvalds /**
26881da177e4SLinus Torvalds  * snd_hda_create_spdif_in_ctls - create Input SPDIF-related controls
26891da177e4SLinus Torvalds  * @codec: the HDA codec
26901da177e4SLinus Torvalds  * @nid: audio in widget NID
26911da177e4SLinus Torvalds  *
26921da177e4SLinus Torvalds  * Creates controls related with the SPDIF input.
26931da177e4SLinus Torvalds  * Called from each patch supporting the SPDIF in.
26941da177e4SLinus Torvalds  *
26951da177e4SLinus Torvalds  * Returns 0 if successful, or a negative error code.
26961da177e4SLinus Torvalds  */
snd_hda_create_spdif_in_ctls(struct hda_codec * codec,hda_nid_t nid)269712f288bfSTakashi Iwai int snd_hda_create_spdif_in_ctls(struct hda_codec *codec, hda_nid_t nid)
26981da177e4SLinus Torvalds {
26991da177e4SLinus Torvalds 	int err;
2700c8b6bf9bSTakashi Iwai 	struct snd_kcontrol *kctl;
270135ace5e8STakashi Iwai 	const struct snd_kcontrol_new *dig_mix;
270209f99701STakashi Iwai 	int idx;
27031da177e4SLinus Torvalds 
2704dcda5806STakashi Iwai 	idx = find_empty_mixer_ctl_idx(codec, "IEC958 Capture Switch", 0);
27051afe206aSTakashi Iwai 	if (idx < 0) {
27064e76a883STakashi Iwai 		codec_err(codec, "too many IEC958 inputs\n");
270709f99701STakashi Iwai 		return -EBUSY;
270809f99701STakashi Iwai 	}
27091da177e4SLinus Torvalds 	for (dig_mix = dig_in_ctls; dig_mix->name; dig_mix++) {
27101da177e4SLinus Torvalds 		kctl = snd_ctl_new1(dig_mix, codec);
2711c8dcdf82STakashi Iwai 		if (!kctl)
2712c8dcdf82STakashi Iwai 			return -ENOMEM;
27131da177e4SLinus Torvalds 		kctl->private_value = nid;
27143911a4c1SJaroslav Kysela 		err = snd_hda_ctl_add(codec, nid, kctl);
27150ba21762STakashi Iwai 		if (err < 0)
27161da177e4SLinus Torvalds 			return err;
27171da177e4SLinus Torvalds 	}
27180ba21762STakashi Iwai 	codec->spdif_in_enable =
27193982d17eSAndrew Paprocki 		snd_hda_codec_read(codec, nid, 0,
27203982d17eSAndrew Paprocki 				   AC_VERB_GET_DIGI_CONVERT_1, 0) &
27210ba21762STakashi Iwai 		AC_DIG1_ENABLE;
27221da177e4SLinus Torvalds 	return 0;
27231da177e4SLinus Torvalds }
27242698ea98STakashi Iwai EXPORT_SYMBOL_GPL(snd_hda_create_spdif_in_ctls);
27251da177e4SLinus Torvalds 
272695a962c3STakashi Iwai /**
272795a962c3STakashi Iwai  * snd_hda_codec_set_power_to_all - Set the power state to all widgets
272895a962c3STakashi Iwai  * @codec: the HDA codec
272995a962c3STakashi Iwai  * @fg: function group (not used now)
273095a962c3STakashi Iwai  * @power_state: the power state to set (AC_PWRST_*)
273195a962c3STakashi Iwai  *
273295a962c3STakashi Iwai  * Set the given power state to all widgets that have the power control.
273395a962c3STakashi Iwai  * If the codec has power_filter set, it evaluates the power state and
273495a962c3STakashi Iwai  * filter out if it's unchanged as D3.
273595a962c3STakashi Iwai  */
snd_hda_codec_set_power_to_all(struct hda_codec * codec,hda_nid_t fg,unsigned int power_state)27364d7fbdbcSTakashi Iwai void snd_hda_codec_set_power_to_all(struct hda_codec *codec, hda_nid_t fg,
27379419ab6bSTakashi Iwai 				    unsigned int power_state)
273854d17403STakashi Iwai {
27397639a06cSTakashi Iwai 	hda_nid_t nid;
274054d17403STakashi Iwai 
27417639a06cSTakashi Iwai 	for_each_hda_codec_node(nid, codec) {
27427eba5c9dSTakashi Iwai 		unsigned int wcaps = get_wcaps(codec, nid);
27439419ab6bSTakashi Iwai 		unsigned int state = power_state;
27444d7fbdbcSTakashi Iwai 		if (!(wcaps & AC_WCAP_POWER))
27454d7fbdbcSTakashi Iwai 			continue;
27469419ab6bSTakashi Iwai 		if (codec->power_filter) {
27479419ab6bSTakashi Iwai 			state = codec->power_filter(codec, nid, power_state);
27489419ab6bSTakashi Iwai 			if (state != power_state && power_state == AC_PWRST_D3)
27491194b5b7STakashi Iwai 				continue;
27501194b5b7STakashi Iwai 		}
27514d7fbdbcSTakashi Iwai 		snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_POWER_STATE,
27529419ab6bSTakashi Iwai 				    state);
275354d17403STakashi Iwai 	}
2754cb53c626STakashi Iwai }
27552698ea98STakashi Iwai EXPORT_SYMBOL_GPL(snd_hda_codec_set_power_to_all);
27564d7fbdbcSTakashi Iwai 
275795a962c3STakashi Iwai /**
275895a962c3STakashi Iwai  * snd_hda_codec_eapd_power_filter - A power filter callback for EAPD
275995a962c3STakashi Iwai  * @codec: the HDA codec
276095a962c3STakashi Iwai  * @nid: widget NID
276195a962c3STakashi Iwai  * @power_state: power state to evalue
276295a962c3STakashi Iwai  *
276395a962c3STakashi Iwai  * Don't power down the widget if it controls eapd and EAPD_BTLENABLE is set.
276495a962c3STakashi Iwai  * This can be used a codec power_filter callback.
276595a962c3STakashi Iwai  */
snd_hda_codec_eapd_power_filter(struct hda_codec * codec,hda_nid_t nid,unsigned int power_state)2766ba615b86STakashi Iwai unsigned int snd_hda_codec_eapd_power_filter(struct hda_codec *codec,
2767ba615b86STakashi Iwai 					     hda_nid_t nid,
27689419ab6bSTakashi Iwai 					     unsigned int power_state)
27699419ab6bSTakashi Iwai {
27707639a06cSTakashi Iwai 	if (nid == codec->core.afg || nid == codec->core.mfg)
2771dfc6e469STakashi Iwai 		return power_state;
27729419ab6bSTakashi Iwai 	if (power_state == AC_PWRST_D3 &&
27739419ab6bSTakashi Iwai 	    get_wcaps_type(get_wcaps(codec, nid)) == AC_WID_PIN &&
27749419ab6bSTakashi Iwai 	    (snd_hda_query_pin_caps(codec, nid) & AC_PINCAP_EAPD)) {
27759419ab6bSTakashi Iwai 		int eapd = snd_hda_codec_read(codec, nid, 0,
27769419ab6bSTakashi Iwai 					      AC_VERB_GET_EAPD_BTLENABLE, 0);
27779419ab6bSTakashi Iwai 		if (eapd & 0x02)
27789419ab6bSTakashi Iwai 			return AC_PWRST_D0;
27799419ab6bSTakashi Iwai 	}
27809419ab6bSTakashi Iwai 	return power_state;
27819419ab6bSTakashi Iwai }
27822698ea98STakashi Iwai EXPORT_SYMBOL_GPL(snd_hda_codec_eapd_power_filter);
27839419ab6bSTakashi Iwai 
2784432c641eSTakashi Iwai /*
278508fa20aeSTakashi Iwai  * set power state of the codec, and return the power state
27864d7fbdbcSTakashi Iwai  */
hda_set_power_state(struct hda_codec * codec,unsigned int power_state)2787d819387eSTakashi Iwai static unsigned int hda_set_power_state(struct hda_codec *codec,
27884d7fbdbcSTakashi Iwai 					unsigned int power_state)
27894d7fbdbcSTakashi Iwai {
27907639a06cSTakashi Iwai 	hda_nid_t fg = codec->core.afg ? codec->core.afg : codec->core.mfg;
279109617ce4SWang Xingchao 	int count;
279209617ce4SWang Xingchao 	unsigned int state;
279363e51fd7STakashi Iwai 	int flags = 0;
279409617ce4SWang Xingchao 
27954d7fbdbcSTakashi Iwai 	/* this delay seems necessary to avoid click noise at power-down */
27960f4ccbb0SWang Xingchao 	if (power_state == AC_PWRST_D3) {
27977f132927SMengdong Lin 		if (codec->depop_delay < 0)
27987639a06cSTakashi Iwai 			msleep(codec_has_epss(codec) ? 10 : 100);
27997f132927SMengdong Lin 		else if (codec->depop_delay > 0)
28007f132927SMengdong Lin 			msleep(codec->depop_delay);
280163e51fd7STakashi Iwai 		flags = HDA_RW_NO_RESPONSE_FALLBACK;
28020f4ccbb0SWang Xingchao 	}
280309617ce4SWang Xingchao 
280409617ce4SWang Xingchao 	/* repeat power states setting at most 10 times*/
280509617ce4SWang Xingchao 	for (count = 0; count < 10; count++) {
2806432c641eSTakashi Iwai 		if (codec->patch_ops.set_power_state)
2807432c641eSTakashi Iwai 			codec->patch_ops.set_power_state(codec, fg,
28084d7fbdbcSTakashi Iwai 							 power_state);
2809432c641eSTakashi Iwai 		else {
2810dfc6e469STakashi Iwai 			state = power_state;
2811dfc6e469STakashi Iwai 			if (codec->power_filter)
2812dfc6e469STakashi Iwai 				state = codec->power_filter(codec, fg, state);
2813dfc6e469STakashi Iwai 			if (state == power_state || power_state != AC_PWRST_D3)
281463e51fd7STakashi Iwai 				snd_hda_codec_read(codec, fg, flags,
2815432c641eSTakashi Iwai 						   AC_VERB_SET_POWER_STATE,
2816dfc6e469STakashi Iwai 						   state);
28179419ab6bSTakashi Iwai 			snd_hda_codec_set_power_to_all(codec, fg, power_state);
2818432c641eSTakashi Iwai 		}
28193b5b899cSAbhijeet Kumar 		state = snd_hda_sync_power_state(codec, fg, power_state);
282009617ce4SWang Xingchao 		if (!(state & AC_PWRST_ERROR))
282109617ce4SWang Xingchao 			break;
282209617ce4SWang Xingchao 	}
2823b8dfc462SMengdong Lin 
282408fa20aeSTakashi Iwai 	return state;
28254d7fbdbcSTakashi Iwai }
2826cb53c626STakashi Iwai 
2827b9c590bbSTakashi Iwai /* sync power states of all widgets;
2828b9c590bbSTakashi Iwai  * this is called at the end of codec parsing
2829b9c590bbSTakashi Iwai  */
sync_power_up_states(struct hda_codec * codec)2830b9c590bbSTakashi Iwai static void sync_power_up_states(struct hda_codec *codec)
2831b9c590bbSTakashi Iwai {
28327639a06cSTakashi Iwai 	hda_nid_t nid;
2833b9c590bbSTakashi Iwai 
2834ba615b86STakashi Iwai 	/* don't care if no filter is used */
2835ba615b86STakashi Iwai 	if (!codec->power_filter)
2836b9c590bbSTakashi Iwai 		return;
2837b9c590bbSTakashi Iwai 
28387639a06cSTakashi Iwai 	for_each_hda_codec_node(nid, codec) {
2839b9c590bbSTakashi Iwai 		unsigned int wcaps = get_wcaps(codec, nid);
28409040d102STakashi Iwai 		unsigned int target;
2841b9c590bbSTakashi Iwai 		if (!(wcaps & AC_WCAP_POWER))
2842b9c590bbSTakashi Iwai 			continue;
2843b9c590bbSTakashi Iwai 		target = codec->power_filter(codec, nid, AC_PWRST_D0);
2844b9c590bbSTakashi Iwai 		if (target == AC_PWRST_D0)
2845b9c590bbSTakashi Iwai 			continue;
28469040d102STakashi Iwai 		if (!snd_hda_check_power_state(codec, nid, target))
2847b9c590bbSTakashi Iwai 			snd_hda_codec_write(codec, nid, 0,
2848b9c590bbSTakashi Iwai 					    AC_VERB_SET_POWER_STATE, target);
2849b9c590bbSTakashi Iwai 	}
2850b9c590bbSTakashi Iwai }
2851b9c590bbSTakashi Iwai 
2852648a8d27STakashi Iwai #ifdef CONFIG_SND_HDA_RECONFIG
285311aeff08STakashi Iwai /* execute additional init verbs */
hda_exec_init_verbs(struct hda_codec * codec)285411aeff08STakashi Iwai static void hda_exec_init_verbs(struct hda_codec *codec)
285511aeff08STakashi Iwai {
285611aeff08STakashi Iwai 	if (codec->init_verbs.list)
285711aeff08STakashi Iwai 		snd_hda_sequence_write(codec, codec->init_verbs.list);
285811aeff08STakashi Iwai }
285911aeff08STakashi Iwai #else
hda_exec_init_verbs(struct hda_codec * codec)286011aeff08STakashi Iwai static inline void hda_exec_init_verbs(struct hda_codec *codec) {}
286111aeff08STakashi Iwai #endif
286211aeff08STakashi Iwai 
28632a43952aSTakashi Iwai #ifdef CONFIG_PM
2864cc72da7dSTakashi Iwai /* update the power on/off account with the current jiffies */
update_power_acct(struct hda_codec * codec,bool on)2865cc72da7dSTakashi Iwai static void update_power_acct(struct hda_codec *codec, bool on)
2866cc72da7dSTakashi Iwai {
2867cc72da7dSTakashi Iwai 	unsigned long delta = jiffies - codec->power_jiffies;
2868cc72da7dSTakashi Iwai 
2869cc72da7dSTakashi Iwai 	if (on)
2870cc72da7dSTakashi Iwai 		codec->power_on_acct += delta;
2871cc72da7dSTakashi Iwai 	else
2872cc72da7dSTakashi Iwai 		codec->power_off_acct += delta;
2873cc72da7dSTakashi Iwai 	codec->power_jiffies += delta;
2874cc72da7dSTakashi Iwai }
2875cc72da7dSTakashi Iwai 
snd_hda_update_power_acct(struct hda_codec * codec)2876cc72da7dSTakashi Iwai void snd_hda_update_power_acct(struct hda_codec *codec)
2877cc72da7dSTakashi Iwai {
2878cc72da7dSTakashi Iwai 	update_power_acct(codec, hda_codec_is_power_on(codec));
2879cc72da7dSTakashi Iwai }
2880cc72da7dSTakashi Iwai 
2881cb53c626STakashi Iwai /*
2882cb53c626STakashi Iwai  * call suspend and power-down; used both from PM and power-save
288308fa20aeSTakashi Iwai  * this function returns the power state in the end
2884cb53c626STakashi Iwai  */
hda_call_codec_suspend(struct hda_codec * codec)2885cc72da7dSTakashi Iwai static unsigned int hda_call_codec_suspend(struct hda_codec *codec)
2886cb53c626STakashi Iwai {
288708fa20aeSTakashi Iwai 	unsigned int state;
288808fa20aeSTakashi Iwai 
2889feb20faeSTakashi Iwai 	snd_hdac_enter_pm(&codec->core);
2890cb53c626STakashi Iwai 	if (codec->patch_ops.suspend)
289168cb2b55STakashi Iwai 		codec->patch_ops.suspend(codec);
2892ee0b089dSKai Vehmanen 	if (!codec->no_stream_clean_at_suspend)
2893eb541337STakashi Iwai 		hda_cleanup_all_streams(codec);
2894d819387eSTakashi Iwai 	state = hda_set_power_state(codec, AC_PWRST_D3);
2895cc72da7dSTakashi Iwai 	update_power_acct(codec, true);
2896feb20faeSTakashi Iwai 	snd_hdac_leave_pm(&codec->core);
289708fa20aeSTakashi Iwai 	return state;
2898cb53c626STakashi Iwai }
2899cb53c626STakashi Iwai 
2900cb53c626STakashi Iwai /*
2901cb53c626STakashi Iwai  * kick up codec; used both from PM and power-save
2902cb53c626STakashi Iwai  */
hda_call_codec_resume(struct hda_codec * codec)2903cb53c626STakashi Iwai static void hda_call_codec_resume(struct hda_codec *codec)
2904cb53c626STakashi Iwai {
2905feb20faeSTakashi Iwai 	snd_hdac_enter_pm(&codec->core);
2906eeecd9d1STakashi Iwai 	if (codec->core.regmap)
2907eeecd9d1STakashi Iwai 		regcache_mark_dirty(codec->core.regmap);
2908eeecd9d1STakashi Iwai 
2909cc72da7dSTakashi Iwai 	codec->power_jiffies = jiffies;
2910cc72da7dSTakashi Iwai 
2911d819387eSTakashi Iwai 	hda_set_power_state(codec, AC_PWRST_D0);
2912ac0547dcSTakashi Iwai 	restore_shutup_pins(codec);
291311aeff08STakashi Iwai 	hda_exec_init_verbs(codec);
291431614bb8STakashi Iwai 	snd_hda_jack_set_dirty_all(codec);
2915cb53c626STakashi Iwai 	if (codec->patch_ops.resume)
2916cb53c626STakashi Iwai 		codec->patch_ops.resume(codec);
2917cb53c626STakashi Iwai 	else {
29189d99f312STakashi Iwai 		if (codec->patch_ops.init)
2919cb53c626STakashi Iwai 			codec->patch_ops.init(codec);
29201a462be5STakashi Iwai 		snd_hda_regmap_sync(codec);
2921cb53c626STakashi Iwai 	}
292226a6cb6cSDavid Henningsson 
292326a6cb6cSDavid Henningsson 	if (codec->jackpoll_interval)
292426a6cb6cSDavid Henningsson 		hda_jackpoll_work(&codec->jackpoll_work.work);
292531614bb8STakashi Iwai 	else
29268a535414STakashi Iwai 		snd_hda_jack_report_sync(codec);
292798081ca6STakashi Iwai 	codec->core.dev.power.power_state = PMSG_ON;
2928feb20faeSTakashi Iwai 	snd_hdac_leave_pm(&codec->core);
2929cb53c626STakashi Iwai }
293059ed1eadSTakashi Iwai 
hda_codec_runtime_suspend(struct device * dev)29312b73649cSKai-Heng Feng static int hda_codec_runtime_suspend(struct device *dev)
293259ed1eadSTakashi Iwai {
293359ed1eadSTakashi Iwai 	struct hda_codec *codec = dev_to_hda_codec(dev);
2934cc72da7dSTakashi Iwai 	unsigned int state;
293559ed1eadSTakashi Iwai 
29367fcd9bb5SRanjani Sridharan 	/* Nothing to do if card registration fails and the component driver never probes */
29377fcd9bb5SRanjani Sridharan 	if (!codec->card)
29387fcd9bb5SRanjani Sridharan 		return 0;
29397fcd9bb5SRanjani Sridharan 
294059ed1eadSTakashi Iwai 	cancel_delayed_work_sync(&codec->jackpoll_work);
2941b33115bdSMohan Kumar 
2942cc72da7dSTakashi Iwai 	state = hda_call_codec_suspend(codec);
294357cb54e5STakashi Iwai 	if (codec->link_down_at_suspend ||
294457cb54e5STakashi Iwai 	    (codec_has_clkstop(codec) && codec_has_epss(codec) &&
294557cb54e5STakashi Iwai 	     (state & AC_PWRST_CLK_STOP_OK)))
29467639a06cSTakashi Iwai 		snd_hdac_codec_link_down(&codec->core);
29473099406eSImre Deak 	snd_hda_codec_display_power(codec, false);
2948636aa880SMohan Kumar 
2949636aa880SMohan Kumar 	if (codec->bus->jackpoll_in_suspend &&
2950636aa880SMohan Kumar 		(dev->power.power_state.event != PM_EVENT_SUSPEND))
2951636aa880SMohan Kumar 		schedule_delayed_work(&codec->jackpoll_work,
2952636aa880SMohan Kumar 					codec->jackpoll_interval);
295359ed1eadSTakashi Iwai 	return 0;
295459ed1eadSTakashi Iwai }
295559ed1eadSTakashi Iwai 
hda_codec_runtime_resume(struct device * dev)29562b73649cSKai-Heng Feng static int hda_codec_runtime_resume(struct device *dev)
295759ed1eadSTakashi Iwai {
295855ed9cd1STakashi Iwai 	struct hda_codec *codec = dev_to_hda_codec(dev);
295955ed9cd1STakashi Iwai 
29607fcd9bb5SRanjani Sridharan 	/* Nothing to do if card registration fails and the component driver never probes */
29617fcd9bb5SRanjani Sridharan 	if (!codec->card)
29627fcd9bb5SRanjani Sridharan 		return 0;
29637fcd9bb5SRanjani Sridharan 
29643099406eSImre Deak 	snd_hda_codec_display_power(codec, true);
29657639a06cSTakashi Iwai 	snd_hdac_codec_link_up(&codec->core);
296655ed9cd1STakashi Iwai 	hda_call_codec_resume(codec);
2967cc72da7dSTakashi Iwai 	pm_runtime_mark_last_busy(dev);
296859ed1eadSTakashi Iwai 	return 0;
296959ed1eadSTakashi Iwai }
2970215a22edSKai-Heng Feng 
29712a43952aSTakashi Iwai #endif /* CONFIG_PM */
297254d17403STakashi Iwai 
297398081ca6STakashi Iwai #ifdef CONFIG_PM_SLEEP
hda_codec_pm_prepare(struct device * dev)2974215a22edSKai-Heng Feng static int hda_codec_pm_prepare(struct device *dev)
2975215a22edSKai-Heng Feng {
2976636aa880SMohan Kumar 	struct hda_codec *codec = dev_to_hda_codec(dev);
2977636aa880SMohan Kumar 
2978636aa880SMohan Kumar 	cancel_delayed_work_sync(&codec->jackpoll_work);
2979b8b90c17SHui Wang 	dev->power.power_state = PMSG_SUSPEND;
2980215a22edSKai-Heng Feng 	return pm_runtime_suspended(dev);
2981215a22edSKai-Heng Feng }
2982215a22edSKai-Heng Feng 
hda_codec_pm_complete(struct device * dev)2983215a22edSKai-Heng Feng static void hda_codec_pm_complete(struct device *dev)
2984b5a236c1SHui Wang {
29854914da2fSTakashi Iwai 	struct hda_codec *codec = dev_to_hda_codec(dev);
2986b5a236c1SHui Wang 
2987b8b90c17SHui Wang 	/* If no other pm-functions are called between prepare() and complete() */
2988b8b90c17SHui Wang 	if (dev->power.power_state.event == PM_EVENT_SUSPEND)
2989b8b90c17SHui Wang 		dev->power.power_state = PMSG_RESUME;
2990b8b90c17SHui Wang 
2991215a22edSKai-Heng Feng 	if (pm_runtime_suspended(dev) && (codec->jackpoll_interval ||
2992215a22edSKai-Heng Feng 	    hda_codec_need_resume(codec) || codec->forced_resume))
2993215a22edSKai-Heng Feng 		pm_request_resume(dev);
2994b5a236c1SHui Wang }
2995b5a236c1SHui Wang 
hda_codec_pm_suspend(struct device * dev)299698081ca6STakashi Iwai static int hda_codec_pm_suspend(struct device *dev)
299798081ca6STakashi Iwai {
299898081ca6STakashi Iwai 	dev->power.power_state = PMSG_SUSPEND;
29992b73649cSKai-Heng Feng 	return pm_runtime_force_suspend(dev);
300098081ca6STakashi Iwai }
300198081ca6STakashi Iwai 
hda_codec_pm_resume(struct device * dev)300298081ca6STakashi Iwai static int hda_codec_pm_resume(struct device *dev)
300398081ca6STakashi Iwai {
300498081ca6STakashi Iwai 	dev->power.power_state = PMSG_RESUME;
30052b73649cSKai-Heng Feng 	return pm_runtime_force_resume(dev);
300698081ca6STakashi Iwai }
300798081ca6STakashi Iwai 
hda_codec_pm_freeze(struct device * dev)300898081ca6STakashi Iwai static int hda_codec_pm_freeze(struct device *dev)
300998081ca6STakashi Iwai {
3010b33115bdSMohan Kumar 	struct hda_codec *codec = dev_to_hda_codec(dev);
3011b33115bdSMohan Kumar 
3012b33115bdSMohan Kumar 	cancel_delayed_work_sync(&codec->jackpoll_work);
301398081ca6STakashi Iwai 	dev->power.power_state = PMSG_FREEZE;
30142b73649cSKai-Heng Feng 	return pm_runtime_force_suspend(dev);
301598081ca6STakashi Iwai }
301698081ca6STakashi Iwai 
hda_codec_pm_thaw(struct device * dev)301798081ca6STakashi Iwai static int hda_codec_pm_thaw(struct device *dev)
301898081ca6STakashi Iwai {
301998081ca6STakashi Iwai 	dev->power.power_state = PMSG_THAW;
30202b73649cSKai-Heng Feng 	return pm_runtime_force_resume(dev);
302198081ca6STakashi Iwai }
302298081ca6STakashi Iwai 
hda_codec_pm_restore(struct device * dev)302398081ca6STakashi Iwai static int hda_codec_pm_restore(struct device *dev)
302498081ca6STakashi Iwai {
302598081ca6STakashi Iwai 	dev->power.power_state = PMSG_RESTORE;
30262b73649cSKai-Heng Feng 	return pm_runtime_force_resume(dev);
302798081ca6STakashi Iwai }
302898081ca6STakashi Iwai #endif /* CONFIG_PM_SLEEP */
302998081ca6STakashi Iwai 
303059ed1eadSTakashi Iwai /* referred in hda_bind.c */
303159ed1eadSTakashi Iwai const struct dev_pm_ops hda_codec_driver_pm = {
303298081ca6STakashi Iwai #ifdef CONFIG_PM_SLEEP
3033215a22edSKai-Heng Feng 	.prepare = hda_codec_pm_prepare,
3034215a22edSKai-Heng Feng 	.complete = hda_codec_pm_complete,
303598081ca6STakashi Iwai 	.suspend = hda_codec_pm_suspend,
303698081ca6STakashi Iwai 	.resume = hda_codec_pm_resume,
303798081ca6STakashi Iwai 	.freeze = hda_codec_pm_freeze,
303898081ca6STakashi Iwai 	.thaw = hda_codec_pm_thaw,
303998081ca6STakashi Iwai 	.poweroff = hda_codec_pm_suspend,
304098081ca6STakashi Iwai 	.restore = hda_codec_pm_restore,
304198081ca6STakashi Iwai #endif /* CONFIG_PM_SLEEP */
3042cc72da7dSTakashi Iwai 	SET_RUNTIME_PM_OPS(hda_codec_runtime_suspend, hda_codec_runtime_resume,
3043cc72da7dSTakashi Iwai 			   NULL)
304459ed1eadSTakashi Iwai };
304554d17403STakashi Iwai 
3046b98444edSTakashi Iwai /* suspend the codec at shutdown; called from driver's shutdown callback */
snd_hda_codec_shutdown(struct hda_codec * codec)3047b98444edSTakashi Iwai void snd_hda_codec_shutdown(struct hda_codec *codec)
3048b98444edSTakashi Iwai {
3049b98444edSTakashi Iwai 	struct hda_pcm *cpcm;
3050b98444edSTakashi Iwai 
30511c7f0e34SPeter Ujfalusi 	/* Skip the shutdown if codec is not registered */
3052e7255c00SCezary Rojewski 	if (!codec->core.registered)
30531c7f0e34SPeter Ujfalusi 		return;
30541c7f0e34SPeter Ujfalusi 
3055b33115bdSMohan Kumar 	cancel_delayed_work_sync(&codec->jackpoll_work);
3056b98444edSTakashi Iwai 	list_for_each_entry(cpcm, &codec->pcm_list_head, list)
3057b98444edSTakashi Iwai 		snd_pcm_suspend_all(cpcm->pcm);
3058b98444edSTakashi Iwai 
30592eaf1635STakashi Iwai 	pm_runtime_force_suspend(hda_codec_dev(codec));
30602eaf1635STakashi Iwai 	pm_runtime_disable(hda_codec_dev(codec));
3061b98444edSTakashi Iwai }
3062b98444edSTakashi Iwai 
30639c9a5175STakashi Iwai /*
30649c9a5175STakashi Iwai  * add standard channel maps if not specified
30659c9a5175STakashi Iwai  */
add_std_chmaps(struct hda_codec * codec)30669c9a5175STakashi Iwai static int add_std_chmaps(struct hda_codec *codec)
30679c9a5175STakashi Iwai {
3068bbbc7e85STakashi Iwai 	struct hda_pcm *pcm;
3069bbbc7e85STakashi Iwai 	int str, err;
30709c9a5175STakashi Iwai 
3071bbbc7e85STakashi Iwai 	list_for_each_entry(pcm, &codec->pcm_list_head, list) {
30729c9a5175STakashi Iwai 		for (str = 0; str < 2; str++) {
3073bbbc7e85STakashi Iwai 			struct hda_pcm_stream *hinfo = &pcm->stream[str];
30749c9a5175STakashi Iwai 			struct snd_pcm_chmap *chmap;
3075ee81abb6STakashi Iwai 			const struct snd_pcm_chmap_elem *elem;
30769c9a5175STakashi Iwai 
3077b25cf30aSTakashi Iwai 			if (!pcm->pcm || pcm->own_chmap || !hinfo->substreams)
30789c9a5175STakashi Iwai 				continue;
3079ee81abb6STakashi Iwai 			elem = hinfo->chmap ? hinfo->chmap : snd_pcm_std_chmaps;
3080bbbc7e85STakashi Iwai 			err = snd_pcm_add_chmap_ctls(pcm->pcm, str, elem,
30819c9a5175STakashi Iwai 						     hinfo->channels_max,
30829c9a5175STakashi Iwai 						     0, &chmap);
30839c9a5175STakashi Iwai 			if (err < 0)
30849c9a5175STakashi Iwai 				return err;
30859c9a5175STakashi Iwai 			chmap->channel_mask = SND_PCM_CHMAP_MASK_2468;
30869c9a5175STakashi Iwai 		}
30879c9a5175STakashi Iwai 	}
30889c9a5175STakashi Iwai 	return 0;
30899c9a5175STakashi Iwai }
30909c9a5175STakashi Iwai 
3091ee81abb6STakashi Iwai /* default channel maps for 2.1 speakers;
3092ee81abb6STakashi Iwai  * since HD-audio supports only stereo, odd number channels are omitted
3093ee81abb6STakashi Iwai  */
3094ee81abb6STakashi Iwai const struct snd_pcm_chmap_elem snd_pcm_2_1_chmaps[] = {
3095ee81abb6STakashi Iwai 	{ .channels = 2,
3096ee81abb6STakashi Iwai 	  .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR } },
3097ee81abb6STakashi Iwai 	{ .channels = 4,
3098ee81abb6STakashi Iwai 	  .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR,
3099ee81abb6STakashi Iwai 		   SNDRV_CHMAP_LFE, SNDRV_CHMAP_LFE } },
3100ee81abb6STakashi Iwai 	{ }
3101ee81abb6STakashi Iwai };
3102ee81abb6STakashi Iwai EXPORT_SYMBOL_GPL(snd_pcm_2_1_chmaps);
3103ee81abb6STakashi Iwai 
snd_hda_codec_build_controls(struct hda_codec * codec)31046c1f45eaSTakashi Iwai int snd_hda_codec_build_controls(struct hda_codec *codec)
31056c1f45eaSTakashi Iwai {
3106cb53c626STakashi Iwai 	int err = 0;
310711aeff08STakashi Iwai 	hda_exec_init_verbs(codec);
3108cb53c626STakashi Iwai 	/* continue to initialize... */
3109cb53c626STakashi Iwai 	if (codec->patch_ops.init)
3110cb53c626STakashi Iwai 		err = codec->patch_ops.init(codec);
3111cb53c626STakashi Iwai 	if (!err && codec->patch_ops.build_controls)
31121da177e4SLinus Torvalds 		err = codec->patch_ops.build_controls(codec);
31131da177e4SLinus Torvalds 	if (err < 0)
31141da177e4SLinus Torvalds 		return err;
31159c9a5175STakashi Iwai 
31169c9a5175STakashi Iwai 	/* we create chmaps here instead of build_pcms */
31179c9a5175STakashi Iwai 	err = add_std_chmaps(codec);
31189c9a5175STakashi Iwai 	if (err < 0)
31199c9a5175STakashi Iwai 		return err;
31209c9a5175STakashi Iwai 
312126a6cb6cSDavid Henningsson 	if (codec->jackpoll_interval)
312226a6cb6cSDavid Henningsson 		hda_jackpoll_work(&codec->jackpoll_work.work);
312326a6cb6cSDavid Henningsson 	else
31248a535414STakashi Iwai 		snd_hda_jack_report_sync(codec); /* call at the last init point */
3125b9c590bbSTakashi Iwai 	sync_power_up_states(codec);
31261da177e4SLinus Torvalds 	return 0;
31271da177e4SLinus Torvalds }
312824494d3fSRakesh Ughreja EXPORT_SYMBOL_GPL(snd_hda_codec_build_controls);
31291da177e4SLinus Torvalds 
31301da177e4SLinus Torvalds /*
31311da177e4SLinus Torvalds  * PCM stuff
31321da177e4SLinus Torvalds  */
hda_pcm_default_open_close(struct hda_pcm_stream * hinfo,struct hda_codec * codec,struct snd_pcm_substream * substream)31331da177e4SLinus Torvalds static int hda_pcm_default_open_close(struct hda_pcm_stream *hinfo,
31341da177e4SLinus Torvalds 				      struct hda_codec *codec,
3135c8b6bf9bSTakashi Iwai 				      struct snd_pcm_substream *substream)
31361da177e4SLinus Torvalds {
31371da177e4SLinus Torvalds 	return 0;
31381da177e4SLinus Torvalds }
31391da177e4SLinus Torvalds 
hda_pcm_default_prepare(struct hda_pcm_stream * hinfo,struct hda_codec * codec,unsigned int stream_tag,unsigned int format,struct snd_pcm_substream * substream)31401da177e4SLinus Torvalds static int hda_pcm_default_prepare(struct hda_pcm_stream *hinfo,
31411da177e4SLinus Torvalds 				   struct hda_codec *codec,
31421da177e4SLinus Torvalds 				   unsigned int stream_tag,
31431da177e4SLinus Torvalds 				   unsigned int format,
3144c8b6bf9bSTakashi Iwai 				   struct snd_pcm_substream *substream)
31451da177e4SLinus Torvalds {
31461da177e4SLinus Torvalds 	snd_hda_codec_setup_stream(codec, hinfo->nid, stream_tag, 0, format);
31471da177e4SLinus Torvalds 	return 0;
31481da177e4SLinus Torvalds }
31491da177e4SLinus Torvalds 
hda_pcm_default_cleanup(struct hda_pcm_stream * hinfo,struct hda_codec * codec,struct snd_pcm_substream * substream)31501da177e4SLinus Torvalds static int hda_pcm_default_cleanup(struct hda_pcm_stream *hinfo,
31511da177e4SLinus Torvalds 				   struct hda_codec *codec,
3152c8b6bf9bSTakashi Iwai 				   struct snd_pcm_substream *substream)
31531da177e4SLinus Torvalds {
3154888afa15STakashi Iwai 	snd_hda_codec_cleanup_stream(codec, hinfo->nid);
31551da177e4SLinus Torvalds 	return 0;
31561da177e4SLinus Torvalds }
31571da177e4SLinus Torvalds 
set_pcm_default_values(struct hda_codec * codec,struct hda_pcm_stream * info)31586c1f45eaSTakashi Iwai static int set_pcm_default_values(struct hda_codec *codec,
31590ba21762STakashi Iwai 				  struct hda_pcm_stream *info)
31601da177e4SLinus Torvalds {
3161ee504710SJaroslav Kysela 	int err;
3162ee504710SJaroslav Kysela 
31631da177e4SLinus Torvalds 	/* query support PCM information from the given NID */
31640ba21762STakashi Iwai 	if (info->nid && (!info->rates || !info->formats)) {
3165ee504710SJaroslav Kysela 		err = snd_hda_query_supported_pcm(codec, info->nid,
31661da177e4SLinus Torvalds 				info->rates ? NULL : &info->rates,
31671da177e4SLinus Torvalds 				info->formats ? NULL : &info->formats,
31681da177e4SLinus Torvalds 				info->maxbps ? NULL : &info->maxbps);
3169ee504710SJaroslav Kysela 		if (err < 0)
3170ee504710SJaroslav Kysela 			return err;
31711da177e4SLinus Torvalds 	}
31721da177e4SLinus Torvalds 	if (info->ops.open == NULL)
31731da177e4SLinus Torvalds 		info->ops.open = hda_pcm_default_open_close;
31741da177e4SLinus Torvalds 	if (info->ops.close == NULL)
31751da177e4SLinus Torvalds 		info->ops.close = hda_pcm_default_open_close;
31761da177e4SLinus Torvalds 	if (info->ops.prepare == NULL) {
3177da3cec35STakashi Iwai 		if (snd_BUG_ON(!info->nid))
3178da3cec35STakashi Iwai 			return -EINVAL;
31791da177e4SLinus Torvalds 		info->ops.prepare = hda_pcm_default_prepare;
31801da177e4SLinus Torvalds 	}
31811da177e4SLinus Torvalds 	if (info->ops.cleanup == NULL) {
3182da3cec35STakashi Iwai 		if (snd_BUG_ON(!info->nid))
3183da3cec35STakashi Iwai 			return -EINVAL;
31841da177e4SLinus Torvalds 		info->ops.cleanup = hda_pcm_default_cleanup;
31851da177e4SLinus Torvalds 	}
31861da177e4SLinus Torvalds 	return 0;
31871da177e4SLinus Torvalds }
31881da177e4SLinus Torvalds 
3189eb541337STakashi Iwai /*
3190eb541337STakashi Iwai  * codec prepare/cleanup entries
3191eb541337STakashi Iwai  */
319295a962c3STakashi Iwai /**
319395a962c3STakashi Iwai  * snd_hda_codec_prepare - Prepare a stream
319495a962c3STakashi Iwai  * @codec: the HDA codec
319595a962c3STakashi Iwai  * @hinfo: PCM information
319695a962c3STakashi Iwai  * @stream: stream tag to assign
319795a962c3STakashi Iwai  * @format: format id to assign
319895a962c3STakashi Iwai  * @substream: PCM substream to assign
319995a962c3STakashi Iwai  *
320095a962c3STakashi Iwai  * Calls the prepare callback set by the codec with the given arguments.
320195a962c3STakashi Iwai  * Clean up the inactive streams when successful.
320295a962c3STakashi Iwai  */
snd_hda_codec_prepare(struct hda_codec * codec,struct hda_pcm_stream * hinfo,unsigned int stream,unsigned int format,struct snd_pcm_substream * substream)3203eb541337STakashi Iwai int snd_hda_codec_prepare(struct hda_codec *codec,
3204eb541337STakashi Iwai 			  struct hda_pcm_stream *hinfo,
3205eb541337STakashi Iwai 			  unsigned int stream,
3206eb541337STakashi Iwai 			  unsigned int format,
3207eb541337STakashi Iwai 			  struct snd_pcm_substream *substream)
3208eb541337STakashi Iwai {
3209eb541337STakashi Iwai 	int ret;
32103f50ac6aSTakashi Iwai 	mutex_lock(&codec->bus->prepare_mutex);
321161ca4107STakashi Iwai 	if (hinfo->ops.prepare)
321261ca4107STakashi Iwai 		ret = hinfo->ops.prepare(hinfo, codec, stream, format,
321361ca4107STakashi Iwai 					 substream);
321461ca4107STakashi Iwai 	else
321561ca4107STakashi Iwai 		ret = -ENODEV;
3216eb541337STakashi Iwai 	if (ret >= 0)
3217eb541337STakashi Iwai 		purify_inactive_streams(codec);
32183f50ac6aSTakashi Iwai 	mutex_unlock(&codec->bus->prepare_mutex);
3219eb541337STakashi Iwai 	return ret;
3220eb541337STakashi Iwai }
32212698ea98STakashi Iwai EXPORT_SYMBOL_GPL(snd_hda_codec_prepare);
3222eb541337STakashi Iwai 
322395a962c3STakashi Iwai /**
322495ce82acSKai Vehmanen  * snd_hda_codec_cleanup - Clean up stream resources
322595a962c3STakashi Iwai  * @codec: the HDA codec
322695a962c3STakashi Iwai  * @hinfo: PCM information
322795a962c3STakashi Iwai  * @substream: PCM substream
322895a962c3STakashi Iwai  *
322995a962c3STakashi Iwai  * Calls the cleanup callback set by the codec with the given arguments.
323095a962c3STakashi Iwai  */
snd_hda_codec_cleanup(struct hda_codec * codec,struct hda_pcm_stream * hinfo,struct snd_pcm_substream * substream)3231eb541337STakashi Iwai void snd_hda_codec_cleanup(struct hda_codec *codec,
3232eb541337STakashi Iwai 			   struct hda_pcm_stream *hinfo,
3233eb541337STakashi Iwai 			   struct snd_pcm_substream *substream)
3234eb541337STakashi Iwai {
32353f50ac6aSTakashi Iwai 	mutex_lock(&codec->bus->prepare_mutex);
323661ca4107STakashi Iwai 	if (hinfo->ops.cleanup)
3237eb541337STakashi Iwai 		hinfo->ops.cleanup(hinfo, codec, substream);
32383f50ac6aSTakashi Iwai 	mutex_unlock(&codec->bus->prepare_mutex);
3239eb541337STakashi Iwai }
32402698ea98STakashi Iwai EXPORT_SYMBOL_GPL(snd_hda_codec_cleanup);
3241eb541337STakashi Iwai 
3242d5191e50STakashi Iwai /* global */
3243e3303235SJaroslav Kysela const char *snd_hda_pcm_type_name[HDA_PCM_NTYPES] = {
3244e3303235SJaroslav Kysela 	"Audio", "SPDIF", "HDMI", "Modem"
3245e3303235SJaroslav Kysela };
3246e3303235SJaroslav Kysela 
3247176d5335STakashi Iwai /*
3248529bd6c4STakashi Iwai  * get the empty PCM device number to assign
3249529bd6c4STakashi Iwai  */
get_empty_pcm_device(struct hda_bus * bus,unsigned int type)325036bb00d4STakashi Iwai static int get_empty_pcm_device(struct hda_bus *bus, unsigned int type)
3251529bd6c4STakashi Iwai {
3252f5d6def5SWu Fengguang 	/* audio device indices; not linear to keep compatibility */
325336bb00d4STakashi Iwai 	/* assigned to static slots up to dev#10; if more needed, assign
325436bb00d4STakashi Iwai 	 * the later slot dynamically (when CONFIG_SND_DYNAMIC_MINORS=y)
325536bb00d4STakashi Iwai 	 */
3256bf82326fSTakashi Iwai 	static const int audio_idx[HDA_PCM_NTYPES][5] = {
3257f5d6def5SWu Fengguang 		[HDA_PCM_TYPE_AUDIO] = { 0, 2, 4, 5, -1 },
3258f5d6def5SWu Fengguang 		[HDA_PCM_TYPE_SPDIF] = { 1, -1 },
325992608badSWu Fengguang 		[HDA_PCM_TYPE_HDMI]  = { 3, 7, 8, 9, -1 },
3260f5d6def5SWu Fengguang 		[HDA_PCM_TYPE_MODEM] = { 6, -1 },
3261529bd6c4STakashi Iwai 	};
3262f5d6def5SWu Fengguang 	int i;
3263529bd6c4STakashi Iwai 
3264f5d6def5SWu Fengguang 	if (type >= HDA_PCM_NTYPES) {
32654e76a883STakashi Iwai 		dev_err(bus->card->dev, "Invalid PCM type %d\n", type);
3266529bd6c4STakashi Iwai 		return -EINVAL;
3267529bd6c4STakashi Iwai 	}
3268f5d6def5SWu Fengguang 
326936bb00d4STakashi Iwai 	for (i = 0; audio_idx[type][i] >= 0; i++) {
327036bb00d4STakashi Iwai #ifndef CONFIG_SND_DYNAMIC_MINORS
327136bb00d4STakashi Iwai 		if (audio_idx[type][i] >= 8)
327236bb00d4STakashi Iwai 			break;
327336bb00d4STakashi Iwai #endif
3274f5d6def5SWu Fengguang 		if (!test_and_set_bit(audio_idx[type][i], bus->pcm_dev_bits))
3275f5d6def5SWu Fengguang 			return audio_idx[type][i];
327636bb00d4STakashi Iwai 	}
3277f5d6def5SWu Fengguang 
327836bb00d4STakashi Iwai #ifdef CONFIG_SND_DYNAMIC_MINORS
327901b65bfbSTakashi Iwai 	/* non-fixed slots starting from 10 */
328001b65bfbSTakashi Iwai 	for (i = 10; i < 32; i++) {
328101b65bfbSTakashi Iwai 		if (!test_and_set_bit(i, bus->pcm_dev_bits))
328201b65bfbSTakashi Iwai 			return i;
328301b65bfbSTakashi Iwai 	}
328436bb00d4STakashi Iwai #endif
328501b65bfbSTakashi Iwai 
32864e76a883STakashi Iwai 	dev_warn(bus->card->dev, "Too many %s devices\n",
328728aedaf7SNorberto Lopes 		snd_hda_pcm_type_name[type]);
328836bb00d4STakashi Iwai #ifndef CONFIG_SND_DYNAMIC_MINORS
32894e76a883STakashi Iwai 	dev_warn(bus->card->dev,
32904e76a883STakashi Iwai 		 "Consider building the kernel with CONFIG_SND_DYNAMIC_MINORS=y\n");
329136bb00d4STakashi Iwai #endif
3292f5d6def5SWu Fengguang 	return -EAGAIN;
3293529bd6c4STakashi Iwai }
3294529bd6c4STakashi Iwai 
32951a4ba30cSTakashi Iwai /* call build_pcms ops of the given codec and set up the default parameters */
snd_hda_codec_parse_pcms(struct hda_codec * codec)32961a4ba30cSTakashi Iwai int snd_hda_codec_parse_pcms(struct hda_codec *codec)
3297176d5335STakashi Iwai {
3298bbbc7e85STakashi Iwai 	struct hda_pcm *cpcm;
32991a4ba30cSTakashi Iwai 	int err;
3300176d5335STakashi Iwai 
3301bbbc7e85STakashi Iwai 	if (!list_empty(&codec->pcm_list_head))
33021a4ba30cSTakashi Iwai 		return 0; /* already parsed */
33031a4ba30cSTakashi Iwai 
33041a4ba30cSTakashi Iwai 	if (!codec->patch_ops.build_pcms)
33051a4ba30cSTakashi Iwai 		return 0;
33061a4ba30cSTakashi Iwai 
33071a4ba30cSTakashi Iwai 	err = codec->patch_ops.build_pcms(codec);
33081a4ba30cSTakashi Iwai 	if (err < 0) {
33091a4ba30cSTakashi Iwai 		codec_err(codec, "cannot build PCMs for #%d (error %d)\n",
3310d068ebc2STakashi Iwai 			  codec->core.addr, err);
33111a4ba30cSTakashi Iwai 		return err;
33121a4ba30cSTakashi Iwai 	}
33131a4ba30cSTakashi Iwai 
3314bbbc7e85STakashi Iwai 	list_for_each_entry(cpcm, &codec->pcm_list_head, list) {
33151a4ba30cSTakashi Iwai 		int stream;
33161a4ba30cSTakashi Iwai 
3317176d5335STakashi Iwai 		for (stream = 0; stream < 2; stream++) {
33181a4ba30cSTakashi Iwai 			struct hda_pcm_stream *info = &cpcm->stream[stream];
33191a4ba30cSTakashi Iwai 
33201a4ba30cSTakashi Iwai 			if (!info->substreams)
33211a4ba30cSTakashi Iwai 				continue;
3322176d5335STakashi Iwai 			err = set_pcm_default_values(codec, info);
33231a4ba30cSTakashi Iwai 			if (err < 0) {
33241a4ba30cSTakashi Iwai 				codec_warn(codec,
33251a4ba30cSTakashi Iwai 					   "fail to setup default for PCM %s\n",
33261a4ba30cSTakashi Iwai 					   cpcm->name);
3327176d5335STakashi Iwai 				return err;
3328176d5335STakashi Iwai 			}
3329176d5335STakashi Iwai 		}
33301a4ba30cSTakashi Iwai 	}
33311a4ba30cSTakashi Iwai 
33321a4ba30cSTakashi Iwai 	return 0;
3333176d5335STakashi Iwai }
333424494d3fSRakesh Ughreja EXPORT_SYMBOL_GPL(snd_hda_codec_parse_pcms);
3335176d5335STakashi Iwai 
3336529bd6c4STakashi Iwai /* assign all PCMs of the given codec */
snd_hda_codec_build_pcms(struct hda_codec * codec)3337529bd6c4STakashi Iwai int snd_hda_codec_build_pcms(struct hda_codec *codec)
3338529bd6c4STakashi Iwai {
33391a4ba30cSTakashi Iwai 	struct hda_bus *bus = codec->bus;
3340bbbc7e85STakashi Iwai 	struct hda_pcm *cpcm;
33411a4ba30cSTakashi Iwai 	int dev, err;
3342529bd6c4STakashi Iwai 
33431a4ba30cSTakashi Iwai 	err = snd_hda_codec_parse_pcms(codec);
3344d289619aSTakashi Iwai 	if (err < 0)
3345529bd6c4STakashi Iwai 		return err;
33461a4ba30cSTakashi Iwai 
33471a4ba30cSTakashi Iwai 	/* attach a new PCM streams */
3348bbbc7e85STakashi Iwai 	list_for_each_entry(cpcm, &codec->pcm_list_head, list) {
33491a4ba30cSTakashi Iwai 		if (cpcm->pcm)
33501a4ba30cSTakashi Iwai 			continue; /* already attached */
3351529bd6c4STakashi Iwai 		if (!cpcm->stream[0].substreams && !cpcm->stream[1].substreams)
335241b5b01aSTakashi Iwai 			continue; /* no substreams assigned */
3353529bd6c4STakashi Iwai 
33541a4ba30cSTakashi Iwai 		dev = get_empty_pcm_device(bus, cpcm->pcm_type);
33551f7f51a6SWang YanQing 		if (dev < 0) {
33561f7f51a6SWang YanQing 			cpcm->device = SNDRV_PCM_INVALID_DEVICE;
33576e655bf2STakashi Iwai 			continue; /* no fatal error */
33581f7f51a6SWang YanQing 		}
3359529bd6c4STakashi Iwai 		cpcm->device = dev;
33600a50575bSTakashi Iwai 		err =  snd_hda_attach_pcm_stream(bus, codec, cpcm);
33616e655bf2STakashi Iwai 		if (err < 0) {
33624e76a883STakashi Iwai 			codec_err(codec,
33634e76a883STakashi Iwai 				  "cannot attach PCM stream %d for codec #%d\n",
3364d068ebc2STakashi Iwai 				  dev, codec->core.addr);
33656e655bf2STakashi Iwai 			continue; /* no fatal error */
33666e655bf2STakashi Iwai 		}
3367529bd6c4STakashi Iwai 	}
33681a4ba30cSTakashi Iwai 
3369529bd6c4STakashi Iwai 	return 0;
3370529bd6c4STakashi Iwai }
3371529bd6c4STakashi Iwai 
33721da177e4SLinus Torvalds /**
33731da177e4SLinus Torvalds  * snd_hda_add_new_ctls - create controls from the array
33741da177e4SLinus Torvalds  * @codec: the HDA codec
3375c8b6bf9bSTakashi Iwai  * @knew: the array of struct snd_kcontrol_new
33761da177e4SLinus Torvalds  *
33771da177e4SLinus Torvalds  * This helper function creates and add new controls in the given array.
33781da177e4SLinus Torvalds  * The array must be terminated with an empty entry as terminator.
33791da177e4SLinus Torvalds  *
33801da177e4SLinus Torvalds  * Returns 0 if successful, or a negative error code.
33811da177e4SLinus Torvalds  */
snd_hda_add_new_ctls(struct hda_codec * codec,const struct snd_kcontrol_new * knew)3382031024eeSTakashi Iwai int snd_hda_add_new_ctls(struct hda_codec *codec,
3383031024eeSTakashi Iwai 			 const struct snd_kcontrol_new *knew)
33841da177e4SLinus Torvalds {
33851da177e4SLinus Torvalds 	int err;
33861da177e4SLinus Torvalds 
33871da177e4SLinus Torvalds 	for (; knew->name; knew++) {
338854d17403STakashi Iwai 		struct snd_kcontrol *kctl;
33891afe206aSTakashi Iwai 		int addr = 0, idx = 0;
3390ebd836edSTakashi Iwai 		if (knew->iface == (__force snd_ctl_elem_iface_t)-1)
3391ebd836edSTakashi Iwai 			continue; /* skip this codec private value */
33921afe206aSTakashi Iwai 		for (;;) {
339354d17403STakashi Iwai 			kctl = snd_ctl_new1(knew, codec);
339454d17403STakashi Iwai 			if (!kctl)
339554d17403STakashi Iwai 				return -ENOMEM;
3396d045bcefSJaroslav Kysela 			/* Do not use the id.device field for MIXER elements.
3397d045bcefSJaroslav Kysela 			 * This field is for real device numbers (like PCM) but codecs
3398d045bcefSJaroslav Kysela 			 * are hidden components from the user space view (unrelated
3399d045bcefSJaroslav Kysela 			 * to the mixer element identification).
3400d045bcefSJaroslav Kysela 			 */
3401d045bcefSJaroslav Kysela 			if (addr > 0 && codec->ctl_dev_id)
34021afe206aSTakashi Iwai 				kctl->id.device = addr;
34031afe206aSTakashi Iwai 			if (idx > 0)
34041afe206aSTakashi Iwai 				kctl->id.index = idx;
34053911a4c1SJaroslav Kysela 			err = snd_hda_ctl_add(codec, 0, kctl);
34061afe206aSTakashi Iwai 			if (!err)
34071afe206aSTakashi Iwai 				break;
34081afe206aSTakashi Iwai 			/* try first with another device index corresponding to
34091afe206aSTakashi Iwai 			 * the codec addr; if it still fails (or it's the
34101afe206aSTakashi Iwai 			 * primary codec), then try another control index
34111afe206aSTakashi Iwai 			 */
3412d045bcefSJaroslav Kysela 			if (!addr && codec->core.addr) {
3413d068ebc2STakashi Iwai 				addr = codec->core.addr;
3414d045bcefSJaroslav Kysela 				if (!codec->ctl_dev_id)
3415d045bcefSJaroslav Kysela 					idx += 10 * addr;
3416d045bcefSJaroslav Kysela 			} else if (!idx && !knew->index) {
34171afe206aSTakashi Iwai 				idx = find_empty_mixer_ctl_idx(codec,
3418dcda5806STakashi Iwai 							       knew->name, 0);
34191afe206aSTakashi Iwai 				if (idx <= 0)
34201da177e4SLinus Torvalds 					return err;
34211afe206aSTakashi Iwai 			} else
342254d17403STakashi Iwai 				return err;
342354d17403STakashi Iwai 		}
34241da177e4SLinus Torvalds 	}
34251da177e4SLinus Torvalds 	return 0;
34261da177e4SLinus Torvalds }
34272698ea98STakashi Iwai EXPORT_SYMBOL_GPL(snd_hda_add_new_ctls);
34281da177e4SLinus Torvalds 
342983012a7cSTakashi Iwai #ifdef CONFIG_PM
3430bb682f7aSCezary Rojewski /**
3431bb682f7aSCezary Rojewski  * snd_hda_codec_set_power_save - Configure codec's runtime PM
3432bb682f7aSCezary Rojewski  * @codec: codec device to configure
3433bb682f7aSCezary Rojewski  * @delay: autosuspend delay
3434bb682f7aSCezary Rojewski  */
snd_hda_codec_set_power_save(struct hda_codec * codec,int delay)3435bb682f7aSCezary Rojewski void snd_hda_codec_set_power_save(struct hda_codec *codec, int delay)
3436cc72da7dSTakashi Iwai {
3437cc72da7dSTakashi Iwai 	struct device *dev = hda_codec_dev(codec);
3438cc72da7dSTakashi Iwai 
34392377c3c3SLu, Han 	if (delay == 0 && codec->auto_runtime_pm)
34402377c3c3SLu, Han 		delay = 3000;
34412377c3c3SLu, Han 
3442cc72da7dSTakashi Iwai 	if (delay > 0) {
3443cc72da7dSTakashi Iwai 		pm_runtime_set_autosuspend_delay(dev, delay);
3444cc72da7dSTakashi Iwai 		pm_runtime_use_autosuspend(dev);
3445cc72da7dSTakashi Iwai 		pm_runtime_allow(dev);
3446cc72da7dSTakashi Iwai 		if (!pm_runtime_suspended(dev))
3447cc72da7dSTakashi Iwai 			pm_runtime_mark_last_busy(dev);
3448cc72da7dSTakashi Iwai 	} else {
3449cc72da7dSTakashi Iwai 		pm_runtime_dont_use_autosuspend(dev);
3450cc72da7dSTakashi Iwai 		pm_runtime_forbid(dev);
3451cc72da7dSTakashi Iwai 	}
3452cc72da7dSTakashi Iwai }
3453bb682f7aSCezary Rojewski EXPORT_SYMBOL_GPL(snd_hda_codec_set_power_save);
3454bb573928STakashi Iwai 
3455bb573928STakashi Iwai /**
3456bb573928STakashi Iwai  * snd_hda_set_power_save - reprogram autosuspend for the given delay
3457bb573928STakashi Iwai  * @bus: HD-audio bus
3458bb573928STakashi Iwai  * @delay: autosuspend delay in msec, 0 = off
3459bb573928STakashi Iwai  *
3460bb573928STakashi Iwai  * Synchronize the runtime PM autosuspend state from the power_save option.
3461bb573928STakashi Iwai  */
snd_hda_set_power_save(struct hda_bus * bus,int delay)3462bb573928STakashi Iwai void snd_hda_set_power_save(struct hda_bus *bus, int delay)
3463bb573928STakashi Iwai {
3464bb573928STakashi Iwai 	struct hda_codec *c;
3465bb573928STakashi Iwai 
3466d068ebc2STakashi Iwai 	list_for_each_codec(c, bus)
3467bb682f7aSCezary Rojewski 		snd_hda_codec_set_power_save(c, delay);
3468bb573928STakashi Iwai }
3469bb573928STakashi Iwai EXPORT_SYMBOL_GPL(snd_hda_set_power_save);
3470cb53c626STakashi Iwai 
3471d5191e50STakashi Iwai /**
3472d5191e50STakashi Iwai  * snd_hda_check_amp_list_power - Check the amp list and update the power
3473d5191e50STakashi Iwai  * @codec: HD-audio codec
3474d5191e50STakashi Iwai  * @check: the object containing an AMP list and the status
3475d5191e50STakashi Iwai  * @nid: NID to check / update
3476d5191e50STakashi Iwai  *
3477d5191e50STakashi Iwai  * Check whether the given NID is in the amp list.  If it's in the list,
3478c7fabbc5SRandy Dunlap  * check the current AMP status, and update the power-status according
3479d5191e50STakashi Iwai  * to the mute status.
3480d5191e50STakashi Iwai  *
3481d5191e50STakashi Iwai  * This function is supposed to be set or called from the check_power_status
3482d5191e50STakashi Iwai  * patch ops.
3483d5191e50STakashi Iwai  */
snd_hda_check_amp_list_power(struct hda_codec * codec,struct hda_loopback_check * check,hda_nid_t nid)3484cb53c626STakashi Iwai int snd_hda_check_amp_list_power(struct hda_codec *codec,
3485cb53c626STakashi Iwai 				 struct hda_loopback_check *check,
3486cb53c626STakashi Iwai 				 hda_nid_t nid)
3487cb53c626STakashi Iwai {
3488031024eeSTakashi Iwai 	const struct hda_amp_list *p;
3489cb53c626STakashi Iwai 	int ch, v;
3490cb53c626STakashi Iwai 
3491cb53c626STakashi Iwai 	if (!check->amplist)
3492cb53c626STakashi Iwai 		return 0;
3493cb53c626STakashi Iwai 	for (p = check->amplist; p->nid; p++) {
3494cb53c626STakashi Iwai 		if (p->nid == nid)
3495cb53c626STakashi Iwai 			break;
3496cb53c626STakashi Iwai 	}
3497cb53c626STakashi Iwai 	if (!p->nid)
3498cb53c626STakashi Iwai 		return 0; /* nothing changed */
3499cb53c626STakashi Iwai 
3500cb53c626STakashi Iwai 	for (p = check->amplist; p->nid; p++) {
3501cb53c626STakashi Iwai 		for (ch = 0; ch < 2; ch++) {
3502cb53c626STakashi Iwai 			v = snd_hda_codec_amp_read(codec, p->nid, ch, p->dir,
3503cb53c626STakashi Iwai 						   p->idx);
3504cb53c626STakashi Iwai 			if (!(v & HDA_AMP_MUTE) && v > 0) {
3505cb53c626STakashi Iwai 				if (!check->power_on) {
3506cb53c626STakashi Iwai 					check->power_on = 1;
3507664c7155STakashi Iwai 					snd_hda_power_up_pm(codec);
3508cb53c626STakashi Iwai 				}
3509cb53c626STakashi Iwai 				return 1;
3510cb53c626STakashi Iwai 			}
3511cb53c626STakashi Iwai 		}
3512cb53c626STakashi Iwai 	}
3513cb53c626STakashi Iwai 	if (check->power_on) {
3514cb53c626STakashi Iwai 		check->power_on = 0;
3515664c7155STakashi Iwai 		snd_hda_power_down_pm(codec);
3516cb53c626STakashi Iwai 	}
3517cb53c626STakashi Iwai 	return 0;
3518cb53c626STakashi Iwai }
35192698ea98STakashi Iwai EXPORT_SYMBOL_GPL(snd_hda_check_amp_list_power);
3520cb53c626STakashi Iwai #endif
35211da177e4SLinus Torvalds 
3522d2a6d7dcSTakashi Iwai /*
35231da177e4SLinus Torvalds  * input MUX helper
35241da177e4SLinus Torvalds  */
3525d5191e50STakashi Iwai 
3526d5191e50STakashi Iwai /**
35273531ba21SPierre-Louis Bossart  * snd_hda_input_mux_info - Info callback helper for the input-mux enum
3528a11e9b16STakashi Iwai  * @imux: imux helper object
3529a11e9b16STakashi Iwai  * @uinfo: pointer to get/store the data
3530d5191e50STakashi Iwai  */
snd_hda_input_mux_info(const struct hda_input_mux * imux,struct snd_ctl_elem_info * uinfo)35310ba21762STakashi Iwai int snd_hda_input_mux_info(const struct hda_input_mux *imux,
35320ba21762STakashi Iwai 			   struct snd_ctl_elem_info *uinfo)
35331da177e4SLinus Torvalds {
35341da177e4SLinus Torvalds 	unsigned int index;
35351da177e4SLinus Torvalds 
35361da177e4SLinus Torvalds 	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
35371da177e4SLinus Torvalds 	uinfo->count = 1;
35381da177e4SLinus Torvalds 	uinfo->value.enumerated.items = imux->num_items;
35395513b0c5STakashi Iwai 	if (!imux->num_items)
35405513b0c5STakashi Iwai 		return 0;
35411da177e4SLinus Torvalds 	index = uinfo->value.enumerated.item;
35421da177e4SLinus Torvalds 	if (index >= imux->num_items)
35431da177e4SLinus Torvalds 		index = imux->num_items - 1;
35441da177e4SLinus Torvalds 	strcpy(uinfo->value.enumerated.name, imux->items[index].label);
35451da177e4SLinus Torvalds 	return 0;
35461da177e4SLinus Torvalds }
35472698ea98STakashi Iwai EXPORT_SYMBOL_GPL(snd_hda_input_mux_info);
35481da177e4SLinus Torvalds 
3549d5191e50STakashi Iwai /**
35503531ba21SPierre-Louis Bossart  * snd_hda_input_mux_put - Put callback helper for the input-mux enum
3551a11e9b16STakashi Iwai  * @codec: the HDA codec
3552a11e9b16STakashi Iwai  * @imux: imux helper object
3553a11e9b16STakashi Iwai  * @ucontrol: pointer to get/store the data
3554a11e9b16STakashi Iwai  * @nid: input mux NID
3555a11e9b16STakashi Iwai  * @cur_val: pointer to get/store the current imux value
3556d5191e50STakashi Iwai  */
snd_hda_input_mux_put(struct hda_codec * codec,const struct hda_input_mux * imux,struct snd_ctl_elem_value * ucontrol,hda_nid_t nid,unsigned int * cur_val)35570ba21762STakashi Iwai int snd_hda_input_mux_put(struct hda_codec *codec,
35580ba21762STakashi Iwai 			  const struct hda_input_mux *imux,
35590ba21762STakashi Iwai 			  struct snd_ctl_elem_value *ucontrol,
35600ba21762STakashi Iwai 			  hda_nid_t nid,
35611da177e4SLinus Torvalds 			  unsigned int *cur_val)
35621da177e4SLinus Torvalds {
35631da177e4SLinus Torvalds 	unsigned int idx;
35641da177e4SLinus Torvalds 
35655513b0c5STakashi Iwai 	if (!imux->num_items)
35665513b0c5STakashi Iwai 		return 0;
35671da177e4SLinus Torvalds 	idx = ucontrol->value.enumerated.item[0];
35681da177e4SLinus Torvalds 	if (idx >= imux->num_items)
35691da177e4SLinus Torvalds 		idx = imux->num_items - 1;
357082beb8fdSTakashi Iwai 	if (*cur_val == idx)
35711da177e4SLinus Torvalds 		return 0;
357282beb8fdSTakashi Iwai 	snd_hda_codec_write_cache(codec, nid, 0, AC_VERB_SET_CONNECT_SEL,
35731da177e4SLinus Torvalds 				  imux->items[idx].index);
35741da177e4SLinus Torvalds 	*cur_val = idx;
35751da177e4SLinus Torvalds 	return 1;
35761da177e4SLinus Torvalds }
35772698ea98STakashi Iwai EXPORT_SYMBOL_GPL(snd_hda_input_mux_put);
35781da177e4SLinus Torvalds 
35791da177e4SLinus Torvalds 
3580a11e9b16STakashi Iwai /**
3581a11e9b16STakashi Iwai  * snd_hda_enum_helper_info - Helper for simple enum ctls
3582a11e9b16STakashi Iwai  * @kcontrol: ctl element
3583a11e9b16STakashi Iwai  * @uinfo: pointer to get/store the data
3584a11e9b16STakashi Iwai  * @num_items: number of enum items
3585a11e9b16STakashi Iwai  * @texts: enum item string array
3586a11e9b16STakashi Iwai  *
3587dda415d4STakashi Iwai  * process kcontrol info callback of a simple string enum array
3588dda415d4STakashi Iwai  * when @num_items is 0 or @texts is NULL, assume a boolean enum array
3589dda415d4STakashi Iwai  */
snd_hda_enum_helper_info(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_info * uinfo,int num_items,const char * const * texts)3590dda415d4STakashi Iwai int snd_hda_enum_helper_info(struct snd_kcontrol *kcontrol,
3591dda415d4STakashi Iwai 			     struct snd_ctl_elem_info *uinfo,
3592dda415d4STakashi Iwai 			     int num_items, const char * const *texts)
3593dda415d4STakashi Iwai {
3594dda415d4STakashi Iwai 	static const char * const texts_default[] = {
3595dda415d4STakashi Iwai 		"Disabled", "Enabled"
3596dda415d4STakashi Iwai 	};
3597dda415d4STakashi Iwai 
3598dda415d4STakashi Iwai 	if (!texts || !num_items) {
3599dda415d4STakashi Iwai 		num_items = 2;
3600dda415d4STakashi Iwai 		texts = texts_default;
3601dda415d4STakashi Iwai 	}
3602dda415d4STakashi Iwai 
36033ff72219STakashi Iwai 	return snd_ctl_enum_info(uinfo, 1, num_items, texts);
3604dda415d4STakashi Iwai }
36052698ea98STakashi Iwai EXPORT_SYMBOL_GPL(snd_hda_enum_helper_info);
3606dda415d4STakashi Iwai 
3607dda415d4STakashi Iwai /*
36081da177e4SLinus Torvalds  * Multi-channel / digital-out PCM helper functions
36091da177e4SLinus Torvalds  */
36101da177e4SLinus Torvalds 
36116b97eb45STakashi Iwai /* setup SPDIF output stream */
setup_dig_out_stream(struct hda_codec * codec,hda_nid_t nid,unsigned int stream_tag,unsigned int format)36126b97eb45STakashi Iwai static void setup_dig_out_stream(struct hda_codec *codec, hda_nid_t nid,
36136b97eb45STakashi Iwai 				 unsigned int stream_tag, unsigned int format)
36146b97eb45STakashi Iwai {
36153bef1c37SLaurence Darby 	struct hda_spdif_out *spdif;
36163bef1c37SLaurence Darby 	unsigned int curr_fmt;
36173bef1c37SLaurence Darby 	bool reset;
36187c935976SStephen Warren 
36193bef1c37SLaurence Darby 	spdif = snd_hda_spdif_out_of_nid(codec, nid);
3620960a581eSLibin Yang 	/* Add sanity check to pass klockwork check.
3621960a581eSLibin Yang 	 * This should never happen.
3622960a581eSLibin Yang 	 */
3623960a581eSLibin Yang 	if (WARN_ON(spdif == NULL))
3624960a581eSLibin Yang 		return;
3625960a581eSLibin Yang 
36263bef1c37SLaurence Darby 	curr_fmt = snd_hda_codec_read(codec, nid, 0,
36273bef1c37SLaurence Darby 				      AC_VERB_GET_STREAM_FORMAT, 0);
36283bef1c37SLaurence Darby 	reset = codec->spdif_status_reset &&
36293bef1c37SLaurence Darby 		(spdif->ctls & AC_DIG1_ENABLE) &&
36303bef1c37SLaurence Darby 		curr_fmt != format;
36313bef1c37SLaurence Darby 
36323bef1c37SLaurence Darby 	/* turn off SPDIF if needed; otherwise the IEC958 bits won't be
36333bef1c37SLaurence Darby 	   updated */
36343bef1c37SLaurence Darby 	if (reset)
36352f72853cSTakashi Iwai 		set_dig_out_convert(codec, nid,
36367c935976SStephen Warren 				    spdif->ctls & ~AC_DIG1_ENABLE & 0xff,
36372f72853cSTakashi Iwai 				    -1);
36386b97eb45STakashi Iwai 	snd_hda_codec_setup_stream(codec, nid, stream_tag, 0, format);
36399ab0cb30STakashi Iwai 	if (codec->follower_dig_outs) {
3640dda14410STakashi Iwai 		const hda_nid_t *d;
36419ab0cb30STakashi Iwai 		for (d = codec->follower_dig_outs; *d; d++)
36422f72853cSTakashi Iwai 			snd_hda_codec_setup_stream(codec, *d, stream_tag, 0,
36432f72853cSTakashi Iwai 						   format);
36442f72853cSTakashi Iwai 	}
36452f72853cSTakashi Iwai 	/* turn on again (if needed) */
36463bef1c37SLaurence Darby 	if (reset)
36472f72853cSTakashi Iwai 		set_dig_out_convert(codec, nid,
36487c935976SStephen Warren 				    spdif->ctls & 0xff, -1);
3649de51ca12SMatthew Ranostay }
3650de51ca12SMatthew Ranostay 
cleanup_dig_out_stream(struct hda_codec * codec,hda_nid_t nid)36512f72853cSTakashi Iwai static void cleanup_dig_out_stream(struct hda_codec *codec, hda_nid_t nid)
36522f72853cSTakashi Iwai {
36532f72853cSTakashi Iwai 	snd_hda_codec_cleanup_stream(codec, nid);
36549ab0cb30STakashi Iwai 	if (codec->follower_dig_outs) {
3655dda14410STakashi Iwai 		const hda_nid_t *d;
36569ab0cb30STakashi Iwai 		for (d = codec->follower_dig_outs; *d; d++)
36572f72853cSTakashi Iwai 			snd_hda_codec_cleanup_stream(codec, *d);
36582f72853cSTakashi Iwai 	}
36596b97eb45STakashi Iwai }
36606b97eb45STakashi Iwai 
3661d5191e50STakashi Iwai /**
3662d5191e50STakashi Iwai  * snd_hda_multi_out_dig_open - open the digital out in the exclusive mode
3663a11e9b16STakashi Iwai  * @codec: the HDA codec
3664a11e9b16STakashi Iwai  * @mout: hda_multi_out object
36651da177e4SLinus Torvalds  */
snd_hda_multi_out_dig_open(struct hda_codec * codec,struct hda_multi_out * mout)36660ba21762STakashi Iwai int snd_hda_multi_out_dig_open(struct hda_codec *codec,
36670ba21762STakashi Iwai 			       struct hda_multi_out *mout)
36681da177e4SLinus Torvalds {
366962932df8SIngo Molnar 	mutex_lock(&codec->spdif_mutex);
36705930ca41STakashi Iwai 	if (mout->dig_out_used == HDA_DIG_ANALOG_DUP)
36715930ca41STakashi Iwai 		/* already opened as analog dup; reset it once */
36722f72853cSTakashi Iwai 		cleanup_dig_out_stream(codec, mout->dig_out_nid);
36731da177e4SLinus Torvalds 	mout->dig_out_used = HDA_DIG_EXCLUSIVE;
367462932df8SIngo Molnar 	mutex_unlock(&codec->spdif_mutex);
36751da177e4SLinus Torvalds 	return 0;
36761da177e4SLinus Torvalds }
36772698ea98STakashi Iwai EXPORT_SYMBOL_GPL(snd_hda_multi_out_dig_open);
36781da177e4SLinus Torvalds 
3679d5191e50STakashi Iwai /**
3680d5191e50STakashi Iwai  * snd_hda_multi_out_dig_prepare - prepare the digital out stream
3681a11e9b16STakashi Iwai  * @codec: the HDA codec
3682a11e9b16STakashi Iwai  * @mout: hda_multi_out object
3683a11e9b16STakashi Iwai  * @stream_tag: stream tag to assign
3684a11e9b16STakashi Iwai  * @format: format id to assign
3685a11e9b16STakashi Iwai  * @substream: PCM substream to assign
3686d5191e50STakashi Iwai  */
snd_hda_multi_out_dig_prepare(struct hda_codec * codec,struct hda_multi_out * mout,unsigned int stream_tag,unsigned int format,struct snd_pcm_substream * substream)36876b97eb45STakashi Iwai int snd_hda_multi_out_dig_prepare(struct hda_codec *codec,
36886b97eb45STakashi Iwai 				  struct hda_multi_out *mout,
36896b97eb45STakashi Iwai 				  unsigned int stream_tag,
36906b97eb45STakashi Iwai 				  unsigned int format,
36916b97eb45STakashi Iwai 				  struct snd_pcm_substream *substream)
36926b97eb45STakashi Iwai {
36936b97eb45STakashi Iwai 	mutex_lock(&codec->spdif_mutex);
36946b97eb45STakashi Iwai 	setup_dig_out_stream(codec, mout->dig_out_nid, stream_tag, format);
36956b97eb45STakashi Iwai 	mutex_unlock(&codec->spdif_mutex);
36966b97eb45STakashi Iwai 	return 0;
36976b97eb45STakashi Iwai }
36982698ea98STakashi Iwai EXPORT_SYMBOL_GPL(snd_hda_multi_out_dig_prepare);
36996b97eb45STakashi Iwai 
3700d5191e50STakashi Iwai /**
3701d5191e50STakashi Iwai  * snd_hda_multi_out_dig_cleanup - clean-up the digital out stream
3702a11e9b16STakashi Iwai  * @codec: the HDA codec
3703a11e9b16STakashi Iwai  * @mout: hda_multi_out object
3704d5191e50STakashi Iwai  */
snd_hda_multi_out_dig_cleanup(struct hda_codec * codec,struct hda_multi_out * mout)37059411e21cSTakashi Iwai int snd_hda_multi_out_dig_cleanup(struct hda_codec *codec,
37069411e21cSTakashi Iwai 				  struct hda_multi_out *mout)
37079411e21cSTakashi Iwai {
37089411e21cSTakashi Iwai 	mutex_lock(&codec->spdif_mutex);
37099411e21cSTakashi Iwai 	cleanup_dig_out_stream(codec, mout->dig_out_nid);
37109411e21cSTakashi Iwai 	mutex_unlock(&codec->spdif_mutex);
37119411e21cSTakashi Iwai 	return 0;
37129411e21cSTakashi Iwai }
37132698ea98STakashi Iwai EXPORT_SYMBOL_GPL(snd_hda_multi_out_dig_cleanup);
37149411e21cSTakashi Iwai 
3715d5191e50STakashi Iwai /**
3716d5191e50STakashi Iwai  * snd_hda_multi_out_dig_close - release the digital out stream
3717a11e9b16STakashi Iwai  * @codec: the HDA codec
3718a11e9b16STakashi Iwai  * @mout: hda_multi_out object
37191da177e4SLinus Torvalds  */
snd_hda_multi_out_dig_close(struct hda_codec * codec,struct hda_multi_out * mout)37200ba21762STakashi Iwai int snd_hda_multi_out_dig_close(struct hda_codec *codec,
37210ba21762STakashi Iwai 				struct hda_multi_out *mout)
37221da177e4SLinus Torvalds {
372362932df8SIngo Molnar 	mutex_lock(&codec->spdif_mutex);
37241da177e4SLinus Torvalds 	mout->dig_out_used = 0;
372562932df8SIngo Molnar 	mutex_unlock(&codec->spdif_mutex);
37261da177e4SLinus Torvalds 	return 0;
37271da177e4SLinus Torvalds }
37282698ea98STakashi Iwai EXPORT_SYMBOL_GPL(snd_hda_multi_out_dig_close);
37291da177e4SLinus Torvalds 
3730d5191e50STakashi Iwai /**
3731d5191e50STakashi Iwai  * snd_hda_multi_out_analog_open - open analog outputs
3732a11e9b16STakashi Iwai  * @codec: the HDA codec
3733a11e9b16STakashi Iwai  * @mout: hda_multi_out object
3734a11e9b16STakashi Iwai  * @substream: PCM substream to assign
3735a11e9b16STakashi Iwai  * @hinfo: PCM information to assign
3736d5191e50STakashi Iwai  *
3737d5191e50STakashi Iwai  * Open analog outputs and set up the hw-constraints.
37389ab0cb30STakashi Iwai  * If the digital outputs can be opened as follower, open the digital
3739d5191e50STakashi Iwai  * outputs, too.
37401da177e4SLinus Torvalds  */
snd_hda_multi_out_analog_open(struct hda_codec * codec,struct hda_multi_out * mout,struct snd_pcm_substream * substream,struct hda_pcm_stream * hinfo)37410ba21762STakashi Iwai int snd_hda_multi_out_analog_open(struct hda_codec *codec,
37420ba21762STakashi Iwai 				  struct hda_multi_out *mout,
37439a08160bSTakashi Iwai 				  struct snd_pcm_substream *substream,
37449a08160bSTakashi Iwai 				  struct hda_pcm_stream *hinfo)
37451da177e4SLinus Torvalds {
37469a08160bSTakashi Iwai 	struct snd_pcm_runtime *runtime = substream->runtime;
37479a08160bSTakashi Iwai 	runtime->hw.channels_max = mout->max_channels;
37489a08160bSTakashi Iwai 	if (mout->dig_out_nid) {
37499a08160bSTakashi Iwai 		if (!mout->analog_rates) {
37509a08160bSTakashi Iwai 			mout->analog_rates = hinfo->rates;
37519a08160bSTakashi Iwai 			mout->analog_formats = hinfo->formats;
37529a08160bSTakashi Iwai 			mout->analog_maxbps = hinfo->maxbps;
37539a08160bSTakashi Iwai 		} else {
37549a08160bSTakashi Iwai 			runtime->hw.rates = mout->analog_rates;
37559a08160bSTakashi Iwai 			runtime->hw.formats = mout->analog_formats;
37569a08160bSTakashi Iwai 			hinfo->maxbps = mout->analog_maxbps;
37579a08160bSTakashi Iwai 		}
37589a08160bSTakashi Iwai 		if (!mout->spdif_rates) {
37599a08160bSTakashi Iwai 			snd_hda_query_supported_pcm(codec, mout->dig_out_nid,
37609a08160bSTakashi Iwai 						    &mout->spdif_rates,
37619a08160bSTakashi Iwai 						    &mout->spdif_formats,
37629a08160bSTakashi Iwai 						    &mout->spdif_maxbps);
37639a08160bSTakashi Iwai 		}
37649a08160bSTakashi Iwai 		mutex_lock(&codec->spdif_mutex);
37659a08160bSTakashi Iwai 		if (mout->share_spdif) {
3766022b466fSTakashi Iwai 			if ((runtime->hw.rates & mout->spdif_rates) &&
3767022b466fSTakashi Iwai 			    (runtime->hw.formats & mout->spdif_formats)) {
37689a08160bSTakashi Iwai 				runtime->hw.rates &= mout->spdif_rates;
37699a08160bSTakashi Iwai 				runtime->hw.formats &= mout->spdif_formats;
37709a08160bSTakashi Iwai 				if (mout->spdif_maxbps < hinfo->maxbps)
37719a08160bSTakashi Iwai 					hinfo->maxbps = mout->spdif_maxbps;
3772022b466fSTakashi Iwai 			} else {
3773022b466fSTakashi Iwai 				mout->share_spdif = 0;
3774022b466fSTakashi Iwai 				/* FIXME: need notify? */
3775022b466fSTakashi Iwai 			}
37769a08160bSTakashi Iwai 		}
37779a08160bSTakashi Iwai 		mutex_unlock(&codec->spdif_mutex);
3778eaa9985bSFrederik Deweerdt 	}
37791da177e4SLinus Torvalds 	return snd_pcm_hw_constraint_step(substream->runtime, 0,
37801da177e4SLinus Torvalds 					  SNDRV_PCM_HW_PARAM_CHANNELS, 2);
37811da177e4SLinus Torvalds }
37822698ea98STakashi Iwai EXPORT_SYMBOL_GPL(snd_hda_multi_out_analog_open);
37831da177e4SLinus Torvalds 
3784d5191e50STakashi Iwai /**
3785d5191e50STakashi Iwai  * snd_hda_multi_out_analog_prepare - Preapre the analog outputs.
3786a11e9b16STakashi Iwai  * @codec: the HDA codec
3787a11e9b16STakashi Iwai  * @mout: hda_multi_out object
3788a11e9b16STakashi Iwai  * @stream_tag: stream tag to assign
3789a11e9b16STakashi Iwai  * @format: format id to assign
3790a11e9b16STakashi Iwai  * @substream: PCM substream to assign
3791d5191e50STakashi Iwai  *
3792d5191e50STakashi Iwai  * Set up the i/o for analog out.
3793d5191e50STakashi Iwai  * When the digital out is available, copy the front out to digital out, too.
37941da177e4SLinus Torvalds  */
snd_hda_multi_out_analog_prepare(struct hda_codec * codec,struct hda_multi_out * mout,unsigned int stream_tag,unsigned int format,struct snd_pcm_substream * substream)37950ba21762STakashi Iwai int snd_hda_multi_out_analog_prepare(struct hda_codec *codec,
37960ba21762STakashi Iwai 				     struct hda_multi_out *mout,
37971da177e4SLinus Torvalds 				     unsigned int stream_tag,
37981da177e4SLinus Torvalds 				     unsigned int format,
3799c8b6bf9bSTakashi Iwai 				     struct snd_pcm_substream *substream)
38001da177e4SLinus Torvalds {
3801dda14410STakashi Iwai 	const hda_nid_t *nids = mout->dac_nids;
38021da177e4SLinus Torvalds 	int chs = substream->runtime->channels;
3803e3245cddSTakashi Iwai 	struct hda_spdif_out *spdif;
38041da177e4SLinus Torvalds 	int i;
38051da177e4SLinus Torvalds 
380662932df8SIngo Molnar 	mutex_lock(&codec->spdif_mutex);
3807e3245cddSTakashi Iwai 	spdif = snd_hda_spdif_out_of_nid(codec, mout->dig_out_nid);
38089a08160bSTakashi Iwai 	if (mout->dig_out_nid && mout->share_spdif &&
38099a08160bSTakashi Iwai 	    mout->dig_out_used != HDA_DIG_EXCLUSIVE) {
3810960a581eSLibin Yang 		if (chs == 2 && spdif != NULL &&
38110ba21762STakashi Iwai 		    snd_hda_is_supported_format(codec, mout->dig_out_nid,
38120ba21762STakashi Iwai 						format) &&
38137c935976SStephen Warren 		    !(spdif->status & IEC958_AES0_NONAUDIO)) {
38141da177e4SLinus Torvalds 			mout->dig_out_used = HDA_DIG_ANALOG_DUP;
38156b97eb45STakashi Iwai 			setup_dig_out_stream(codec, mout->dig_out_nid,
38166b97eb45STakashi Iwai 					     stream_tag, format);
38171da177e4SLinus Torvalds 		} else {
38181da177e4SLinus Torvalds 			mout->dig_out_used = 0;
38192f72853cSTakashi Iwai 			cleanup_dig_out_stream(codec, mout->dig_out_nid);
38201da177e4SLinus Torvalds 		}
38211da177e4SLinus Torvalds 	}
382262932df8SIngo Molnar 	mutex_unlock(&codec->spdif_mutex);
38231da177e4SLinus Torvalds 
38241da177e4SLinus Torvalds 	/* front */
38250ba21762STakashi Iwai 	snd_hda_codec_setup_stream(codec, nids[HDA_FRONT], stream_tag,
38260ba21762STakashi Iwai 				   0, format);
3827d29240ceSTakashi Iwai 	if (!mout->no_share_stream &&
3828d29240ceSTakashi Iwai 	    mout->hp_nid && mout->hp_nid != nids[HDA_FRONT])
38291da177e4SLinus Torvalds 		/* headphone out will just decode front left/right (stereo) */
38300ba21762STakashi Iwai 		snd_hda_codec_setup_stream(codec, mout->hp_nid, stream_tag,
38310ba21762STakashi Iwai 					   0, format);
383282bc955fSTakashi Iwai 	/* extra outputs copied from front */
3833a06dbfc2STakashi Iwai 	for (i = 0; i < ARRAY_SIZE(mout->hp_out_nid); i++)
3834a06dbfc2STakashi Iwai 		if (!mout->no_share_stream && mout->hp_out_nid[i])
3835a06dbfc2STakashi Iwai 			snd_hda_codec_setup_stream(codec,
3836a06dbfc2STakashi Iwai 						   mout->hp_out_nid[i],
3837a06dbfc2STakashi Iwai 						   stream_tag, 0, format);
383882bc955fSTakashi Iwai 
38391da177e4SLinus Torvalds 	/* surrounds */
38401da177e4SLinus Torvalds 	for (i = 1; i < mout->num_dacs; i++) {
38414b3acaf5STakashi Iwai 		if (chs >= (i + 1) * 2) /* independent out */
38420ba21762STakashi Iwai 			snd_hda_codec_setup_stream(codec, nids[i], stream_tag,
38430ba21762STakashi Iwai 						   i * 2, format);
3844d29240ceSTakashi Iwai 		else if (!mout->no_share_stream) /* copy front */
38450ba21762STakashi Iwai 			snd_hda_codec_setup_stream(codec, nids[i], stream_tag,
38460ba21762STakashi Iwai 						   0, format);
38471da177e4SLinus Torvalds 	}
3848cd4035e8SDavid Henningsson 
3849cd4035e8SDavid Henningsson 	/* extra surrounds */
3850cd4035e8SDavid Henningsson 	for (i = 0; i < ARRAY_SIZE(mout->extra_out_nid); i++) {
3851cd4035e8SDavid Henningsson 		int ch = 0;
3852cd4035e8SDavid Henningsson 		if (!mout->extra_out_nid[i])
3853cd4035e8SDavid Henningsson 			break;
3854cd4035e8SDavid Henningsson 		if (chs >= (i + 1) * 2)
3855cd4035e8SDavid Henningsson 			ch = i * 2;
3856cd4035e8SDavid Henningsson 		else if (!mout->no_share_stream)
3857cd4035e8SDavid Henningsson 			break;
3858cd4035e8SDavid Henningsson 		snd_hda_codec_setup_stream(codec, mout->extra_out_nid[i],
3859cd4035e8SDavid Henningsson 					   stream_tag, ch, format);
3860cd4035e8SDavid Henningsson 	}
3861cd4035e8SDavid Henningsson 
38621da177e4SLinus Torvalds 	return 0;
38631da177e4SLinus Torvalds }
38642698ea98STakashi Iwai EXPORT_SYMBOL_GPL(snd_hda_multi_out_analog_prepare);
38651da177e4SLinus Torvalds 
3866d5191e50STakashi Iwai /**
3867d5191e50STakashi Iwai  * snd_hda_multi_out_analog_cleanup - clean up the setting for analog out
3868a11e9b16STakashi Iwai  * @codec: the HDA codec
3869a11e9b16STakashi Iwai  * @mout: hda_multi_out object
38701da177e4SLinus Torvalds  */
snd_hda_multi_out_analog_cleanup(struct hda_codec * codec,struct hda_multi_out * mout)38710ba21762STakashi Iwai int snd_hda_multi_out_analog_cleanup(struct hda_codec *codec,
38720ba21762STakashi Iwai 				     struct hda_multi_out *mout)
38731da177e4SLinus Torvalds {
3874dda14410STakashi Iwai 	const hda_nid_t *nids = mout->dac_nids;
38751da177e4SLinus Torvalds 	int i;
38761da177e4SLinus Torvalds 
38771da177e4SLinus Torvalds 	for (i = 0; i < mout->num_dacs; i++)
3878888afa15STakashi Iwai 		snd_hda_codec_cleanup_stream(codec, nids[i]);
38791da177e4SLinus Torvalds 	if (mout->hp_nid)
3880888afa15STakashi Iwai 		snd_hda_codec_cleanup_stream(codec, mout->hp_nid);
3881a06dbfc2STakashi Iwai 	for (i = 0; i < ARRAY_SIZE(mout->hp_out_nid); i++)
3882a06dbfc2STakashi Iwai 		if (mout->hp_out_nid[i])
3883a06dbfc2STakashi Iwai 			snd_hda_codec_cleanup_stream(codec,
3884a06dbfc2STakashi Iwai 						     mout->hp_out_nid[i]);
388582bc955fSTakashi Iwai 	for (i = 0; i < ARRAY_SIZE(mout->extra_out_nid); i++)
388682bc955fSTakashi Iwai 		if (mout->extra_out_nid[i])
3887888afa15STakashi Iwai 			snd_hda_codec_cleanup_stream(codec,
3888888afa15STakashi Iwai 						     mout->extra_out_nid[i]);
388962932df8SIngo Molnar 	mutex_lock(&codec->spdif_mutex);
38901da177e4SLinus Torvalds 	if (mout->dig_out_nid && mout->dig_out_used == HDA_DIG_ANALOG_DUP) {
38912f72853cSTakashi Iwai 		cleanup_dig_out_stream(codec, mout->dig_out_nid);
38921da177e4SLinus Torvalds 		mout->dig_out_used = 0;
38931da177e4SLinus Torvalds 	}
389462932df8SIngo Molnar 	mutex_unlock(&codec->spdif_mutex);
38951da177e4SLinus Torvalds 	return 0;
38961da177e4SLinus Torvalds }
38972698ea98STakashi Iwai EXPORT_SYMBOL_GPL(snd_hda_multi_out_analog_cleanup);
38981da177e4SLinus Torvalds 
38994740860bSTakashi Iwai /**
39004740860bSTakashi Iwai  * snd_hda_get_default_vref - Get the default (mic) VREF pin bits
3901a11e9b16STakashi Iwai  * @codec: the HDA codec
3902a11e9b16STakashi Iwai  * @pin: referred pin NID
39034740860bSTakashi Iwai  *
39044740860bSTakashi Iwai  * Guess the suitable VREF pin bits to be set as the pin-control value.
39054740860bSTakashi Iwai  * Note: the function doesn't set the AC_PINCTL_IN_EN bit.
39064740860bSTakashi Iwai  */
snd_hda_get_default_vref(struct hda_codec * codec,hda_nid_t pin)39074740860bSTakashi Iwai unsigned int snd_hda_get_default_vref(struct hda_codec *codec, hda_nid_t pin)
39084740860bSTakashi Iwai {
39094740860bSTakashi Iwai 	unsigned int pincap;
39104740860bSTakashi Iwai 	unsigned int oldval;
39114740860bSTakashi Iwai 	oldval = snd_hda_codec_read(codec, pin, 0,
39124740860bSTakashi Iwai 				    AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
39134740860bSTakashi Iwai 	pincap = snd_hda_query_pin_caps(codec, pin);
39144740860bSTakashi Iwai 	pincap = (pincap & AC_PINCAP_VREF) >> AC_PINCAP_VREF_SHIFT;
39154740860bSTakashi Iwai 	/* Exception: if the default pin setup is vref50, we give it priority */
39164740860bSTakashi Iwai 	if ((pincap & AC_PINCAP_VREF_80) && oldval != PIN_VREF50)
39174740860bSTakashi Iwai 		return AC_PINCTL_VREF_80;
39184740860bSTakashi Iwai 	else if (pincap & AC_PINCAP_VREF_50)
39194740860bSTakashi Iwai 		return AC_PINCTL_VREF_50;
39204740860bSTakashi Iwai 	else if (pincap & AC_PINCAP_VREF_100)
39214740860bSTakashi Iwai 		return AC_PINCTL_VREF_100;
39224740860bSTakashi Iwai 	else if (pincap & AC_PINCAP_VREF_GRD)
39234740860bSTakashi Iwai 		return AC_PINCTL_VREF_GRD;
39244740860bSTakashi Iwai 	return AC_PINCTL_VREF_HIZ;
39254740860bSTakashi Iwai }
39262698ea98STakashi Iwai EXPORT_SYMBOL_GPL(snd_hda_get_default_vref);
39274740860bSTakashi Iwai 
3928a11e9b16STakashi Iwai /**
3929a11e9b16STakashi Iwai  * snd_hda_correct_pin_ctl - correct the pin ctl value for matching with the pin cap
3930a11e9b16STakashi Iwai  * @codec: the HDA codec
3931a11e9b16STakashi Iwai  * @pin: referred pin NID
3932a11e9b16STakashi Iwai  * @val: pin ctl value to audit
3933a11e9b16STakashi Iwai  */
snd_hda_correct_pin_ctl(struct hda_codec * codec,hda_nid_t pin,unsigned int val)393462f3a2f7STakashi Iwai unsigned int snd_hda_correct_pin_ctl(struct hda_codec *codec,
393562f3a2f7STakashi Iwai 				     hda_nid_t pin, unsigned int val)
393662f3a2f7STakashi Iwai {
3937bf82326fSTakashi Iwai 	static const unsigned int cap_lists[][2] = {
393862f3a2f7STakashi Iwai 		{ AC_PINCTL_VREF_100, AC_PINCAP_VREF_100 },
393962f3a2f7STakashi Iwai 		{ AC_PINCTL_VREF_80, AC_PINCAP_VREF_80 },
394062f3a2f7STakashi Iwai 		{ AC_PINCTL_VREF_50, AC_PINCAP_VREF_50 },
394162f3a2f7STakashi Iwai 		{ AC_PINCTL_VREF_GRD, AC_PINCAP_VREF_GRD },
394262f3a2f7STakashi Iwai 	};
394362f3a2f7STakashi Iwai 	unsigned int cap;
394462f3a2f7STakashi Iwai 
394562f3a2f7STakashi Iwai 	if (!val)
394662f3a2f7STakashi Iwai 		return 0;
394762f3a2f7STakashi Iwai 	cap = snd_hda_query_pin_caps(codec, pin);
394862f3a2f7STakashi Iwai 	if (!cap)
394962f3a2f7STakashi Iwai 		return val; /* don't know what to do... */
395062f3a2f7STakashi Iwai 
395162f3a2f7STakashi Iwai 	if (val & AC_PINCTL_OUT_EN) {
395262f3a2f7STakashi Iwai 		if (!(cap & AC_PINCAP_OUT))
395362f3a2f7STakashi Iwai 			val &= ~(AC_PINCTL_OUT_EN | AC_PINCTL_HP_EN);
395462f3a2f7STakashi Iwai 		else if ((val & AC_PINCTL_HP_EN) && !(cap & AC_PINCAP_HP_DRV))
395562f3a2f7STakashi Iwai 			val &= ~AC_PINCTL_HP_EN;
395662f3a2f7STakashi Iwai 	}
395762f3a2f7STakashi Iwai 
395862f3a2f7STakashi Iwai 	if (val & AC_PINCTL_IN_EN) {
395962f3a2f7STakashi Iwai 		if (!(cap & AC_PINCAP_IN))
396062f3a2f7STakashi Iwai 			val &= ~(AC_PINCTL_IN_EN | AC_PINCTL_VREFEN);
396162f3a2f7STakashi Iwai 		else {
396262f3a2f7STakashi Iwai 			unsigned int vcap, vref;
396362f3a2f7STakashi Iwai 			int i;
396462f3a2f7STakashi Iwai 			vcap = (cap & AC_PINCAP_VREF) >> AC_PINCAP_VREF_SHIFT;
396562f3a2f7STakashi Iwai 			vref = val & AC_PINCTL_VREFEN;
396662f3a2f7STakashi Iwai 			for (i = 0; i < ARRAY_SIZE(cap_lists); i++) {
396762f3a2f7STakashi Iwai 				if (vref == cap_lists[i][0] &&
396862f3a2f7STakashi Iwai 				    !(vcap & cap_lists[i][1])) {
396962f3a2f7STakashi Iwai 					if (i == ARRAY_SIZE(cap_lists) - 1)
397062f3a2f7STakashi Iwai 						vref = AC_PINCTL_VREF_HIZ;
397162f3a2f7STakashi Iwai 					else
397262f3a2f7STakashi Iwai 						vref = cap_lists[i + 1][0];
397362f3a2f7STakashi Iwai 				}
397462f3a2f7STakashi Iwai 			}
397562f3a2f7STakashi Iwai 			val &= ~AC_PINCTL_VREFEN;
397662f3a2f7STakashi Iwai 			val |= vref;
397762f3a2f7STakashi Iwai 		}
397862f3a2f7STakashi Iwai 	}
397962f3a2f7STakashi Iwai 
398062f3a2f7STakashi Iwai 	return val;
398162f3a2f7STakashi Iwai }
39822698ea98STakashi Iwai EXPORT_SYMBOL_GPL(snd_hda_correct_pin_ctl);
398362f3a2f7STakashi Iwai 
3984a11e9b16STakashi Iwai /**
39853531ba21SPierre-Louis Bossart  * _snd_hda_set_pin_ctl - Helper to set pin ctl value
3986a11e9b16STakashi Iwai  * @codec: the HDA codec
3987a11e9b16STakashi Iwai  * @pin: referred pin NID
3988a11e9b16STakashi Iwai  * @val: pin control value to set
3989a11e9b16STakashi Iwai  * @cached: access over codec pinctl cache or direct write
3990a11e9b16STakashi Iwai  *
3991a11e9b16STakashi Iwai  * This function is a helper to set a pin ctl value more safely.
3992a11e9b16STakashi Iwai  * It corrects the pin ctl value via snd_hda_correct_pin_ctl(), stores the
3993a11e9b16STakashi Iwai  * value in pin target array via snd_hda_codec_set_pin_target(), then
3994401caff7STakashi Iwai  * actually writes the value via either snd_hda_codec_write_cache() or
3995a11e9b16STakashi Iwai  * snd_hda_codec_write() depending on @cached flag.
3996a11e9b16STakashi Iwai  */
_snd_hda_set_pin_ctl(struct hda_codec * codec,hda_nid_t pin,unsigned int val,bool cached)3997cdd03cedSTakashi Iwai int _snd_hda_set_pin_ctl(struct hda_codec *codec, hda_nid_t pin,
3998cdd03cedSTakashi Iwai 			 unsigned int val, bool cached)
3999cdd03cedSTakashi Iwai {
400062f3a2f7STakashi Iwai 	val = snd_hda_correct_pin_ctl(codec, pin, val);
4001d7fdc00aSTakashi Iwai 	snd_hda_codec_set_pin_target(codec, pin, val);
4002cdd03cedSTakashi Iwai 	if (cached)
4003401caff7STakashi Iwai 		return snd_hda_codec_write_cache(codec, pin, 0,
4004cdd03cedSTakashi Iwai 				AC_VERB_SET_PIN_WIDGET_CONTROL, val);
4005cdd03cedSTakashi Iwai 	else
4006cdd03cedSTakashi Iwai 		return snd_hda_codec_write(codec, pin, 0,
4007cdd03cedSTakashi Iwai 					   AC_VERB_SET_PIN_WIDGET_CONTROL, val);
4008cdd03cedSTakashi Iwai }
40092698ea98STakashi Iwai EXPORT_SYMBOL_GPL(_snd_hda_set_pin_ctl);
4010cdd03cedSTakashi Iwai 
4011990061c2STakashi Iwai /**
4012990061c2STakashi Iwai  * snd_hda_add_imux_item - Add an item to input_mux
4013a11e9b16STakashi Iwai  * @codec: the HDA codec
4014a11e9b16STakashi Iwai  * @imux: imux helper object
4015a11e9b16STakashi Iwai  * @label: the name of imux item to assign
4016a11e9b16STakashi Iwai  * @index: index number of imux item to assign
4017a11e9b16STakashi Iwai  * @type_idx: pointer to store the resultant label index
4018990061c2STakashi Iwai  *
4019990061c2STakashi Iwai  * When the same label is used already in the existing items, the number
4020990061c2STakashi Iwai  * suffix is appended to the label.  This label index number is stored
4021990061c2STakashi Iwai  * to type_idx when non-NULL pointer is given.
4022990061c2STakashi Iwai  */
snd_hda_add_imux_item(struct hda_codec * codec,struct hda_input_mux * imux,const char * label,int index,int * type_idx)40236194b99dSTakashi Iwai int snd_hda_add_imux_item(struct hda_codec *codec,
40246194b99dSTakashi Iwai 			  struct hda_input_mux *imux, const char *label,
402510a20af7STakashi Iwai 			  int index, int *type_idx)
402610a20af7STakashi Iwai {
402710a20af7STakashi Iwai 	int i, label_idx = 0;
402810a20af7STakashi Iwai 	if (imux->num_items >= HDA_MAX_NUM_INPUTS) {
40296194b99dSTakashi Iwai 		codec_err(codec, "hda_codec: Too many imux items!\n");
403010a20af7STakashi Iwai 		return -EINVAL;
403110a20af7STakashi Iwai 	}
403210a20af7STakashi Iwai 	for (i = 0; i < imux->num_items; i++) {
403310a20af7STakashi Iwai 		if (!strncmp(label, imux->items[i].label, strlen(label)))
403410a20af7STakashi Iwai 			label_idx++;
403510a20af7STakashi Iwai 	}
403610a20af7STakashi Iwai 	if (type_idx)
403710a20af7STakashi Iwai 		*type_idx = label_idx;
403810a20af7STakashi Iwai 	if (label_idx > 0)
403910a20af7STakashi Iwai 		snprintf(imux->items[imux->num_items].label,
404010a20af7STakashi Iwai 			 sizeof(imux->items[imux->num_items].label),
404110a20af7STakashi Iwai 			 "%s %d", label, label_idx);
4042b5786e85STakashi Iwai 	else
404375b1a8f9SJoe Perches 		strscpy(imux->items[imux->num_items].label, label,
404410a20af7STakashi Iwai 			sizeof(imux->items[imux->num_items].label));
404510a20af7STakashi Iwai 	imux->items[imux->num_items].index = index;
404610a20af7STakashi Iwai 	imux->num_items++;
404710a20af7STakashi Iwai 	return 0;
4048d7b1ae9dSTakashi Iwai }
40492698ea98STakashi Iwai EXPORT_SYMBOL_GPL(snd_hda_add_imux_item);
4050d7b1ae9dSTakashi Iwai 
40511da177e4SLinus Torvalds /**
40520a50575bSTakashi Iwai  * snd_hda_bus_reset_codecs - Reset the bus
405359ed1eadSTakashi Iwai  * @bus: HD-audio bus
40541da177e4SLinus Torvalds  */
snd_hda_bus_reset_codecs(struct hda_bus * bus)40550a50575bSTakashi Iwai void snd_hda_bus_reset_codecs(struct hda_bus *bus)
40561da177e4SLinus Torvalds {
40570ba21762STakashi Iwai 	struct hda_codec *codec;
40581da177e4SLinus Torvalds 
4059d068ebc2STakashi Iwai 	list_for_each_codec(codec, bus) {
406059ed1eadSTakashi Iwai 		/* FIXME: maybe a better way needed for forced reset */
406116037643STakashi Iwai 		if (current_work() != &codec->jackpoll_work.work)
406226a6cb6cSDavid Henningsson 			cancel_delayed_work_sync(&codec->jackpoll_work);
406359ed1eadSTakashi Iwai #ifdef CONFIG_PM
40640e24dbb7SMengdong Lin 		if (hda_codec_is_power_on(codec)) {
4065cc72da7dSTakashi Iwai 			hda_call_codec_suspend(codec);
4066cb53c626STakashi Iwai 			hda_call_codec_resume(codec);
40671da177e4SLinus Torvalds 		}
406859ed1eadSTakashi Iwai #endif
40691da177e4SLinus Torvalds 	}
407059ed1eadSTakashi Iwai }
4071b2e18597STakashi Iwai 
4072d5191e50STakashi Iwai /**
4073d5191e50STakashi Iwai  * snd_print_pcm_bits - Print the supported PCM fmt bits to the string buffer
4074d5191e50STakashi Iwai  * @pcm: PCM caps bits
4075d5191e50STakashi Iwai  * @buf: the string buffer to write
4076d5191e50STakashi Iwai  * @buflen: the max buffer length
4077d5191e50STakashi Iwai  *
4078d5191e50STakashi Iwai  * used by hda_proc.c and hda_eld.c
4079d5191e50STakashi Iwai  */
snd_print_pcm_bits(int pcm,char * buf,int buflen)4080b2022266STakashi Iwai void snd_print_pcm_bits(int pcm, char *buf, int buflen)
4081b2022266STakashi Iwai {
4082bf82326fSTakashi Iwai 	static const unsigned int bits[] = { 8, 16, 20, 24, 32 };
4083b2022266STakashi Iwai 	int i, j;
4084b2022266STakashi Iwai 
4085b2022266STakashi Iwai 	for (i = 0, j = 0; i < ARRAY_SIZE(bits); i++)
4086b2022266STakashi Iwai 		if (pcm & (AC_SUPPCM_BITS_8 << i))
408744eeb081STakashi Iwai 			j += scnprintf(buf + j, buflen - j,  " %d", bits[i]);
4088b2022266STakashi Iwai 
4089b2022266STakashi Iwai 	buf[j] = '\0'; /* necessary when j == 0 */
4090b2022266STakashi Iwai }
40912698ea98STakashi Iwai EXPORT_SYMBOL_GPL(snd_print_pcm_bits);
40921289e9e8STakashi Iwai 
40931289e9e8STakashi Iwai MODULE_DESCRIPTION("HDA codec core");
40941289e9e8STakashi Iwai MODULE_LICENSE("GPL");
4095