Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    3)  * HD-audio codec core device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    4)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    5) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    6) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    7) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    8) #include <linux/device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    9) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   10) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   11) #include <linux/export.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   12) #include <linux/pm_runtime.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   13) #include <sound/hdaudio.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   14) #include <sound/hda_regmap.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   15) #include <sound/pcm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   16) #include "local.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   17) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   18) static void setup_fg_nodes(struct hdac_device *codec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   19) static int get_codec_vendor_name(struct hdac_device *codec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   20) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   21) static void default_release(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   22) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   23) 	snd_hdac_device_exit(dev_to_hdac_dev(dev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   24) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   25) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   26) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   27)  * snd_hdac_device_init - initialize the HD-audio codec base device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   28)  * @codec: device to initialize
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   29)  * @bus: but to attach
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   30)  * @name: device name string
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   31)  * @addr: codec address
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   32)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   33)  * Returns zero for success or a negative error code.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   34)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   35)  * This function increments the runtime PM counter and marks it active.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   36)  * The caller needs to turn it off appropriately later.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   37)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   38)  * The caller needs to set the device's release op properly by itself.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   39)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   40) int snd_hdac_device_init(struct hdac_device *codec, struct hdac_bus *bus,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   41) 			 const char *name, unsigned int addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   42) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   43) 	struct device *dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   44) 	hda_nid_t fg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   45) 	int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   46) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   47) 	dev = &codec->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   48) 	device_initialize(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   49) 	dev->parent = bus->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   50) 	dev->bus = &snd_hda_bus_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   51) 	dev->release = default_release;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   52) 	dev->groups = hdac_dev_attr_groups;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   53) 	dev_set_name(dev, "%s", name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   54) 	device_enable_async_suspend(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   55) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   56) 	codec->bus = bus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   57) 	codec->addr = addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   58) 	codec->type = HDA_DEV_CORE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   59) 	mutex_init(&codec->widget_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   60) 	mutex_init(&codec->regmap_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   61) 	pm_runtime_set_active(&codec->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   62) 	pm_runtime_get_noresume(&codec->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   63) 	atomic_set(&codec->in_pm, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   64) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   65) 	err = snd_hdac_bus_add_device(bus, codec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   66) 	if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   67) 		goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   68) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   69) 	/* fill parameters */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   70) 	codec->vendor_id = snd_hdac_read_parm(codec, AC_NODE_ROOT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   71) 					      AC_PAR_VENDOR_ID);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   72) 	if (codec->vendor_id == -1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   73) 		/* read again, hopefully the access method was corrected
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   74) 		 * in the last read...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   75) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   76) 		codec->vendor_id = snd_hdac_read_parm(codec, AC_NODE_ROOT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   77) 						      AC_PAR_VENDOR_ID);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   78) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   79) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   80) 	codec->subsystem_id = snd_hdac_read_parm(codec, AC_NODE_ROOT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   81) 						 AC_PAR_SUBSYSTEM_ID);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   82) 	codec->revision_id = snd_hdac_read_parm(codec, AC_NODE_ROOT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   83) 						AC_PAR_REV_ID);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   84) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   85) 	setup_fg_nodes(codec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   86) 	if (!codec->afg && !codec->mfg) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   87) 		dev_err(dev, "no AFG or MFG node found\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   88) 		err = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   89) 		goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   90) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   91) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   92) 	fg = codec->afg ? codec->afg : codec->mfg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   93) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   94) 	err = snd_hdac_refresh_widgets(codec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   95) 	if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   96) 		goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   97) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   98) 	codec->power_caps = snd_hdac_read_parm(codec, fg, AC_PAR_POWER_STATE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   99) 	/* reread ssid if not set by parameter */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  100) 	if (codec->subsystem_id == -1 || codec->subsystem_id == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  101) 		snd_hdac_read(codec, fg, AC_VERB_GET_SUBSYSTEM_ID, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  102) 			      &codec->subsystem_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  103) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  104) 	err = get_codec_vendor_name(codec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  105) 	if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  106) 		goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  107) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  108) 	codec->chip_name = kasprintf(GFP_KERNEL, "ID %x",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  109) 				     codec->vendor_id & 0xffff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  110) 	if (!codec->chip_name) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  111) 		err = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  112) 		goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  113) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  114) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  115) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  116) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  117)  error:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  118) 	put_device(&codec->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  119) 	return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  120) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  121) EXPORT_SYMBOL_GPL(snd_hdac_device_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  122) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  123) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  124)  * snd_hdac_device_exit - clean up the HD-audio codec base device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  125)  * @codec: device to clean up
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  126)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  127) void snd_hdac_device_exit(struct hdac_device *codec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  128) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  129) 	pm_runtime_put_noidle(&codec->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  130) 	/* keep balance of runtime PM child_count in parent device */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  131) 	pm_runtime_set_suspended(&codec->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  132) 	snd_hdac_bus_remove_device(codec->bus, codec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  133) 	kfree(codec->vendor_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  134) 	kfree(codec->chip_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  135) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  136) EXPORT_SYMBOL_GPL(snd_hdac_device_exit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  137) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  138) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  139)  * snd_hdac_device_register - register the hd-audio codec base device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  140)  * @codec: the device to register
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  141)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  142) int snd_hdac_device_register(struct hdac_device *codec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  143) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  144) 	int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  145) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  146) 	err = device_add(&codec->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  147) 	if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  148) 		return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  149) 	mutex_lock(&codec->widget_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  150) 	err = hda_widget_sysfs_init(codec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  151) 	mutex_unlock(&codec->widget_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  152) 	if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  153) 		device_del(&codec->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  154) 		return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  155) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  156) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  157) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  158) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  159) EXPORT_SYMBOL_GPL(snd_hdac_device_register);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  160) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  161) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  162)  * snd_hdac_device_unregister - unregister the hd-audio codec base device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  163)  * @codec: the device to unregister
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  164)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  165) void snd_hdac_device_unregister(struct hdac_device *codec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  166) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  167) 	if (device_is_registered(&codec->dev)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  168) 		mutex_lock(&codec->widget_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  169) 		hda_widget_sysfs_exit(codec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  170) 		mutex_unlock(&codec->widget_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  171) 		device_del(&codec->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  172) 		snd_hdac_bus_remove_device(codec->bus, codec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  173) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  174) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  175) EXPORT_SYMBOL_GPL(snd_hdac_device_unregister);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  176) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  177) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  178)  * snd_hdac_device_set_chip_name - set/update the codec name
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  179)  * @codec: the HDAC device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  180)  * @name: name string to set
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  181)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  182)  * Returns 0 if the name is set or updated, or a negative error code.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  183)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  184) int snd_hdac_device_set_chip_name(struct hdac_device *codec, const char *name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  185) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  186) 	char *newname;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  187) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  188) 	if (!name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  189) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  190) 	newname = kstrdup(name, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  191) 	if (!newname)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  192) 		return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  193) 	kfree(codec->chip_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  194) 	codec->chip_name = newname;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  195) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  196) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  197) EXPORT_SYMBOL_GPL(snd_hdac_device_set_chip_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  198) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  199) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  200)  * snd_hdac_codec_modalias - give the module alias name
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  201)  * @codec: HDAC device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  202)  * @buf: string buffer to store
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  203)  * @size: string buffer size
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  204)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  205)  * Returns the size of string, like snprintf(), or a negative error code.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  206)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  207) int snd_hdac_codec_modalias(struct hdac_device *codec, char *buf, size_t size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  208) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  209) 	return scnprintf(buf, size, "hdaudio:v%08Xr%08Xa%02X\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  210) 			codec->vendor_id, codec->revision_id, codec->type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  211) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  212) EXPORT_SYMBOL_GPL(snd_hdac_codec_modalias);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  213) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  214) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  215)  * snd_hdac_make_cmd - compose a 32bit command word to be sent to the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  216)  *	HD-audio controller
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  217)  * @codec: the codec object
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  218)  * @nid: NID to encode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  219)  * @verb: verb to encode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  220)  * @parm: parameter to encode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  221)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  222)  * Return an encoded command verb or -1 for error.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  223)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  224) static unsigned int snd_hdac_make_cmd(struct hdac_device *codec, hda_nid_t nid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  225) 				      unsigned int verb, unsigned int parm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  226) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  227) 	u32 val, addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  228) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  229) 	addr = codec->addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  230) 	if ((addr & ~0xf) || (nid & ~0x7f) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  231) 	    (verb & ~0xfff) || (parm & ~0xffff)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  232) 		dev_err(&codec->dev, "out of range cmd %x:%x:%x:%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  233) 			addr, nid, verb, parm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  234) 		return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  235) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  236) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  237) 	val = addr << 28;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  238) 	val |= (u32)nid << 20;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  239) 	val |= verb << 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  240) 	val |= parm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  241) 	return val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  242) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  243) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  244) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  245)  * snd_hdac_exec_verb - execute an encoded verb
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  246)  * @codec: the codec object
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  247)  * @cmd: encoded verb to execute
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  248)  * @flags: optional flags, pass zero for default
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  249)  * @res: the pointer to store the result, NULL if running async
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  250)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  251)  * Returns zero if successful, or a negative error code.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  252)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  253)  * This calls the exec_verb op when set in hdac_codec.  If not,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  254)  * call the default snd_hdac_bus_exec_verb().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  255)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  256) int snd_hdac_exec_verb(struct hdac_device *codec, unsigned int cmd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  257) 		       unsigned int flags, unsigned int *res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  258) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  259) 	if (codec->exec_verb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  260) 		return codec->exec_verb(codec, cmd, flags, res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  261) 	return snd_hdac_bus_exec_verb(codec->bus, codec->addr, cmd, res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  262) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  263) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  264) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  265) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  266)  * snd_hdac_read - execute a verb
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  267)  * @codec: the codec object
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  268)  * @nid: NID to execute a verb
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  269)  * @verb: verb to execute
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  270)  * @parm: parameter for a verb
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  271)  * @res: the pointer to store the result, NULL if running async
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  272)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  273)  * Returns zero if successful, or a negative error code.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  274)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  275) int snd_hdac_read(struct hdac_device *codec, hda_nid_t nid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  276) 		  unsigned int verb, unsigned int parm, unsigned int *res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  277) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  278) 	unsigned int cmd = snd_hdac_make_cmd(codec, nid, verb, parm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  279) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  280) 	return snd_hdac_exec_verb(codec, cmd, 0, res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  281) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  282) EXPORT_SYMBOL_GPL(snd_hdac_read);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  283) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  284) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  285)  * _snd_hdac_read_parm - read a parmeter
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  286)  * @codec: the codec object
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  287)  * @nid: NID to read a parameter
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  288)  * @parm: parameter to read
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  289)  * @res: pointer to store the read value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  290)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  291)  * This function returns zero or an error unlike snd_hdac_read_parm().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  292)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  293) int _snd_hdac_read_parm(struct hdac_device *codec, hda_nid_t nid, int parm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  294) 			unsigned int *res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  295) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  296) 	unsigned int cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  297) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  298) 	cmd = snd_hdac_regmap_encode_verb(nid, AC_VERB_PARAMETERS) | parm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  299) 	return snd_hdac_regmap_read_raw(codec, cmd, res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  300) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  301) EXPORT_SYMBOL_GPL(_snd_hdac_read_parm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  302) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  303) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  304)  * snd_hdac_read_parm_uncached - read a codec parameter without caching
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  305)  * @codec: the codec object
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  306)  * @nid: NID to read a parameter
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  307)  * @parm: parameter to read
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  308)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  309)  * Returns -1 for error.  If you need to distinguish the error more
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  310)  * strictly, use snd_hdac_read() directly.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  311)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  312) int snd_hdac_read_parm_uncached(struct hdac_device *codec, hda_nid_t nid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  313) 				int parm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  314) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  315) 	unsigned int cmd, val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  316) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  317) 	cmd = snd_hdac_regmap_encode_verb(nid, AC_VERB_PARAMETERS) | parm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  318) 	if (snd_hdac_regmap_read_raw_uncached(codec, cmd, &val) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  319) 		return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  320) 	return val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  321) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  322) EXPORT_SYMBOL_GPL(snd_hdac_read_parm_uncached);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  323) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  324) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  325)  * snd_hdac_override_parm - override read-only parameters
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  326)  * @codec: the codec object
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  327)  * @nid: NID for the parameter
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  328)  * @parm: the parameter to change
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  329)  * @val: the parameter value to overwrite
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  330)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  331) int snd_hdac_override_parm(struct hdac_device *codec, hda_nid_t nid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  332) 			   unsigned int parm, unsigned int val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  333) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  334) 	unsigned int verb = (AC_VERB_PARAMETERS << 8) | (nid << 20) | parm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  335) 	int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  336) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  337) 	if (!codec->regmap)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  338) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  339) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  340) 	codec->caps_overwriting = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  341) 	err = snd_hdac_regmap_write_raw(codec, verb, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  342) 	codec->caps_overwriting = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  343) 	return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  344) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  345) EXPORT_SYMBOL_GPL(snd_hdac_override_parm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  346) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  347) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  348)  * snd_hdac_get_sub_nodes - get start NID and number of subtree nodes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  349)  * @codec: the codec object
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  350)  * @nid: NID to inspect
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  351)  * @start_id: the pointer to store the starting NID
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  352)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  353)  * Returns the number of subtree nodes or zero if not found.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  354)  * This function reads parameters always without caching.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  355)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  356) int snd_hdac_get_sub_nodes(struct hdac_device *codec, hda_nid_t nid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  357) 			   hda_nid_t *start_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  358) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  359) 	unsigned int parm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  360) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  361) 	parm = snd_hdac_read_parm_uncached(codec, nid, AC_PAR_NODE_COUNT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  362) 	if (parm == -1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  363) 		*start_id = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  364) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  365) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  366) 	*start_id = (parm >> 16) & 0x7fff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  367) 	return (int)(parm & 0x7fff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  368) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  369) EXPORT_SYMBOL_GPL(snd_hdac_get_sub_nodes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  370) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  371) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  372)  * look for an AFG and MFG nodes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  373)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  374) static void setup_fg_nodes(struct hdac_device *codec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  375) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  376) 	int i, total_nodes, function_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  377) 	hda_nid_t nid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  378) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  379) 	total_nodes = snd_hdac_get_sub_nodes(codec, AC_NODE_ROOT, &nid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  380) 	for (i = 0; i < total_nodes; i++, nid++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  381) 		function_id = snd_hdac_read_parm(codec, nid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  382) 						 AC_PAR_FUNCTION_TYPE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  383) 		switch (function_id & 0xff) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  384) 		case AC_GRP_AUDIO_FUNCTION:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  385) 			codec->afg = nid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  386) 			codec->afg_function_id = function_id & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  387) 			codec->afg_unsol = (function_id >> 8) & 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  388) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  389) 		case AC_GRP_MODEM_FUNCTION:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  390) 			codec->mfg = nid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  391) 			codec->mfg_function_id = function_id & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  392) 			codec->mfg_unsol = (function_id >> 8) & 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  393) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  394) 		default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  395) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  396) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  397) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  398) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  399) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  400) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  401)  * snd_hdac_refresh_widgets - Reset the widget start/end nodes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  402)  * @codec: the codec object
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  403)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  404) int snd_hdac_refresh_widgets(struct hdac_device *codec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  405) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  406) 	hda_nid_t start_nid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  407) 	int nums, err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  408) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  409) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  410) 	 * Serialize against multiple threads trying to update the sysfs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  411) 	 * widgets array.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  412) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  413) 	mutex_lock(&codec->widget_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  414) 	nums = snd_hdac_get_sub_nodes(codec, codec->afg, &start_nid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  415) 	if (!start_nid || nums <= 0 || nums >= 0xff) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  416) 		dev_err(&codec->dev, "cannot read sub nodes for FG 0x%02x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  417) 			codec->afg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  418) 		err = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  419) 		goto unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  420) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  421) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  422) 	err = hda_widget_sysfs_reinit(codec, start_nid, nums);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  423) 	if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  424) 		goto unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  425) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  426) 	codec->num_nodes = nums;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  427) 	codec->start_nid = start_nid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  428) 	codec->end_nid = start_nid + nums;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  429) unlock:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  430) 	mutex_unlock(&codec->widget_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  431) 	return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  432) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  433) EXPORT_SYMBOL_GPL(snd_hdac_refresh_widgets);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  434) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  435) /* return CONNLIST_LEN parameter of the given widget */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  436) static unsigned int get_num_conns(struct hdac_device *codec, hda_nid_t nid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  437) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  438) 	unsigned int wcaps = get_wcaps(codec, nid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  439) 	unsigned int parm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  440) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  441) 	if (!(wcaps & AC_WCAP_CONN_LIST) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  442) 	    get_wcaps_type(wcaps) != AC_WID_VOL_KNB)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  443) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  444) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  445) 	parm = snd_hdac_read_parm(codec, nid, AC_PAR_CONNLIST_LEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  446) 	if (parm == -1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  447) 		parm = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  448) 	return parm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  449) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  450) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  451) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  452)  * snd_hdac_get_connections - get a widget connection list
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  453)  * @codec: the codec object
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  454)  * @nid: NID
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  455)  * @conn_list: the array to store the results, can be NULL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  456)  * @max_conns: the max size of the given array
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  457)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  458)  * Returns the number of connected widgets, zero for no connection, or a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  459)  * negative error code.  When the number of elements don't fit with the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  460)  * given array size, it returns -ENOSPC.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  461)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  462)  * When @conn_list is NULL, it just checks the number of connections.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  463)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  464) int snd_hdac_get_connections(struct hdac_device *codec, hda_nid_t nid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  465) 			     hda_nid_t *conn_list, int max_conns)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  466) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  467) 	unsigned int parm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  468) 	int i, conn_len, conns, err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  469) 	unsigned int shift, num_elems, mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  470) 	hda_nid_t prev_nid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  471) 	int null_count = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  472) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  473) 	parm = get_num_conns(codec, nid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  474) 	if (!parm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  475) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  476) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  477) 	if (parm & AC_CLIST_LONG) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  478) 		/* long form */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  479) 		shift = 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  480) 		num_elems = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  481) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  482) 		/* short form */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  483) 		shift = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  484) 		num_elems = 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  485) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  486) 	conn_len = parm & AC_CLIST_LENGTH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  487) 	mask = (1 << (shift-1)) - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  488) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  489) 	if (!conn_len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  490) 		return 0; /* no connection */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  491) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  492) 	if (conn_len == 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  493) 		/* single connection */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  494) 		err = snd_hdac_read(codec, nid, AC_VERB_GET_CONNECT_LIST, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  495) 				    &parm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  496) 		if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  497) 			return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  498) 		if (conn_list)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  499) 			conn_list[0] = parm & mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  500) 		return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  501) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  502) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  503) 	/* multi connection */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  504) 	conns = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  505) 	prev_nid = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  506) 	for (i = 0; i < conn_len; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  507) 		int range_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  508) 		hda_nid_t val, n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  509) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  510) 		if (i % num_elems == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  511) 			err = snd_hdac_read(codec, nid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  512) 					    AC_VERB_GET_CONNECT_LIST, i,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  513) 					    &parm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  514) 			if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  515) 				return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  516) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  517) 		range_val = !!(parm & (1 << (shift-1))); /* ranges */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  518) 		val = parm & mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  519) 		if (val == 0 && null_count++) {  /* no second chance */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  520) 			dev_dbg(&codec->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  521) 				"invalid CONNECT_LIST verb %x[%i]:%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  522) 				nid, i, parm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  523) 			return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  524) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  525) 		parm >>= shift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  526) 		if (range_val) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  527) 			/* ranges between the previous and this one */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  528) 			if (!prev_nid || prev_nid >= val) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  529) 				dev_warn(&codec->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  530) 					 "invalid dep_range_val %x:%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  531) 					 prev_nid, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  532) 				continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  533) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  534) 			for (n = prev_nid + 1; n <= val; n++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  535) 				if (conn_list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  536) 					if (conns >= max_conns)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  537) 						return -ENOSPC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  538) 					conn_list[conns] = n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  539) 				}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  540) 				conns++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  541) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  542) 		} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  543) 			if (conn_list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  544) 				if (conns >= max_conns)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  545) 					return -ENOSPC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  546) 				conn_list[conns] = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  547) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  548) 			conns++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  549) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  550) 		prev_nid = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  551) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  552) 	return conns;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  553) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  554) EXPORT_SYMBOL_GPL(snd_hdac_get_connections);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  555) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  556) #ifdef CONFIG_PM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  557) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  558)  * snd_hdac_power_up - power up the codec
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  559)  * @codec: the codec object
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  560)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  561)  * This function calls the runtime PM helper to power up the given codec.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  562)  * Unlike snd_hdac_power_up_pm(), you should call this only for the code
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  563)  * path that isn't included in PM path.  Otherwise it gets stuck.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  564)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  565)  * Returns zero if successful, or a negative error code.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  566)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  567) int snd_hdac_power_up(struct hdac_device *codec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  568) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  569) 	return pm_runtime_get_sync(&codec->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  570) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  571) EXPORT_SYMBOL_GPL(snd_hdac_power_up);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  572) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  573) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  574)  * snd_hdac_power_down - power down the codec
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  575)  * @codec: the codec object
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  576)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  577)  * Returns zero if successful, or a negative error code.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  578)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  579) int snd_hdac_power_down(struct hdac_device *codec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  580) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  581) 	struct device *dev = &codec->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  582) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  583) 	pm_runtime_mark_last_busy(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  584) 	return pm_runtime_put_autosuspend(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  585) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  586) EXPORT_SYMBOL_GPL(snd_hdac_power_down);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  587) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  588) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  589)  * snd_hdac_power_up_pm - power up the codec
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  590)  * @codec: the codec object
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  591)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  592)  * This function can be called in a recursive code path like init code
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  593)  * which may be called by PM suspend/resume again.  OTOH, if a power-up
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  594)  * call must wake up the sleeper (e.g. in a kctl callback), use
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  595)  * snd_hdac_power_up() instead.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  596)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  597)  * Returns zero if successful, or a negative error code.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  598)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  599) int snd_hdac_power_up_pm(struct hdac_device *codec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  600) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  601) 	if (!atomic_inc_not_zero(&codec->in_pm))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  602) 		return snd_hdac_power_up(codec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  603) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  604) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  605) EXPORT_SYMBOL_GPL(snd_hdac_power_up_pm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  606) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  607) /* like snd_hdac_power_up_pm(), but only increment the pm count when
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  608)  * already powered up.  Returns -1 if not powered up, 1 if incremented
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  609)  * or 0 if unchanged.  Only used in hdac_regmap.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  610)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  611) int snd_hdac_keep_power_up(struct hdac_device *codec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  612) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  613) 	if (!atomic_inc_not_zero(&codec->in_pm)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  614) 		int ret = pm_runtime_get_if_in_use(&codec->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  615) 		if (!ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  616) 			return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  617) 		if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  618) 			return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  619) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  620) 	return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  621) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  622) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  623) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  624)  * snd_hdac_power_down_pm - power down the codec
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  625)  * @codec: the codec object
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  626)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  627)  * Like snd_hdac_power_up_pm(), this function is used in a recursive
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  628)  * code path like init code which may be called by PM suspend/resume again.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  629)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  630)  * Returns zero if successful, or a negative error code.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  631)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  632) int snd_hdac_power_down_pm(struct hdac_device *codec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  633) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  634) 	if (atomic_dec_if_positive(&codec->in_pm) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  635) 		return snd_hdac_power_down(codec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  636) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  637) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  638) EXPORT_SYMBOL_GPL(snd_hdac_power_down_pm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  639) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  640) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  641) /* codec vendor labels */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  642) struct hda_vendor_id {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  643) 	unsigned int id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  644) 	const char *name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  645) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  646) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  647) static const struct hda_vendor_id hda_vendor_ids[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  648) 	{ 0x1002, "ATI" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  649) 	{ 0x1013, "Cirrus Logic" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  650) 	{ 0x1057, "Motorola" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  651) 	{ 0x1095, "Silicon Image" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  652) 	{ 0x10de, "Nvidia" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  653) 	{ 0x10ec, "Realtek" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  654) 	{ 0x1102, "Creative" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  655) 	{ 0x1106, "VIA" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  656) 	{ 0x111d, "IDT" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  657) 	{ 0x11c1, "LSI" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  658) 	{ 0x11d4, "Analog Devices" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  659) 	{ 0x13f6, "C-Media" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  660) 	{ 0x14f1, "Conexant" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  661) 	{ 0x17e8, "Chrontel" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  662) 	{ 0x1854, "LG" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  663) 	{ 0x1aec, "Wolfson Microelectronics" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  664) 	{ 0x1af4, "QEMU" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  665) 	{ 0x434d, "C-Media" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  666) 	{ 0x8086, "Intel" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  667) 	{ 0x8384, "SigmaTel" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  668) 	{} /* terminator */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  669) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  670) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  671) /* store the codec vendor name */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  672) static int get_codec_vendor_name(struct hdac_device *codec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  673) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  674) 	const struct hda_vendor_id *c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  675) 	u16 vendor_id = codec->vendor_id >> 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  676) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  677) 	for (c = hda_vendor_ids; c->id; c++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  678) 		if (c->id == vendor_id) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  679) 			codec->vendor_name = kstrdup(c->name, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  680) 			return codec->vendor_name ? 0 : -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  681) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  682) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  683) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  684) 	codec->vendor_name = kasprintf(GFP_KERNEL, "Generic %04x", vendor_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  685) 	return codec->vendor_name ? 0 : -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  686) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  687) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  688) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  689)  * stream formats
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  690)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  691) struct hda_rate_tbl {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  692) 	unsigned int hz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  693) 	unsigned int alsa_bits;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  694) 	unsigned int hda_fmt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  695) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  696) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  697) /* rate = base * mult / div */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  698) #define HDA_RATE(base, mult, div) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  699) 	(AC_FMT_BASE_##base##K | (((mult) - 1) << AC_FMT_MULT_SHIFT) | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  700) 	 (((div) - 1) << AC_FMT_DIV_SHIFT))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  701) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  702) static const struct hda_rate_tbl rate_bits[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  703) 	/* rate in Hz, ALSA rate bitmask, HDA format value */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  704) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  705) 	/* autodetected value used in snd_hda_query_supported_pcm */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  706) 	{ 8000, SNDRV_PCM_RATE_8000, HDA_RATE(48, 1, 6) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  707) 	{ 11025, SNDRV_PCM_RATE_11025, HDA_RATE(44, 1, 4) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  708) 	{ 16000, SNDRV_PCM_RATE_16000, HDA_RATE(48, 1, 3) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  709) 	{ 22050, SNDRV_PCM_RATE_22050, HDA_RATE(44, 1, 2) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  710) 	{ 32000, SNDRV_PCM_RATE_32000, HDA_RATE(48, 2, 3) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  711) 	{ 44100, SNDRV_PCM_RATE_44100, HDA_RATE(44, 1, 1) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  712) 	{ 48000, SNDRV_PCM_RATE_48000, HDA_RATE(48, 1, 1) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  713) 	{ 88200, SNDRV_PCM_RATE_88200, HDA_RATE(44, 2, 1) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  714) 	{ 96000, SNDRV_PCM_RATE_96000, HDA_RATE(48, 2, 1) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  715) 	{ 176400, SNDRV_PCM_RATE_176400, HDA_RATE(44, 4, 1) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  716) 	{ 192000, SNDRV_PCM_RATE_192000, HDA_RATE(48, 4, 1) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  717) #define AC_PAR_PCM_RATE_BITS	11
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  718) 	/* up to bits 10, 384kHZ isn't supported properly */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  719) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  720) 	/* not autodetected value */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  721) 	{ 9600, SNDRV_PCM_RATE_KNOT, HDA_RATE(48, 1, 5) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  722) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  723) 	{ 0 } /* terminator */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  724) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  725) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  726) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  727)  * snd_hdac_calc_stream_format - calculate the format bitset
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  728)  * @rate: the sample rate
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  729)  * @channels: the number of channels
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  730)  * @format: the PCM format (SNDRV_PCM_FORMAT_XXX)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  731)  * @maxbps: the max. bps
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  732)  * @spdif_ctls: HD-audio SPDIF status bits (0 if irrelevant)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  733)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  734)  * Calculate the format bitset from the given rate, channels and th PCM format.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  735)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  736)  * Return zero if invalid.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  737)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  738) unsigned int snd_hdac_calc_stream_format(unsigned int rate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  739) 					 unsigned int channels,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  740) 					 snd_pcm_format_t format,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  741) 					 unsigned int maxbps,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  742) 					 unsigned short spdif_ctls)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  743) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  744) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  745) 	unsigned int val = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  746) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  747) 	for (i = 0; rate_bits[i].hz; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  748) 		if (rate_bits[i].hz == rate) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  749) 			val = rate_bits[i].hda_fmt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  750) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  751) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  752) 	if (!rate_bits[i].hz)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  753) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  754) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  755) 	if (channels == 0 || channels > 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  756) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  757) 	val |= channels - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  758) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  759) 	switch (snd_pcm_format_width(format)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  760) 	case 8:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  761) 		val |= AC_FMT_BITS_8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  762) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  763) 	case 16:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  764) 		val |= AC_FMT_BITS_16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  765) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  766) 	case 20:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  767) 	case 24:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  768) 	case 32:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  769) 		if (maxbps >= 32 || format == SNDRV_PCM_FORMAT_FLOAT_LE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  770) 			val |= AC_FMT_BITS_32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  771) 		else if (maxbps >= 24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  772) 			val |= AC_FMT_BITS_24;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  773) 		else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  774) 			val |= AC_FMT_BITS_20;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  775) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  776) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  777) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  778) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  779) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  780) 	if (spdif_ctls & AC_DIG1_NONAUDIO)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  781) 		val |= AC_FMT_TYPE_NON_PCM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  782) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  783) 	return val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  784) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  785) EXPORT_SYMBOL_GPL(snd_hdac_calc_stream_format);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  786) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  787) static unsigned int query_pcm_param(struct hdac_device *codec, hda_nid_t nid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  788) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  789) 	unsigned int val = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  790) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  791) 	if (nid != codec->afg &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  792) 	    (get_wcaps(codec, nid) & AC_WCAP_FORMAT_OVRD))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  793) 		val = snd_hdac_read_parm(codec, nid, AC_PAR_PCM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  794) 	if (!val || val == -1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  795) 		val = snd_hdac_read_parm(codec, codec->afg, AC_PAR_PCM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  796) 	if (!val || val == -1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  797) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  798) 	return val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  799) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  800) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  801) static unsigned int query_stream_param(struct hdac_device *codec, hda_nid_t nid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  802) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  803) 	unsigned int streams = snd_hdac_read_parm(codec, nid, AC_PAR_STREAM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  804) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  805) 	if (!streams || streams == -1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  806) 		streams = snd_hdac_read_parm(codec, codec->afg, AC_PAR_STREAM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  807) 	if (!streams || streams == -1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  808) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  809) 	return streams;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  810) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  811) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  812) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  813)  * snd_hdac_query_supported_pcm - query the supported PCM rates and formats
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  814)  * @codec: the codec object
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  815)  * @nid: NID to query
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  816)  * @ratesp: the pointer to store the detected rate bitflags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  817)  * @formatsp: the pointer to store the detected formats
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  818)  * @bpsp: the pointer to store the detected format widths
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  819)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  820)  * Queries the supported PCM rates and formats.  The NULL @ratesp, @formatsp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  821)  * or @bsps argument is ignored.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  822)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  823)  * Returns 0 if successful, otherwise a negative error code.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  824)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  825) int snd_hdac_query_supported_pcm(struct hdac_device *codec, hda_nid_t nid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  826) 				 u32 *ratesp, u64 *formatsp, unsigned int *bpsp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  827) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  828) 	unsigned int i, val, wcaps;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  829) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  830) 	wcaps = get_wcaps(codec, nid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  831) 	val = query_pcm_param(codec, nid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  832) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  833) 	if (ratesp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  834) 		u32 rates = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  835) 		for (i = 0; i < AC_PAR_PCM_RATE_BITS; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  836) 			if (val & (1 << i))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  837) 				rates |= rate_bits[i].alsa_bits;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  838) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  839) 		if (rates == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  840) 			dev_err(&codec->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  841) 				"rates == 0 (nid=0x%x, val=0x%x, ovrd=%i)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  842) 				nid, val,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  843) 				(wcaps & AC_WCAP_FORMAT_OVRD) ? 1 : 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  844) 			return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  845) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  846) 		*ratesp = rates;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  847) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  848) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  849) 	if (formatsp || bpsp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  850) 		u64 formats = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  851) 		unsigned int streams, bps;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  852) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  853) 		streams = query_stream_param(codec, nid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  854) 		if (!streams)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  855) 			return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  856) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  857) 		bps = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  858) 		if (streams & AC_SUPFMT_PCM) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  859) 			if (val & AC_SUPPCM_BITS_8) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  860) 				formats |= SNDRV_PCM_FMTBIT_U8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  861) 				bps = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  862) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  863) 			if (val & AC_SUPPCM_BITS_16) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  864) 				formats |= SNDRV_PCM_FMTBIT_S16_LE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  865) 				bps = 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  866) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  867) 			if (wcaps & AC_WCAP_DIGITAL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  868) 				if (val & AC_SUPPCM_BITS_32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  869) 					formats |= SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_LE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  870) 				if (val & (AC_SUPPCM_BITS_20|AC_SUPPCM_BITS_24))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  871) 					formats |= SNDRV_PCM_FMTBIT_S32_LE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  872) 				if (val & AC_SUPPCM_BITS_24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  873) 					bps = 24;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  874) 				else if (val & AC_SUPPCM_BITS_20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  875) 					bps = 20;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  876) 			} else if (val & (AC_SUPPCM_BITS_20|AC_SUPPCM_BITS_24|
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  877) 					  AC_SUPPCM_BITS_32)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  878) 				formats |= SNDRV_PCM_FMTBIT_S32_LE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  879) 				if (val & AC_SUPPCM_BITS_32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  880) 					bps = 32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  881) 				else if (val & AC_SUPPCM_BITS_24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  882) 					bps = 24;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  883) 				else if (val & AC_SUPPCM_BITS_20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  884) 					bps = 20;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  885) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  886) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  887) #if 0 /* FIXME: CS4206 doesn't work, which is the only codec supporting float */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  888) 		if (streams & AC_SUPFMT_FLOAT32) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  889) 			formats |= SNDRV_PCM_FMTBIT_FLOAT_LE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  890) 			if (!bps)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  891) 				bps = 32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  892) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  893) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  894) 		if (streams == AC_SUPFMT_AC3) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  895) 			/* should be exclusive */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  896) 			/* temporary hack: we have still no proper support
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  897) 			 * for the direct AC3 stream...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  898) 			 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  899) 			formats |= SNDRV_PCM_FMTBIT_U8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  900) 			bps = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  901) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  902) 		if (formats == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  903) 			dev_err(&codec->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  904) 				"formats == 0 (nid=0x%x, val=0x%x, ovrd=%i, streams=0x%x)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  905) 				nid, val,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  906) 				(wcaps & AC_WCAP_FORMAT_OVRD) ? 1 : 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  907) 				streams);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  908) 			return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  909) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  910) 		if (formatsp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  911) 			*formatsp = formats;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  912) 		if (bpsp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  913) 			*bpsp = bps;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  914) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  915) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  916) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  917) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  918) EXPORT_SYMBOL_GPL(snd_hdac_query_supported_pcm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  919) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  920) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  921)  * snd_hdac_is_supported_format - Check the validity of the format
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  922)  * @codec: the codec object
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  923)  * @nid: NID to check
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  924)  * @format: the HD-audio format value to check
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  925)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  926)  * Check whether the given node supports the format value.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  927)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  928)  * Returns true if supported, false if not.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  929)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  930) bool snd_hdac_is_supported_format(struct hdac_device *codec, hda_nid_t nid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  931) 				  unsigned int format)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  932) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  933) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  934) 	unsigned int val = 0, rate, stream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  935) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  936) 	val = query_pcm_param(codec, nid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  937) 	if (!val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  938) 		return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  939) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  940) 	rate = format & 0xff00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  941) 	for (i = 0; i < AC_PAR_PCM_RATE_BITS; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  942) 		if (rate_bits[i].hda_fmt == rate) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  943) 			if (val & (1 << i))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  944) 				break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  945) 			return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  946) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  947) 	if (i >= AC_PAR_PCM_RATE_BITS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  948) 		return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  949) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  950) 	stream = query_stream_param(codec, nid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  951) 	if (!stream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  952) 		return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  953) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  954) 	if (stream & AC_SUPFMT_PCM) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  955) 		switch (format & 0xf0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  956) 		case 0x00:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  957) 			if (!(val & AC_SUPPCM_BITS_8))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  958) 				return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  959) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  960) 		case 0x10:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  961) 			if (!(val & AC_SUPPCM_BITS_16))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  962) 				return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  963) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  964) 		case 0x20:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  965) 			if (!(val & AC_SUPPCM_BITS_20))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  966) 				return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  967) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  968) 		case 0x30:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  969) 			if (!(val & AC_SUPPCM_BITS_24))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  970) 				return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  971) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  972) 		case 0x40:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  973) 			if (!(val & AC_SUPPCM_BITS_32))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  974) 				return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  975) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  976) 		default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  977) 			return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  978) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  979) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  980) 		/* FIXME: check for float32 and AC3? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  981) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  982) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  983) 	return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  984) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  985) EXPORT_SYMBOL_GPL(snd_hdac_is_supported_format);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  986) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  987) static unsigned int codec_read(struct hdac_device *hdac, hda_nid_t nid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  988) 			int flags, unsigned int verb, unsigned int parm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  989) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  990) 	unsigned int cmd = snd_hdac_make_cmd(hdac, nid, verb, parm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  991) 	unsigned int res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  992) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  993) 	if (snd_hdac_exec_verb(hdac, cmd, flags, &res))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  994) 		return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  995) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  996) 	return res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  997) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  998) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  999) static int codec_write(struct hdac_device *hdac, hda_nid_t nid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) 			int flags, unsigned int verb, unsigned int parm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) 	unsigned int cmd = snd_hdac_make_cmd(hdac, nid, verb, parm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) 	return snd_hdac_exec_verb(hdac, cmd, flags, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008)  * snd_hdac_codec_read - send a command and get the response
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009)  * @hdac: the HDAC device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010)  * @nid: NID to send the command
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011)  * @flags: optional bit flags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012)  * @verb: the verb to send
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013)  * @parm: the parameter for the verb
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015)  * Send a single command and read the corresponding response.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017)  * Returns the obtained response value, or -1 for an error.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) int snd_hdac_codec_read(struct hdac_device *hdac, hda_nid_t nid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) 			int flags, unsigned int verb, unsigned int parm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) 	return codec_read(hdac, nid, flags, verb, parm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) EXPORT_SYMBOL_GPL(snd_hdac_codec_read);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027)  * snd_hdac_codec_write - send a single command without waiting for response
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028)  * @hdac: the HDAC device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029)  * @nid: NID to send the command
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030)  * @flags: optional bit flags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031)  * @verb: the verb to send
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032)  * @parm: the parameter for the verb
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034)  * Send a single command without waiting for response.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036)  * Returns 0 if successful, or a negative error code.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) int snd_hdac_codec_write(struct hdac_device *hdac, hda_nid_t nid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) 			int flags, unsigned int verb, unsigned int parm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) 	return codec_write(hdac, nid, flags, verb, parm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) EXPORT_SYMBOL_GPL(snd_hdac_codec_write);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046)  * snd_hdac_check_power_state - check whether the actual power state matches
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047)  * with the target state
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049)  * @hdac: the HDAC device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050)  * @nid: NID to send the command
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051)  * @target_state: target state to check for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053)  * Return true if state matches, false if not
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) bool snd_hdac_check_power_state(struct hdac_device *hdac,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) 		hda_nid_t nid, unsigned int target_state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) 	unsigned int state = codec_read(hdac, nid, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) 				AC_VERB_GET_POWER_STATE, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) 	if (state & AC_PWRST_ERROR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) 		return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) 	state = (state >> 4) & 0x0f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) 	return (state == target_state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) EXPORT_SYMBOL_GPL(snd_hdac_check_power_state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068)  * snd_hdac_sync_power_state - wait until actual power state matches
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069)  * with the target state
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071)  * @codec: the HDAC device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072)  * @nid: NID to send the command
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073)  * @power_state: target power state to wait for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075)  * Return power state or PS_ERROR if codec rejects GET verb.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) unsigned int snd_hdac_sync_power_state(struct hdac_device *codec,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) 			hda_nid_t nid, unsigned int power_state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) 	unsigned long end_time = jiffies + msecs_to_jiffies(500);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) 	unsigned int state, actual_state, count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) 	for (count = 0; count < 500; count++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) 		state = snd_hdac_codec_read(codec, nid, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) 				AC_VERB_GET_POWER_STATE, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) 		if (state & AC_PWRST_ERROR) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) 			msleep(20);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) 		actual_state = (state >> 4) & 0x0f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) 		if (actual_state == power_state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) 		if (time_after_eq(jiffies, end_time))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) 		/* wait until the codec reachs to the target state */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) 		msleep(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) 	return state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) EXPORT_SYMBOL_GPL(snd_hdac_sync_power_state);